summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2011-06-12 22:48:00 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2011-06-12 22:48:00 +0000
commitffd0ae64c497d13956d16526c46245bfbf48e91f (patch)
tree49f581b1858c351db0553cab30050bd7a4e213a4
parent7e7c9cc31a9c0ca337235ae04fc268e58da1d01b (diff)
downloadllvm-ffd0ae64c497d13956d16526c46245bfbf48e91f.tar.gz
llvm-ffd0ae64c497d13956d16526c46245bfbf48e91f.tar.bz2
llvm-ffd0ae64c497d13956d16526c46245bfbf48e91f.tar.xz
InstCombine: Shrink ((zext X) & C1) == C2 to fold away the cast if the "zext" and the "and" have one use.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132897 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp18
-rw-r--r--test/Transforms/InstCombine/icmp.ll10
2 files changed, 27 insertions, 1 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 92cbc1b7f1..5ddf23ba8e 100644
--- a/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1097,7 +1097,23 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
ConstantExpr::getZExt(RHS, Cast->getSrcTy()));
}
}
-
+
+ // If the LHS is an AND of a zext, and we have an equality compare, we can
+ // shrink the and/compare to the smaller type, eliminating the cast.
+ if (ZExtInst *Cast = dyn_cast<ZExtInst>(LHSI->getOperand(0))) {
+ const IntegerType *Ty = cast<IntegerType>(Cast->getSrcTy());
+ // Make sure we don't compare the upper bits, SimplifyDemandedBits
+ // should fold the icmp to true/false in that case.
+ if (ICI.isEquality() && RHSV.getActiveBits() <= Ty->getBitWidth()) {
+ Value *NewAnd =
+ Builder->CreateAnd(Cast->getOperand(0),
+ ConstantExpr::getTrunc(AndCST, Ty));
+ NewAnd->takeName(LHSI);
+ return new ICmpInst(ICI.getPredicate(), NewAnd,
+ ConstantExpr::getTrunc(RHS, Ty));
+ }
+ }
+
// If this is: (X >> C1) & C2 != C3 (where any shift and any compare
// could exist), turn it into (X & (C2 << C1)) != (C3 << C1). This
// happens a LOT in code produced by the C front-end, for bitfield
diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll
index 1237adee74..ecbba23091 100644
--- a/test/Transforms/InstCombine/icmp.ll
+++ b/test/Transforms/InstCombine/icmp.ll
@@ -521,3 +521,13 @@ define i1 @test53(i32 %a, i32 %b) nounwind {
%z = icmp eq i32 %x, %y
ret i1 %z
}
+
+; CHECK: @test54
+; CHECK-NEXT: %and = and i8 %a, -64
+; CHECK-NEXT icmp eq i8 %and, -128
+define i1 @test54(i8 %a) nounwind {
+ %ext = zext i8 %a to i32
+ %and = and i32 %ext, 192
+ %ret = icmp eq i32 %and, 128
+ ret i1 %ret
+}