aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp84
-rw-r--r--test/Transforms/InstCombine/load-cmp.ll12
2 files changed, 70 insertions, 26 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 088e440ed2..6cda71b8a3 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -6043,15 +6043,16 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
// Variables for our state machines.
- // OnlyTrueElement - Used to emit a comparison of "i == 47", where 47 is the
- // only index the condition is true for. The values are -1 -> undef,
- // -2 -> overdef, >= 0 -> that index is true.
- int OnlyTrueElement = -1;
+ // FirstTrueElement/SecondTrueElement - Used to emit a comparison of the form
+ // "i == 47 | i == 87", where 47 is the first index the condition is true for,
+ // and 87 is the second (and last) index. FirstTrueElement is -1 when
+ // undefined, otherwise set to the first true element. SecondTrueElement is
+ // -1 when undefined, -2 when overdefined and >= 0 when that index is true.
+ int FirstTrueElement = -1, SecondTrueElement = -1;
- // OnlyFalseElement - Used to emit a comparison of "i != 47", where 47 is the
- // only index the condition is false for. The values are -1 -> undef,
- // -2 -> overdef, >= 0 -> that index is false.
- int OnlyFalseElement = -1;
+ // FirstFalseElement/SecondFalseElement - Used to emit a comparison of the
+ // form "i != 47 & i != 87". Same state transitions as for true elements.
+ int FirstFalseElement = -1, SecondFalseElement = -1;
// MagicBitvector - This is a magic bitvector where we set a bit if the
// comparison is true for element 'i'. If there are 64 elements or less in
@@ -6079,11 +6080,21 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
// State machine for single index comparison.
if (IsTrueForElt) {
- // If undefined -> defined. Otherwise -> overdefined.
- OnlyTrueElement = OnlyTrueElement == -1 ? i : -2;
+ // Update the TrueElement state machine.
+ if (FirstTrueElement == -1)
+ FirstTrueElement = i;
+ else if (SecondTrueElement == -1)
+ SecondTrueElement = i;
+ else
+ SecondTrueElement = -2;
} else {
- // If undefined -> defined. Otherwise -> overdefined.
- OnlyFalseElement = OnlyFalseElement == -1 ? i : -2;
+ // Update the FalseElement state machine.
+ if (FirstFalseElement == -1)
+ FirstFalseElement = i;
+ else if (SecondFalseElement == -1)
+ SecondFalseElement = i;
+ else
+ SecondFalseElement = -2;
}
// If this element is in range, update our magic bitvector.
@@ -6091,31 +6102,52 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
MagicBitvector |= 1ULL << i;
// If all of our states become overdefined, bail out early.
- if (i >= 64 && OnlyTrueElement == -2 && OnlyFalseElement == -2)
+ if (i >= 64 && SecondTrueElement == -2 && SecondFalseElement == -2)
return 0;
}
// Now that we've scanned the entire array, emit our new comparison(s). We
// order the state machines in complexity of the generated code.
- if (OnlyTrueElement != -2) {
+ Value *Idx = GEP->getOperand(2);
+
+ // If the comparison is only true for one or two elements, emit direct
+ // comparisons.
+ if (SecondTrueElement != -2) {
// None true -> false.
- if (OnlyTrueElement == -1)
+ if (FirstTrueElement == -1)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(*Context));
+ Value *FirstTrueIdx = ConstantInt::get(Idx->getType(), FirstTrueElement);
+
// True for one element -> 'i == 47'.
- return new ICmpInst(ICmpInst::ICMP_EQ, GEP->getOperand(2),
- ConstantInt::get(GEP->getOperand(2)->getType(),
- OnlyTrueElement));
+ if (SecondTrueElement == -1)
+ return new ICmpInst(ICmpInst::ICMP_EQ, Idx, FirstTrueIdx);
+
+ // True for two elements -> 'i == 47 | i == 72'.
+ Value *C1 = Builder->CreateICmpEQ(Idx, FirstTrueIdx);
+ Value *SecondTrueIdx = ConstantInt::get(Idx->getType(), SecondTrueElement);
+ Value *C2 = Builder->CreateICmpEQ(Idx, SecondTrueIdx);
+ return BinaryOperator::CreateOr(C1, C2);
}
- if (OnlyFalseElement != -2) {
+ // If the comparison is only false for one or two elements, emit direct
+ // comparisons.
+ if (SecondFalseElement != -2) {
// None false -> true.
- if (OnlyFalseElement == -1)
+ if (FirstFalseElement == -1)
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(*Context));
- return new ICmpInst(ICmpInst::ICMP_NE, GEP->getOperand(2),
- ConstantInt::get(GEP->getOperand(2)->getType(),
- OnlyFalseElement));
+ Value *FirstFalseIdx = ConstantInt::get(Idx->getType(), FirstFalseElement);
+
+ // False for one element -> 'i != 47'.
+ if (SecondFalseElement == -1)
+ return new ICmpInst(ICmpInst::ICMP_NE, Idx, FirstFalseIdx);
+
+ // False for two elements -> 'i != 47 & i != 72'.
+ Value *C1 = Builder->CreateICmpNE(Idx, FirstFalseIdx);
+ Value *SecondFalseIdx = ConstantInt::get(Idx->getType(),SecondFalseElement);
+ Value *C2 = Builder->CreateICmpNE(Idx, SecondFalseIdx);
+ return BinaryOperator::CreateAnd(C1, C2);
}
// If a 32-bit or 64-bit magic bitvector captures the entire comparison state
@@ -6128,14 +6160,14 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
Ty = Type::getInt32Ty(Init->getContext());
else
Ty = Type::getInt64Ty(Init->getContext());
- Value *V = Builder->CreateIntCast(GEP->getOperand(2), Ty, false);
+ Value *V = Builder->CreateIntCast(Idx, Ty, false);
V = Builder->CreateLShr(ConstantInt::get(Ty, MagicBitvector), V);
V = Builder->CreateAnd(ConstantInt::get(Ty, 1), V);
return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
}
- // TODO: Range check, two compares.
-
+ // TODO: Range check
+ // TODO: GEP 0, i, 4
return 0;
}
diff --git a/test/Transforms/InstCombine/load-cmp.ll b/test/Transforms/InstCombine/load-cmp.ll
index e44105791a..fabafed93f 100644
--- a/test/Transforms/InstCombine/load-cmp.ll
+++ b/test/Transforms/InstCombine/load-cmp.ll
@@ -45,3 +45,15 @@ define i1 @test4(i32 %X) {
; CHECK-NEXT: %R = icmp ne i32 {{.*}}, 0
; CHECK-NEXT: ret i1 %R
}
+
+define i1 @test5(i32 %X) {
+ %P = getelementptr [10 x i16]* @G16, i32 0, i32 %X
+ %Q = load i16* %P
+ %R = icmp eq i16 %Q, 69
+ ret i1 %R
+; CHECK: @test5
+; CHECK-NEXT: icmp eq i32 %X, 2
+; CHECK-NEXT: icmp eq i32 %X, 7
+; CHECK-NEXT: %R = or i1
+; CHECK-NEXT: ret i1 %R
+}