summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp26
-rw-r--r--llvm/test/Transforms/InstCombine/select-gep.ll35
2 files changed, 34 insertions, 27 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 7f5fb926440..62ff22acc75 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -300,12 +300,13 @@ Instruction *InstCombiner::foldSelectOpOp(SelectInst &SI, Instruction *TI,
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::foldSelectOpOp(SelectInst &SI, Instruction *TI,
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) {
diff --git a/llvm/test/Transforms/InstCombine/select-gep.ll b/llvm/test/Transforms/InstCombine/select-gep.ll
index 41304a8de0b..90bbc4907b9 100644
--- a/llvm/test/Transforms/InstCombine/select-gep.ll
+++ b/llvm/test/Transforms/InstCombine/select-gep.ll
@@ -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
OpenPOWER on IntegriCloud