summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp39
-rw-r--r--test/Transforms/InstCombine/load-cmp.ll11
2 files changed, 39 insertions, 11 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 05da044e38..85ef7b18ef 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -6053,6 +6053,12 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
// -2 -> overdef, >= 0 -> that index is false.
int OnlyFalseElement = -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
+ // the array, this will fully represent all the comparison results.
+ uint64_t MagicBitvector = 0;
+
+
// Scan the array and see if one of our patterns matches.
Constant *CompareRHS = cast<Constant>(ICI.getOperand(1));
for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
@@ -6080,8 +6086,12 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
OnlyFalseElement = OnlyFalseElement == -1 ? i : -2;
}
+ // If this element is in range, update our magic bitvector.
+ if (i < 64 && IsTrueForElt)
+ MagicBitvector |= 1 << i;
+
// If all of our states become overdefined, bail out early.
- if (OnlyTrueElement == -2 && OnlyFalseElement == -2)
+ if (i >= 64 && OnlyTrueElement == -2 && OnlyFalseElement == -2)
return 0;
}
@@ -6108,17 +6118,24 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
OnlyFalseElement));
}
- assert(0 && "Should have bailed out early");
-
- // TODO: FCMP.
-
- // TODO: Range check.
+ // If a 32-bit or 64-bit magic bitvector captures the entire comparison state
+ // of this load, replace it with computation that does:
+ // ((magic_cst >> i) & 1) != 0
+ if (Init->getNumOperands() <= 32 ||
+ (TD && Init->getNumOperands() <= 64 && TD->isLegalInteger(64))) {
+ const Type *Ty;
+ if (Init->getNumOperands() <= 32)
+ Ty = Type::getInt32Ty(Init->getContext());
+ else
+ Ty = Type::getInt64Ty(Init->getContext());
+ Value *V = Builder->CreateIntCast(GEP->getOperand(2), 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: If the global array has 32 (or 64 if native!) or less entries, we
- // can turn this into something like:
- // ((magicbitconstant >> i) & 1) != 0)
- // where we populate magicbitconstant with 0101010 based on the comparison
- // results.
+ // TODO: Range check, two compares.
+
return 0;
}
diff --git a/test/Transforms/InstCombine/load-cmp.ll b/test/Transforms/InstCombine/load-cmp.ll
index eac9ae495d..e44105791a 100644
--- a/test/Transforms/InstCombine/load-cmp.ll
+++ b/test/Transforms/InstCombine/load-cmp.ll
@@ -34,3 +34,14 @@ define i1 @test3(i32 %X) {
; CHECK-NEXT: ret i1 %R
}
+define i1 @test4(i32 %X) {
+ %P = getelementptr [10 x i16]* @G16, i32 0, i32 %X
+ %Q = load i16* %P
+ %R = icmp sle i16 %Q, 73
+ ret i1 %R
+; CHECK: @test4
+; CHECK-NEXT: lshr i32 933, %X
+; CHECK-NEXT: and i32 {{.*}}, 1
+; CHECK-NEXT: %R = icmp ne i32 {{.*}}, 0
+; CHECK-NEXT: ret i1 %R
+}