summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Doerfert <doerfert@cs.uni-saarland.de>2015-03-29 20:45:09 +0000
committerJohannes Doerfert <doerfert@cs.uni-saarland.de>2015-03-29 20:45:09 +0000
commitbe40996cfe7a8ae40e065120a40a15ead80ea393 (patch)
tree71dcb44b5d07e6f00544019893282ce98444ff2c
parent9de151ee5d6b6c7311e6e497cfb8507902652da4 (diff)
downloadbcm5719-llvm-be40996cfe7a8ae40e065120a40a15ead80ea393.tar.gz
bcm5719-llvm-be40996cfe7a8ae40e065120a40a15ead80ea393.zip
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
-rw-r--r--polly/include/polly/Support/SCEVValidator.h9
-rw-r--r--polly/lib/Analysis/ScopInfo.cpp26
-rw-r--r--polly/lib/Support/SCEVValidator.cpp19
-rw-r--r--polly/test/ScopInfo/constant_factor_in_parameter.ll43
-rw-r--r--polly/test/ScopInfo/multidim_single_and_multidim_array.ll4
5 files changed, 83 insertions, 18 deletions
diff --git a/polly/include/polly/Support/SCEVValidator.h b/polly/include/polly/Support/SCEVValidator.h
index 17294cef84a..75e8ca894f2 100644
--- a/polly/include/polly/Support/SCEVValidator.h
+++ b/polly/include/polly/Support/SCEVValidator.h
@@ -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
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index 0a62efddd6e..3e19a33c4a4 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -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;
diff --git a/polly/lib/Support/SCEVValidator.cpp b/polly/lib/Support/SCEVValidator.cpp
index 5a3706b2fac..048fdc32aa1 100644
--- a/polly/lib/Support/SCEVValidator.cpp
+++ b/polly/lib/Support/SCEVValidator.cpp
@@ -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);
+}
}
diff --git a/polly/test/ScopInfo/constant_factor_in_parameter.ll b/polly/test/ScopInfo/constant_factor_in_parameter.ll
new file mode 100644
index 00000000000..e31b709771c
--- /dev/null
+++ b/polly/test/ScopInfo/constant_factor_in_parameter.ll
@@ -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
+}
diff --git a/polly/test/ScopInfo/multidim_single_and_multidim_array.ll b/polly/test/ScopInfo/multidim_single_and_multidim_array.ll
index 6ff3267ae71..b52cd2950bf 100644
--- a/polly/test/ScopInfo/multidim_single_and_multidim_array.ll
+++ b/polly/test/ScopInfo/multidim_single_and_multidim_array.ll
@@ -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 :=
OpenPOWER on IntegriCloud