[llvm-commits] [polly] r137930 - /polly/trunk/lib/Analysis/ScopInfo.cpp

Tobias Grosser grosser at fim.uni-passau.de
Wed Aug 17 23:31:50 PDT 2011


Author: grosser
Date: Thu Aug 18 01:31:50 2011
New Revision: 137930

URL: http://llvm.org/viewvc/llvm-project?rev=137930&view=rev
Log:
ScopInfo: Build isl_pw_aff directly from SCEV.

Do not use AffFunc to derive the affine expressions, but use isl_pw_aff to
analyze the original SCEV directly. This will allow several simplifications in
follow up patches, with the final goal of removing AffFunc completely.

Modified:
    polly/trunk/lib/Analysis/ScopInfo.cpp

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=137930&r1=137929&r2=137930&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Thu Aug 18 01:31:50 2011
@@ -38,6 +38,8 @@
 #include "isl/constraint.h"
 #include "isl/set.h"
 #include "isl/map.h"
+#include "isl/aff.h"
+#include "isl/printer.h"
 #include <sstream>
 #include <string>
 #include <vector>
@@ -48,65 +50,261 @@
 STATISTIC(ScopFound,  "Number of valid Scops");
 STATISTIC(RichScopFound,   "Number of Scops containing a loop");
 
