[polly] r244730 - Expose the SCEVAffinator and make it a member of a SCoP.

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 12 03:19:51 PDT 2015


Author: jdoerfert
Date: Wed Aug 12 05:19:50 2015
New Revision: 244730

URL: http://llvm.org/viewvc/llvm-project?rev=244730&view=rev
Log:
Expose the SCEVAffinator and make it a member of a SCoP.

  This change has three major advantages:
    - The ScopInfo becomes smaller.
    - It allows to use the SCEVAffinator from outside the ScopInfo.
    - A member object allows state which in turn allows e.g., caching.

Differential Revision: http://reviews.llvm.org/D9099

Added:
    polly/trunk/include/polly/Support/SCEVAffinator.h
    polly/trunk/lib/Support/SCEVAffinator.cpp
Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/CMakeLists.txt
    polly/trunk/lib/Makefile

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=244730&r1=244729&r2=244730&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Wed Aug 12 05:19:50 2015
@@ -21,6 +21,8 @@
 #define POLLY_SCOP_INFO_H
 
 #include "polly/ScopDetection.h"
+#include "polly/Support/SCEVAffinator.h"
+
 #include "llvm/ADT/MapVector.h"
 #include "llvm/Analysis/RegionPass.h"
 #include "isl/ctx.h"
@@ -51,6 +53,7 @@ struct isl_union_map;
 struct isl_space;
 struct isl_ast_build;
 struct isl_constraint;
+struct isl_pw_aff;
 struct isl_pw_multi_aff;
 struct isl_schedule;
 
@@ -61,8 +64,8 @@ class Scop;
 class ScopStmt;
 class ScopInfo;
 class TempScop;
-class SCEVAffFunc;
 class Comparison;
+class SCEVAffFunc;
 
 /// @brief A class to store information about arrays in the SCoP.
 ///
@@ -680,6 +683,9 @@ public:
   /// @param NewDomain The new statement domain.
   void restrictDomain(__isl_take isl_set *NewDomain);
 
+  /// @brief Compute the isl representation for the SCEV @p E in this stmt.
+  __isl_give isl_pw_aff *getPwAff(const SCEV *E);
+
   /// @brief Get the loop for a dimension.
   ///
   /// @param Dimension The dimension of the induction variable
@@ -774,6 +780,9 @@ private:
   /// Constraints on parameters.
   isl_set *Context;
 
+  /// @brief The affinator used to translate SCEVs to isl expressions.
+  SCEVAffinator Affinator;
+
   typedef MapVector<std::pair<const Value *, int>,
                     std::unique_ptr<ScopArrayInfo>> ArrayInfoMapTy;
   /// @brief A map to remember ScopArrayInfo objects for all base pointers.
@@ -1104,6 +1113,9 @@ public:
   /// @return The isl context of this static control part.
   isl_ctx *getIslCtx() const;
 
+  /// @brief Compute the isl representation for the SCEV @p E in @p Stmt.
+  __isl_give isl_pw_aff *getPwAff(const SCEV *E, ScopStmt *Stmt);
+
   /// @brief Get a union set containing the iteration domains of all statements.
   __isl_give isl_union_set *getDomains() const;
 

