<div dir="ltr">This broke the Clang -Werror build due to dangling elses. I've committed a fix for this in r191059.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Sep 19, 2013 at 4:00 PM, Kai Nacke <span dir="ltr"><<a href="mailto:kai.nacke@redstar.de" target="_blank">kai.nacke@redstar.de</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: redstar<br>
Date: Thu Sep 19 18:00:28 2013<br>
New Revision: 191049<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=191049&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=191049&view=rev</a><br>
Log:<br>
PR16726: extend rol/ror matching<br>
<br>
C-like languages promote types like unsigned short to unsigned int before<br>
performing an arithmetic operation. Currently the rotate matcher in the<br>
DAGCombiner does not consider this situation.<br>
<br>
This commit extends the DAGCombiner in the way that the pattern<br>
<br>
(or (shl ([az]ext x), (*ext y)), (srl ([az]ext x), (*ext (sub 32, y))))<br>
<br>
is folded into<br>
<br>
([az]ext (rotl x, y))<br>
<br>
The matching is restricted to aext and zext because in this cases the upper<br>
bits are either undefined or known. Test case is included.<br>
<br>
This fixes PR16726.<br>
<br>
Added:<br>
    llvm/trunk/test/CodeGen/X86/rotate3.ll<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=191049&r1=191048&r2=191049&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=191049&r1=191048&r2=191049&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Thu Sep 19 18:00:28 2013<br>
@@ -3341,6 +3341,7 @@ SDNode *DAGCombiner::MatchRotate(SDValue<br>
   unsigned OpSizeInBits = VT.getSizeInBits();<br>
   SDValue LHSShiftArg = LHSShift.getOperand(0);<br>
   SDValue LHSShiftAmt = LHSShift.getOperand(1);<br>
+  SDValue RHSShiftArg = RHSShift.getOperand(0);<br>
   SDValue RHSShiftAmt = RHSShift.getOperand(1);<br>
<br>
   // fold (or (shl x, C1), (srl x, C2)) -> (rotl x, C1)<br>
@@ -3420,10 +3421,27 @@ SDNode *DAGCombiner::MatchRotate(SDValue<br>
       //   (rotr x, (sub 32, y))<br>
       if (ConstantSDNode *SUBC =<br>
             dyn_cast<ConstantSDNode>(RExtOp0.getOperand(0)))<br>
-        if (SUBC->getAPIntValue() == OpSizeInBits)<br>
+        if (SUBC->getAPIntValue() == OpSizeInBits) {<br>
           return DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, DL, VT,<br>
                              LHSShiftArg,<br>
                              HasROTL ? LHSShiftAmt : RHSShiftAmt).getNode();<br>
+        } else if (LHSShiftArg.getOpcode() == ISD::ZERO_EXTEND ||<br>
+                 LHSShiftArg.getOpcode() == ISD::ANY_EXTEND) {<br>
+          // fold (or (shl (*ext x), (*ext y)),<br>
+          //          (srl (*ext x), (*ext (sub 32, y)))) -><br>
+          //   (*ext (rotl x, y))<br>
+          // fold (or (shl (*ext x), (*ext y)),<br>
+          //          (srl (*ext x), (*ext (sub 32, y)))) -><br>
+          //   (*ext (rotr x, (sub 32, y)))<br>
+          SDValue LArgExtOp0 = LHSShiftArg.getOperand(0);<br>
+          EVT LArgVT = LArgExtOp0.getValueType();<br>
+          if (LArgVT.getSizeInBits() == SUBC->getAPIntValue()) {<br>
+            SDValue V = DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, DL, LArgVT,<br>
+                             LArgExtOp0,<br>
+                             HasROTL ? LHSShiftAmt : RHSShiftAmt);<br>
+            return DAG.getNode(LHSShiftArg.getOpcode(), DL, VT, V).getNode();<br>
+          }<br>
+        }<br>
     } else if (LExtOp0.getOpcode() == ISD::SUB &&<br>
                RExtOp0 == LExtOp0.getOperand(1)) {<br>
       // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext y))) -><br>
@@ -3432,10 +3450,27 @@ SDNode *DAGCombiner::MatchRotate(SDValue<br>
       //   (rotl x, (sub 32, y))<br>
       if (ConstantSDNode *SUBC =<br>
             dyn_cast<ConstantSDNode>(LExtOp0.getOperand(0)))<br>
-        if (SUBC->getAPIntValue() == OpSizeInBits)<br>
+        if (SUBC->getAPIntValue() == OpSizeInBits) {<br>
           return DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, DL, VT,<br>
                              LHSShiftArg,<br>
                              HasROTR ? RHSShiftAmt : LHSShiftAmt).getNode();<br>
+        } else if (RHSShiftArg.getOpcode() == ISD::ZERO_EXTEND ||<br>
+                 RHSShiftArg.getOpcode() == ISD::ANY_EXTEND) {<br>
+          // fold (or (shl (*ext x), (*ext (sub 32, y))),<br>
+          //          (srl (*ext x), (*ext y))) -><br>
+          //   (*ext (rotl x, y))<br>
+          // fold (or (shl (*ext x), (*ext (sub 32, y))),<br>
+          //          (srl (*ext x), (*ext y))) -><br>
+          //   (*ext (rotr x, (sub 32, y)))<br>
+          SDValue RArgExtOp0 = RHSShiftArg.getOperand(0);<br>
+          EVT RArgVT = RArgExtOp0.getValueType();<br>
+          if (RArgVT.getSizeInBits() == SUBC->getAPIntValue()) {<br>
+            SDValue V = DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, DL, RArgVT,<br>
+                             RArgExtOp0,<br>
+                             HasROTR ? RHSShiftAmt : LHSShiftAmt);<br>
+            return DAG.getNode(RHSShiftArg.getOpcode(), DL, VT, V).getNode();<br>
+          }<br>
+        }<br>
     }<br>
   }<br>
