Strip constant factors from SCoP parameters

This will strip the constant factor of a parameter befor we add it to
  the SCoP. As a result the access functions are simplified, e.g., for
  the attached test case.

llvm-svn: 233501
This commit is contained in:
Johannes Doerfert 2015-03-29 20:45:09 +00:00
parent 9de151ee5d
commit be40996cfe
5 changed files with 83 additions and 18 deletions

View File

@ -51,6 +51,15 @@ std::vector<const llvm::SCEV *>
getParamsInAffineExpr(const llvm::Region *R, const llvm::SCEV *Expression,
llvm::ScalarEvolution &SE,
const llvm::Value *BaseAddress = 0);
/// @brief Extract the constant factors from the multiplication @p M.
///
/// @param M A potential SCEV multiplication.
/// @param SE The ScalarEvolution analysis to create new SCEVs.
///
/// @returns The constant factor in @p M and the rest of @p M.
std::pair<const llvm::SCEV *, const llvm::SCEV *>
extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE);
}
#endif

View File

@ -194,22 +194,15 @@ __isl_give isl_pw_aff *SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) {
}
__isl_give isl_pw_aff *SCEVAffinator::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 nullptr;
}
Product = isl_pw_aff_mul(Product, NextOperand);
}
// TODO: Check for NSW and NUW.
return Product;
// 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) {
@ -1246,6 +1239,7 @@ void Scop::setContext(__isl_take isl_set *NewContext) {
void Scop::addParams(std::vector<const SCEV *> NewParameters) {
for (const SCEV *Parameter : NewParameters) {
Parameter = extractConstantFactor(Parameter, *SE).second;
if (ParameterIds.find(Parameter) != ParameterIds.end())
continue;

View File

@ -562,4 +562,23 @@ std::vector<const SCEV *> getParamsInAffineExpr(const Region *R,
return Result.getParameters();
}
std::pair<const SCEV *, const SCEV *>
extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
const SCEV *LeftOver = SE.getConstant(S->getType(), 1);
const SCEV *ConstPart = SE.getConstant(S->getType(), 1);
const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(S);
if (!M)
return std::make_pair(ConstPart, S);
for (const SCEV *Op : M->operands())
if (isa<SCEVConstant>(Op))
ConstPart = SE.getMulExpr(ConstPart, Op);
else
LeftOver = SE.getMulExpr(LeftOver, Op);
return std::make_pair(ConstPart, LeftOver);
}
}

View File

@ -0,0 +1,43 @@
; RUN: opt %loadPolly -analyze -polly-scops -polly-detect-unprofitable < %s | FileCheck %s
;
; Check that the constant part of the N * M * 4 expression is not part of the
; parameter but explicit in the access function. This can avoid existentially
; quantified variables, e.g., when computing the stride.
;
; CHECK: p1: (%N * %M)
; CHECK: [N, p_1] -> { Stmt_for_body[i0] -> MemRef_A[4p_1 + i0] };
;
; void f(int *A, int N, int M) {
; for (int i = 0; i < N; i++)
; A[i + N * M * 4] = i;
; }
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @f(i32* %A, i32 %N, i32 %M) {
entry:
%tmp = sext i32 %N to i64
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%cmp = icmp slt i64 %indvars.iv, %tmp
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%mul = mul nsw i32 %N, %M
%mul2 = mul nsw i32 %mul, 4
%tmp2 = sext i32 %mul2 to i64
%tmp3 = add nsw i64 %indvars.iv, %tmp2
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %tmp3
%tmp4 = trunc i64 %indvars.iv to i32
store i32 %tmp4, i32* %arrayidx, align 4
br label %for.inc
for.inc: ; preds = %for.body
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond
for.end: ; preds = %for.cond
ret void
}

View File

@ -20,14 +20,14 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; CHECK-NOT: Stmt_for_i_1
; NONAFFINE: p0: %n
; NONAFFINE: p1: (4 * (-1 + %n) * %n)
; NONAFFINE: p1: ((-1 + %n) * %n)
; NONAFFINE: Statements {
; NONAFFINE: Stmt_for_i_1
; NONAFFINE: MayWriteAccess := [Reduction Type: NONE]
; NONAFFINE: [n, p_1] -> { Stmt_for_i_1[i0] -> MemRef_X[o0] : o0 >= -2305843009213693952 and o0 <= 2305843009213693949 };
; NONAFFINE: Stmt_for_i_2
; NONAFFINE: MustWriteAccess := [Reduction Type: NONE]
; NONAFFINE: [n, p_1] -> { Stmt_for_i_2[i0] -> MemRef_X[o0] : 4o0 = p_1 + 4i0 };
; NONAFFINE: [n, p_1] -> { Stmt_for_i_2[i0] -> MemRef_X[p_1 + i0] };
; DELIN: Stmt_for_i_1
; DELIN: MustWriteAccess :=