<div class="gmail_quote">On 19 April 2012 09:46, Jakob Stoklund Olesen <span dir="ltr"><<a href="mailto:stoklund@2pi.dk">stoklund@2pi.dk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Author: stoklund<br>
Date: Thu Apr 19 11:46:26 2012<br>
New Revision: 155136<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=155136&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=155136&view=rev</a><br>
Log:<br>
Defer some shl transforms to DAGCombine.<br>
<br>
The shl instruction is used to represent multiplication by a constant<br>
power of two as well as bitwise left shifts. Some InstCombine<br>
transformations would turn an shl instruction into a bit mask operation,<br>
making it difficult for later analysis passes to recognize the<br>
constsnt multiplication.<br>
<br>
Disable those shl transformations, deferring them to DAGCombine time.<br>
An 'shl X, C' instruction is now treated mostly the same was as 'mul X, C'.<br>
<br>
These transformations are deferred:<br>
<br>
  (X >>? C) << C   --> X & (-1 << C)  (When X >> C has multiple uses)<br>
  (X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2)   (When C2 > C1)<br>
  (X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2)  (When C1 > C2)<br></blockquote><div><br></div><div>If the form on the left is better, please make sure that we turn the code on the right into the code on the left.</div>

<div><br></div><div>Nick</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
The corresponding exact transformations are preserved, just like<br>
div-exact + mul:<br>
<br>
  (X >>?,exact C) << C   --> X<br>
  (X >>?,exact C1) << C2 --> X << (C2-C1)<br>
  (X >>?,exact C1) << C2 --> X >>?,exact (C1-C2)<br>
<br>
The disabled transformations could also prevent the instruction selector<br>
from recognizing rotate patterns in hash functions and cryptographic<br>
primitives. I have a test case for that, but it is too fragile.<br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/PhaseOrdering/scev.ll<br>
Modified:<br>
    llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp<br>
    llvm/trunk/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll<br>
    llvm/trunk/test/Transforms/InstCombine/apint-shift.ll<br>
    llvm/trunk/test/Transforms/InstCombine/cast.ll<br>
    llvm/trunk/test/Transforms/InstCombine/shift.ll<br>
    llvm/trunk/test/Transforms/PhaseOrdering/basic.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp?rev=155136&r1=155135&r2=155136&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp?rev=155136&r1=155135&r2=155136&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp Thu Apr 19 11:46:26 2012<br>
@@ -529,6 +529,19 @@<br>
     ShiftOp = 0;<br>
<br>
   if (ShiftOp && isa<ConstantInt>(ShiftOp->getOperand(1))) {<br>
+<br>
+    // This is a constant shift of a constant shift. Be careful about hiding<br>
+    // shl instructions behind bit masks. They are used to represent multiplies<br>
+    // by a constant, and it is important that simple arithmetic expressions<br>
+    // are still recognizable by scalar evolution.<br>
+    //<br>
+    // The transforms applied to shl are very similar to the transforms applied<br>
+    // to mul by constant. We can be more aggressive about optimizing right<br>
+    // shifts.<br>
+    //<br>
+    // Combinations of right and left shifts will still be optimized in<br>
+    // DAGCombine where scalar evolution no longer applies.<br>
+<br>
     ConstantInt *ShiftAmt1C = cast<ConstantInt>(ShiftOp->getOperand(1));<br>
     uint32_t ShiftAmt1 = ShiftAmt1C->getLimitedValue(TypeBits);<br>
     uint32_t ShiftAmt2 = Op1->getLimitedValue(TypeBits);<br>
@@ -554,13 +567,6 @@<br>
     }<br>
