<div dir="ltr">This looks fine to me.<div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 20, 2016 at 9:29 PM, David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">majnemer created this revision.<br>
majnemer added reviewers: nlewycky, dberlin.<br>
majnemer added a subscriber: llvm-commits.<br>
<br>
If we have two comparisons:<br>
<br>
  %iszero = icmp eq i32 %A, 0<br>
  %isnotzero = icmp ne i32 %A, 0<br>
<br>
we should be able to turn one into the logical not of the other:<br>
<br>
  %iszero = icmp eq i32 %A, 0<br>
  %isnotzero = xor i1 %iszero, true<br>
<br>
This fixes PR27431.<br>
<br>
<a href="http://reviews.llvm.org/D19353" rel="noreferrer" target="_blank">http://reviews.llvm.org/D19353</a><br>
<br>
Files:<br>
  lib/Transforms/Scalar/GVN.cpp<br>
  test/Transforms/GVN/pr27431.ll<br>
<br>
Index: test/Transforms/GVN/pr27431.ll<br>
===================================================================<br>
--- /dev/null<br>
+++ test/Transforms/GVN/pr27431.ll<br>
@@ -0,0 +1,17 @@<br>
+; RUN: opt -S -gvn < %s | FileCheck %s<br>
+<br>
+declare void @use(i1)<br>
+<br>
+define void @test1(i32 %A) {<br>
+entry:<br>
+  %iszero = icmp eq i32 %A, 0<br>
+  %isnotzero = icmp ne i32 %A, 0<br>
+  call void @use(i1 %iszero)<br>
+  call void @use(i1 %isnotzero)<br>
+  ret void<br>
+; CHECK-LABEL: define void @test1(<br>
+; CHECK: %[[iszero:.*]] = icmp eq i32 %A, 0<br>
+; CHECK: %[[isnotzero:.*]] = xor i1 %[[iszero]], true<br>
+; CHECK: call void @use(i1 %[[iszero]])<br>
+; CHECK: call void @use(i1 %[[isnotzero]])<br>
+}<br>
Index: lib/Transforms/Scalar/GVN.cpp<br>
===================================================================<br>
--- lib/Transforms/Scalar/GVN.cpp<br>
+++ lib/Transforms/Scalar/GVN.cpp<br>
@@ -1964,6 +1964,13 @@<br>
       continue;<br>
     }<br>
<br>
+    // If "!A" is known true then A is known false.<br>
+    // If "!A" is known false then A is known true.<br>
+    if (match(LHS, m_Not(m_Value(A)))) {<br>
+      Worklist.push_back(std::make_pair(A, ConstantExpr::getNot(CI)));<br>
+      continue;<br>
+    }<br>
+<br>
     // If we are propagating an equality like "(A == B)" == "true" then also<br>
     // propagate the equality A == B.  When propagating a comparison such as<br>
     // "(A >= B)" == "true", replace all instances of "A < B" with "false".<br>
@@ -2123,6 +2130,32 @@<br>
   uint32_t NextNum = VN.getNextUnusedValueNumber();<br>
   unsigned Num = VN.lookup_or_add(I);<br>
<br>
+  // Try to transform:<br>
+  //   %isnotzero = icmp ne i32 %A, 0<br>
+  //   %iszero = icmp eq i32 %A, 0<br>
+  // to:<br>
+  //   %isnotzero = icmp ne i32 %A, 0<br>
+  //   %iszero = xor i1 %isnotzero, true<br>
+  if (auto *Cmp = dyn_cast<CmpInst>(I)) {<br>
+    CmpInst::Predicate NotPred = Cmp->getInversePredicate();<br>
+    Value *LHS = Cmp->getOperand(0), *RHS = Cmp->getOperand(1);<br>
+    uint32_t InverseNum =<br>
+        VN.lookup_or_add_cmp(Cmp->getOpcode(), NotPred, LHS, RHS);<br>
+    if (InverseNum < NextNum) {<br>
+      if (Value *NotCmp = findLeader(Cmp->getParent(), InverseNum)) {<br>
+        auto *InvertedNotCmp =<br>
+            BinaryOperator::CreateNot(NotCmp, NotCmp->getName() + ".not", Cmp);<br>
+        InvertedNotCmp->setDebugLoc(Cmp->getDebugLoc());<br>
+        patchAndReplaceAllUsesWith(Cmp, InvertedNotCmp);<br>
+        markInstructionForDeletion(Cmp);<br>
+<br>
+        // Update the availability map to include the new instruction.<br>
+        addToLeaderTable(Num, InvertedNotCmp, InvertedNotCmp->getParent());<br>
+        return true;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
   // Allocations are always uniquely numbered, so we can save time and memory<br>
   // by fast failing them.<br>
   if (isa<AllocaInst>(I) || isa<TerminatorInst>(I) || isa<PHINode>(I)) {<br>
<br>
<br>
</blockquote></div><br></div>