[llvm-commits] [LLVMdev] [polly] scev codegen (first step to remove the dependence on ivcanon pass)

Sebastian Pop spop at codeaurora.org
Thu Dec 13 12:32:17 PST 2012


Ping.

Thanks,
Sebastian

Sebastian Pop wrote:
> Hi Tobi,
> 
> here is the first part of removing the ivcanon pass: the two patches for llvm
> are implementing the scev apply function and the parameter rewriter (based on
> your previous code SCEVRewriter).  On the Polly side the two patches are first
> collecting the LoopToScev map and using the apply function and the parameter
> rewriter.
> 
> Ok to commit?
> 
> Thanks,
> Sebastian
> 
> Sebastian Pop wrote:
> > Hi Tobi,
> > 
> > I would like to remove the SCEVRewriter code and replace it with a call to
> > SCEVAddRec::apply (see attached a patch that adds just this function).  More
> > precisely I want to add another function called apply_map that applies a map
> > (loop -> expr) on a given scev.  This is the apply function on a multi-variate
> > polynomial.
> > 
> > So here is an overview of how I would like the scev code generator to work on an
> > example: supposing that we have a Stmt_1 that gets code generated by either
> > CLooG or ISL-codegen like this:
> > 
> >   Stmt_1(c1, c1+4, c1+c2);
> > 
> > we will construct a map that maps the old iteration domain with 3 dimensions
> > (there are 3 arguments in Stmt_1 representing the original loop nest in which
> > Stmt_1 was located, let's call the original loop nest loop_1, loop_2, loop_3) to
> > the new expressions generated by cloog that are function of the new iteration
> > domain with 2 dimensions (c1 and c2 are the new induction variables of the code
> > generated by cloog).  So the content of that map is:
> > 
> > loop_1 -> c1
> > loop_2 -> c1+7
> > loop_3 -> c1+c2
> > 
> > Given an access function from the original program: 
> >   Scev_1 = {{{0, +, 4}_1, +, 5}_2, +, 6}_3
> > 
> > we will apply the map on it, and we will get a symbolic expression function of
> > the new induction variables c1, and c2:
> > 
> > Scev_2 = apply (loop_1 -> c1)    on Scev_1 = {{4*c1, +, 5}_2, +, 6}_3
> > Scev_3 = apply (loop_2 -> c1+7)  on Scev_2 = {4*c1 + 5*(c1+7), +, 6}_3
> > Scev_4 = apply (loop_3 -> c1+c2) on Scev_3 = 4*c1 + 5*(c1+7) + 6*(c1+c2)
> > 
> > We will then code generate Scev_4 and we will use this new expression for the
> > array access in the new loop nest.
> > 
> > Remark that in all this process we have never referred to the original
> > "canonical induction variable".  SCEV actually provides such a canonical form
> > for the induction variables without having to transform the code.
> > 
> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

> From 328c0cd4c246768b73dff1f8f5a3c9a089b5fa64 Mon Sep 17 00:00:00 2001
> From: Sebastian Pop <spop at codeaurora.org>
> Date: Fri, 7 Dec 2012 09:37:17 -0600
> Subject: [PATCH 1/2] add SCEVParameterRewriter
> 
> ---
>  include/llvm/Analysis/ScalarEvolutionExpressions.h |  104 ++++++++++++++++++++
>  1 file changed, 104 insertions(+)
> 
> diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
> index b74cb33..48babff 100644
> --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
> +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h
> @@ -548,6 +548,110 @@ namespace llvm {
>      SCEVTraversal<SV> T(Visitor);
>      T.visitAll(Root);
>    }
> +
> +  /// The ScevRewriter takes a scalar evolution expression and copies all its
> +  /// components. The result after a rewrite is an identical SCEV.
> +  struct ScevRewriter
> +    : public SCEVVisitor<ScevRewriter, const SCEV*> {
> +  public:
> +    ScevRewriter(ScalarEvolution &S) : SE(S) {}
> +
> +    virtual const SCEV *visitConstant(const SCEVConstant *Constant) {
> +      return Constant;
> +    }
> +
> +    virtual const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
> +      const SCEV *Operand = visit(Expr->getOperand());
> +      return SE.getTruncateExpr(Operand, Expr->getType());
> +    }
> +
> +    virtual const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
> +      const SCEV *Operand = visit(Expr->getOperand());
> +      return SE.getZeroExtendExpr(Operand, Expr->getType());
> +    }
> +
> +    virtual const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
> +      const SCEV *Operand = visit(Expr->getOperand());
> +      return SE.getSignExtendExpr(Operand, Expr->getType());
> +    }
> +
> +    virtual const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
> +      SmallVector<const SCEV *, 2> Operands;
> +      for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
> +        Operands.push_back(visit(Expr->getOperand(i)));
> +      return SE.getAddExpr(Operands);
> +    }
> +
> +    virtual const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
> +      SmallVector<const SCEV *, 2> Operands;
> +      for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
> +        Operands.push_back(visit(Expr->getOperand(i)));
> +      return SE.getMulExpr(Operands);
> +    }
> +
> +    virtual const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) {
> +      return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS()));
> +    }
> +
> +    virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
> +      SmallVector<const SCEV *, 2> Operands;
> +      for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
> +        Operands.push_back(visit(Expr->getOperand(i)));
> +      return SE.getAddRecExpr(Operands, Expr->getLoop(),
> +                              Expr->getNoWrapFlags());
> +    }
> +
> +    virtual const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) {
> +      SmallVector<const SCEV *, 2> Operands;
> +      for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
> +        Operands.push_back(visit(Expr->getOperand(i)));
> +      return SE.getSMaxExpr(Operands);
> +    }
> +
> +    virtual const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) {
> +      SmallVector<const SCEV *, 2> Operands;
> +      for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
> +        Operands.push_back(visit(Expr->getOperand(i)));
> +      return SE.getUMaxExpr(Operands);
> +    }
> +
> +    virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) {
> +      return Expr;
> +    }
> +
> +    virtual const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) {
> +      return Expr;
> +    }
> +
> +  protected:
> +    ScalarEvolution &SE;
> +  };
> +
> +  typedef DenseMap<const Value*, Value*> ValueToValueMap;
> +
> +  /// The ScevParameterRewriter takes a scalar evolution expression and updates
> +  /// the SCEVUnknown components following the Map (Value -> Value).
> +  struct ScevParameterRewriter: public ScevRewriter {
> +  public:
> +    static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE,
> +                               ValueToValueMap &Map) {
> +      ScevParameterRewriter Rewriter(SE, Map);
> +      return Rewriter.visit(Scev);
> +    }
> +    ScevParameterRewriter(ScalarEvolution &S, ValueToValueMap &M)
> +      : ScevRewriter(S), Map(M) {}
> +
> +    virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) {
> +      Value *V = Expr->getValue();
> +      if (Map.count(V))
> +        return SE.getUnknown(Map[V]);
> +      return Expr;
> +    }
> +
> +  private:
> +    ValueToValueMap ⤅
> +  };
> +
>  }
>  
>  #endif
> -- 
> 1.7.9.5
> 

> From 455451da4f213a9a6f9f12565331a7a1d86ee5e5 Mon Sep 17 00:00:00 2001
> From: Sebastian Pop <spop at codeaurora.org>
> Date: Sat, 8 Dec 2012 10:16:49 -0600
> Subject: [PATCH 2/2] add ScevApplyRewriter
> 
> ---
>  include/llvm/Analysis/ScalarEvolutionExpressions.h |   39 ++++++++++++++++++++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
> index 48babff..f9ed59e 100644
> --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
> +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h
> @@ -652,6 +652,45 @@ namespace llvm {
>      ValueToValueMap ⤅
>    };
>  
> +  typedef DenseMap<const Loop*, const SCEV*> LoopToScevMapT;
> +
> +  /// The ScevApplyRewriter takes a scalar evolution expression and applies
> +  /// the Map (Loop -> SCEV) to all AddRecExprs.
> +  struct ScevApplyRewriter: public ScevRewriter {
> +  public:
> +    static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map,
> +                               ScalarEvolution &SE) {
> +      ScevApplyRewriter Rewriter(SE, Map);
> +      return Rewriter.visit(Scev);
> +    }
> +    ScevApplyRewriter(ScalarEvolution &S, LoopToScevMapT &M)
> +      : ScevRewriter(S), Map(M) {}
> +
> +    virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
> +      SmallVector<const SCEV *, 2> Operands;
> +      for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
> +        Operands.push_back(visit(Expr->getOperand(i)));
> +
> +      const Loop *L = Expr->getLoop();
> +      const SCEV *Res = SE.getAddRecExpr(Operands, L, Expr->getNoWrapFlags());
> +
> +      if (0 == Map.count(L))
> +        return Res;
> +
> +      const SCEVAddRecExpr *Rec = (const SCEVAddRecExpr *) Res;
> +      return Rec->evaluateAtIteration(Map[L], SE);
> +    }
> +
> +  private:
> +    LoopToScevMapT ⤅
> +  };
> +
> +/// Applies the Map (Loop -> SCEV) to the given Scev.
> +static inline const SCEV *apply(const SCEV *Scev, LoopToScevMapT &Map,
> +                                ScalarEvolution &SE) {
> +  return ScevApplyRewriter::rewrite(Scev, Map, SE);
> +}
> +
>  }
>  
>  #endif
> -- 
> 1.7.9.5
> 

> From de79e54850b9c8433a0b28e32f51fd305737e87f Mon Sep 17 00:00:00 2001
> From: Sebastian Pop <spop at codeaurora.org>
> Date: Mon, 3 Dec 2012 11:54:43 -0600
> Subject: [PATCH 1/2] add LoopToScev maps
> 
> ---
>  include/polly/CodeGen/BlockGenerators.h |   19 +++++++++++++------
>  lib/CodeGen/BlockGenerators.cpp         |   20 ++++++++++++--------
>  lib/CodeGen/CodeGeneration.cpp          |   20 ++++++++++++++++++--
>  lib/CodeGen/IslCodeGeneration.cpp       |   23 +++++++++++++++++++----
>  4 files changed, 62 insertions(+), 20 deletions(-)
> 
> diff --git a/include/polly/CodeGen/BlockGenerators.h b/include/polly/CodeGen/BlockGenerators.h
> index ed5ff3c..aad4a89 100644
> --- a/include/polly/CodeGen/BlockGenerators.h
> +++ b/include/polly/CodeGen/BlockGenerators.h
> @@ -18,6 +18,7 @@
>  
>  #include "llvm/IRBuilder.h"
>  #include "llvm/ADT/DenseMap.h"
> +#include "llvm/Analysis/ScalarEvolutionExpressions.h"
>  
>  #include "isl/map.h"
>  
> @@ -47,11 +48,14 @@ public:
>    /// @param Stmt      The statement to code generate.
>    /// @param GlobalMap A map that defines for certain Values referenced from the
>    ///                  original code new Values they should be replaced with.
> +  /// @param LoopToScev Map the loops from the old code to expressions function
> +  ///                  of the induction variables in the new code.
>    /// @param P         A reference to the pass this function is called from.
>    ///                  The pass is needed to update other analysis.
>    static void generate(IRBuilder<> &Builder, ScopStmt &Stmt,
> -                       ValueMapT &GlobalMap, Pass *P) {
> -    BlockGenerator Generator(Builder, Stmt, P);
> +                       ValueMapT &GlobalMap, LoopToScevMapT &LoopToScev,
> +                       Pass *P) {
> +    BlockGenerator Generator(Builder, Stmt, P, LoopToScev);
>      Generator.copyBB(GlobalMap);
>    }
>  
> @@ -60,8 +64,10 @@ protected:
>    ScopStmt &Statement;
>    Pass *P;
>    ScalarEvolution &SE;
> +  LoopToScevMapT &LoopToScev;
>  
> -  BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P);
> +  BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P,
> +                 LoopToScevMapT &LoopToScev);
>  
>    /// @brief Check if an instruction can be 'SCEV-ignored'
>    ///
> @@ -156,8 +162,8 @@ public:
>    ///                   The pass is needed to update other analysis.
>    static void generate(IRBuilder<> &B, ScopStmt &Stmt,
>                         VectorValueMapT &GlobalMaps, __isl_keep isl_set *Domain,
> -                       Pass *P) {
> -    VectorBlockGenerator Generator(B, GlobalMaps, Stmt, Domain, P);
> +                       Pass *P, LoopToScevMapT &LTS) {
> +    VectorBlockGenerator Generator(B, GlobalMaps, Stmt, Domain, P, LTS);
>      Generator.copyBB();
>    }
>  
> @@ -172,7 +178,8 @@ private:
>    isl_set *Domain;
>  
>    VectorBlockGenerator(IRBuilder<> &B, VectorValueMapT &GlobalMaps,
> -                       ScopStmt &Stmt, __isl_keep isl_set *Domain, Pass *P);
> +                       ScopStmt &Stmt, __isl_keep isl_set *Domain, Pass *P,
> +                       LoopToScevMapT &LTS);
>  
>    int getVectorWidth();
>  
> diff --git a/lib/CodeGen/BlockGenerators.cpp b/lib/CodeGen/BlockGenerators.cpp
> index e8109bd..9964a3c 100644
> --- a/lib/CodeGen/BlockGenerators.cpp
> +++ b/lib/CodeGen/BlockGenerators.cpp
> @@ -342,8 +342,10 @@ Value *IslGenerator::generateIslPwAff(__isl_take isl_pw_aff *PwAff) {
>  }
>  
>  
> -BlockGenerator::BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P):
> -  Builder(B), Statement(Stmt), P(P), SE(P->getAnalysis<ScalarEvolution>()) {}
> +BlockGenerator::BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P,
> +                               LoopToScevMapT &LTS):
> +  Builder(B), Statement(Stmt), P(P), SE(P->getAnalysis<ScalarEvolution>()),
> +  LoopToScev(LTS) {}
>  
>  bool BlockGenerator::isSCEVIgnore(const Instruction *Inst) {
>    if (SCEVCodegen && SE.isSCEVable(Inst->getType()))
> @@ -562,12 +564,14 @@ void BlockGenerator::copyBB(ValueMapT &GlobalMap) {
>  }
>  
>  VectorBlockGenerator::VectorBlockGenerator(IRBuilder<> &B,
> -  VectorValueMapT &GlobalMaps, ScopStmt &Stmt, __isl_keep isl_set *Domain,
> -  Pass *P) : BlockGenerator(B, Stmt, P), GlobalMaps(GlobalMaps),
> -  Domain(Domain) {
> -    assert(GlobalMaps.size() > 1 && "Only one vector lane found");
> -    assert(Domain && "No statement domain provided");
> -  }
> +                                           VectorValueMapT &GlobalMaps,
> +                                           ScopStmt &Stmt,
> +                                           __isl_keep isl_set *Domain,
> +                                           Pass *P, LoopToScevMapT &LTS)
> +  : BlockGenerator(B, Stmt, P, LTS), GlobalMaps(GlobalMaps), Domain(Domain) {
> +  assert(GlobalMaps.size() > 1 && "Only one vector lane found");
> +  assert(Domain && "No statement domain provided");
> +}
>  
>  Value *VectorBlockGenerator::getVectorValue(const Value *Old,
>                                              ValueMapT &VectorMap,
> diff --git a/lib/CodeGen/CodeGeneration.cpp b/lib/CodeGen/CodeGeneration.cpp
> index 064c828..ff1b429 100644
> --- a/lib/CodeGen/CodeGeneration.cpp
> +++ b/lib/CodeGen/CodeGeneration.cpp
> @@ -234,6 +234,20 @@ private:
>    // Map the Values from the old code to their counterparts in the new code.
>    ValueMapT ValueMap;
>  
> +  // Map the loops from the old code to expressions function of the induction
> +  // variables in the new code.  For example, when the code generator produces
> +  // this AST:
> +  //
> +  //   for (int c1 = 0; c1 <= 1023; c1 += 1)
> +  //     for (int c2 = 0; c2 <= 1023; c2 += 1)
> +  //       Stmt(c2 + 3, c1);
> +  //
> +  // the loop corresponding to the outer dimension in the old loop nest is
> +  // associated to the expression obtained by code generating "c2 + 3" and the
> +  // loop for the inner dimension of the original loop nest is associated to the
> +  // new code generated for expression "c1".
> +  LoopToScevMapT LoopToScev;
> +
>    // clastVars maps from the textual representation of a clast variable to its
>    // current *Value. clast variables are scheduling variables, original
>    // induction variables or parameters. They are used either in loop bounds or
> @@ -377,6 +391,7 @@ void ClastStmtCodeGen::codegen(const clast_assignment *A, ScopStmt *Stmt,
>      (*VectorVMap)[VectorDim][PN] = RHS;
>  
>    ValueMap[PN] = RHS;
> +  LoopToScev[Stmt->getLoopForDimension(Dim)] = S->getSE()->getUnknown(RHS);
>  }
>  
>  void ClastStmtCodeGen::codegenSubstitutions(const clast_stmt *Assignment,
> @@ -405,7 +420,7 @@ void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
>    int VectorDimensions = IVS ? IVS->size() : 1;
>  
>    if (VectorDimensions == 1) {
> -    BlockGenerator::generate(Builder, *Statement, ValueMap, P);
> +    BlockGenerator::generate(Builder, *Statement, ValueMap, LoopToScev, P);
>      return;
>    }
>  
> @@ -422,7 +437,8 @@ void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
>      }
>    }
>  
> -  VectorBlockGenerator::generate(Builder, *Statement, VectorMap, Domain, P);
> +  VectorBlockGenerator::generate(Builder, *Statement, VectorMap, Domain, P,
> +                                 LoopToScev);
>  }
>  
>  void ClastStmtCodeGen::codegen(const clast_block *b) {
> diff --git a/lib/CodeGen/IslCodeGeneration.cpp b/lib/CodeGen/IslCodeGeneration.cpp
> index 9bfdd1d..509ae19 100644
> --- a/lib/CodeGen/IslCodeGeneration.cpp
> +++ b/lib/CodeGen/IslCodeGeneration.cpp
> @@ -541,8 +541,8 @@ Value *IslExprBuilder::create(__isl_take isl_ast_expr *Expr) {
>  
>  class IslNodeBuilder {
>  public:
> -  IslNodeBuilder(IRBuilder<> &Builder, Pass *P):
> -    Builder(Builder), ExprBuilder(Builder, IDToValue, P), P(P) {}
> +  IslNodeBuilder(IRBuilder<> &Builder, Pass *P, LoopToScevMapT &LTS):
> +    Builder(Builder), ExprBuilder(Builder, IDToValue, P), P(P), LoopToScev(LTS) {}
>  
>    void addParameters(__isl_take isl_set *Context);
>    void create(__isl_take isl_ast_node *Node);
> @@ -557,6 +557,20 @@ private:
>    // ivs.
>    std::map<isl_id *, Value*> IDToValue;
>  
> +  // Map the loops from the old code to expressions function of the induction
> +  // variables in the new code.  For example, when the code generator produces
> +  // this AST:
> +  //
> +  //   for (int c1 = 0; c1 <= 1023; c1 += 1)
> +  //     for (int c2 = 0; c2 <= 1023; c2 += 1)
> +  //       Stmt(c2 + 3, c1);
> +  //
> +  // the loop corresponding to the outer dimension in the old loop nest is
> +  // associated to the expression obtained by code generating "c2 + 3" and the
> +  // loop for the inner dimension of the original loop nest is associated to the
> +  // new code generated for expression "c1".
> +  LoopToScevMapT LoopToScev;
> +
>    // Extract the upper bound of this loop
>    //
>    // The isl code generation can generate arbitrary expressions to check if the
> @@ -768,7 +782,7 @@ void IslNodeBuilder::createUser(__isl_take isl_ast_node *User) {
>      VMap[OldIV] = V;
>    }
>  
> -  BlockGenerator::generate(Builder, *Stmt, VMap, P);
> +  BlockGenerator::generate(Builder, *Stmt, VMap, LoopToScev, P);
>  
>    isl_ast_node_free(User);
>    isl_id_free(Annotation);
> @@ -843,7 +857,8 @@ class IslCodeGeneration : public ScopPass {
>      isl_ast_node *Ast = AstInfo.getAst();
>      IRBuilder<> Builder(StartBlock->begin());
>  
> -    IslNodeBuilder NodeBuilder(Builder, this);
> +    LoopToScevMapT LTS;
> +    IslNodeBuilder NodeBuilder(Builder, this, LTS);
>      NodeBuilder.addParameters(S.getContext());
>      NodeBuilder.create(Ast);
>      return true;
> -- 
> 1.7.9.5
> 

> From 968c590024c4b1526e982ba2a6099d7b0c9ea3dc Mon Sep 17 00:00:00 2001
> From: Sebastian Pop <spop at codeaurora.org>
> Date: Mon, 10 Dec 2012 13:33:51 -0600
> Subject: [PATCH 2/2] use apply and ScevParameterRewriter::rewrite instead of
>  SCEVRewriter
> 
> ---
>  lib/CodeGen/BlockGenerators.cpp             |  205 +--------------------------
>  test/Cloog/CodeGen/simple_vec_call_2.ll     |    2 +-
>  test/Cloog/CodeGen/simple_vec_ptr_ptr_ty.ll |    2 +-
>  3 files changed, 6 insertions(+), 203 deletions(-)
> 
> diff --git a/lib/CodeGen/BlockGenerators.cpp b/lib/CodeGen/BlockGenerators.cpp
> index 9964a3c..a0cc229 100644
> --- a/lib/CodeGen/BlockGenerators.cpp
> +++ b/lib/CodeGen/BlockGenerators.cpp
> @@ -41,204 +41,6 @@ SCEVCodegen("polly-codegen-scev",
>              cl::desc("Use SCEV based code generation."), cl::Hidden,
>              cl::init(false), cl::ZeroOrMore);
>  
> -/// The SCEVRewriter takes a scalar evolution expression and updates the
> -/// following components:
> -///
> -/// - SCEVUnknown
> -///
> -///   Values referenced in SCEVUnknown subexpressions are looked up in
> -///   two Value to Value maps (GlobalMap and BBMap). If they are found they are
> -///   replaced by a reference to the value they map to.
> -///
> -/// - SCEVAddRecExpr
> -///
> -///   Based on a Loop -> Value map {Loop_1: %Value}, an expression
> -///   {%Base, +, %Step}<Loop_1> is rewritten to %Base + %Value * %Step.
> -///   AddRecExpr's with more than two operands can not be translated.
> -///
> -///   FIXME: The comment above is not yet reality. At the moment we derive
> -///   %Value by looking up the canonical IV of the loop and by defining
> -///   %Value = GlobalMap[%IV]. This needs to be changed to remove the need for
> -///   canonical induction variables.
> -///
> -///
> -/// How can this be used?
> -/// ====================
> -///
> -/// SCEVRewrite based code generation works on virtually independent blocks.
> -/// This means we do not run the independent blocks pass to rewrite scalar
> -/// instructions, but just ignore instructions that we can analyze with scalar
> -/// evolution. Virtually independent blocks are blocks that only reference the
> -/// following values:
> -///
> -/// o Values calculated within a basic block
> -/// o Values representable by SCEV
> -///
> -/// During code generation we can ignore all instructions:
> -///
> -/// - Ignore all instructions except:
> -///   - Load instructions
> -///   - Instructions that reference operands already calculated within the
> -///     basic block.
> -///   - Store instructions
> -struct SCEVRewriter : public SCEVVisitor<SCEVRewriter, const SCEV*> {
> -public:
> -  static const SCEV *rewrite(const SCEV *scev, Scop &S, ScalarEvolution &SE,
> -                             ValueMapT &GlobalMap,  ValueMapT &BBMap) {
> -    SCEVRewriter Rewriter(S, SE, GlobalMap, BBMap);
> -    return Rewriter.visit(scev);
> -  }
> -
> -  SCEVRewriter(Scop &S, ScalarEvolution &SE, ValueMapT &GlobalMap,
> -               ValueMapT &BBMap) : S(S), SE(SE), GlobalMap(GlobalMap),
> -               BBMap(BBMap) {}
> -
> -  const SCEV *visit(const SCEV *Expr) {
> -    // FIXME: The parameter handling is incorrect.
> -    //
> -    // Polly does only detect parameters in Access function and loop iteration
> -    // counters, but it does not get parameters that are just used by
> -    // instructions within the basic block.
> -    //
> -    // There are two options to solve this:
> -    //  o Iterate over all instructions of the SCoP and find the actual
> -    //    parameters.
> -    //  o Just check within the SCEVRewriter if Values lay outside of the SCoP
> -    //    and detect parameters on the fly.
> -    //
> -    // This is especially important for OpenMP and GPGPU code generation, as
> -    // they require us to detect and possibly rewrite the corresponding
> -    // parameters.
> -    if (isl_id *Id = S.getIdForParam(Expr)) {
> -      isl_id_free(Id);
> -      return Expr;
> -    }
> -
> -
> -    return SCEVVisitor<SCEVRewriter, const SCEV*>::visit(Expr);
> -  }
> -
> -  const SCEV *visitConstant(const SCEVConstant *Constant) {
> -    return Constant;
> -  }
> -
> -  const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
> -    const SCEV *Operand = visit(Expr->getOperand());
> -    return SE.getTruncateExpr(Operand, Expr->getType());
> -  }
> -
> -  const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
> -    const SCEV *Operand = visit(Expr->getOperand());
> -    return SE.getZeroExtendExpr(Operand, Expr->getType());
> -  }
> -
> -  const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
> -    const SCEV *Operand = visit(Expr->getOperand());
> -    return SE.getSignExtendExpr(Operand, Expr->getType());
> -  }
> -
> -  const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
> -    SmallVector<const SCEV *, 2> Operands;
> -    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
> -      const SCEV *Operand = visit(Expr->getOperand(i));
> -      Operands.push_back(Operand);
> -    }
> -
> -    return SE.getAddExpr(Operands);
> -  }
> -
> -  const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
> -    SmallVector<const SCEV *, 2> Operands;
> -    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
> -      const SCEV *Operand = visit(Expr->getOperand(i));
> -      Operands.push_back(Operand);
> -    }
> -
> -    return SE.getMulExpr(Operands);
> -  }
> -
> -  const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) {
> -    return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS()));
> -  }
> -
> -  // Return a new induction variable if the loop is within the original SCoP
> -  // or NULL otherwise.
> -  Value *getNewIV(const Loop *L) {
> -    Value *IV = L->getCanonicalInductionVariable();
> -    if (!IV)
> -      return NULL;
> -
> -    ValueMapT::iterator NewIV = GlobalMap.find(IV);
> -
> -    if (NewIV == GlobalMap.end())
> -      return NULL;
> -
> -    return NewIV->second;
> -  }
> -
> -  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
> -    Value *IV;
> -
> -    IV = getNewIV(Expr->getLoop());
> -
> -    // The IV is not within the GlobalMaps. So do not rewrite it and also do
> -    // not rewrite any descendants.
> -    if (!IV)
> -      return Expr;
> -
> -    assert(Expr->getNumOperands() == 2
> -          && "An AddRecExpr with more than two operands can not be rewritten.");
> -
> -    const SCEV *Base, *Step, *IVExpr, *Product;
> -
> -    Base = visit(Expr->getStart());
> -    Step = visit(Expr->getOperand(1));
> -    IVExpr = SE.getUnknown(IV);
> -    IVExpr = SE.getTruncateOrSignExtend(IVExpr, Step->getType());
> -    Product = SE.getMulExpr(Step, IVExpr);
> -
> -    return SE.getAddExpr(Base, Product);
> -  }
> -
> -  const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) {
> -    SmallVector<const SCEV *, 2> Operands;
> -    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
> -      const SCEV *Operand = visit(Expr->getOperand(i));
> -      Operands.push_back(Operand);
> -    }
> -
> -    return SE.getSMaxExpr(Operands);
> -  }
> -
> -  const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) {
> -    SmallVector<const SCEV *, 2> Operands;
> -    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
> -      const SCEV *Operand = visit(Expr->getOperand(i));
> -      Operands.push_back(Operand);
> -    }
> -
> -    return SE.getUMaxExpr(Operands);
> -  }
> -
> -  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
> -    Value *V = Expr->getValue();
> -
> -    if (GlobalMap.count(V))
> -      return SE.getUnknown(GlobalMap[V]);
> -
> -    if (BBMap.count(V))
> -      return SE.getUnknown(BBMap[V]);
> -
> -    return Expr;
> -  }
> -
> -private:
> -  Scop &S;
> -  ScalarEvolution &SE;
> -  ValueMapT &GlobalMap;
> -  ValueMapT &BBMap;
> -};
> -
>  // Helper class to generate memory location.
>  namespace {
>  class IslGenerator {
> @@ -386,9 +188,10 @@ Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap,
>    if (SCEVCodegen && SE.isSCEVable(Old->getType()))
>      if (const SCEV *Scev = SE.getSCEV(const_cast<Value*>(Old)))
>        if (!isa<SCEVCouldNotCompute>(Scev)) {
> -        const SCEV *NewScev = SCEVRewriter::rewrite(Scev,
> -                                                    *Statement.getParent(), SE,
> -                                                    GlobalMap, BBMap);
> +        const SCEV *NewScev = apply(Scev, LoopToScev, SE);
> +        ValueToValueMap VTV = GlobalMap;
> +        VTV.insert(BBMap.begin(), BBMap.end());
> +        NewScev = ScevParameterRewriter::rewrite(NewScev, SE, VTV);
>          SCEVExpander Expander(SE, "polly");
>          Value *Expanded = Expander.expandCodeFor(NewScev, Old->getType(),
>                                                   Builder.GetInsertPoint());
> diff --git a/test/Cloog/CodeGen/simple_vec_call_2.ll b/test/Cloog/CodeGen/simple_vec_call_2.ll
> index bb2a680..645599f 100644
> --- a/test/Cloog/CodeGen/simple_vec_call_2.ll
> +++ b/test/Cloog/CodeGen/simple_vec_call_2.ll
> @@ -58,4 +58,4 @@ return:
>  ; CHECK-SCEV: %5 = insertelement <4 x float**> %4, float** %p_result1, i32 1
>  ; CHECK-SCEV: %6 = insertelement <4 x float**> %5, float** %p_result2, i32 2
>  ; CHECK-SCEV: %7 = insertelement <4 x float**> %6, float** %p_result3, i32 3
> -; CHECK-SCEV: store <4 x float**> %7, <4 x float**>* bitcast ([1024 x float**]* @B to <4 x float**>*), align 
> +; CHECK-SCEV: store <4 x float**> %7, <4 x float**>* bitcast (float*** getelementptr inbounds ([1024 x float**]* @B, i64 0, i64 3) to <4 x float**>*), align
> diff --git a/test/Cloog/CodeGen/simple_vec_ptr_ptr_ty.ll b/test/Cloog/CodeGen/simple_vec_ptr_ptr_ty.ll
> index d295be7..b6c6502 100644
> --- a/test/Cloog/CodeGen/simple_vec_ptr_ptr_ty.ll
> +++ b/test/Cloog/CodeGen/simple_vec_ptr_ptr_ty.ll
> @@ -37,4 +37,4 @@ return:
>  
>  ; CHECK-SCEV: %value_p_splat_one = load <1 x float**>* bitcast ([1024 x float**]* @A to <1 x float**>*), align 8
>  ; CHECK-SCEV: %value_p_splat = shufflevector <1 x float**> %value_p_splat_one, <1 x float**> %value_p_splat_one, <4 x i32> zeroinitializer
> -; CHECK-SCEV: store <4 x float**> %value_p_splat, <4 x float**>* bitcast ([1024 x float**]* @B to <4 x float**>*), align 8
> +; CHECK-SCEV: store <4 x float**> %value_p_splat, <4 x float**>* bitcast (float*** getelementptr inbounds ([1024 x float**]* @B, i64 0, i64 3) to <4 x float**>*), align
> -- 
> 1.7.9.5
> 

> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



More information about the llvm-commits mailing list