<br>
     if (ShiftAmt1 == ShiftAmt2) {<br>
-      // If we have ((X >>? C) << C), turn this into X & (-1 << C).<br>
-      if (I.getOpcode() == Instruction::Shl &&<br>
-          ShiftOp->getOpcode() != Instruction::Shl) {<br>
-        APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt1));<br>
-        return BinaryOperator::CreateAnd(X,<br>
-                                         ConstantInt::get(I.getContext(),Mask));<br>
-      }<br>
       // If we have ((X << C) >>u C), turn this into X & (-1 >>u C).<br>
       if (I.getOpcode() == Instruction::LShr &&<br>
           ShiftOp->getOpcode() == Instruction::Shl) {<br>
@@ -570,28 +576,23 @@<br>
       }<br>
     } else if (ShiftAmt1 < ShiftAmt2) {<br>
       uint32_t ShiftDiff = ShiftAmt2-ShiftAmt1;<br>
-<br>
-      // (X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2)<br>
+<br>
+      // (X >>?,exact C1) << C2 --> X << (C2-C1)<br>
+      // The inexact version is deferred to DAGCombine so we don't hide shl<br>
+      // behind a bit mask.<br>
       if (I.getOpcode() == Instruction::Shl &&<br>
-          ShiftOp->getOpcode() != Instruction::Shl) {<br>
+          ShiftOp->getOpcode() != Instruction::Shl &&<br>
+          ShiftOp->isExact()) {<br>
         assert(ShiftOp->getOpcode() == Instruction::LShr ||<br>
                ShiftOp->getOpcode() == Instruction::AShr);<br>
         ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);<br>
-        if (ShiftOp->isExact()) {<br>
-          // (X >>?,exact C1) << C2 --> X << (C2-C1)<br>
-          BinaryOperator *NewShl = BinaryOperator::Create(Instruction::Shl,<br>
-                                                          X, ShiftDiffCst);<br>
-          NewShl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());<br>
-          NewShl->setHasNoSignedWrap(I.hasNoSignedWrap());<br>
-          return NewShl;<br>
-        }<br>
-        Value *Shift = Builder->CreateShl(X, ShiftDiffCst);<br>
-<br>
-        APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2));<br>
-        return BinaryOperator::CreateAnd(Shift,<br>
-                                         ConstantInt::get(I.getContext(),Mask));<br>
+        BinaryOperator *NewShl = BinaryOperator::Create(Instruction::Shl,<br>
+                                                        X, ShiftDiffCst);<br>
+        NewShl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());<br>
+        NewShl->setHasNoSignedWrap(I.hasNoSignedWrap());<br>
+        return NewShl;<br>
       }<br>
-<br>
+<br>
       // (X << C1) >>u C2  --> X >>u (C2-C1) & (-1 >> C2)<br>
       if (I.getOpcode() == Instruction::LShr &&<br>
           ShiftOp->getOpcode() == Instruction::Shl) {<br>
@@ -627,24 +628,19 @@<br>
       assert(ShiftAmt2 < ShiftAmt1);<br>
       uint32_t ShiftDiff = ShiftAmt1-ShiftAmt2;<br>
<br>
-      // (X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2)<br>
+      // (X >>?exact C1) << C2 --> X >>?exact (C1-C2)<br>
+      // The inexact version is deferred to DAGCombine so we don't hide shl<br>
+      // behind a bit mask.<br>
       if (I.getOpcode() == Instruction::Shl &&<br>
-          ShiftOp->getOpcode() != Instruction::Shl) {<br>
+          ShiftOp->getOpcode() != Instruction::Shl &&<br>
+          ShiftOp->isExact()) {<br>
         ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);<br>
-        if (ShiftOp->isExact()) {<br>
-          // (X >>?exact C1) << C2 --> X >>?exact (C1-C2)<br>
-          BinaryOperator *NewShr = BinaryOperator::Create(ShiftOp->getOpcode(),<br>
-                                                          X, ShiftDiffCst);<br>
-          NewShr->setIsExact(true);<br>
-          return NewShr;<br>
-        }<br>
-        Value *Shift = Builder->CreateBinOp(ShiftOp->getOpcode(),<br>
-                                            X, ShiftDiffCst);<br>
-        APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2));<br>
-        return BinaryOperator::CreateAnd(Shift,<br>
-                                         ConstantInt::get(I.getContext(),Mask));<br>
+        BinaryOperator *NewShr = BinaryOperator::Create(ShiftOp->getOpcode(),<br>
+                                                        X, ShiftDiffCst);<br>
+        NewShr->setIsExact(true);<br>
+        return NewShr;<br>
       }<br>