Added: polly/trunk/include/polly/Support/SCEVAffinator.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/SCEVAffinator.h?rev=244730&view=auto
==============================================================================
--- polly/trunk/include/polly/Support/SCEVAffinator.h (added)
+++ polly/trunk/include/polly/Support/SCEVAffinator.h Wed Aug 12 05:19:50 2015
@@ -0,0 +1,82 @@
+//===------ polly/SCEVAffinator.h - Create isl expressions from SCEVs -----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Create a polyhedral description for a SCEV value.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_SCEV_AFFINATOR_H
+#define POLLY_SCEV_AFFINATOR_H
+
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+
+#include "isl/ctx.h"
+
+struct isl_ctx;
+struct isl_map;
+struct isl_basic_map;
+struct isl_id;
+struct isl_set;
+struct isl_union_set;
+struct isl_union_map;
+struct isl_space;
+struct isl_ast_build;
+struct isl_constraint;
+struct isl_pw_aff;
+struct isl_schedule;
+
+namespace llvm {
+class Region;
+class ScalarEvolution;
+}
+
+namespace polly {
+class Scop;
+class ScopStmt;
+
+/// Translate a SCEV to an isl_pw_aff.
+struct SCEVAffinator : public llvm::SCEVVisitor<SCEVAffinator, isl_pw_aff *> {
+public:
+  SCEVAffinator(Scop *S);
+
+  /// @brief Translate a SCEV to an isl_pw_aff.
+  ///
+  /// @param E    The expression that is translated.
+  /// @param Stmt The SCoP statment surrounding @p E.
+  __isl_give isl_pw_aff *getPwAff(const llvm::SCEV *E, const ScopStmt *Stmt);
+
+private:
+  Scop *S;
+  isl_ctx *Ctx;
+  unsigned NumIterators;
+  const llvm::Region &R;
+  llvm::ScalarEvolution &SE;
+
+  int getLoopDepth(const llvm::Loop *L);
+
+  __isl_give isl_pw_aff *visit(const llvm::SCEV *E);
+  __isl_give isl_pw_aff *visitConstant(const llvm::SCEVConstant *E);
+  __isl_give isl_pw_aff *visitTruncateExpr(const llvm::SCEVTruncateExpr *E);
+  __isl_give isl_pw_aff *visitZeroExtendExpr(const llvm::SCEVZeroExtendExpr *E);
+  __isl_give isl_pw_aff *visitSignExtendExpr(const llvm::SCEVSignExtendExpr *E);
+  __isl_give isl_pw_aff *visitAddExpr(const llvm::SCEVAddExpr *E);
+  __isl_give isl_pw_aff *visitMulExpr(const llvm::SCEVMulExpr *E);
+  __isl_give isl_pw_aff *visitUDivExpr(const llvm::SCEVUDivExpr *E);
+  __isl_give isl_pw_aff *visitAddRecExpr(const llvm::SCEVAddRecExpr *E);
+  __isl_give isl_pw_aff *visitSMaxExpr(const llvm::SCEVSMaxExpr *E);
+  __isl_give isl_pw_aff *visitUMaxExpr(const llvm::SCEVUMaxExpr *E);
+  __isl_give isl_pw_aff *visitUnknown(const llvm::SCEVUnknown *E);
+  __isl_give isl_pw_aff *visitSDivInstruction(llvm::Instruction *SDiv);
+  __isl_give isl_pw_aff *visitSRemInstruction(llvm::Instruction *SRem);
+
+  friend struct llvm::SCEVVisitor<SCEVAffinator, isl_pw_aff *>;
+};
+}
+
+#endif

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=244730&r1=244729&r2=244730&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Wed Aug 12 05:19:50 2015
@@ -90,255 +90,6 @@ combineInSequence(__isl_take isl_schedul
   return isl_schedule_sequence(Prev, Succ);
 }
 