<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/rotate3.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/rotate3.ll?rev=191049&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/rotate3.ll?rev=191049&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/rotate3.ll (added)<br>
+++ llvm/trunk/test/CodeGen/X86/rotate3.ll Thu Sep 19 18:00:28 2013<br>
@@ -0,0 +1,76 @@<br>
+; Check that (or (shl x, y), (srl x, (sub 32, y))) is folded into (rotl x, y)<br>
+; and (or (shl x, (sub 32, y)), (srl x, r)) into (rotr x, y) even if the<br>
+; argument is zero extended. Fix for PR16726.<br>
+<br>
+; RUN: llc < %s -march=x86-64 -mcpu=corei7 | FileCheck %s<br>
+<br>
+define zeroext i8 @rolbyte(i32 %nBits_arg, i8 %x_arg) nounwind readnone {<br>
+entry:<br>
+  %tmp1 = zext i8 %x_arg to i32<br>
+  %tmp3 = shl i32 %tmp1, %nBits_arg<br>
+  %tmp8 = sub i32 8, %nBits_arg<br>
+  %tmp10 = lshr i32 %tmp1, %tmp8<br>
+  %tmp11 = or i32 %tmp3, %tmp10<br>
+  %tmp12 = trunc i32 %tmp11 to i8<br>
+  ret i8 %tmp12<br>
+}<br>
+; CHECK:    rolb %cl, %{{[a-z0-9]+}}<br>
+<br>
+<br>
+define zeroext i8 @rorbyte(i32 %nBits_arg, i8 %x_arg) nounwind readnone {<br>
+entry:<br>
+  %tmp1 = zext i8 %x_arg to i32<br>
+  %tmp3 = lshr i32 %tmp1, %nBits_arg<br>
+  %tmp8 = sub i32 8, %nBits_arg<br>
+  %tmp10 = shl i32 %tmp1, %tmp8<br>
+  %tmp11 = or i32 %tmp3, %tmp10<br>
+  %tmp12 = trunc i32 %tmp11 to i8<br>
+  ret i8 %tmp12<br>
+}<br>
+; CHECK:    rorb %cl, %{{[a-z0-9]+}}<br>
+<br>
+define zeroext i16 @rolword(i32 %nBits_arg, i16 %x_arg) nounwind readnone {<br>
+entry:<br>
+  %tmp1 = zext i16 %x_arg to i32<br>
+  %tmp3 = shl i32 %tmp1, %nBits_arg<br>
+  %tmp8 = sub i32 16, %nBits_arg<br>
+  %tmp10 = lshr i32 %tmp1, %tmp8<br>
+  %tmp11 = or i32 %tmp3, %tmp10<br>
+  %tmp12 = trunc i32 %tmp11 to i16<br>
+  ret i16 %tmp12<br>
+}<br>
+; CHECK:    rolw %cl, %{{[a-z0-9]+}}<br>
+<br>
+define zeroext i16 @rorword(i32 %nBits_arg, i16 %x_arg) nounwind readnone {<br>
+entry:<br>
+  %tmp1 = zext i16 %x_arg to i32<br>
+  %tmp3 = lshr i32 %tmp1, %nBits_arg<br>
+  %tmp8 = sub i32 16, %nBits_arg<br>
+  %tmp10 = shl i32 %tmp1, %tmp8<br>
+  %tmp11 = or i32 %tmp3, %tmp10<br>
+  %tmp12 = trunc i32 %tmp11 to i16<br>
+  ret i16 %tmp12<br>
+}<br>
+; CHECK:    rorw %cl, %{{[a-z0-9]+}}<br>
+<br>
+define i64 @roldword(i64 %nBits_arg, i32 %x_arg) nounwind readnone {<br>
+entry:<br>
+  %tmp1 = zext i32 %x_arg to i64<br>
+  %tmp3 = shl i64 %tmp1, %nBits_arg<br>
+  %tmp8 = sub i64 32, %nBits_arg<br>
+  %tmp10 = lshr i64 %tmp1, %tmp8<br>
+  %tmp11 = or i64 %tmp3, %tmp10<br>
+  ret i64 %tmp11<br>
+}<br>
+; CHECK:    roll %cl, %{{[a-z0-9]+}}<br>
+<br>
+define zeroext i64 @rordword(i64 %nBits_arg, i32 %x_arg) nounwind readnone {<br>
+entry:<br>
+  %tmp1 = zext i32 %x_arg to i64<br>
+  %tmp3 = lshr i64 %tmp1, %nBits_arg<br>
+  %tmp8 = sub i64 32, %nBits_arg<br>
+  %tmp10 = shl i64 %tmp1, %tmp8<br>
+  %tmp11 = or i64 %tmp3, %tmp10<br>
+  ret i64 %tmp11<br>
+}<br>
+; CHECK:    rorl %cl, %{{[a-z0-9]+}}<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>