<span style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">Unless the situation is not as symmetric as it appears, you should factor this pattern matching into a separate static function just call it twice, once with the parameters interchanged. That will be a lot cleaner and less error-prone.</span><div>
<font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">--Sean Silva</font></div><div><font face="arial, sans-serif">(sorry Ben for sending this twice, forgot to CC the list)<br></font><br><div class="gmail_quote">
On Sun, Jun 10, 2012 at 1:35 PM, Benjamin Kramer <span dir="ltr"><<a href="mailto:benny.kra@googlemail.com" target="_blank">benny.kra@googlemail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: d0k<br>
Date: Sun Jun 10 15:35:00 2012<br>
New Revision: 158297<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=158297&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=158297&view=rev</a><br>
Log:<br>
InstCombine: Turn (zext A) == (B & (1<<X)-1) into A == (trunc B), narrowing the compare.<br>
<br>
This saves a cast, and zext is more expensive on platforms with subreg support<br>
than trunc is. This occurs in the BSD implementation of memchr(3), see PR12750.<br>
On the synthetic benchmark from that bug stupid_memchr and bsd_memchr have the<br>
same performance now when not inlining either function.<br>
<br>
stupid_memchr: 323.0us<br>
bsd_memchr: 321.0us<br>
memchr: 479.0us<br>
<br>
where memchr is the llvm-gcc compiled bsd_memchr from osx lion's libc. When<br>
inlining is enabled bsd_memchr still regresses down to llvm-gcc memchr time,<br>
I haven't fully understood the issue yet, something is grossly mangling the<br>
loop after inlining.<br>
<br>
Modified:<br>
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
    llvm/trunk/test/Transforms/InstCombine/icmp.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=158297&r1=158296&r2=158297&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=158297&r1=158296&r2=158297&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Sun Jun 10 15:35:00 2012<br>
@@ -2580,10 +2580,32 @@<br>
       }<br>
     }<br>
<br>
+    // Transform (zext A) == (B & (1<<X)-1) --> A == (trunc B)<br>
+    ConstantInt *Cst1;<br>
+    if (Op0->hasOneUse() &&<br>
+        match(Op0, m_ZExt(m_Value(A))) &&<br>
+        match(Op1, m_And(m_Value(B), m_ConstantInt(Cst1)))) {<br>
+      APInt Pow2 = Cst1->getValue() + 1;<br>
+      if (Pow2.isPowerOf2() && isa<IntegerType>(A->getType()) &&<br>
+          Pow2.logBase2() == cast<IntegerType>(A->getType())->getBitWidth())<br>
+        return new ICmpInst(I.getPredicate(), A,<br>
+                            Builder->CreateTrunc(B, A->getType()));<br>
+    }<br>
+<br>
+    // Transform (B & (1<<X)-1) == (zext A) --> A == (trunc B)<br>
+    if (Op1->hasOneUse() &&<br>
+        match(Op0, m_And(m_Value(B), m_ConstantInt(Cst1))) &&<br>
+        match(Op1, m_ZExt(m_Value(A)))) {<br>
+      APInt Pow2 = Cst1->getValue() + 1;<br>
+      if (Pow2.isPowerOf2() && isa<IntegerType>(A->getType()) &&<br>
+          Pow2.logBase2() == cast<IntegerType>(A->getType())->getBitWidth())<br>
+        return new ICmpInst(I.getPredicate(), A,<br>
+                            Builder->CreateTrunc(B, A->getType()));<br>
+    }<br>
+<br>
     // Transform "icmp eq (trunc (lshr(X, cst1)), cst" to<br>
     // "icmp (and X, mask), cst"<br>
     uint64_t ShAmt = 0;<br>
-    ConstantInt *Cst1;<br>
     if (Op0->hasOneUse() &&<br>
         match(Op0, m_Trunc(m_OneUse(m_LShr(m_Value(A),<br>
                                            m_ConstantInt(ShAmt))))) &&<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/icmp.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp.ll?rev=158297&r1=158296&r2=158297&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp.ll?rev=158297&r1=158296&r2=158297&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/icmp.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/icmp.ll Sun Jun 10 15:35:00 2012<br>
@@ -637,3 +637,25 @@<br>
 ; CHECK: @test62<br>
 ; CHECK-NEXT: ret i1 true<br>
 }<br>
+<br>
+define i1 @test63(i8 %a, i32 %b) nounwind {<br>
+  %z = zext i8 %a to i32<br>
+  %t = and i32 %b, 255<br>
+  %c = icmp eq i32 %z, %t<br>
+  ret i1 %c<br>
+; CHECK: @test63<br>
+; CHECK-NEXT: %1 = trunc i32 %b to i8<br>
+; CHECK-NEXT: %c = icmp eq i8 %1, %a<br>
+; CHECK-NEXT: ret i1 %c<br>
+}<br>
+<br>
+define i1 @test64(i8 %a, i32 %b) nounwind {<br>
+  %t = and i32 %b, 255<br>
+  %z = zext i8 %a to i32<br>
+  %c = icmp eq i32 %t, %z<br>
+  ret i1 %c<br>
+; CHECK: @test64<br>
+; CHECK-NEXT: %1 = trunc i32 %b to i8<br>
+; CHECK-NEXT: %c = icmp eq i8 %1, %a<br>
+; CHECK-NEXT: ret i1 %c<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>