Transform (A == C1 || A == C2) into (A & ~(C1 ^ C2)) == C1
authorJakub Staszak <kubastaszak@gmail.com>
Mon, 31 Dec 2012 00:34:55 +0000 (00:34 +0000)
committerJakub Staszak <kubastaszak@gmail.com>
Mon, 31 Dec 2012 00:34:55 +0000 (00:34 +0000)
if C1 and C2 differ only with one bit.
Fixes PR14708.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171270 91177308-0d34-0410-b5e6-96231b3b80d8

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

index ecae3b60452e3dc4c64eb93d412c87016bab88ad..0fd1e2b2e4f634bfb760ca9f4717732edfec1c06 100644 (file)
@@ -1524,6 +1524,18 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
         AddCST = ConstantExpr::getSub(AddOne(RHSCst), LHSCst);
         return Builder->CreateICmpULT(Add, AddCST);
       }
+
+      if (LHS->getOperand(0) == RHS->getOperand(0)) {
+        // if LHSCst and RHSCst differ with only one bit:
+        // (A == C1 || A == C2) -> (A & ~(C1 ^ C2)) == C1
+        APInt Xor = LHSCst->getValue() ^ RHSCst->getValue();
+        if (Xor.isPowerOf2()) {
+          Value *NegCst = Builder->getInt(~Xor);
+          Value *And = Builder->CreateAnd(LHS->getOperand(0), NegCst);
+          return Builder->CreateICmp(ICmpInst::ICMP_EQ, And, LHSCst);
+        }
+      }
+
       break;                         // (X == 13 | X == 15) -> no change
     case ICmpInst::ICMP_UGT:         // (X == 13 | X u> 14) -> no change
     case ICmpInst::ICMP_SGT:         // (X == 13 | X s> 14) -> no change
index 138b10eaa0276d25368287d38e8c152141b25acc..5102a9cb6a1acd49fe28ce6aa9f9dceab61fa8de 100644 (file)
@@ -694,3 +694,14 @@ define i1 @test68(i32 %x) nounwind uwtable {
   %cmp = icmp sgt i32 %and, 30
   ret i1 %cmp
 }
+
+; PR14708
+; CHECK: @test69
+; CHECK: %1 = and i32 %c, -33
+; CHECK: %2 = icmp eq i32 %1, 65
+define i1 @test69(i32 %c) nounwind uwtable {
+  %1 = icmp eq i32 %c, 97
+  %2 = icmp eq i32 %c, 65
+  %3 = or i1 %1, %2
+  ret i1 %3
+}