<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>