-<br>
+<br>
       // (X << C1) >>u C2  --> X << (C1-C2) & (-1 >> C2)<br>
       if (I.getOpcode() == Instruction::LShr &&<br>
           ShiftOp->getOpcode() == Instruction::Shl) {<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll?rev=155136&r1=155135&r2=155136&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll?rev=155136&r1=155135&r2=155136&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll Thu Apr 19 11:46:26 2012<br>
@@ -5,8 +5,8 @@<br>
 define i32 @main(i32 %argc) nounwind ssp {<br>
 entry:<br>
   %tmp3151 = trunc i32 %argc to i8<br>
-; CHECK: %tmp3162 = shl i8 %tmp3151, 5<br>
-; CHECK: and i8 %tmp3162, 64<br>
+; CHECK: %tmp3163 = shl i8 %tmp3162, 6<br>
+; CHECK: and i8 %tmp3163, 64<br>
 ; CHECK-NOT: shl<br>
 ; CHECK-NOT: shr<br>
   %tmp3161 = or i8 %tmp3151, -17<br>
@@ -38,8 +38,8 @@<br>
   %tmp10 = lshr i8 %tmp8, 7<br>
   %tmp11 = shl i8 %tmp10, 5<br>
<br>
-; CHECK: %0 = lshr i8 %tmp8, 2<br>
-; CHECK: %tmp11 = and i8 %0, 32<br>
+; CHECK: %tmp10 = lshr i8 %tmp8, 7<br>
+; CHECK: %tmp11 = shl nuw nsw i8 %tmp10, 5<br>
<br>
   %tmp12 = xor i8 %tmp11, %tmp9<br>
   ret i8 %tmp12<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/apint-shift.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/apint-shift.ll?rev=155136&r1=155135&r2=155136&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/apint-shift.ll?rev=155136&r1=155135&r2=155136&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/apint-shift.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/apint-shift.ll Thu Apr 19 11:46:26 2012<br>
@@ -47,13 +47,21 @@<br>
 }<br>
<br>
 ; CHECK: @test6<br>
-; CHECK-NOT: sh<br>
+; CHECK: mul i55 %A, 6<br>
 define i55 @test6(i55 %A) {<br>
        %B = shl i55 %A, 1              ; <i55> [#uses=1]<br>
        %C = mul i55 %B, 3              ; <i55> [#uses=1]<br>
        ret i55 %C<br>
 }<br>
<br>
+; CHECK: @test6a<br>
+; CHECK: mul i55 %A, 6<br>
+define i55 @test6a(i55 %A) {<br>
+       %B = mul i55 %A, 3              ; <i55> [#uses=1]<br>
+       %C = shl i55 %B, 1              ; <i55> [#uses=1]<br>
+       ret i55 %C<br>
+}<br>
+<br>
 ; CHECK: @test7<br>
 ; CHECK-NOT: sh<br>
 define i29 @test7(i8 %X) {<br>
@@ -87,7 +95,8 @@<br>
 }<br>
<br>
 ; CHECK: @test11<br>
-; CHECK-NOT: sh<br>
+; Don't hide the shl from scalar evolution. DAGCombine will get it.<br>
+; CHECK: shl<br>
 define i23 @test11(i23 %A) {<br>
        %a = mul i23 %A, 3              ; <i23> [#uses=1]<br>
        %B = lshr i23 %a, 11            ; <i23> [#uses=1]<br>
@@ -104,7 +113,8 @@<br>
 }<br>
<br>
 ; CHECK: @test13<br>
-; CHECK-NOT: sh<br>
+; Don't hide the shl from scalar evolution. DAGCombine will get it.<br>
+; CHECK: shl<br>
 define i18 @test13(i18 %A) {<br>
        %a = mul i18 %A, 3              ; <i18> [#uses=1]<br>
        %B = ashr i18 %a, 8             ; <i18> [#uses=1]<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/cast.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=155136&r1=155135&r2=155136&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=155136&r1=155135&r2=155136&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/cast.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/cast.ll Thu Apr 19 11:46:26 2012<br>
@@ -457,10 +457,12 @@<br>
   %E = sext i32 %D to i64<br>
   ret i64 %E<br>
 ; CHECK: @test50<br>
-; CHECK-NEXT: shl i64 %A, 30<br>
+; lshr+shl will be handled by DAGCombine.<br>
+; CHECK-NEXT: lshr i64 %A, 2<br>
+; CHECK-NEXT: shl i64 %a, 32<br>
 ; CHECK-NEXT: add i64 {{.*}}, -4294967296<br>
-; CHECK-NEXT: %sext = ashr i64 {{.*}}, 32<br>
-; CHECK-NEXT: ret i64 %sext<br>
+; CHECK-NEXT: %E = ashr exact i64 {{.*}}, 32<br>
+; CHECK-NEXT: ret i64 %E<br>
 }<br>
<br>
 define i64 @test51(i64 %A, i1 %cond) {<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/shift.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift.ll?rev=155136&r1=155135&r2=155136&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift.ll?rev=155136&r1=155135&r2=155136&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/shift.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/shift.ll Thu Apr 19 11:46:26 2012<br>
@@ -65,8 +65,17 @@<br>
 ; CHECK: @test6<br>
 ; CHECK-NEXT: mul i32 %A, 6<br>
 ; CHECK-NEXT: ret i32<br>
-        %B = shl i32 %A, 1      ;; convert to an mul instruction<br>
-        %C = mul i32 %B, 3<br>
+        %B = shl i32 %A, 1      ;; convert to an mul instruction<br>
+        %C = mul i32 %B, 3<br>
+        ret i32 %C<br>
+}<br>
+<br>
+define i32 @test6a(i32 %A) {<br>
+; CHECK: @test6a<br>
+; CHECK-NEXT: mul i32 %A, 6<br>
+; CHECK-NEXT: ret i32<br>
+        %B = mul i32 %A, 3<br>
+        %C = shl i32 %B, 1      ;; convert to an mul instruction<br>
         ret i32 %C<br>
 }<br>
<br>
@@ -97,7 +106,9 @@<br>
         ret i8 %C<br>
 }<br>
<br>
+;; This transformation is deferred to DAGCombine:<br>
 ;; (A >> 7) << 7 === A & 128<br>
+;; The shl may be valuable to scalar evolution.<br>
 define i8 @test10(i8 %A) {<br>
 ; CHECK: @test10<br>
 ; CHECK-NEXT: and i8 %A, -128<br>
@@ -107,11 +118,21 @@<br>
         ret i8 %C<br>
 }<br>
<br>
+;; Allow the simplification when the lshr shift is exact.<br>
+define i8 @test10a(i8 %A) {<br>
+; CHECK: @test10a<br>
+; CHECK-NEXT: ret i8 %A<br>
+        %B = lshr exact i8 %A, 7<br>
+        %C = shl i8 %B, 7<br>
+        ret i8 %C<br>
+}<br>
+<br>
+;; This transformation is deferred to DAGCombine:<br>
 ;; (A >> 3) << 4 === (A & 0x1F) << 1<br>
+;; The shl may be valuable to scalar evolution.<br>
 define i8 @test11(i8 %A) {<br>
 ; CHECK: @test11<br>
-; CHECK-NEXT: mul i8 %A, 6<br>
-; CHECK-NEXT: and i8<br>
+; CHECK: shl i8<br>
 ; CHECK-NEXT: ret i8<br>
         %a = mul i8 %A, 3               ; <i8> [#uses=1]<br>
         %B = lshr i8 %a, 3              ; <i8> [#uses=1]<br>
@@ -119,6 +140,18 @@<br>
         ret i8 %C<br>
 }<br>
<br>
+;; Allow the simplification in InstCombine when the lshr shift is exact.<br>
+define i8 @test11a(i8 %A) {<br>
+; CHECK: @test11a<br>
+; CHECK-NEXT: mul i8 %A, 6<br>
+; CHECK-NEXT: ret i8<br>
+        %a = mul i8 %A, 3<br>
+        %B = lshr exact i8 %a, 3<br>
+        %C = shl i8 %B, 4<br>
+        ret i8 %C<br>
+}<br>
+<br>
+;; This is deferred to DAGCombine unless %B is single-use.<br>
 ;; (A >> 8) << 8 === A & -256<br>
 define i32 @test12(i32 %A) {<br>
 ; CHECK: @test12<br>
@@ -129,11 +162,12 @@<br>
         ret i32 %C<br>
 }<br>
<br>
+;; This transformation is deferred to DAGCombine:<br>
 ;; (A >> 3) << 4 === (A & -8) * 2<br>
+;; The shl may be valuable to scalar evolution.<br>
 define i8 @test13(i8 %A) {<br>
 ; CHECK: @test13<br>
-; CHECK-NEXT: mul i8 %A, 6<br>
-; CHECK-NEXT: and i8<br>
+; CHECK: shl i8<br>
 ; CHECK-NEXT: ret i8<br>
         %a = mul i8 %A, 3               ; <i8> [#uses=1]<br>
         %B = ashr i8 %a, 3              ; <i8> [#uses=1]<br>
@@ -141,6 +175,16 @@<br>
         ret i8 %C<br>
 }<br>
<br>
+define i8 @test13a(i8 %A) {<br>
+; CHECK: @test13a<br>
+; CHECK-NEXT: mul i8 %A, 6<br>
+; CHECK-NEXT: ret i8<br>
+        %a = mul i8 %A, 3<br>
+        %B = ashr exact i8 %a, 3<br>
+        %C = shl i8 %B, 4<br>
+        ret i8 %C<br>
+}<br>
+<br>
 ;; D = ((B | 1234) << 4) === ((B << 4)|(1234 << 4)<br>
 define i32 @test14(i32 %A) {<br>
 ; CHECK: @test14<br>
@@ -477,10 +521,11 @@<br>
   %tmp49 = lshr i8 %tmp48, 5<br>
   %tmp50 = mul i8 %tmp49, 64<br>
   %tmp51 = xor i8 %tmp50, %tmp5<br>
-; CHECK: and i8 %0, 16<br>
   %tmp52 = and i8 %tmp51, -128<br>
   %tmp53 = lshr i8 %tmp52, 7<br>
+; CHECK: lshr i8 %tmp51, 7<br>
   %tmp54 = mul i8 %tmp53, 16<br>
+; CHECK: shl nuw nsw i8 %tmp53, 4<br>
   %tmp55 = xor i8 %tmp54, %tmp51<br>
 ; CHECK: ret i8 %tmp551<br>
   ret i8 %tmp55<br>
<br>
Modified: llvm/trunk/test/Transforms/PhaseOrdering/basic.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PhaseOrdering/basic.ll?rev=155136&r1=155135&r2=155136&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PhaseOrdering/basic.ll?rev=155136&r1=155135&r2=155136&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/PhaseOrdering/basic.ll (original)<br>
+++ llvm/trunk/test/Transforms/PhaseOrdering/basic.ll Thu Apr 19 11:46:26 2012<br>
@@ -22,3 +22,30 @@<br>
 ; CHECK: @test1<br>
 ; CHECK-NEXT: ret void<br>
 }<br>
+<br>
+; This function exposes a phase ordering problem when InstCombine is<br>
+; turning %add into a bitmask, making it difficult to spot a 0 return value.<br>
+;<br>
+; It it also important that %add is expressed as a multiple of %div so scalar<br>
+; evolution can recognize it.<br>
+define i32 @test2(i32 %a, i32* %p) nounwind uwtable ssp {<br>
+entry:<br>
+  %div = udiv i32 %a, 4<br>
+  %arrayidx = getelementptr inbounds i32* %p, i64 0<br>
+  store i32 %div, i32* %arrayidx, align 4<br>
+  %add = add i32 %div, %div<br>
+  %arrayidx1 = getelementptr inbounds i32* %p, i64 1<br>
+  store i32 %add, i32* %arrayidx1, align 4<br>
+  %arrayidx2 = getelementptr inbounds i32* %p, i64 1<br>
+  %0 = load i32* %arrayidx2, align 4<br>
+  %arrayidx3 = getelementptr inbounds i32* %p, i64 0<br>
+  %1 = load i32* %arrayidx3, align 4<br>
+  %mul = mul i32 2, %1<br>
+  %sub = sub i32 %0, %mul<br>
+  ret i32 %sub<br>
+<br>
+; CHECK: @test2<br>
+; CHECK: %div = lshr i32 %a, 2<br>
+; CHECK: %add = shl nuw nsw i32 %div, 1<br>
+; CHECK: ret i32 0<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/PhaseOrdering/scev.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PhaseOrdering/scev.ll?rev=155136&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PhaseOrdering/scev.ll?rev=155136&view=auto</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/PhaseOrdering/scev.ll (added)<br>
+++ llvm/trunk/test/Transforms/PhaseOrdering/scev.ll Thu Apr 19 11:46:26 2012<br>
@@ -0,0 +1,64 @@<br>
+; RUN: opt -O3 -S -analyze -scalar-evolution %s | FileCheck %s<br>
+;<br>
+; This file contains phase ordering tests for scalar evolution.<br>
+; Test that the standard passes don't obfuscate the IR so scalar evolution can't<br>
+; recognize expressions.<br>
+<br>
+; CHECK: test1<br>
+; The loop body contains two increments by %div.<br>
+; Make sure that 2*%div is recognizable, and not expressed as a bit mask of %d.<br>
+; CHECK: -->  {%p,+,(2 * (%d /u 4) * sizeof(i32))}<br>
+define void @test1(i64 %d, i32* %p) nounwind uwtable ssp {<br>
+entry:<br>
+  %div = udiv i64 %d, 4<br>
+  br label %for.cond<br>
+<br>
+for.cond:                                         ; preds = %for.inc, %entry<br>
+  %p.addr.0 = phi i32* [ %p, %entry ], [ %add.ptr1, %for.inc ]<br>
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]<br>
+  %cmp = icmp ne i32 %i.0, 64<br>
+  br i1 %cmp, label %for.body, label %for.end<br>
+<br>
+for.body:                                         ; preds = %for.cond<br>
+  store i32 0, i32* %p.addr.0, align 4<br>
+  %add.ptr = getelementptr inbounds i32* %p.addr.0, i64 %div<br>
+  store i32 1, i32* %add.ptr, align 4<br>
+  %add.ptr1 = getelementptr inbounds i32* %add.ptr, i64 %div<br>
+  br label %for.inc<br>
+<br>
+for.inc:                                          ; preds = %for.body<br>
+  %inc = add i32 %i.0, 1<br>
+  br label %for.cond<br>
+<br>
+for.end:                                          ; preds = %for.cond<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK: test1a<br>
+; Same thing as test1, but it is even more tempting to fold 2 * (%d /u 2)<br>
+; CHECK: -->  {%p,+,(2 * (%d /u 2) * sizeof(i32))}<br>
+define void @test1a(i64 %d, i32* %p) nounwind uwtable ssp {<br>
+entry:<br>
+  %div = udiv i64 %d, 2<br>
+  br label %for.cond<br>
+<br>
+for.cond:                                         ; preds = %for.inc, %entry<br>
+  %p.addr.0 = phi i32* [ %p, %entry ], [ %add.ptr1, %for.inc ]<br>
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]<br>
+  %cmp = icmp ne i32 %i.0, 64<br>
+  br i1 %cmp, label %for.body, label %for.end<br>
+<br>
+for.body:                                         ; preds = %for.cond<br>
+  store i32 0, i32* %p.addr.0, align 4<br>
+  %add.ptr = getelementptr inbounds i32* %p.addr.0, i64 %div<br>
+  store i32 1, i32* %add.ptr, align 4<br>
+  %add.ptr1 = getelementptr inbounds i32* %add.ptr, i64 %div<br>
+  br label %for.inc<br>
+<br>
+for.inc:                                          ; preds = %for.body<br>
+  %inc = add i32 %i.0, 1<br>
+  br label %for.cond<br>
+<br>
+for.end:                                          ; preds = %for.cond<br>
+  ret void<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>