[llvm] r322930 - [InstCombine] Make foldSelectOpOp able to handle two-operand getelementptr

John Brawn via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 19 02:05:15 PST 2018


Author: john.brawn
Date: Fri Jan 19 02:05:15 2018
New Revision: 322930

URL: http://llvm.org/viewvc/llvm-project?rev=322930&view=rev
Log:
[InstCombine] Make foldSelectOpOp able to handle two-operand getelementptr

Three (or more) operand getelementptrs could plausibly also be handled, but
handling only two-operand fits in easily with the existing BinaryOperator
handling.

Differential Revision: https://reviews.llvm.org/D39958

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/trunk/test/Transforms/InstCombine/select-gep.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=322930&r1=322929&r2=322930&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Fri Jan 19 02:05:15 2018
@@ -300,12 +300,13 @@ Instruction *InstCombiner::foldSelectOpO
                             TI->getType());
   }
 
-  // Only handle binary operators with one-use here. As with the cast case
-  // above, it may be possible to relax the one-use constraint, but that needs
-  // be examined carefully since it may not reduce the total number of
-  // instructions.
-  BinaryOperator *BO = dyn_cast<BinaryOperator>(TI);
-  if (!BO || !TI->hasOneUse() || !FI->hasOneUse())
+  // Only handle binary operators (including two-operand getelementptr) with
+  // one-use here. As with the cast case above, it may be possible to relax the
+  // one-use constraint, but that needs be examined carefully since it may not
+  // reduce the total number of instructions.
+  if (TI->getNumOperands() != 2 || FI->getNumOperands() != 2 ||
+      (!isa<BinaryOperator>(TI) && !isa<GetElementPtrInst>(TI)) ||
+      !TI->hasOneUse() || !FI->hasOneUse())
     return nullptr;
 
   // Figure out if the operations have any operands in common.
@@ -342,7 +343,18 @@ Instruction *InstCombiner::foldSelectOpO
                                       SI.getName() + ".v", &SI);
   Value *Op0 = MatchIsOpZero ? MatchOp : NewSI;
   Value *Op1 = MatchIsOpZero ? NewSI : MatchOp;
-  return BinaryOperator::Create(BO->getOpcode(), Op0, Op1);
+  if (auto *BO = dyn_cast<BinaryOperator>(TI)) {
+    return BinaryOperator::Create(BO->getOpcode(), Op0, Op1);
+  }
+  if (auto *TGEP = dyn_cast<GetElementPtrInst>(TI)) {
+    auto *FGEP = cast<GetElementPtrInst>(FI);
+    Type *ElementType = TGEP->getResultElementType();
+    return TGEP->isInBounds() && FGEP->isInBounds()
+               ? GetElementPtrInst::CreateInBounds(ElementType, Op0, {Op1})
+               : GetElementPtrInst::Create(ElementType, Op0, {Op1});
+  }
+  llvm_unreachable("Expected BinaryOperator or GEP");
+  return nullptr;
 }
 
 static bool isSelect01(const APInt &C1I, const APInt &C2I) {

Modified: llvm/trunk/test/Transforms/InstCombine/select-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/select-gep.ll?rev=322930&r1=322929&r2=322930&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/select-gep.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/select-gep.ll Fri Jan 19 02:05:15 2018
@@ -3,10 +3,9 @@
 
 define i32* @test1a(i32* %p, i32* %q) {
 ; CHECK-LABEL: @test1a(
-; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 4
-; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 4
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P]], [[Q]]
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], i32* [[GEP1]], i32* [[GEP2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P:%.*]], [[Q:%.*]]
+; CHECK-NEXT:    [[SELECT_V:%.*]] = select i1 [[CMP]], i32* [[P]], i32* [[Q]]
+; CHECK-NEXT:    [[SELECT:%.*]] = getelementptr i32, i32* [[SELECT_V]], i64 4
 ; CHECK-NEXT:    ret i32* [[SELECT]]
 ;
   %gep1 = getelementptr i32, i32* %p, i64 4
@@ -18,10 +17,9 @@ define i32* @test1a(i32* %p, i32* %q) {
 
 define i32* @test1b(i32* %p, i32* %q) {
 ; CHECK-LABEL: @test1b(
-; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 4
-; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 4
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P]], [[Q]]
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], i32* [[GEP1]], i32* [[GEP2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P:%.*]], [[Q:%.*]]
+; CHECK-NEXT:    [[SELECT_V:%.*]] = select i1 [[CMP]], i32* [[P]], i32* [[Q]]
+; CHECK-NEXT:    [[SELECT:%.*]] = getelementptr i32, i32* [[SELECT_V]], i64 4
 ; CHECK-NEXT:    ret i32* [[SELECT]]
 ;
   %gep1 = getelementptr inbounds i32, i32* %p, i64 4
@@ -33,10 +31,9 @@ define i32* @test1b(i32* %p, i32* %q) {
 
 define i32* @test1c(i32* %p, i32* %q) {
 ; CHECK-LABEL: @test1c(
-; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 4
-; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i32, i32* [[Q:%.*]], i64 4
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P]], [[Q]]
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], i32* [[GEP1]], i32* [[GEP2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P:%.*]], [[Q:%.*]]
+; CHECK-NEXT:    [[SELECT_V:%.*]] = select i1 [[CMP]], i32* [[P]], i32* [[Q]]
+; CHECK-NEXT:    [[SELECT:%.*]] = getelementptr i32, i32* [[SELECT_V]], i64 4
 ; CHECK-NEXT:    ret i32* [[SELECT]]
 ;
   %gep1 = getelementptr i32, i32* %p, i64 4
@@ -48,10 +45,9 @@ define i32* @test1c(i32* %p, i32* %q) {
 
 define i32* @test1d(i32* %p, i32* %q) {
 ; CHECK-LABEL: @test1d(
-; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 4
-; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i32, i32* [[Q:%.*]], i64 4
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P]], [[Q]]
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], i32* [[GEP1]], i32* [[GEP2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32* [[P:%.*]], [[Q:%.*]]
+; CHECK-NEXT:    [[SELECT_V:%.*]] = select i1 [[CMP]], i32* [[P]], i32* [[Q]]
+; CHECK-NEXT:    [[SELECT:%.*]] = getelementptr inbounds i32, i32* [[SELECT_V]], i64 4
 ; CHECK-NEXT:    ret i32* [[SELECT]]
 ;
   %gep1 = getelementptr inbounds i32, i32* %p, i64 4
@@ -63,10 +59,9 @@ define i32* @test1d(i32* %p, i32* %q) {
 
 define i32* @test2(i32* %p, i64 %x, i64 %y) {
 ; CHECK-LABEL: @test2(
-; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[X:%.*]]
-; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 [[Y:%.*]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[X]], [[Y]]
-; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], i32* [[GEP1]], i32* [[GEP2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[SELECT_V:%.*]] = select i1 [[CMP]], i64 [[X]], i64 [[Y]]
+; CHECK-NEXT:    [[SELECT:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[SELECT_V]]
 ; CHECK-NEXT:    ret i32* [[SELECT]]
 ;
   %gep1 = getelementptr inbounds i32, i32* %p, i64 %x




More information about the llvm-commits mailing list