[PATCH] D39911: [SelectionDAG] Teach SelectionDAGBuilder's getUniformBase for gather/scatter handling to accept GEPs with more than 2 operands if the middle operands are all 0s
Craig Topper via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 10 11:00:27 PST 2017
craig.topper created this revision.
Currently we can only get a uniform base from a simple GEP with 2 operands. This causes us to miss address folding opportunities for simple global array accesses as the test case shows.
This patch adds support for larger GEPs if the other indices are 0 since those don't require any additional computations to be inserted.
We may also want to handle constant splats of zero here, but I'm leaving that for future work when I have a real world example.
https://reviews.llvm.org/D39911
Files:
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
test/CodeGen/X86/masked_gather_scatter.ll
Index: test/CodeGen/X86/masked_gather_scatter.ll
===================================================================
--- test/CodeGen/X86/masked_gather_scatter.ll
+++ test/CodeGen/X86/masked_gather_scatter.ll
@@ -2330,46 +2330,34 @@
define <8 x i32> @test_global_array(<8 x i64> %indxs) {
; KNL_64-LABEL: test_global_array:
; KNL_64: # BB#0:
-; KNL_64-NEXT: vpsllq $2, %zmm0, %zmm0
; KNL_64-NEXT: movl $glob_array, %eax
-; KNL_64-NEXT: vpbroadcastq %rax, %zmm1
-; KNL_64-NEXT: vpaddq %zmm0, %zmm1, %zmm1
; KNL_64-NEXT: kxnorw %k0, %k0, %k1
-; KNL_64-NEXT: vpgatherqd (,%zmm1), %ymm0 {%k1}
+; KNL_64-NEXT: vpgatherqd (%rax,%zmm0,4), %ymm1 {%k1}
+; KNL_64-NEXT: vmovdqa %ymm1, %ymm0
; KNL_64-NEXT: retq
;
; KNL_32-LABEL: test_global_array:
; KNL_32: # BB#0:
-; KNL_32-NEXT: vpmovqd %zmm0, %ymm0
-; KNL_32-NEXT: vpslld $2, %ymm0, %ymm0
; KNL_32-NEXT: movl $glob_array, %eax
-; KNL_32-NEXT: vmovd %eax, %xmm1
-; KNL_32-NEXT: vpbroadcastd %xmm1, %ymm1
-; KNL_32-NEXT: vpaddd %ymm0, %ymm1, %ymm0
-; KNL_32-NEXT: vpmovsxdq %ymm0, %zmm1
; KNL_32-NEXT: kxnorw %k0, %k0, %k1
-; KNL_32-NEXT: vpgatherqd (,%zmm1), %ymm0 {%k1}
+; KNL_32-NEXT: vpgatherqd (%eax,%zmm0,4), %ymm1 {%k1}
+; KNL_32-NEXT: vmovdqa %ymm1, %ymm0
; KNL_32-NEXT: retl
;
; SKX-LABEL: test_global_array:
; SKX: # BB#0:
-; SKX-NEXT: vpsllq $2, %zmm0, %zmm0
; SKX-NEXT: movl $glob_array, %eax
-; SKX-NEXT: vpbroadcastq %rax, %zmm1
-; SKX-NEXT: vpaddq %zmm0, %zmm1, %zmm1
; SKX-NEXT: kxnorw %k0, %k0, %k1
-; SKX-NEXT: vpgatherqd (,%zmm1), %ymm0 {%k1}
+; SKX-NEXT: vpgatherqd (%rax,%zmm0,4), %ymm1 {%k1}
+; SKX-NEXT: vmovdqa %ymm1, %ymm0
; SKX-NEXT: retq
;
; SKX_32-LABEL: test_global_array:
; SKX_32: # BB#0:
; SKX_32-NEXT: movl $glob_array, %eax
-; SKX_32-NEXT: vpbroadcastd %eax, %ymm1
-; SKX_32-NEXT: vpmovqd %zmm0, %ymm0
-; SKX_32-NEXT: vpslld $2, %ymm0, %ymm0
-; SKX_32-NEXT: vpaddd %ymm0, %ymm1, %ymm1
; SKX_32-NEXT: kxnorw %k0, %k0, %k1
-; SKX_32-NEXT: vpgatherdd (,%ymm1), %ymm0 {%k1}
+; SKX_32-NEXT: vpgatherqd (%eax,%zmm0,4), %ymm1 {%k1}
+; SKX_32-NEXT: vmovdqa %ymm1, %ymm0
; SKX_32-NEXT: retl
%p = getelementptr inbounds [16 x i32], [16 x i32]* @glob_array, i64 0, <8 x i64> %indxs
%g = call <8 x i32> @llvm.masked.gather.v8i32.v8p0i32(<8 x i32*> %p, i32 8, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef)
Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3871,16 +3871,23 @@
assert(Ptr->getType()->isVectorTy() && "Uexpected pointer type");
const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr);
- if (!GEP || GEP->getNumOperands() > 2)
+ if (!GEP || !GEP->hasIndices())
return false;
const Value *GEPPtr = GEP->getPointerOperand();
if (!GEPPtr->getType()->isVectorTy())
Ptr = GEPPtr;
else if (!(Ptr = getSplatValue(GEPPtr)))
return false;
- Value *IndexVal = GEP->getOperand(1);
+ unsigned FinalIndex = GEP->getNumOperands() - 1;
+ Value *IndexVal = GEP->getOperand(FinalIndex);
+
+ // Ensure all the other indices are 0.
+ for (unsigned i = 1; i < FinalIndex; ++i)
+ if (auto *C = dyn_cast<ConstantInt>(GEP->getOperand(i)))
+ if (!C->isZero())
+ return false;
// The operands of the GEP may be defined in another basic block.
// In this case we'll not find nodes for the operands.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D39911.122479.patch
Type: text/x-patch
Size: 3635 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171110/25e97f7f/attachment.bin>
More information about the llvm-commits
mailing list