[PATCH] D19353: [GVN] Replace an inverted comparison with a logical not

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 20 21:29:55 PDT 2016


majnemer created this revision.
majnemer added reviewers: nlewycky, dberlin.
majnemer added a subscriber: llvm-commits.

If we have two comparisons:

  %iszero = icmp eq i32 %A, 0
  %isnotzero = icmp ne i32 %A, 0

we should be able to turn one into the logical not of the other:

  %iszero = icmp eq i32 %A, 0
  %isnotzero = xor i1 %iszero, true

This fixes PR27431.

http://reviews.llvm.org/D19353

Files:
  lib/Transforms/Scalar/GVN.cpp
  test/Transforms/GVN/pr27431.ll

Index: test/Transforms/GVN/pr27431.ll
===================================================================
--- /dev/null
+++ test/Transforms/GVN/pr27431.ll
@@ -0,0 +1,17 @@
+; RUN: opt -S -gvn < %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @test1(i32 %A) {
+entry:
+  %iszero = icmp eq i32 %A, 0
+  %isnotzero = icmp ne i32 %A, 0
+  call void @use(i1 %iszero)
+  call void @use(i1 %isnotzero)
+  ret void
+; CHECK-LABEL: define void @test1(
+; CHECK: %[[iszero:.*]] = icmp eq i32 %A, 0
+; CHECK: %[[isnotzero:.*]] = xor i1 %[[iszero]], true
+; CHECK: call void @use(i1 %[[iszero]])
+; CHECK: call void @use(i1 %[[isnotzero]])
+}
Index: lib/Transforms/Scalar/GVN.cpp
===================================================================
--- lib/Transforms/Scalar/GVN.cpp
+++ lib/Transforms/Scalar/GVN.cpp
@@ -1964,6 +1964,13 @@
       continue;
     }
 
+    // If "!A" is known true then A is known false.
+    // If "!A" is known false then A is known true.
+    if (match(LHS, m_Not(m_Value(A)))) {
+      Worklist.push_back(std::make_pair(A, ConstantExpr::getNot(CI)));
+      continue;
+    }
+
     // If we are propagating an equality like "(A == B)" == "true" then also
     // propagate the equality A == B.  When propagating a comparison such as
     // "(A >= B)" == "true", replace all instances of "A < B" with "false".
@@ -2123,6 +2130,32 @@
   uint32_t NextNum = VN.getNextUnusedValueNumber();
   unsigned Num = VN.lookup_or_add(I);
 
+  // Try to transform:
+  //   %isnotzero = icmp ne i32 %A, 0
+  //   %iszero = icmp eq i32 %A, 0
+  // to:
+  //   %isnotzero = icmp ne i32 %A, 0
+  //   %iszero = xor i1 %isnotzero, true
+  if (auto *Cmp = dyn_cast<CmpInst>(I)) {
+    CmpInst::Predicate NotPred = Cmp->getInversePredicate();
+    Value *LHS = Cmp->getOperand(0), *RHS = Cmp->getOperand(1);
+    uint32_t InverseNum =
+        VN.lookup_or_add_cmp(Cmp->getOpcode(), NotPred, LHS, RHS);
+    if (InverseNum < NextNum) {
+      if (Value *NotCmp = findLeader(Cmp->getParent(), InverseNum)) {
+        auto *InvertedNotCmp =
+            BinaryOperator::CreateNot(NotCmp, NotCmp->getName() + ".not", Cmp);
+        InvertedNotCmp->setDebugLoc(Cmp->getDebugLoc());
+        patchAndReplaceAllUsesWith(Cmp, InvertedNotCmp);
+        markInstructionForDeletion(Cmp);
+
+        // Update the availability map to include the new instruction.
+        addToLeaderTable(Num, InvertedNotCmp, InvertedNotCmp->getParent());
+        return true;
+      }
+    }
+  }
+
   // Allocations are always uniquely numbered, so we can save time and memory
   // by fast failing them.
   if (isa<AllocaInst>(I) || isa<TerminatorInst>(I) || isa<PHINode>(I)) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D19353.54454.patch
Type: text/x-patch
Size: 2666 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160421/12ca1ea0/attachment.bin>


More information about the llvm-commits mailing list