[llvm-commits] [llvm] r72452 - in /llvm/trunk: lib/Analysis/ScalarEvolutionExpander.cpp test/Transforms/IndVarSimplify/preserve-gep-remainder.ll

Dan Gohman gohman at apple.com
Tue May 26 19:00:54 PDT 2009


Author: djg
Date: Tue May 26 21:00:53 2009
New Revision: 72452

URL: http://llvm.org/viewvc/llvm-project?rev=72452&view=rev
Log:
Teach SCEVExpander to avoid creating over-indexed GEP indices when
possible. For example, it now emits

  %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 2, i64 %tmp, i64 1

instead of the equivalent but less obvious

  %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 0, i64 %tmp, i64 19

Added:
    llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll
Modified:
    llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp

Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=72452&r1=72451&r2=72452&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Tue May 26 21:00:53 2009
@@ -144,12 +144,15 @@
   return BO;
 }
 
-/// FactorOutConstant - Test if S is evenly divisible by Factor, using signed
+/// FactorOutConstant - Test if S is divisible by Factor, using signed
 /// division. If so, update S with Factor divided out and return true.
+/// S need not be evenly divisble if a reasonable remainder can be
+/// computed.
 /// TODO: When ScalarEvolution gets a SCEVSDivExpr, this can be made
 /// unnecessary; in its place, just signed-divide Ops[i] by the scale and
 /// check to see if the divide was folded.
 static bool FactorOutConstant(SCEVHandle &S,
+                              SCEVHandle &Remainder,
                               const APInt &Factor,
                               ScalarEvolution &SE) {
   // Everything is divisible by one.
@@ -157,14 +160,21 @@
     return true;
 
   // For a Constant, check for a multiple of the given factor.
-  if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
-    if (!C->getValue()->getValue().srem(Factor)) {
-      ConstantInt *CI =
-        ConstantInt::get(C->getValue()->getValue().sdiv(Factor));
+  if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S)) {
+    ConstantInt *CI =
+      ConstantInt::get(C->getValue()->getValue().sdiv(Factor));
+    // If the quotient is zero and the remainder is non-zero, reject
+    // the value at this scale. It will be considered for subsequent
+    // smaller scales.
+    if (C->isZero() || !CI->isZero()) {
       SCEVHandle Div = SE.getConstant(CI);
       S = Div;
+      Remainder =
+        SE.getAddExpr(Remainder,
+                      SE.getConstant(C->getValue()->getValue().srem(Factor)));
       return true;
     }
+  }
 
   // In a Mul, check if there is a constant operand which is a multiple
   // of the given factor.
@@ -180,11 +190,14 @@
 
   // In an AddRec, check if both start and step are divisible.
   if (const SCEVAddRecExpr *A = dyn_cast<SCEVAddRecExpr>(S)) {
-    SCEVHandle Start = A->getStart();
-    if (!FactorOutConstant(Start, Factor, SE))
-      return false;
     SCEVHandle Step = A->getStepRecurrence(SE);
-    if (!FactorOutConstant(Step, Factor, SE))
+    SCEVHandle StepRem = SE.getIntegerSCEV(0, Step->getType());
+    if (!FactorOutConstant(Step, StepRem, Factor, SE))
+      return false;
+    if (!StepRem->isZero())
+      return false;
+    SCEVHandle Start = A->getStart();
+    if (!FactorOutConstant(Start, Remainder, Factor, SE))
       return false;
     S = SE.getAddRecExpr(Start, Step, A->getLoop());
     return true;
@@ -253,8 +266,10 @@
       // If the scale size is not 0, attempt to factor out a scale.
       if (ElSize != 0) {
         SCEVHandle Op = Ops[i];
-        if (FactorOutConstant(Op, ElSize, SE)) {
+        SCEVHandle Remainder = SE.getIntegerSCEV(0, Op->getType());
+        if (FactorOutConstant(Op, Remainder, ElSize, SE)) {
           ScaledOps.push_back(Op); // Op now has ElSize factored out.
+          NewOps.push_back(Remainder);
           continue;
         }
       }

Added: llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll?rev=72452&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll Tue May 26 21:00:53 2009
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | opt -indvars | llvm-dis \
+; RUN:   | grep {\[%\]p.2.ip.1 = getelementptr \\\[3 x \\\[3 x double\\\]\\\]\\* \[%\]p, i64 2, i64 \[%\]tmp, i64 1}
+
+; Indvars shouldn't expand this to
+;   %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 0, i64 %tmp, i64 19
+; or something. That's valid, but more obscure.
+
+define void @foo([3 x [3 x double]]* noalias %p) nounwind {
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+  %ip = add i64 %i, 1
+  %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 2, i64 %ip, i64 1
+  volatile store double 0.0, double* %p.2.ip.1
+  %i.next = add i64 %i, 1
+  br label %loop
+}





More information about the llvm-commits mailing list