diff options
author | Luke Lau <luke@igalia.com> | 2024-06-03 11:12:27 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-03 11:12:27 +0100 |
commit | 910098e40572f9fe6bfde161eafd1b390a356043 (patch) | |
tree | 71dcc714fd2550d212cbec16e7e58ee062f5f62c /llvm/lib | |
parent | bf4eaec44054fa3908d50898f572e15d89119c67 (diff) | |
download | llvm-910098e40572f9fe6bfde161eafd1b390a356043.zip llvm-910098e40572f9fe6bfde161eafd1b390a356043.tar.gz llvm-910098e40572f9fe6bfde161eafd1b390a356043.tar.bz2 |
[RISCV] Match strided vector bases in RISCVGatherScatterLowering (#93972)
Currently we only match GEPs with a scalar base pointer, but a common
pattern that's emitted from the loop vectorizer is a strided vector base
plus some sort of scalar offset:
%base = getelementptr i64, ptr %p, <vscale x 1 x i64> %step
%gep = getelementptr i64, <vscale x 1 x ptr> %base, i64 %offset
This is common for accesses into a struct e.g. f[i].b below:
struct F { int a; char b; };
void foo(struct F *f) {
for (int i = 0; i < 1024; i += 2) {
f[i].a++;
f[i].b++;
}
}
This patch handles this case in RISCVGatherScatterLowering by recursing
on the base pointer if it's a vector.
With this we can convert roughly 80% of the indexed loads and stores
emitted to strided loads and stores on SPEC CPU 2017, -O3
-march=rva22u64_v
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp b/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp index f0bd25f..cff46e1 100644 --- a/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp @@ -349,8 +349,27 @@ RISCVGatherScatterLowering::determineBaseAndStride(Instruction *Ptr, SmallVector<Value *, 2> Ops(GEP->operands()); + // If the base pointer is a vector, check if it's strided. + Value *Base = GEP->getPointerOperand(); + if (auto *BaseInst = dyn_cast<Instruction>(Base); + BaseInst && BaseInst->getType()->isVectorTy()) { + // If GEP's offset is scalar then we can add it to the base pointer's base. + auto IsScalar = [](Value *Idx) { return !Idx->getType()->isVectorTy(); }; + if (all_of(GEP->indices(), IsScalar)) { + auto [BaseBase, Stride] = determineBaseAndStride(BaseInst, Builder); + if (BaseBase) { + Builder.SetInsertPoint(GEP); + SmallVector<Value *> Indices(GEP->indices()); + Value *OffsetBase = + Builder.CreateGEP(GEP->getSourceElementType(), BaseBase, Indices, + GEP->getName() + "offset", GEP->isInBounds()); + return {OffsetBase, Stride}; + } + } + } + // Base pointer needs to be a scalar. - Value *ScalarBase = Ops[0]; + Value *ScalarBase = Base; if (ScalarBase->getType()->isVectorTy()) { ScalarBase = getSplatValue(ScalarBase); if (!ScalarBase) |