Model scalar writes with uses outside the SCoP

These write are important as they will force the scheduling and code
  generation of an otherwise trivial statement and also impose an order of
  execution needed to guarantee the correct final value for a scalar in a loop.

  Added test case modeled after ClamAV/clamscan.

llvm-svn: 228847
This commit is contained in:
Johannes Doerfert 2015-02-11 17:02:52 +00:00
parent ecd3b04cd7
commit 1f87f485b1
2 changed files with 71 additions and 8 deletions

View File

@ -141,10 +141,7 @@ void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
}
bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R) {
// No need to translate these scalar dependences into polyhedral form, because
// synthesizable scalars can be generated by the code generator.
if (canSynthesize(Inst, LI, SE, R))
return false;
bool canSynthesizeInst = canSynthesize(Inst, LI, SE, R);
if (isIgnoredIntrinsic(Inst))
return false;
@ -170,12 +167,23 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R) {
if (UseParent == ParentBB)
continue;
// Check whether or not the use is in the SCoP.
if (!R->contains(UseParent)) {
AnyCrossStmtUse = true;
continue;
}
// If the instruction can be synthesized and the user is in the region
// we do not need to add scalar dependences.
if (canSynthesizeInst)
continue;
// No need to translate these scalar dependences into polyhedral form,
// because synthesizable scalars can be generated by the code generator.
if (canSynthesize(UI, LI, SE, R))
continue;
// Skip PHI nodes as they handle their operands on their own.
// Skip PHI nodes in the region as they handle their operands on their own.
if (isa<PHINode>(UI))
continue;
@ -183,9 +191,6 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R) {
AnyCrossStmtUse = true;
// Do not build a read access that is not in the current SCoP
if (!R->contains(UseParent))
continue;
// Use the def instruction as base address of the IRAccess, so that it will
// become the name of the scalar access in the polyhedral form.
IRAccess ScalarAccess(IRAccess::READ, Inst, ZeroOffset, 1, true);

View File

@ -0,0 +1,58 @@
; RUN: opt %loadPolly -polly-scops -disable-polly-intra-scop-scalar-to-array -polly-model-phi-nodes -analyze < %s | FileCheck %s
;
; void g();
; int f(int *A) {
; int a0 = 0, a1 = 0, a2 = 0;
; for (int i = 0; i < 1000; i++) {
; a0 = 2 * i;
; // split
; A[0] = i;
; a1 = 2 * i;
; // split
; a2 = 2 * i;
; }
; g();
; return a1 + a2;
; }
;
; CHECK: Stmt_bb1
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb1[i0] -> MemRef_a_0[] };
; CHECK: Stmt_bb2
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb2[i0] -> MemRef_a_1[] };
; CHECK: Stmt_bb3
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb3[i0] -> MemRef_a_2[] };
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define i32 @f(i32* %A) {
bb:
br label %bb1
bb1: ; preds = %bb3, %bb
%i.0 = phi i32 [ 0, %bb ], [ %tmp4, %bb3 ]
%a.0 = mul i32 %i.0, 2
br label %bb2
bb2: ; preds = %bb1
%a.1 = mul i32 %i.0, 2
store i32 %i.0, i32 *%A, align 4
br label %bb3
bb3: ; preds = %bb2
%tmp = shl nsw i32 %i.0, 1
%tmp4 = add nuw nsw i32 %i.0, 1
%a.2 = mul i32 %i.0, 2
%exitcond = icmp ne i32 %i.0, 1000
br i1 %exitcond, label %bb1, label %bb5
bb5: ; preds = %bb1
call void (...)* @g() #2
%add = add i32 %a.0, %a.1
%add2 = add i32 %add, %a.2
ret i32 %add2
}
declare void @g(...) #1