[PATCH] Little improvement in IndVarSimplify

Michele Scandale michele.scandale at gmail.com
Mon Jul 8 06:46:28 PDT 2013


michele.scandale added you to the CC list for the revision "Little improvement in IndVarSimplify".

Hi everybody,

I would like to propose a little improvement to IndVarSimplify pass. The attached patch adds a special handling of the case where, during the loop exit condition rewriting, the exit value is a constant of bitwidth lower than the type of the induction variable: instead of introducing a trunc operation in order to match correctly the operand types, it allows to convert the constant value to an equivalent constant, depending on the initial value of the induction variable and the trip count, in order have an equivalent comparison between the induction variable and the new constant.

Thanks in advance.

Michele Scandale

http://llvm-reviews.chandlerc.com/D1112

Files:
  lib/Transforms/Scalar/IndVarSimplify.cpp
  test/Transforms/IndVarSimplify/exitcnt-const-arstart-const-opt.ll

Index: lib/Transforms/Scalar/IndVarSimplify.cpp
===================================================================
--- lib/Transforms/Scalar/IndVarSimplify.cpp
+++ lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -1612,10 +1612,27 @@
                << "  IVCount:\t" << *IVCount << "\n");
 
   IRBuilder<> Builder(BI);
-  if (SE->getTypeSizeInBits(CmpIndVar->getType())
-      > SE->getTypeSizeInBits(ExitCnt->getType())) {
-    CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(),
-                                    "lftr.wideiv");
+
+  unsigned CmpIndVarSize = SE->getTypeSizeInBits(CmpIndVar->getType());
+  unsigned ExitCntSize = SE->getTypeSizeInBits(ExitCnt->getType());
+  if (CmpIndVarSize > ExitCntSize) {
+    const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(SE->getSCEV(IndVar));
+    const SCEV *ARStart = AR->getStart();
+    const SCEV *ARStep = AR->getStepRecurrence(*SE);
+    if (isa<SCEVConstant>(ARStart) && isa<SCEVConstant>(IVCount)) {
+      const APInt &Start = cast<SCEVConstant>(ARStart)->getValue()->getValue();
+      const APInt &Count = cast<SCEVConstant>(IVCount)->getValue()->getValue();
+
+      APInt NewLimit;
+      if (cast<SCEVConstant>(ARStep)->getValue()->isNegative())
+        NewLimit = Start - Count.zext(CmpIndVarSize);
+      else
+        NewLimit = Start + Count.zext(CmpIndVarSize);
+      ExitCnt = ConstantInt::get(CmpIndVar->getType(), NewLimit);
+
+      DEBUG(dbgs() << "  Widen RHS:\t" << *ExitCnt << "\n");
+    } else CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(),
+                                           "lftr.wideiv");
   }
 
   Value *Cond = Builder.CreateICmp(P, CmpIndVar, ExitCnt, "exitcond");
Index: test/Transforms/IndVarSimplify/exitcnt-const-arstart-const-opt.ll
===================================================================
--- test/Transforms/IndVarSimplify/exitcnt-const-arstart-const-opt.ll
+++ test/Transforms/IndVarSimplify/exitcnt-const-arstart-const-opt.ll
@@ -0,0 +1,25 @@
+;RUN: opt -S %s -indvars | FileCheck %s
+
+; Function Attrs: nounwind uwtable
+define void @foo() #0 {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i16 [ 0, %entry ], [ %inc, %for.body ]
+  %conv2 = sext i16 %i.01 to i32
+  call void @bar(i32 %conv2) #1
+  %inc = add i16 %i.01, 1
+;CHECK-NOT: %lftr.wideiv = trunc i32 %indvars.iv.next to i16
+;CHECK: %exitcond = icmp ne i32 %indvars.iv.next, 512
+  %cmp = icmp slt i16 %inc, 512
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+declare void @bar(i32)
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1112.1.patch
Type: text/x-patch
Size: 2726 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130708/bb1677ce/attachment.bin>


More information about the llvm-commits mailing list