forked from OSchip/llvm-project
Use arguments of user statements to perform induction variable substitution
To translate the old induction variables as they exist before Polly to new new induction variables introduced during AST code generation we need to generate code that computes the new values from the old ones. We can do this by just looking at the arguments isl generates in each scheduled statement. Example: // Old for i S(i) // New for c0 for c1 S(c0 + c1) To get the value of i, we need to compute 'c0 + c1'. This expression is readily available in the user statements generated by isl and just needs to be translated to LLVM-IR. This replaces an old confusing construct that constructed during ast generation an isl multi affine expression that described this relation and which was then again ast generated for each statement and argument when translating the isl ast to LLVM-IR. This approach was difficult to understand and the additional ast generation calls where entirely redundant as isl provides the relevant expressions as arguments of the generated user statements. llvm-svn: 212186
This commit is contained in:
parent
35af19ab1f
commit
ce67a044e0
|
@ -44,7 +44,6 @@ class IslAst;
|
|||
// Information about an ast node.
|
||||
struct IslAstUser {
|
||||
struct isl_ast_build *Context;
|
||||
struct isl_pw_multi_aff *PMA;
|
||||
// The node is the outermost parallel loop.
|
||||
int IsOutermostParallel;
|
||||
|
||||
|
|
|
@ -121,7 +121,6 @@ printFor(__isl_take isl_printer *Printer,
|
|||
static struct IslAstUser *allocateIslAstUser() {
|
||||
struct IslAstUser *NodeInfo;
|
||||
NodeInfo = (struct IslAstUser *)malloc(sizeof(struct IslAstUser));
|
||||
NodeInfo->PMA = 0;
|
||||
NodeInfo->Context = 0;
|
||||
NodeInfo->IsOutermostParallel = 0;
|
||||
NodeInfo->IsInnermostParallel = 0;
|
||||
|
@ -132,7 +131,6 @@ static struct IslAstUser *allocateIslAstUser() {
|
|||
static void freeIslAstUser(void *Ptr) {
|
||||
struct IslAstUser *UserStruct = (struct IslAstUser *)Ptr;
|
||||
isl_ast_build_free(UserStruct->Context);
|
||||
isl_pw_multi_aff_free(UserStruct->PMA);
|
||||
free(UserStruct);
|
||||
}
|
||||
|
||||
|
@ -313,10 +311,6 @@ static __isl_give isl_ast_node *AtEachDomain(__isl_take isl_ast_node *Node,
|
|||
Id = isl_id_set_free_user(Id, &freeIslAstUser);
|
||||
}
|
||||
|
||||
if (!Info->PMA) {
|
||||
isl_map *Map = isl_map_from_union_map(isl_ast_build_get_schedule(Context));
|
||||
Info->PMA = isl_pw_multi_aff_from_map(isl_map_reverse(Map));
|
||||
}
|
||||
if (!Info->Context)
|
||||
Info->Context = isl_ast_build_copy(Context);
|
||||
|
||||
|
|
|
@ -669,12 +669,50 @@ private:
|
|||
void createFor(__isl_take isl_ast_node *For);
|
||||
void createForVector(__isl_take isl_ast_node *For, int VectorWidth);
|
||||
void createForSequential(__isl_take isl_ast_node *For);
|
||||
void createSubstitutions(__isl_take isl_pw_multi_aff *PMA,
|
||||
__isl_take isl_ast_build *Context, ScopStmt *Stmt,
|
||||
|
||||
/// Generate LLVM-IR that computes the values of the original induction
|
||||
/// variables in function of the newly generated loop induction variables.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// // Original
|
||||
/// for i
|
||||
/// for j
|
||||
/// S(i)
|
||||
///
|
||||
/// Schedule: [i,j] -> [i+j, j]
|
||||
///
|
||||
/// // New
|
||||
/// for c0
|
||||
/// for c1
|
||||
/// S(c0 - c1, c1)
|
||||
///
|
||||
/// Assuming the original code consists of two loops which are
|
||||
/// transformed according to a schedule [i,j] -> [c0=i+j,c1=j]. The resulting
|
||||
/// ast models the original statement as a call expression where each argument
|
||||
/// is an expression that computes the old induction variables from the new
|
||||
/// ones, ordered such that the first argument computes the value of induction
|
||||
/// variable that was outermost in the original code.
|
||||
///
|
||||
/// @param Expr The call expression that represents the statement.
|
||||
/// @param Stmt The statement that is called.
|
||||
/// @param VMap The value map into which the mapping from the old induction
|
||||
/// variable to the new one is inserted. This mapping is used
|
||||
/// for the classical code generation (not scev-based) and
|
||||
/// gives an explicit mapping from an original, materialized
|
||||
/// induction variable. It consequently can only be expressed
|
||||
/// if there was an explicit induction variable.
|
||||
/// @param LTS The loop to SCEV map in which the mapping from the original
|
||||
/// loop to a SCEV representing the new loop iv is added. This
|
||||
/// mapping does not require an explicit induction variable.
|
||||
/// Instead, we think in terms of an implicit induction variable
|
||||
/// that counts the number of times a loop is executed. For each
|
||||
/// original loop this count, expressed in function of the new
|
||||
/// induction variables, is added to the LTS map.
|
||||
void createSubstitutions(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt,
|
||||
ValueMapT &VMap, LoopToScevMapT <S);
|
||||
void createSubstitutionsVector(__isl_take isl_pw_multi_aff *PMA,
|
||||
__isl_take isl_ast_build *Context,
|
||||
ScopStmt *Stmt, VectorValueMapT &VMap,
|
||||
void createSubstitutionsVector(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt,
|
||||
VectorValueMapT &VMap,
|
||||
std::vector<LoopToScevMapT> &VLTS,
|
||||
std::vector<Value *> &IVS,
|
||||
__isl_take isl_id *IteratorID);
|
||||
|
@ -762,13 +800,10 @@ void IslNodeBuilder::createUserVector(__isl_take isl_ast_node *User,
|
|||
std::vector<Value *> &IVS,
|
||||
__isl_take isl_id *IteratorID,
|
||||
__isl_take isl_union_map *Schedule) {
|
||||
isl_id *Annotation = isl_ast_node_get_annotation(User);
|
||||
assert(Annotation && "Vector user statement is not annotated");
|
||||
|
||||
struct IslAstUser *Info = (struct IslAstUser *)isl_id_get_user(Annotation);
|
||||
assert(Info && "Vector user statement annotation does not contain info");
|
||||
|
||||
isl_id *Id = isl_pw_multi_aff_get_tuple_id(Info->PMA, isl_dim_out);
|
||||
isl_ast_expr *Expr = isl_ast_node_user_get_expr(User);
|
||||
isl_ast_expr *StmtExpr = isl_ast_expr_get_op_arg(Expr, 0);
|
||||
isl_id *Id = isl_ast_expr_get_id(StmtExpr);
|
||||
isl_ast_expr_free(StmtExpr);
|
||||
ScopStmt *Stmt = (ScopStmt *)isl_id_get_user(Id);
|
||||
VectorValueMapT VectorMap(IVS.size());
|
||||
std::vector<LoopToScevMapT> VLTS(IVS.size());
|
||||
|
@ -777,13 +812,10 @@ void IslNodeBuilder::createUserVector(__isl_take isl_ast_node *User,
|
|||
Schedule = isl_union_map_intersect_domain(Schedule, Domain);
|
||||
isl_map *S = isl_map_from_union_map(Schedule);
|
||||
|
||||
createSubstitutionsVector(isl_pw_multi_aff_copy(Info->PMA),
|
||||
isl_ast_build_copy(Info->Context), Stmt, VectorMap,
|
||||
VLTS, IVS, IteratorID);
|
||||
createSubstitutionsVector(Expr, Stmt, VectorMap, VLTS, IVS, IteratorID);
|
||||
VectorBlockGenerator::generate(Builder, *Stmt, VectorMap, VLTS, S, P);
|
||||
|
||||
isl_map_free(S);
|
||||
isl_id_free(Annotation);
|
||||
isl_id_free(Id);
|
||||
isl_ast_node_free(User);
|
||||
}
|
||||
|
@ -977,19 +1009,18 @@ void IslNodeBuilder::createIf(__isl_take isl_ast_node *If) {
|
|||
isl_ast_node_free(If);
|
||||
}
|
||||
|
||||
void IslNodeBuilder::createSubstitutions(__isl_take isl_pw_multi_aff *PMA,
|
||||
__isl_take isl_ast_build *Context,
|
||||
ScopStmt *Stmt, ValueMapT &VMap,
|
||||
LoopToScevMapT <S) {
|
||||
for (unsigned i = 0; i < isl_pw_multi_aff_dim(PMA, isl_dim_out); ++i) {
|
||||
isl_pw_aff *Aff;
|
||||
isl_ast_expr *Expr;
|
||||
void IslNodeBuilder::createSubstitutions(isl_ast_expr *Expr, ScopStmt *Stmt,
|
||||
ValueMapT &VMap, LoopToScevMapT <S) {
|
||||
assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
|
||||
"Expression of type 'op' expected");
|
||||
assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_call &&
|
||||
"Opertation of type 'call' expected");
|
||||
for (int i = 0; i < isl_ast_expr_get_op_n_arg(Expr) - 1; ++i) {
|
||||
isl_ast_expr *SubExpr;
|
||||
Value *V;
|
||||
|
||||
Aff = isl_pw_multi_aff_get_pw_aff(PMA, i);
|
||||
Expr = isl_ast_build_expr_from_pw_aff(Context, Aff);
|
||||
V = ExprBuilder.create(Expr);
|
||||
|
||||
SubExpr = isl_ast_expr_get_op_arg(Expr, i + 1);
|
||||
V = ExprBuilder.create(SubExpr);
|
||||
ScalarEvolution *SE = Stmt->getParent()->getSE();
|
||||
LTS[Stmt->getLoopForDimension(i)] = SE->getUnknown(V);
|
||||
|
||||
|
@ -1003,53 +1034,43 @@ void IslNodeBuilder::createSubstitutions(__isl_take isl_pw_multi_aff *PMA,
|
|||
}
|
||||
}
|
||||
|
||||
isl_pw_multi_aff_free(PMA);
|
||||
isl_ast_build_free(Context);
|
||||
isl_ast_expr_free(Expr);
|
||||
}
|
||||
|
||||
void IslNodeBuilder::createSubstitutionsVector(
|
||||
__isl_take isl_pw_multi_aff *PMA, __isl_take isl_ast_build *Context,
|
||||
ScopStmt *Stmt, VectorValueMapT &VMap, std::vector<LoopToScevMapT> &VLTS,
|
||||
std::vector<Value *> &IVS, __isl_take isl_id *IteratorID) {
|
||||
__isl_take isl_ast_expr *Expr, ScopStmt *Stmt, VectorValueMapT &VMap,
|
||||
std::vector<LoopToScevMapT> &VLTS, std::vector<Value *> &IVS,
|
||||
__isl_take isl_id *IteratorID) {
|
||||
int i = 0;
|
||||
|
||||
Value *OldValue = IDToValue[IteratorID];
|
||||
for (Value *IV : IVS) {
|
||||
IDToValue[IteratorID] = IV;
|
||||
createSubstitutions(isl_pw_multi_aff_copy(PMA), isl_ast_build_copy(Context),
|
||||
Stmt, VMap[i], VLTS[i]);
|
||||
createSubstitutions(isl_ast_expr_copy(Expr), Stmt, VMap[i], VLTS[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
IDToValue[IteratorID] = OldValue;
|
||||
isl_id_free(IteratorID);
|
||||
isl_pw_multi_aff_free(PMA);
|
||||
isl_ast_build_free(Context);
|
||||
isl_ast_expr_free(Expr);
|
||||
}
|
||||
|
||||
void IslNodeBuilder::createUser(__isl_take isl_ast_node *User) {
|
||||
ValueMapT VMap;
|
||||
LoopToScevMapT LTS;
|
||||
struct IslAstUser *Info;
|
||||
isl_id *Annotation, *Id;
|
||||
isl_id *Id;
|
||||
ScopStmt *Stmt;
|
||||
|
||||
Annotation = isl_ast_node_get_annotation(User);
|
||||
assert(Annotation && "Scalar user statement is not annotated");
|
||||
isl_ast_expr *Expr = isl_ast_node_user_get_expr(User);
|
||||
isl_ast_expr *StmtExpr = isl_ast_expr_get_op_arg(Expr, 0);
|
||||
Id = isl_ast_expr_get_id(StmtExpr);
|
||||
isl_ast_expr_free(StmtExpr);
|
||||
|
||||
Info = (struct IslAstUser *)isl_id_get_user(Annotation);
|
||||
assert(Info && "Scalar user statement annotation does not contain info");
|
||||
|
||||
Id = isl_pw_multi_aff_get_tuple_id(Info->PMA, isl_dim_out);
|
||||
Stmt = (ScopStmt *)isl_id_get_user(Id);
|
||||
|
||||
createSubstitutions(isl_pw_multi_aff_copy(Info->PMA),
|
||||
isl_ast_build_copy(Info->Context), Stmt, VMap, LTS);
|
||||
|
||||
createSubstitutions(Expr, Stmt, VMap, LTS);
|
||||
BlockGenerator::generate(Builder, *Stmt, VMap, LTS, P);
|
||||
|
||||
isl_ast_node_free(User);
|
||||
isl_id_free(Annotation);
|
||||
isl_id_free(Id);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue