[PATCH] Converting ‘sext of addrec’ to ‘addrec of sext’

Ashutosh Nema ashutosh.nema at amd.com
Wed May 6 04:11:33 PDT 2015


Hi sanjoy, majnemer,

This change is for converting ‘sext of addrec’ to ‘addrec of sext’ when 
compiler is sure transformation will not overflow.

By doing this will open opportunity for optimizations dependent on addRecExpr.

Consider below case:

for (j=1; j < itr; j++) {
     - - - - 
     for (i=1; i < itr; i++) {
     {
       temp=  var[i * 2];
        - - - - - 
     }
}

“var[i * 2]” "SCEVAddRecExpr" is computable in *Outer Loop* 

I expected Scalar evolution to get that, but it's not doing that 
if ‘*2’ is transformed to shift reduction in some specific circumstances.

In the above example, ‘var[i * 2]’ is converted into ‘var[i << 1]’ 
by Instruction combiner (Shift reduction).

After this addRecExpr is not computable.

To fix that issue made changes in ScalarEvolution & SimplifyIndVar.

In ScalarEvolution converting ‘sext of addrec’ to ‘addrec of sext’ only when 
Compiler is sure operation will not overflow:
// i.e. (sext i32 Addrec{2,+,2}<nuw><%for.body4> to i64)
// will be transformed into:
// addrec{(sext i32 '2' to i64),+,(sext i32 '2' to i64)}<nsw><%for.body4>

In “SimplifyIndVar.cpp” we strengthen overflow operation for left shift.

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D9521

Files:
  lib/Analysis/ScalarEvolution.cpp
  lib/Transforms/Utils/SimplifyIndVar.cpp
  test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll

Index: lib/Analysis/ScalarEvolution.cpp
===================================================================
--- lib/Analysis/ScalarEvolution.cpp
+++ lib/Analysis/ScalarEvolution.cpp
@@ -4328,8 +4328,33 @@
   case Instruction::ZExt:
     return getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType());
 
-  case Instruction::SExt:
-    return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType());
+  case Instruction::SExt: {
+    // Converting 'sext of addRec' to 'addRec of sext'
+    // i.e. (sext i32 Addrec{2,+,2}<nuw><%for.body4> to i64)
+    // will be transformed into:
+    // addrec{(sext i32 '2' to i64),+,(sext i32 '2' to i64)}<nsw><%for.body4>
+    const SCEVAddRecExpr *AddRec =
+        dyn_cast<SCEVAddRecExpr>(getSCEV(U->getOperand(0)));
+    if (AddRec && (AddRec->getNoWrapFlags(SCEV::FlagNSW) ||
+                   AddRec->getNoWrapFlags(SCEV::FlagNUW))) {
+      SmallVector<const SCEV *, 4> Operands;
+      for (SCEVAddRecExpr::op_iterator I = AddRec->op_begin(),
+                                       E = AddRec->op_end();
+           I != E; ++I) {
+        const SCEV *addRecOpr = *I;
+        addRecOpr = getSignExtendExpr(addRecOpr, U->getType());
+        Operands.push_back(addRecOpr);
+      }
+      if (AddRec->getNoWrapFlags(SCEV::FlagNSW))
+        return getAddRecExpr(Operands, AddRec->getLoop(),
+                             AddRec->getNoWrapFlags(SCEV::FlagNSW));
+      else
+        return getAddRecExpr(Operands, AddRec->getLoop(),
+                             AddRec->getNoWrapFlags(SCEV::FlagNUW));
+    } else {
+      return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType());
+    }
+  }
 
   case Instruction::BitCast:
     // BitCasts are no-op casts so we just eliminate the cast.
Index: lib/Transforms/Utils/SimplifyIndVar.cpp
===================================================================
--- lib/Transforms/Utils/SimplifyIndVar.cpp
+++ lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -292,6 +292,18 @@
   case Instruction::Mul:
     GetExprForBO = &ScalarEvolution::getMulExpr;
     break;
+
+  case Instruction::Shl:
+    // shift by operand should be constant.
+    if (dyn_cast<ConstantInt>(BO->getOperand(1))) {
+      // shift should be marked with 'nsw' or 'nuw'.
+      if (!BO->hasNoUnsignedWrap() && !BO->hasNoSignedWrap())
+        return false;
+      GetExprForBO = &ScalarEvolution::getMulExpr;
+      break;
+    } else {
+      return false;
+    }
   }
 
   unsigned BitWidth = cast<IntegerType>(BO->getType())->getBitWidth();
Index: test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
===================================================================
--- test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
+++ test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
@@ -11,7 +11,7 @@
   %idx.inc = add nsw i32 %idx, 1
   %idx.inc.sext = sext i32 %idx.inc to i64
 ; CHECK: %idx.inc.sext = sext i32 %idx.inc to i64
-; CHECK-NEXT: -->  {(1 + (sext i32 %start to i64)),+,1}<nsw><%loop>
+; CHECK-NEXT: -->  {(sext i32 (1 + %start) to i64),+,1}<nsw><%loop>
   %condition = icmp eq i32 %counter, 1
   %counter.inc = add i32 %counter, 1
   br i1 %condition, label %exit, label %loop
@@ -71,7 +71,7 @@
   %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ]
   %idx.sext = sext i8 %idx to i16
 ; CHECK: %idx.sext = sext i8 %idx to i16
-; CHECK-NEXT: -->  {(1 + (sext i8 %start to i16)),+,1}<nsw><%loop>
+; CHECK-NEXT: -->  {(sext i8 (1 + %start) to i16),+,1}<nsw><%loop>
   %idx.inc = add nsw i8 %idx, 1
   %condition = load volatile i1, i1* %c
   br i1 %condition, label %exit, label %loop

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D9521.25035.patch
Type: text/x-patch
Size: 3589 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150506/cebf04dd/attachment.bin>


More information about the llvm-commits mailing list