InstCombine: Shrink ((zext X) & C1) == C2 to fold away the cast if the "zext" and...
authorBenjamin Kramer <benny.kra@googlemail.com>
Sun, 12 Jun 2011 22:48:00 +0000 (22:48 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sun, 12 Jun 2011 22:48:00 +0000 (22:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132897 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCompares.cpp
test/Transforms/InstCombine/icmp.ll

index 92cbc1b7f1801bfe64c86ae8b81832dca65a3318..5ddf23ba8e1870b40e9277443bf93d947732c2c0 100644 (file)
@@ -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
index 1237adee74d67ce3530df2b216cdf01d802c712c..ecbba23091c5f456d249a567f74d414fc8e1136a 100644 (file)
@@ -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
+}