[InstCombine] handle icmp i1 X, C early to avoid creating an unknown pattern
authorSanjay Patel <spatel@rotateright.com>
Wed, 17 May 2017 22:29:40 +0000 (22:29 +0000)
committerSanjay Patel <spatel@rotateright.com>
Wed, 17 May 2017 22:29:40 +0000 (22:29 +0000)
The missing optimization for xor-of-icmps still needs to be added, but by
being more efficient (not generating unnecessary logic ops with constants)
we avoid the bug.

See discussion in post-commit comments:
https://reviews.llvm.org/D32143

llvm-svn: 303312

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/set.ll

index 6a6e831..e272951 100644 (file)
@@ -4266,6 +4266,29 @@ static Instruction *canonicalizeICmpBool(ICmpInst &I,
   Value *A = I.getOperand(0), *B = I.getOperand(1);
   assert(A->getType()->getScalarType()->isIntegerTy(1) && "Bools only");
 
+  // A boolean compared to true/false can be simplified to Op0/true/false in
+  // 14 out of the 20 (10 predicates * 2 constants) possible combinations.
+  // Cases not handled by InstSimplify are always 'not' of Op0.
+  if (match(B, m_Zero())) {
+    switch (I.getPredicate()) {
+      case CmpInst::ICMP_EQ:  // A ==   0 -> !A
+      case CmpInst::ICMP_ULE: // A <=u  0 -> !A
+      case CmpInst::ICMP_SGE: // A >=s  0 -> !A
+        return BinaryOperator::CreateNot(A);
+      default:
+        llvm_unreachable("ICmp i1 X, C not simplified as expected.");
+    }
+  } else if (match(B, m_One())) {
+    switch (I.getPredicate()) {
+      case CmpInst::ICMP_NE:  // A !=  1 -> !A
+      case CmpInst::ICMP_ULT: // A <u  1 -> !A
+      case CmpInst::ICMP_SGT: // A >s -1 -> !A
+        return BinaryOperator::CreateNot(A);
+      default:
+        llvm_unreachable("ICmp i1 X, C not simplified as expected.");
+    }
+  }
+
   switch (I.getPredicate()) {
   default:
     llvm_unreachable("Invalid icmp instruction!");
index f1bbc6c..5955eae 100644 (file)
@@ -152,10 +152,8 @@ define <3 x i1> @test14vec(<3 x i1> %A, <3 x i1> %B) {
 
 define i1 @bool_eq0(i64 %a) {
 ; CHECK-LABEL: @bool_eq0(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt i64 %a, 0
-; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 %a, 1
-; CHECK-NEXT:    [[AND:%.*]] = xor i1 [[C]], [[B]]
-; CHECK-NEXT:    ret i1 [[AND]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 %a, 1
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %b = icmp sgt i64 %a, 0
   %c = icmp eq i64 %a, 1