-/// Translate a 'const SCEV *' expression in an isl_pw_aff.
-struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff *> {
-public:
-  /// @brief Translate a 'const SCEV *' to an isl_pw_aff.
-  ///
-  /// @param Stmt The location at which the scalar evolution expression
-  ///             is evaluated.
-  /// @param Expr The expression that is translated.
-  static __isl_give isl_pw_aff *getPwAff(ScopStmt *Stmt, const SCEV *Expr);
-
-private:
-  isl_ctx *Ctx;
-  int NbLoopSpaces;
-  const Scop *S;
-
-  SCEVAffinator(const ScopStmt *Stmt);
-  int getLoopDepth(const Loop *L);
-
-  __isl_give isl_pw_aff *visit(const SCEV *Expr);
-  __isl_give isl_pw_aff *visitConstant(const SCEVConstant *Expr);
-  __isl_give isl_pw_aff *visitTruncateExpr(const SCEVTruncateExpr *Expr);
-  __isl_give isl_pw_aff *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr);
-  __isl_give isl_pw_aff *visitSignExtendExpr(const SCEVSignExtendExpr *Expr);
-  __isl_give isl_pw_aff *visitAddExpr(const SCEVAddExpr *Expr);
-  __isl_give isl_pw_aff *visitMulExpr(const SCEVMulExpr *Expr);
-  __isl_give isl_pw_aff *visitUDivExpr(const SCEVUDivExpr *Expr);
-  __isl_give isl_pw_aff *visitAddRecExpr(const SCEVAddRecExpr *Expr);
-  __isl_give isl_pw_aff *visitSMaxExpr(const SCEVSMaxExpr *Expr);
-  __isl_give isl_pw_aff *visitUMaxExpr(const SCEVUMaxExpr *Expr);
-  __isl_give isl_pw_aff *visitUnknown(const SCEVUnknown *Expr);
-  __isl_give isl_pw_aff *visitSDivInstruction(Instruction *SDiv);
-  __isl_give isl_pw_aff *visitSRemInstruction(Instruction *SDiv);
-
-  friend struct SCEVVisitor<SCEVAffinator, isl_pw_aff *>;
-};
-
-SCEVAffinator::SCEVAffinator(const ScopStmt *Stmt)
-    : Ctx(Stmt->getIslCtx()), NbLoopSpaces(Stmt->getNumIterators()),
-      S(Stmt->getParent()) {}
-
-__isl_give isl_pw_aff *SCEVAffinator::getPwAff(ScopStmt *Stmt,
-                                               const SCEV *Scev) {
-  Scop *S = Stmt->getParent();
-  const Region *Reg = &S->getRegion();
-
-  S->addParams(getParamsInAffineExpr(Reg, Scev, *S->getSE()));
-
-  SCEVAffinator Affinator(Stmt);
-  return Affinator.visit(Scev);
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) {
-  // In case the scev is a valid parameter, 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.
-  if (isl_id *Id = S->getIdForParam(Expr)) {
-    isl_space *Space = isl_space_set_alloc(Ctx, 1, NbLoopSpaces);
-    Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id);
-
-    isl_set *Domain = isl_set_universe(isl_space_copy(Space));
-    isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space));
-    Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
-
-    return isl_pw_aff_alloc(Domain, Affine);
-  }
-
-  return SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr);
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
-  ConstantInt *Value = Expr->getValue();
-  isl_val *v;
-
-  // 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.
-  v = isl_valFromAPInt(Ctx, Value->getValue(), /* isSigned */ true);
-
-  isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
-  isl_local_space *ls = isl_local_space_from_space(Space);
-  return isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v));
-}
-
-__isl_give isl_pw_aff *
-SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
-  llvm_unreachable("SCEVTruncateExpr not yet supported");
-}
-
-__isl_give isl_pw_aff *
-SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
-  llvm_unreachable("SCEVZeroExtendExpr not yet supported");
-}
-
-__isl_give isl_pw_aff *
-SCEVAffinator::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());
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::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 *SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) {
-  // Divide Expr into a constant part and the rest. Then visit both and multiply
-  // the result to obtain the representation for Expr. While the second part of
-  // ConstantAndLeftOverPair might still be a SCEVMulExpr we will not get to
-  // this point again. The reason is that if it is a multiplication it consists
-  // only of parameters and we will stop in the visit(const SCEV *) function and
-  // return the isl_pw_aff for that parameter.
-  auto ConstantAndLeftOverPair = extractConstantFactor(Expr, *S->getSE());
-  return isl_pw_aff_mul(visit(ConstantAndLeftOverPair.first),
-                        visit(ConstantAndLeftOverPair.second));
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
-  llvm_unreachable("SCEVUDivExpr not yet supported");
-}
-
-__isl_give isl_pw_aff *
-SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
-  assert(Expr->isAffine() && "Only affine AddRecurrences allowed");
-
-  auto Flags = Expr->getNoWrapFlags();
-
-  // Directly generate isl_pw_aff for Expr if 'start' is zero.
-  if (Expr->getStart()->isZero()) {
-    assert(S->getRegion().contains(Expr->getLoop()) &&
-           "Scop does not contain the loop referenced in this AddRec");
-
-    isl_pw_aff *Start = visit(Expr->getStart());
-    isl_pw_aff *Step = visit(Expr->getOperand(1));
-    isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
-    isl_local_space *LocalSpace = isl_local_space_from_space(Space);
-
-    int loopDimension = getLoopDepth(Expr->getLoop());
-
-    isl_aff *LAff = isl_aff_set_coefficient_si(
-        isl_aff_zero_on_domain(LocalSpace), isl_dim_in, 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));
-  }
-
-  // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
-  // if 'start' is not zero.
-  // TODO: Using the original SCEV no-wrap flags is not always safe, however
-  //       as our code generation is reordering the expression anyway it doesn't
-  //       really matter.
-  ScalarEvolution &SE = *S->getSE();
-  const SCEV *ZeroStartExpr =
-      SE.getAddRecExpr(SE.getConstant(Expr->getStart()->getType(), 0),
-                       Expr->getStepRecurrence(SE), Expr->getLoop(), Flags);
-
-  isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr);
-  isl_pw_aff *Start = visit(Expr->getStart());
-
-  return isl_pw_aff_add(ZeroStartResult, Start);
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::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 *SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) {
-  llvm_unreachable("SCEVUMaxExpr not yet supported");
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::visitSDivInstruction(Instruction *SDiv) {
-  assert(SDiv->getOpcode() == Instruction::SDiv && "Assumed SDiv instruction!");
-  auto *SE = S->getSE();
-
-  auto *Divisor = SDiv->getOperand(1);
-  auto *DivisorSCEV = SE->getSCEV(Divisor);
-  auto *DivisorPWA = visit(DivisorSCEV);
-  assert(isa<ConstantInt>(Divisor) &&
-         "SDiv is no parameter but has a non-constant RHS.");
-
-  auto *Dividend = SDiv->getOperand(0);
-  auto *DividendSCEV = SE->getSCEV(Dividend);
-  auto *DividendPWA = visit(DividendSCEV);
-  return isl_pw_aff_tdiv_q(DividendPWA, DivisorPWA);
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::visitSRemInstruction(Instruction *SRem) {
-  assert(SRem->getOpcode() == Instruction::SRem && "Assumed SRem instruction!");
-  auto *SE = S->getSE();
-
-  auto *Divisor = dyn_cast<ConstantInt>(SRem->getOperand(1));
-  assert(Divisor && "SRem is no parameter but has a non-constant RHS.");
-  auto *DivisorVal = isl_valFromAPInt(Ctx, Divisor->getValue(),
-                                      /* isSigned */ true);
-
-  auto *Dividend = SRem->getOperand(0);
-  auto *DividendSCEV = SE->getSCEV(Dividend);
-  auto *DividendPWA = visit(DividendSCEV);
-
-  return isl_pw_aff_mod_val(DividendPWA, isl_val_abs(DivisorVal));
-}
-
-__isl_give isl_pw_aff *SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
-  if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
-    switch (I->getOpcode()) {
-    case Instruction::SDiv:
-      return visitSDivInstruction(I);
-    case Instruction::SRem:
-      return visitSRemInstruction(I);
-    default:
-      break; // Fall through.
-    }
-  }
-
-  llvm_unreachable(
-      "Unknowns SCEV was neither parameter nor a valid instruction.");
-}
-
-int SCEVAffinator::getLoopDepth(const Loop *L) {
-  Loop *outerLoop = S->getRegion().outermostLoopInRegion(const_cast<Loop *>(L));
-  assert(outerLoop && "Scop does not contain this loop");
-  return L->getLoopDepth() - outerLoop->getLoopDepth();
-}
-
-/// @brief Add the bounds of @p Range to the set @p S for dimension @p dim.
 static __isl_give isl_set *addRangeBoundsToSet(__isl_take isl_set *S,
                                                const ConstantRange &Range,
                                                int dim,
@@ -560,7 +311,7 @@ void MemoryAccess::assumeNoOutOfBound(co
     isl_set *DimOutside;
 
     DimOutside = isl_pw_aff_lt_set(isl_pw_aff_copy(Var), Zero);
-    isl_pw_aff *SizeE = SCEVAffinator::getPwAff(Statement, Access.Sizes[i - 1]);
+    isl_pw_aff *SizeE = Statement->getPwAff(Access.Sizes[i - 1]);
 
     SizeE = isl_pw_aff_drop_dims(SizeE, isl_dim_in, 0,
                                  Statement->getNumIterators());
@@ -629,7 +380,7 @@ __isl_give isl_map *MemoryAccess::foldAc
   for (int i = Size - 2; i >= 0; --i) {
     isl_space *Space;
     isl_map *MapOne, *MapTwo;
-    isl_pw_aff *DimSize = SCEVAffinator::getPwAff(Statement, Access.Sizes[i]);
+    isl_pw_aff *DimSize = Statement->getPwAff(Access.Sizes[i]);
 
     isl_space *SpaceSize = isl_pw_aff_get_space(DimSize);
     isl_pw_aff_free(DimSize);
@@ -704,8 +455,7 @@ MemoryAccess::MemoryAccess(const IRAcces
   AccessRelation = isl_map_universe(Space);
 
   for (int i = 0, Size = Access.Subscripts.size(); i < Size; ++i) {
-    isl_pw_aff *Affine =
-        SCEVAffinator::getPwAff(Statement, Access.Subscripts[i]);
+    isl_pw_aff *Affine = Statement->getPwAff(Access.Subscripts[i]);
 
     if (Size == 1) {
       // For the non delinearized arrays, divide the access function of the last
@@ -887,6 +637,10 @@ isl_map *ScopStmt::getSchedule() const {
   return M;
 }
 
+__isl_give isl_pw_aff *ScopStmt::getPwAff(const SCEV *E) {
+  return getParent()->getPwAff(E, this);
+}
+
 void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) {
   assert(isl_set_is_subset(NewDomain, Domain) &&
          "New domain is not a subset of old domain!");
@@ -939,8 +693,8 @@ void ScopStmt::realignParams() {
 }
 
 __isl_give isl_set *ScopStmt::buildConditionSet(const Comparison &Comp) {
-  isl_pw_aff *L = SCEVAffinator::getPwAff(this, Comp.getLHS());
-  isl_pw_aff *R = SCEVAffinator::getPwAff(this, Comp.getRHS());
+  isl_pw_aff *L = getPwAff(Comp.getLHS());
+  isl_pw_aff *R = getPwAff(Comp.getRHS());
 
   switch (Comp.getPred()) {
   case ICmpInst::ICMP_EQ:
@@ -989,7 +743,7 @@ __isl_give isl_set *ScopStmt::addLoopBou
     // IV <= LatchExecutions.
     const Loop *L = getLoopForDimension(i);
     const SCEV *LatchExecutions = SE->getBackedgeTakenCount(L);
-    isl_pw_aff *UpperBound = SCEVAffinator::getPwAff(this, LatchExecutions);
+    isl_pw_aff *UpperBound = getPwAff(LatchExecutions);
     isl_set *UpperBoundSet = isl_pw_aff_le_set(IV, UpperBound);
     Domain = isl_set_intersect(Domain, UpperBoundSet);
   }
@@ -1059,7 +813,7 @@ void ScopStmt::deriveAssumptionsFromGEP(
     const SCEV *Expr = SE.getSCEV(GEP->getOperand(Operand));
 
     if (isAffineExpr(&Parent.getRegion(), Expr, SE)) {
-      isl_pw_aff *AccessOffset = SCEVAffinator::getPwAff(this, Expr);
+      isl_pw_aff *AccessOffset = getPwAff(Expr);
       AccessOffset =
           isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId());
 
@@ -1693,7 +1447,7 @@ static unsigned getMaxLoopDepthInRegion(
 Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, isl_ctx *Context,
            unsigned MaxLoopDepth)
     : SE(&ScalarEvolution), R(R), IsOptimized(false),
-      MaxLoopDepth(MaxLoopDepth), IslCtx(Context) {}
+      MaxLoopDepth(MaxLoopDepth), IslCtx(Context), Affinator(this) {}
 
 void Scop::initFromTempScop(TempScop &TempScop, LoopInfo &LI,
                             ScopDetection &SD) {
@@ -1891,6 +1645,10 @@ void Scop::dump() const { print(dbgs());
 
 isl_ctx *Scop::getIslCtx() const { return IslCtx; }
 
+__isl_give isl_pw_aff *Scop::getPwAff(const SCEV *E, ScopStmt *Stmt) {
+  return Affinator.getPwAff(E, Stmt);
+}
+
 __isl_give isl_union_set *Scop::getDomains() const {
   isl_union_set *Domain = isl_union_set_empty(getParamSpace());
 

Modified: polly/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CMakeLists.txt?rev=244730&r1=244729&r2=244730&view=diff
==============================================================================
--- polly/trunk/lib/CMakeLists.txt (original)
+++ polly/trunk/lib/CMakeLists.txt Wed Aug 12 05:19:50 2015
@@ -285,6 +285,7 @@ add_polly_library(Polly
   ${GPGPU_CODEGEN_FILES}
   Exchange/JSONExporter.cpp
   Support/GICHelper.cpp
+  Support/SCEVAffinator.cpp
   Support/SCEVValidator.cpp
   Support/RegisterPasses.cpp
   Support/ScopHelper.cpp

Modified: polly/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Makefile?rev=244730&r1=244729&r2=244730&view=diff
==============================================================================
--- polly/trunk/lib/Makefile (original)
+++ polly/trunk/lib/Makefile Wed Aug 12 05:19:50 2015
@@ -111,6 +111,7 @@ ISL_FILES= External/isl/basis_reduction_
 SOURCES= Polly.cpp \
          Support/GICHelper.cpp \
          Support/SCEVValidator.cpp \
+         Support/SCEVAffinator.cpp \
          Support/RegisterPasses.cpp \
          Support/ScopHelper.cpp \
          Support/ScopLocation.cpp \

Added: polly/trunk/lib/Support/SCEVAffinator.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/SCEVAffinator.cpp?rev=244730&view=auto
==============================================================================
--- polly/trunk/lib/Support/SCEVAffinator.cpp (added)
+++ polly/trunk/lib/Support/SCEVAffinator.cpp Wed Aug 12 05:19:50 2015
@@ -0,0 +1,236 @@
+//===--------- SCEVAffinator.cpp  - Create Scops from LLVM IR -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Create a polyhedral description for a SCEV value.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/Support/SCEVAffinator.h"
+
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+#include "polly/Support/ScopHelper.h"
+#include "polly/Support/SCEVValidator.h"
+
+#include "isl/aff.h"
+#include "isl/set.h"
+#include "isl/val.h"
+#include "isl/local_space.h"
+
+using namespace llvm;
+using namespace polly;
+
+SCEVAffinator::SCEVAffinator(Scop *S)
+    : S(S), Ctx(S->getIslCtx()), R(S->getRegion()), SE(*S->getSE()) {}
+
+__isl_give isl_pw_aff *SCEVAffinator::getPwAff(const SCEV *Expr,
+                                               const ScopStmt *Stmt) {
+  NumIterators = Stmt->getNumIterators();
+
+  S->addParams(getParamsInAffineExpr(&R, Expr, SE));
+
+  return visit(Expr);
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) {
+  // In case the scev is a valid parameter, 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.
+  if (isl_id *Id = S->getIdForParam(Expr)) {
+    isl_space *Space = isl_space_set_alloc(Ctx, 1, NumIterators);
+    Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id);
+
+    isl_set *Domain = isl_set_universe(isl_space_copy(Space));
+    isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space));
+    Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
+
+    return isl_pw_aff_alloc(Domain, Affine);
+  }
+
+  return SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr);
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
+  ConstantInt *Value = Expr->getValue();
+  isl_val *v;
+
+  // 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.
+  v = isl_valFromAPInt(Ctx, Value->getValue(), /* isSigned */ true);
+
+  isl_space *Space = isl_space_set_alloc(Ctx, 0, NumIterators);
+  isl_local_space *ls = isl_local_space_from_space(Space);
+  return isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v));
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
+  llvm_unreachable("SCEVTruncateExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
+  llvm_unreachable("SCEVZeroExtendExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::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());
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::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 *SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) {
+  // Divide Expr into a constant part and the rest. Then visit both and multiply
+  // the result to obtain the representation for Expr. While the second part of
+  // ConstantAndLeftOverPair might still be a SCEVMulExpr we will not get to
+  // this point again. The reason is that if it is a multiplication it consists
+  // only of parameters and we will stop in the visit(const SCEV *) function and
+  // return the isl_pw_aff for that parameter.
+  auto ConstantAndLeftOverPair = extractConstantFactor(Expr, *S->getSE());
+  return isl_pw_aff_mul(visit(ConstantAndLeftOverPair.first),
+                        visit(ConstantAndLeftOverPair.second));
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
+  llvm_unreachable("SCEVUDivExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+  assert(Expr->isAffine() && "Only affine AddRecurrences allowed");
+
+  auto Flags = Expr->getNoWrapFlags();
+
+  // Directly generate isl_pw_aff for Expr if 'start' is zero.
+  if (Expr->getStart()->isZero()) {
+    assert(S->getRegion().contains(Expr->getLoop()) &&
+           "Scop does not contain the loop referenced in this AddRec");
+
+    isl_pw_aff *Start = visit(Expr->getStart());
+    isl_pw_aff *Step = visit(Expr->getOperand(1));
+    isl_space *Space = isl_space_set_alloc(Ctx, 0, NumIterators);
+    isl_local_space *LocalSpace = isl_local_space_from_space(Space);
+
+    int loopDimension = getLoopDepth(Expr->getLoop());
+
+    isl_aff *LAff = isl_aff_set_coefficient_si(
+        isl_aff_zero_on_domain(LocalSpace), isl_dim_in, 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));
+  }
+
+  // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
+  // if 'start' is not zero.
+  // TODO: Using the original SCEV no-wrap flags is not always safe, however
+  //       as our code generation is reordering the expression anyway it doesn't
+  //       really matter.
+  ScalarEvolution &SE = *S->getSE();
+  const SCEV *ZeroStartExpr =
+      SE.getAddRecExpr(SE.getConstant(Expr->getStart()->getType(), 0),
+                       Expr->getStepRecurrence(SE), Expr->getLoop(), Flags);
+
+  isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr);
+  isl_pw_aff *Start = visit(Expr->getStart());
+
+  return isl_pw_aff_add(ZeroStartResult, Start);
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::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 *SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) {
+  llvm_unreachable("SCEVUMaxExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitSDivInstruction(Instruction *SDiv) {
+  assert(SDiv->getOpcode() == Instruction::SDiv && "Assumed SDiv instruction!");
+  auto *SE = S->getSE();
+
+  auto *Divisor = SDiv->getOperand(1);
+  auto *DivisorSCEV = SE->getSCEV(Divisor);
+  auto *DivisorPWA = visit(DivisorSCEV);
+  assert(isa<ConstantInt>(Divisor) &&
+         "SDiv is no parameter but has a non-constant RHS.");
+
+  auto *Dividend = SDiv->getOperand(0);
+  auto *DividendSCEV = SE->getSCEV(Dividend);
+  auto *DividendPWA = visit(DividendSCEV);
+  return isl_pw_aff_tdiv_q(DividendPWA, DivisorPWA);
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitSRemInstruction(Instruction *SRem) {
+  assert(SRem->getOpcode() == Instruction::SRem && "Assumed SRem instruction!");
+  auto *SE = S->getSE();
+
+  auto *Divisor = dyn_cast<ConstantInt>(SRem->getOperand(1));
+  assert(Divisor && "SRem is no parameter but has a non-constant RHS.");
+  auto *DivisorVal = isl_valFromAPInt(Ctx, Divisor->getValue(),
+                                      /* isSigned */ true);
+
+  auto *Dividend = SRem->getOperand(0);
+  auto *DividendSCEV = SE->getSCEV(Dividend);
+  auto *DividendPWA = visit(DividendSCEV);
+
+  return isl_pw_aff_mod_val(DividendPWA, isl_val_abs(DivisorVal));
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
+  if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
+    switch (I->getOpcode()) {
+    case Instruction::SDiv:
+      return visitSDivInstruction(I);
+    case Instruction::SRem:
+      return visitSRemInstruction(I);
+    default:
+      break; // Fall through.
+    }
+  }
+
+  llvm_unreachable(
+      "Unknowns SCEV was neither parameter nor a valid instruction.");
+}
+
+int SCEVAffinator::getLoopDepth(const Loop *L) {
+  Loop *outerLoop = S->getRegion().outermostLoopInRegion(const_cast<Loop *>(L));
+  assert(outerLoop && "Scop does not contain this loop");
+  return L->getLoopDepth() - outerLoop->getLoopDepth();
+}




More information about the llvm-commits mailing list