+/// Convert an int into a string.
+static std::string convertInt(int number)
+{
+  if (number == 0)
+    return "0";
+  std::string temp = "";
+  std::string returnvalue = "";
+  while (number > 0)
+  {
+    temp += number % 10 + 48;
+    number /= 10;
+  }
+  for (unsigned i = 0; i < temp.length(); i++)
+    returnvalue+=temp[temp.length() - i - 1];
+  return returnvalue;
+}
+
+static isl_map *map_remove_dim_ids(isl_map *map) {
+  isl_ctx *ctx = isl_map_get_ctx(map);
+  int numParams = isl_map_n_param(map);
+  isl_printer *p = isl_printer_to_str(ctx);
+  char *str;
+
+  p = isl_printer_set_output_format (p, ISL_FORMAT_EXT_POLYLIB);
+  p = isl_printer_print_map(p, map);
+  isl_map_free (map);
+
+  str = isl_printer_get_str (p);
+  map = isl_map_read_from_str (ctx, str, numParams);
+  free (str);
+  isl_printer_free (p);
+  return map;
+}
+
+/// Translate a SCEVExpression into an isl_pw_aff object.
+struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff*> {
+private:
+  isl_ctx *ctx;
+  int NbLoopDims;
+  const Scop *scop;
+
+  /// baseAdress is set if we analyze a memory access. It holds the base address
+  /// of this memory access.
+  const Value *baseAddress;
+
+public:
+  static isl_pw_aff *getPwAff(const ScopStmt *stmt, const SCEV *scev,
+                              const Value *baseAddress) {
+    SCEVAffinator Affinator(stmt, baseAddress);
+    return Affinator.visit(scev);
+  }
 
-//===----------------------------------------------------------------------===//
-static void setCoefficient(const SCEV *Coeff, mpz_t v, bool negative,
-                           bool isSigned = true) {
-  if (Coeff) {
-    const SCEVConstant *C = dyn_cast<SCEVConstant>(Coeff);
-    const APInt &CI = C->getValue()->getValue();
-    MPZ_from_APInt(v, negative ? (-CI) : CI, isSigned);
-  } else
-    isl_int_set_si(v, 0);
-}
+  isl_pw_aff *visit(const SCEV *scev) {
+    // In case the scev is contained in our list of parameters, we do not
+    // further analyze this expression, but create a new parameter in the
+    // isl_pw_aff. This allows us to treat subexpressions that we cannot
+    // translate into an piecewise affine expression, as constant parameters of
+    // the piecewise affine expression.
+    int i = 0;
+    for (Scop::const_param_iterator PI = scop->param_begin(),
+         PE = scop->param_end(); PI != PE; ++PI) {
+      if (*PI == scev) {
+        isl_id *ID = isl_id_alloc(ctx, ("p" + convertInt(i)).c_str(),
+                                  (void *) scev);
+        isl_dim *Dim = isl_dim_set_alloc(ctx, 1, NbLoopDims);
+        Dim = isl_dim_set_dim_id(Dim, isl_dim_param, 0, ID);
+
+        isl_set *Domain = isl_set_universe(isl_dim_copy(Dim));
+        isl_aff *Affine = isl_aff_zero(isl_local_space_from_dim(Dim));
+        Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
+
+        return isl_pw_aff_alloc(Domain, Affine);
+      }
+      i++;
+    }
 
-static isl_map *getValueOf(const SCEVAffFunc &AffFunc,
-                           const ScopStmt *Statement, isl_dim *dim) {
+    return SCEVVisitor<SCEVAffinator, isl_pw_aff*>::visit(scev);
+  }
 
-  const SmallVectorImpl<const SCEV*> &Params =
-    Statement->getParent()->getParams();
-  unsigned num_in = Statement->getNumIterators(), num_param = Params.size();
+  SCEVAffinator(const ScopStmt *stmt, const Value *baseAddress) :
+    ctx(stmt->getParent()->getCtx()),
+    NbLoopDims(stmt->getNumIterators()),
+    scop(stmt->getParent()),
+    baseAddress(baseAddress) {};
 
-  const char *dimname = isl_dim_get_tuple_name(dim, isl_dim_set);
-  dim = isl_dim_alloc(isl_dim_get_ctx(dim), num_param,
-                      isl_dim_size(dim, isl_dim_set), 1);
-  dim = isl_dim_set_tuple_name(dim, isl_dim_in, dimname);
+  __isl_give isl_pw_aff *visitConstant(const SCEVConstant *Constant) {
+    ConstantInt *Value = Constant->getValue();
+    isl_int v;
+    isl_int_init(v);
 
-  assert((AffFunc.getType() == SCEVAffFunc::Eq
-          || AffFunc.getType() == SCEVAffFunc::ReadMem
-          || AffFunc.getType() == SCEVAffFunc::WriteMem)
-          && "AffFunc is not an equality");
+    // LLVM does not define if an integer value is interpreted as a signed or
+    // unsigned value. Hence, without further information, it is unknown how
+    // this value needs to be converted to GMP. At the moment, we only support
+    // signed operations. So we just interpret it as signed. Later, there are
+    // two options:
+    //
+    // 1. We always interpret any value as signed and convert the values on
+    //    demand.
+    // 2. We pass down the signedness of the calculation and use it to interpret
+    //    this constant correctly.
+    MPZ_from_APInt(v, Value->getValue(), /* isSigned */ true);
+
+    isl_dim *dim = isl_dim_set_alloc(ctx, 0, NbLoopDims);
+    isl_local_space *ls = isl_local_space_from_dim(isl_dim_copy(dim));
+    isl_aff *Affine = isl_aff_zero(ls);
+    isl_set *Domain = isl_set_universe(dim);
 
-  isl_constraint *c = isl_equality_alloc(isl_dim_copy(dim));
+    Affine = isl_aff_add_constant(Affine, v);
+    isl_int_clear(v);
 
-  isl_int v;
-  isl_int_init(v);
+    return isl_pw_aff_alloc(Domain, Affine);
+  }
 
-  // Set single output dimension.
-  isl_int_set_si(v, -1);
-  isl_constraint_set_coefficient(c, isl_dim_out, 0, v);
+  __isl_give isl_pw_aff *visitTruncateExpr(const SCEVTruncateExpr* Expr) {
+    assert(0 && "Not yet supported");
+  }
 
-  // Set the coefficient for induction variables.
-  for (unsigned i = 0, e = num_in; i != e; ++i) {
-    setCoefficient(AffFunc.getCoeff(Statement->getSCEVForDimension(i)), v,
-                   false, AffFunc.isSigned());
-    isl_constraint_set_coefficient(c, isl_dim_in, i, v);
+  __isl_give isl_pw_aff *visitZeroExtendExpr(const SCEVZeroExtendExpr * Expr) {
+    assert(0 && "Not yet supported");
   }
 
-  // Set the coefficient of parameters
-  for (unsigned i = 0, e = num_param; i != e; ++i) {
-    setCoefficient(AffFunc.getCoeff(Params[i]), v, false, AffFunc.isSigned());
-    isl_constraint_set_coefficient(c, isl_dim_param, i, v);
+  __isl_give isl_pw_aff *visitSignExtendExpr(const SCEVSignExtendExpr* Expr) {
+    // Assuming the value is signed, a sign extension is basically a noop.
+    // TODO: Reconsider this as soon as we support unsigned values.
+    return visit(Expr->getOperand());
   }
 
-  // Set the constant.
-  setCoefficient(AffFunc.getTransComp(), v, false, AffFunc.isSigned());
-  isl_constraint_set_constant(c, v);
-  isl_int_clear(v);
+  __isl_give isl_pw_aff *visitAddExpr(const SCEVAddExpr* Expr) {
+    isl_pw_aff *Sum = visit(Expr->getOperand(0));
+
+    for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
+      isl_pw_aff *NextSummand = visit(Expr->getOperand(i));
+      Sum = isl_pw_aff_add(Sum, NextSummand);
+    }
+
+    // TODO: Check for NSW and NUW.
+
+    return Sum;
+  }
+
+  __isl_give isl_pw_aff *visitMulExpr(const SCEVMulExpr* Expr) {
+    isl_pw_aff *Product = visit(Expr->getOperand(0));
+
+    for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
+      isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
+
+      if (!isl_pw_aff_is_cst(Product) && !isl_pw_aff_is_cst(NextOperand)) {
+        isl_pw_aff_free(Product);
+        isl_pw_aff_free(NextOperand);
+        return NULL;
+      }
 
-  isl_basic_map *BasicMap = isl_basic_map_universe(isl_dim_copy(dim));
-  BasicMap = isl_basic_map_add_constraint(BasicMap, c);
-  return isl_map_from_basic_map(BasicMap);
+      Product = isl_pw_aff_mul(Product, NextOperand);
+    }
+
+    // TODO: Check for NSW and NUW.
+    return Product;
+  }
+
+  __isl_give isl_pw_aff *visitUDivExpr(const SCEVUDivExpr* Expr) {
+    assert(0 && "Not yet supported");
+  }
+
+  int getLoopDepth(const Loop *L) {
+    Loop *outerLoop =
+      scop->getRegion().outermostLoopInRegion(const_cast<Loop*>(L));
+    return L->getLoopDepth() - outerLoop->getLoopDepth();
+  }
+
+  __isl_give isl_pw_aff *visitAddRecExpr(const SCEVAddRecExpr* Expr) {
+    assert(Expr->isAffine() && "Only affine AddRecurrences allowed");
+
+    isl_pw_aff *Start = visit(Expr->getStart());
+    isl_pw_aff *Step = visit(Expr->getOperand(1));
+    isl_dim *Dim = isl_dim_set_alloc (ctx, 0, NbLoopDims);
+    isl_local_space *LocalSpace = isl_local_space_from_dim (Dim);
+
+    int loopDimension = getLoopDepth(Expr->getLoop());
+
+    isl_aff *LAff = isl_aff_set_coefficient_si (isl_aff_zero (LocalSpace),
+                                                isl_dim_set, loopDimension, 1);
+    isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff);
+
+    // TODO: Do we need to check for NSW and NUW?
+    return isl_pw_aff_add(Start, isl_pw_aff_mul(Step, LPwAff));
+  }
+
+  __isl_give isl_pw_aff *visitSMaxExpr(const SCEVSMaxExpr* Expr) {
+    isl_pw_aff *Max = visit(Expr->getOperand(0));
+
+    for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
+      isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
+      Max = isl_pw_aff_max(Max, NextOperand);
+    }
+
+    return Max;
+  }
+
+  __isl_give isl_pw_aff *visitUMaxExpr(const SCEVUMaxExpr* Expr) {
+    assert(0 && "Not yet supported");
+  }
+
+  __isl_give isl_pw_aff *visitUnknown(const SCEVUnknown* Expr) {
+    Value *Value = Expr->getValue();
+
+    isl_dim *Dim;
+
+    /// If baseAddress is set, we ignore its Value object in the scev and do not
+    /// add it to the isl_pw_aff. This is because it is regarded as defining the
+    /// name of an array, in contrast to its array subscript.
+    if (baseAddress != Value) {
+      isl_id *ID = isl_id_alloc(ctx, Value->getNameStr().c_str(), Value);
+      Dim = isl_dim_set_alloc(ctx, 1, NbLoopDims);
+      Dim = isl_dim_set_dim_id(Dim, isl_dim_param, 0, ID);
+    } else {
+      Dim = isl_dim_set_alloc(ctx, 0, NbLoopDims);
+    }
+
+    isl_set *Domain = isl_set_universe(isl_dim_copy(Dim));
+    isl_aff *Affine = isl_aff_zero(isl_local_space_from_dim(Dim));
+
+    if (baseAddress != Value)
+      Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
+
+    return isl_pw_aff_alloc(Domain, Affine);
+  }
+};
+
+static isl_map *getValueOf(const SCEVAffFunc &AffFunc,
+                           const ScopStmt *Statement, isl_dim *dim) {
+  assert((AffFunc.getType() == SCEVAffFunc::Eq
+          || AffFunc.getType() == SCEVAffFunc::ReadMem
+          || AffFunc.getType() == SCEVAffFunc::WriteMem)
+          && "AffFunc is not an equality");
+  isl_pw_aff *Affine = SCEVAffinator::getPwAff(Statement, AffFunc.OriginalSCEV,
+                                               AffFunc.getBaseAddr());
+  isl_map *Map = isl_map_from_pw_aff(Affine);
+  isl_dim *CtxDim = isl_set_get_dim(Statement->getParent()->getContext());
+
+  int i = 0;
+  for (Scop::const_param_iterator PI = Statement->getParent()->param_begin(),
+       PE = Statement->getParent()->param_end(); PI != PE; ++PI) {
+    const SCEV *scev = *PI;
+    isl_id *id = isl_id_alloc(isl_dim_get_ctx(CtxDim),
+                              ("p" + convertInt(i)).c_str(),
+                              (void *) scev);
+    CtxDim = isl_dim_set_dim_id(CtxDim, isl_dim_param, i, id);
+    i++;
+  }
+
+  isl_map_align_params(Map, CtxDim);
+  const char *dimname = isl_dim_get_tuple_name(dim, isl_dim_set);
+  Map = map_remove_dim_ids(Map);
+  Map = isl_map_set_tuple_name(Map, isl_dim_in, dimname);
+  return Map;
 }
 //===----------------------------------------------------------------------===//
 





More information about the llvm-commits mailing list