[CodeGen] Add flag to code-generate most memory access expressions

Introduce the new flag -polly-codegen-generate-expressions which forces Polly
to code generate AST expressions instead of using our SCEV based access
expression generation even for cases where the original memory access relation
was not changed and the SCEV based access expression could be code generated
without any issue.

This is an experimental option for better testing the isl ast expression
generation. The default behavior of Polly remains unchanged. We also exclude
a couple of cases for which the AST expression is not yet working.

llvm-svn: 287694
This commit is contained in:
Tobias Grosser 2016-11-22 20:21:16 +00:00
parent 198955536e
commit b3c3d149b9
3 changed files with 86 additions and 4 deletions

View File

@ -597,8 +597,6 @@ private:
isl_map *NewAccessRelation;
// @}
bool isAffine() const { return IsAffine; }
__isl_give isl_basic_map *createBasicAccessMap(ScopStmt *Statement);
void assumeNoOutOfBound();
@ -1037,6 +1035,9 @@ public:
/// Print the MemoryAccess to stderr.
void dump() const;
/// Is the memory access affine?
bool isAffine() const { return IsAffine; }
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,

View File

@ -65,6 +65,15 @@ static cl::opt<bool> PollyGenerateRTCPrint(
cl::desc("Emit code that prints the runtime check result dynamically."),
cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
// If this option is set we always use the isl AST generator to regenerate
// memory accesses. Without this option set we regenerate expressions using the
// original SCEV expressions and only generate new expressions in case the
// access relation has been changed and consequently must be regenerated.
static cl::opt<bool> PollyGenerateExpressions(
"polly-codegen-generate-expressions",
cl::desc("Generate AST expressions for unmodified and modified accesses"),
cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
__isl_give isl_ast_expr *
IslNodeBuilder::getUpperBound(__isl_keep isl_ast_node *For,
ICmpInst::Predicate &Predicate) {
@ -728,9 +737,23 @@ IslNodeBuilder::createNewAccesses(ScopStmt *Stmt,
Stmt->setAstBuild(Build);
for (auto *MA : *Stmt) {
if (!MA->hasNewAccessRelation())
continue;
if (!MA->hasNewAccessRelation()) {
if (PollyGenerateExpressions) {
if (!MA->isAffine())
continue;
if (MA->getLatestScopArrayInfo()->getBasePtrOriginSAI())
continue;
auto *BasePtr =
dyn_cast<Instruction>(MA->getLatestScopArrayInfo()->getBasePtr());
if (BasePtr && Stmt->getParent()->getRegion().contains(BasePtr))
continue;
} else {
continue;
}
}
assert(MA->isAffine() &&
"Only affine memory accesses can be code generated");
assert(!MA->getLatestScopArrayInfo()->getBasePtrOriginSAI() &&
"Generating new index expressions to indirect arrays not working");

View File

@ -0,0 +1,58 @@
; RUN: opt %loadPolly -polly-codegen -polly-codegen-generate-expressions=false \
; RUN: -S < %s | FileCheck %s -check-prefix=SCEV
; RUN: opt %loadPolly -polly-codegen -polly-codegen-generate-expressions=true \
; RUN: -S < %s | FileCheck %s -check-prefix=ASTEXPR
;
; void foo(float A[]) {
; for (long i = 0; i < 100; i++)
; A[i % 4] += 10;
; }
; SCEV: polly.stmt.bb2: ; preds = %polly.loop_header
; SCEV-NEXT: %p_tmp = srem i64 %polly.indvar, 4
; SCEV-NEXT: %p_tmp3 = getelementptr inbounds float, float* %A, i64 %p_tmp
; SCEV-NEXT: %tmp4_p_scalar_ = load float, float* %p_tmp3, align 4, !alias.scope !0, !noalias !2
; SCEV-NEXT: %p_tmp5 = fadd float %tmp4_p_scalar_, 1.000000e+01
; SCEV-NEXT: store float %p_tmp5, float* %p_tmp3, align 4, !alias.scope !0, !noalias !2
; SCEV-NEXT: %polly.indvar_next = add nsw i64 %polly.indvar, 1
; SCEV-NEXT: %polly.loop_cond = icmp sle i64 %polly.indvar, 98
; SCEV-NEXT: br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
; ASTEXPR: polly.stmt.bb2: ; preds = %polly.loop_header
; ASTEXPR-NEXT: %pexp.pdiv_r = urem i64 %polly.indvar, 4
; ASTEXPR-NEXT: %polly.access.A = getelementptr float, float* %A, i64 %pexp.pdiv_r
; ASTEXPR-NEXT: %tmp4_p_scalar_ = load float, float* %polly.access.A, align 4, !alias.scope !0, !noalias !2
; ASTEXPR-NEXT: %p_tmp5 = fadd float %tmp4_p_scalar_, 1.000000e+01
; ASTEXPR-NEXT: %pexp.pdiv_r1 = urem i64 %polly.indvar, 4
; ASTEXPR-NEXT: %polly.access.A2 = getelementptr float, float* %A, i64 %pexp.pdiv_r1
; ASTEXPR-NEXT: store float %p_tmp5, float* %polly.access.A2, align 4, !alias.scope !0, !noalias !2
; ASTEXPR-NEXT: %polly.indvar_next = add nsw i64 %polly.indvar, 1
; ASTEXPR-NEXT: %polly.loop_cond = icmp sle i64 %polly.indvar, 98
; ASTEXPR-NEXT: br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @foo(float* %A) {
bb:
br label %bb1
bb1: ; preds = %bb6, %bb
%i.0 = phi i64 [ 0, %bb ], [ %tmp7, %bb6 ]
%exitcond = icmp ne i64 %i.0, 100
br i1 %exitcond, label %bb2, label %bb8
bb2: ; preds = %bb1
%tmp = srem i64 %i.0, 4
%tmp3 = getelementptr inbounds float, float* %A, i64 %tmp
%tmp4 = load float, float* %tmp3, align 4
%tmp5 = fadd float %tmp4, 1.000000e+01
store float %tmp5, float* %tmp3, align 4
br label %bb6
bb6: ; preds = %bb2
%tmp7 = add nuw nsw i64 %i.0, 1
br label %bb1
bb8: ; preds = %bb1
ret void
}