aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorLuke Lau <luke@igalia.com>2024-06-03 11:12:27 +0100
committerGitHub <noreply@github.com>2024-06-03 11:12:27 +0100
commit910098e40572f9fe6bfde161eafd1b390a356043 (patch)
tree71dcc714fd2550d212cbec16e7e58ee062f5f62c /llvm/lib
parentbf4eaec44054fa3908d50898f572e15d89119c67 (diff)
downloadllvm-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.cpp21
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)