[PATCH] PR19711: use computeKnownBits to simplify (in)equality comparisons

Jay Foad jay.foad at gmail.com
Tue May 20 05:08:16 PDT 2014


PR19711: Souper (https://github.com/google/souper/) discovered that we
don't simplify this comparison to false:

  %mul = mul nsw i32 %0, -2
  %cmp = icmp eq i32 %mul, 1

Fix this by calling computeKnownBits to see if any bits are known to be 0
in one operand and 1 in the other, in which case the operands can't be
equal.

I was a bit surprised that before this patch, there were no calls from
InstructionSimplify.cpp to computeKnownBits. Is this the right approach? OK
to commit?

The tweak to align-2d-gep.ll just avoids an unintended simplification,
where we could prove that %indvar.next was always even so could never equal
557.

Thanks,
Jay.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140520/9cba2ed8/attachment.html>
-------------- next part --------------
Index: lib/Analysis/InstructionSimplify.cpp
===================================================================
--- lib/Analysis/InstructionSimplify.cpp	(revision 209203)
+++ lib/Analysis/InstructionSimplify.cpp	(working copy)
@@ -2652,6 +2652,21 @@
     if (Value *V = ThreadCmpOverPHI(Pred, LHS, RHS, Q, MaxRecurse))
       return V;
 
+  // Try using bitwise analysis to prove that the operands are unequal.
+  if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) {
+    unsigned BitWidth = OpTy->getScalarSizeInBits();
+
+    APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0);
+    computeKnownBits(LHS, LHSKnownZero, LHSKnownOne, Q.DL, 0);
+
+    APInt RHSKnownZero(BitWidth, 0), RHSKnownOne(BitWidth, 0);
+    computeKnownBits(RHS, RHSKnownZero, RHSKnownOne, Q.DL, 0);
+
+    if ((LHSKnownZero & RHSKnownOne) != 0 || (LHSKnownOne & RHSKnownZero) != 0)
+      // The operands differ in one or more bit positions.
+      return Pred == CmpInst::ICMP_NE ? getTrue(ITy) : getFalse(ITy);
+  }
+
   return nullptr;
 }
 
Index: test/Transforms/InstCombine/align-2d-gep.ll
===================================================================
--- test/Transforms/InstCombine/align-2d-gep.ll	(revision 209203)
+++ test/Transforms/InstCombine/align-2d-gep.ll	(working copy)
@@ -31,7 +31,7 @@
   store <2 x double><double 0.0, double 0.0>, <2 x double>* %r, align 8
 
   %indvar.next = add i64 %j, 2
-  %exitcond = icmp eq i64 %indvar.next, 557
+  %exitcond = icmp eq i64 %indvar.next, 556
   br i1 %exitcond, label %bb11, label %bb1
 
 bb11:
Index: test/Transforms/InstCombine/icmp.ll
===================================================================
--- test/Transforms/InstCombine/icmp.ll	(revision 209203)
+++ test/Transforms/InstCombine/icmp.ll	(working copy)
@@ -1365,3 +1365,11 @@
   %2 = icmp slt i32 %1, -10
   ret i1 %2
 }
+
+; CHECK-LABEL: @icmp_mul_neg2
+; CHECK: ret i1 false
+define i1 @icmp_mul_neg2(i32 %a) nounwind {
+  %mul = mul i32 %a, -2
+  %cmp = icmp eq i32 %mul, 1
+  ret i1 %cmp
+}


More information about the llvm-commits mailing list