InstCombine: If we have a bit test and a sign test anded/ored together, merge the...
authorBenjamin Kramer <benny.kra@googlemail.com>
Sun, 8 Jan 2012 18:32:24 +0000 (18:32 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sun, 8 Jan 2012 18:32:24 +0000 (18:32 +0000)
This is common in bit field code, e.g. checking if the first or the last bit of a bit field is set.

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

lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
test/Transforms/InstCombine/sign-test-and-or.ll

index 4b1e7feef075b2fea34431ae121d9f4e3d8b911c..96ca40a3cf95db5dbf263ae96f70250251304783 100644 (file)
@@ -743,6 +743,22 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
       }
     }
   }
+
+  // (X & C) == 0 & X > -1  ->  (X & (C | SignBit)) == 0
+  if (LHS->hasOneUse() && RHS->hasOneUse() &&
+      ((LHSCC == ICmpInst::ICMP_EQ && LHSCst->isZero() &&
+        RHSCC == ICmpInst::ICMP_SGT && RHSCst->isAllOnesValue()) ||
+       (RHSCC == ICmpInst::ICMP_EQ && RHSCst->isZero() &&
+        LHSCC == ICmpInst::ICMP_SGT && LHSCst->isAllOnesValue()))) {
+    BinaryOperator *BO =
+      dyn_cast<BinaryOperator>(LHSCC == ICmpInst::ICMP_EQ ? Val : Val2);
+    ConstantInt *AndCst;
+    if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) {
+      APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth());
+      BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New));
+      return BO == Val ? LHS : RHS;
+    }
+  }
   
   // From here on, we only handle:
   //    (icmp1 A, C1) & (icmp2 A, C2) --> something simpler.
@@ -1442,6 +1458,22 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
     }
   }
 
+  // (X & C) != 0 & X < 0  ->  (X & (C | SignBit)) != 0
+  if (LHS->hasOneUse() && RHS->hasOneUse() &&
+      ((LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero() &&
+        RHSCC == ICmpInst::ICMP_SLT && RHSCst->isZero()) ||
+       (RHSCC == ICmpInst::ICMP_NE && RHSCst->isZero() &&
+        LHSCC == ICmpInst::ICMP_SLT && LHSCst->isZero()))) {
+    BinaryOperator *BO =
+      dyn_cast<BinaryOperator>(LHSCC == ICmpInst::ICMP_NE ? Val : Val2);
+    ConstantInt *AndCst;
+    if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) {
+      APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth());
+      BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New));
+      return BO == Val ? LHS : RHS;
+    }
+  }
+
   // (icmp ult (X + CA), C1) | (icmp eq X, C2) -> (icmp ule (X + CA), C1)
   //   iff C2 + CA == C1.
   if (LHSCC == ICmpInst::ICMP_ULT && RHSCC == ICmpInst::ICMP_EQ) {
index 47f5f3051e468c284af0f2dabd49b56b87ebc4fe..2a5f7725066ce93ea5252eea2af2a2f8d19a121c 100644 (file)
@@ -77,3 +77,83 @@ if.then:
 if.end:
   ret void
 }
+
+define void @test5(i32 %a) nounwind {
+  %and = and i32 %a, 134217728
+  %1 = icmp eq i32 %and, 0
+  %2 = icmp sgt i32 %a, -1
+  %or.cond = and i1 %1, %2
+  br i1 %or.cond, label %if.then, label %if.end
+
+; CHECK: @test5
+; CHECK-NEXT: %and = and i32 %a, -2013265920
+; CHECK-NEXT: %1 = icmp eq i32 %and, 0
+; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
+
+if.then:
+  tail call void @foo() nounwind
+  ret void
+
+if.end:
+  ret void
+}
+
+define void @test6(i32 %a) nounwind {
+  %1 = icmp sgt i32 %a, -1
+  %and = and i32 %a, 134217728
+  %2 = icmp eq i32 %and, 0
+  %or.cond = and i1 %1, %2
+  br i1 %or.cond, label %if.then, label %if.end
+
+; CHECK: @test6
+; CHECK-NEXT: %and = and i32 %a, -2013265920
+; CHECK-NEXT: %1 = icmp eq i32 %and, 0
+; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
+
+if.then:
+  tail call void @foo() nounwind
+  ret void
+
+if.end:
+  ret void
+}
+
+define void @test7(i32 %a) nounwind {
+  %and = and i32 %a, 134217728
+  %1 = icmp ne i32 %and, 0
+  %2 = icmp slt i32 %a, 0
+  %or.cond = or i1 %1, %2
+  br i1 %or.cond, label %if.then, label %if.end
+
+; CHECK: @test7
+; CHECK-NEXT: %and = and i32 %a, -2013265920
+; CHECK-NEXT: %1 = icmp eq i32 %and, 0
+; CHECK-NEXT: br i1 %1, label %if.end, label %if.the
+
+if.then:
+  tail call void @foo() nounwind
+  ret void
+
+if.end:
+  ret void
+}
+
+define void @test8(i32 %a) nounwind {
+  %1 = icmp slt i32 %a, 0
+  %and = and i32 %a, 134217728
+  %2 = icmp ne i32 %and, 0
+  %or.cond = or i1 %1, %2
+  br i1 %or.cond, label %if.then, label %if.end
+
+; CHECK: @test8
+; CHECK-NEXT: %and = and i32 %a, -2013265920
+; CHECK-NEXT: %1 = icmp eq i32 %and, 0
+; CHECK-NEXT: br i1 %1, label %if.end, label %if.the
+
+if.then:
+  tail call void @foo() nounwind
+  ret void
+
+if.end:
+  ret void
+}