Follow uses to create value MemoryAccesses

The previously implemented approach is to follow value definitions and
create write accesses ("push defs") while searching for uses. This
requires the same relatively validity- and requirement conditions to be
replicated at multiple locations (PHI instructions, other instructions,
uses by PHIs).

We replace this by iterating over the uses in a SCoP ("pull in
requirements"), and add writes only when at least one read has been
added. It turns out to be simpler code because each use is only iterated
over once and writes are added for the first access that reads it. We
need another iteration to identify escaping values (uses not in the
SCoP), which also makes the difference between such accesses more
obvious. As a side-effect, the order of scalar MemoryAccess can change.

Differential Revision: http://reviews.llvm.org/D15706

llvm-svn: 259987
This commit is contained in:
Michael Kruse 2016-02-06 09:19:40 +00:00
parent df6763abe8
commit 2e02d560aa
16 changed files with 128 additions and 176 deletions

View File

@ -2039,14 +2039,15 @@ class ScopInfo : public RegionPass {
/// @brief Analyze and extract the cross-BB scalar dependences (or,
/// dataflow dependencies) of an instruction.
///
/// @param Inst The instruction to be analyzed
/// @param R The SCoP region
/// @param NonAffineSubRegion The non affine sub-region @p Inst is in.
/// @param Inst The instruction to be analyzed.
void buildScalarDependences(Instruction *Inst);
/// @brief Search for uses of the llvm::Value defined by @p Inst that are not
/// within the SCoP. If there is such use, add a SCALAR WRITE such that
/// it is available after the SCoP as escaping value.
///
/// @return True if the Instruction is used in other BB and a scalar write
/// Access is required.
bool buildScalarDependences(Instruction *Inst, Region *R,
Region *NonAffineSubRegio);
/// @param Inst The instruction to be analyzed.
void buildEscapingDependences(Instruction *Inst);
/// @brief Create MemoryAccesses for the given PHI node in the given region.
///

View File

@ -321,5 +321,14 @@ bool isIgnoredIntrinsic(const llvm::Value *V);
/// otherwise return false.
bool canSynthesize(const llvm::Value *V, const llvm::LoopInfo *LI,
llvm::ScalarEvolution *SE, const llvm::Region *R);
/// @brief Return the block in which a value is used.
///
/// For normal instructions, this is the instruction's parent block. For PHI
/// nodes, this is the incoming block of that use, because this is where the
/// operand must be defined (i.e. its definition dominates this block).
/// Non-instructions do not use operands at a specific point such that in this
/// case this function returns nullptr.
llvm::BasicBlock *getUseBlock(llvm::Use &U);
}
#endif

View File

@ -3677,25 +3677,6 @@ void ScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
continue;
OnlyNonAffineSubRegionOperands = false;
if (!R.contains(OpBB))
continue;
Instruction *OpI = dyn_cast<Instruction>(Op);
if (OpI) {
BasicBlock *OpIBB = OpI->getParent();
// As we pretend there is a use (or more precise a write) of OpI in OpBB
// we have to insert a scalar dependence from the definition of OpI to
// OpBB if the definition is not in OpBB.
if (scop->getStmtForBasicBlock(OpIBB) !=
scop->getStmtForBasicBlock(OpBB)) {
ensureValueRead(OpI, OpBB);
ensureValueWrite(OpI);
}
} else if (ModelReadOnlyScalars && !isa<Constant>(Op)) {
ensureValueRead(Op, OpBB);
}
ensurePHIWrite(PHI, OpBB, Op, IsExitBlock);
}
@ -3704,115 +3685,41 @@ void ScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
}
}
bool ScopInfo::buildScalarDependences(Instruction *Inst, Region *R,
Region *NonAffineSubRegion) {
bool canSynthesizeInst = canSynthesize(Inst, LI, SE, R);
if (isIgnoredIntrinsic(Inst))
return false;
void ScopInfo::buildScalarDependences(Instruction *Inst) {
assert(!isa<PHINode>(Inst));
bool AnyCrossStmtUse = false;
BasicBlock *ParentBB = Inst->getParent();
// Pull-in required operands.
for (Use &Op : Inst->operands())
ensureValueRead(Op.get(), Inst->getParent());
}
for (User *U : Inst->users()) {
Instruction *UI = dyn_cast<Instruction>(U);
void ScopInfo::buildEscapingDependences(Instruction *Inst) {
Region *R = &scop->getRegion();
// Ignore the strange user
if (UI == 0)
// Check for uses of this instruction outside the scop. Because we do not
// iterate over such instructions and therefore did not "ensure" the existence
// of a write, we must determine such use here.
for (Use &U : Inst->uses()) {
Instruction *UI = dyn_cast<Instruction>(U.getUser());
if (!UI)
continue;
BasicBlock *UseParent = UI->getParent();
BasicBlock *UseParent = getUseBlock(U);
BasicBlock *UserParent = UI->getParent();
// Ignore basic block local uses. A value that is defined in a scop, but
// used in a PHI node in the same basic block does not count as basic block
// local, as for such cases a control flow edge is passed between definition
// and use.
if (UseParent == ParentBB && !isa<PHINode>(UI))
continue;
// Uses by PHI nodes in the entry node count as external uses in case the
// use is through an incoming block that is itself not contained in the
// region.
if (R->getEntry() == UseParent) {
if (auto *PHI = dyn_cast<PHINode>(UI)) {
bool ExternalUse = false;
for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
if (PHI->getIncomingValue(i) == Inst &&
!R->contains(PHI->getIncomingBlock(i))) {
ExternalUse = true;
break;
}
}
if (ExternalUse) {
AnyCrossStmtUse = true;
continue;
}
}
}
// Do not build scalar dependences inside a non-affine subregion.
if (NonAffineSubRegion && NonAffineSubRegion->contains(UseParent))
continue;
// Check for PHI nodes in the region exit and skip them, if they will be
// modeled as PHI nodes.
//
// PHI nodes in the region exit that have more than two incoming edges need
// to be modeled as PHI-Nodes to correctly model the fact that depending on
// the control flow a different value will be assigned to the PHI node. In
// case this is the case, there is no need to create an additional normal
// scalar dependence. Hence, bail out before we register an "out-of-region"
// use for this definition.
if (isa<PHINode>(UI) && UI->getParent() == R->getExit() &&
!R->getExitingBlock())
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 in the region as they handle their operands on their own.
if (isa<PHINode>(UI))
continue;
// Now U is used in another statement.
AnyCrossStmtUse = true;
// Do not build a read access that is not in the current SCoP
// Use the def instruction as base address of the MemoryAccess, so that it
// will become the name of the scalar access in the polyhedral form.
ensureValueRead(Inst, UI->getParent());
}
if (ModelReadOnlyScalars && !isa<PHINode>(Inst)) {
for (Value *Op : Inst->operands()) {
if (canSynthesize(Op, LI, SE, R))
continue;
if (Instruction *OpInst = dyn_cast<Instruction>(Op))
if (R->contains(OpInst))
continue;
if (isa<Constant>(Op))
continue;
ensureValueRead(Op, Inst->getParent());
// An escaping value is either used by an instruction not within the scop,
// or (when the scop region's exit needs to be simplified) by a PHI in the
// scop's exit block. This is because region simplification before code
// generation inserts new basic blocks before the PHI such that its incoming
// blocks are not in the scop anymore.
if (!R->contains(UseParent) ||
(isa<PHINode>(UI) && UserParent == R->getExit() &&
R->getExitingBlock())) {
// At least one escaping use found.
ensureValueWrite(Inst);
break;
}
}
return AnyCrossStmtUse;
}
extern MapInsnToMemAcc InsnToMemAcc;
@ -4018,10 +3925,8 @@ void ScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB,
// The set of loads that are required to be invariant.
auto &ScopRIL = *SD->getRequiredInvariantLoads(&R);
for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) {
Instruction *Inst = &*I;
PHINode *PHI = dyn_cast<PHINode>(Inst);
for (Instruction &Inst : BB) {
PHINode *PHI = dyn_cast<PHINode>(&Inst);
if (PHI)
buildPHIAccesses(PHI, R, NonAffineSubRegion, IsExitBlock);
@ -4036,18 +3941,13 @@ void ScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB,
if (auto MemInst = MemAccInst::dyn_cast(Inst))
buildMemoryAccess(MemInst, L, &R, BoxedLoops, ScopRIL);
if (isIgnoredIntrinsic(Inst))
if (isIgnoredIntrinsic(&Inst))
continue;
// Do not build scalar dependences for required invariant loads as we will
// hoist them later on anyway or drop the SCoP if we cannot.
if (ScopRIL.count(dyn_cast<LoadInst>(Inst)))
continue;
if (buildScalarDependences(Inst, &R, NonAffineSubRegion)) {
if (!isa<StoreInst>(Inst))
ensureValueWrite(Inst);
}
if (!PHI)
buildScalarDependences(&Inst);
if (!IsExitBlock)
buildEscapingDependences(&Inst);
}
}
@ -4127,18 +4027,45 @@ void ScopInfo::ensureValueWrite(Instruction *Value) {
}
void ScopInfo::ensureValueRead(Value *Value, BasicBlock *UserBB) {
// There cannot be an "access" for literal constants. BasicBlock references
// (jump destinations) also never change.
if ((isa<Constant>(Value) && !isa<GlobalVariable>(Value)) ||
isa<BasicBlock>(Value))
return;
// If the instruction can be synthesized and the user is in the region we do
// not need to add a value dependences.
Region &ScopRegion = scop->getRegion();
if (canSynthesize(Value, LI, SE, &ScopRegion))
return;
// Do not build scalar dependences for required invariant loads as we will
// hoist them later on anyway or drop the SCoP if we cannot.
auto ScopRIL = SD->getRequiredInvariantLoads(&ScopRegion);
if (ScopRIL->count(dyn_cast<LoadInst>(Value)))
return;
// Determine the ScopStmt containing the value's definition and use. There is
// no defining ScopStmt if the value is a function argument, a global value,
// or defined outside the SCoP.
Instruction *ValueInst = dyn_cast<Instruction>(Value);
ScopStmt *ValueStmt =
ValueInst ? scop->getStmtForBasicBlock(ValueInst->getParent()) : nullptr;
ScopStmt *UserStmt = scop->getStmtForBasicBlock(UserBB);
// We do not model uses outside the scop.
if (!UserStmt)
return;
// Add MemoryAccess for invariant values only if requested.
if (!ModelReadOnlyScalars && !ValueStmt)
return;
// Ignore use-def chains within the same ScopStmt.
if (ValueStmt == UserStmt)
return;
// Do not create another MemoryAccess for reloading the value if one already
// exists.
if (UserStmt->lookupValueReadOf(Value))
@ -4147,10 +4074,21 @@ void ScopInfo::ensureValueRead(Value *Value, BasicBlock *UserBB) {
addMemoryAccess(UserBB, nullptr, MemoryAccess::READ, Value, 1, true, Value,
ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
ScopArrayInfo::MK_Value);
if (ValueInst)
ensureValueWrite(ValueInst);
}
void ScopInfo::ensurePHIWrite(PHINode *PHI, BasicBlock *IncomingBlock,
Value *IncomingValue, bool IsExitBlock) {
ScopStmt *IncomingStmt = scop->getStmtForBasicBlock(IncomingBlock);
if (!IncomingStmt)
return;
// Take care for the incoming value being available in the incoming block.
// This must be done before the check for multiple PHI writes because multiple
// exiting edges from subregion each can be the effective written value of the
// subregion. As such, all of them must be made available in the subregion
// statement.
ensureValueRead(IncomingValue, IncomingBlock);
// Do not add more than one MemoryAccess per PHINode and ScopStmt.
if (MemoryAccess *Acc = IncomingStmt->lookupPHIWriteOf(PHI)) {

View File

@ -442,3 +442,14 @@ bool polly::canSynthesize(const Value *V, const llvm::LoopInfo *LI,
return false;
}
llvm::BasicBlock *polly::getUseBlock(llvm::Use &U) {
Instruction *UI = dyn_cast<Instruction>(U.getUser());
if (!UI)
return nullptr;
if (PHINode *PHI = dyn_cast<PHINode>(UI))
return PHI->getIncomingBlock(U);
return UI->getParent();
}

View File

@ -8,8 +8,8 @@
; CHECK: polly.stmt.loop3:
; CHECK-NEXT: %val.s2a.reload = load double, double* %val.s2a
; CHECK-NEXT: %polly.access.A20 = getelementptr double, double* %A, i64 42
; CHECK-NEXT: store double %val.s2a.reload, double* %polly.access.A20
; CHECK-NEXT: %scevgep[[R21:[0-9]*]] = getelementptr double, double* %scevgep{{[0-9]*}}, i64 %polly.indvar16
; CHECK-NEXT: store double %val.s2a.reload, double* %scevgep[[R21]]
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -4,12 +4,6 @@
; In this case, we do not reload %ncol.load from the scalar stack slot, but
; instead use directly the preloaded value stored in GlobalMap.
;
; TODO: We may want to not add preloaded values to GlobalMap, but instead model
; them as normal read/write memory accesses. This will allow us to
; easily reason about the use of preloaded data in scop statements.
; At the moment, we would need to scan the IR to understand if a stmt
; uses any preloaded values.
;
; CHECK-NOT: alloca
; CHECK: %dec3.s2a = alloca i32
; CHECK-NOT: alloca
@ -22,7 +16,6 @@
; CHECK-NEXT: store i32 %ncol.load, i32* %tmp0.preload.s2a
;
; CHECK: polly.stmt.while.body.lr.ph:
; CHECK-NEXT: %tmp0.preload.s2a.reload = load i32, i32* %tmp0.preload.s2a
; CHECK-NEXT: store i32 %ncol.load, i32* %dec3.in.phiops
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -8,16 +8,14 @@
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_top_split[] -> [0, 0, 0, 0] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_top_split[] -> MemRef_25[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_top_split[] -> MemRef_26[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_top_split[] -> MemRef_25[] };
; CHECK-NEXT: Stmt_L_4
; CHECK-NEXT: Domain :=
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_L_4[i0, i1, i2] : 0 <= i0 < p_0 and 0 <= i1 < p_0 and 0 <= i2 < p_0 };
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_L_4[i0, i1, i2] -> [1, i0, i1, i2] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_L_4[i0, i1, i2] -> MemRef_25[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_L_4[i0, i1, i2] -> MemRef_19[i1, i0] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
@ -26,6 +24,8 @@
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_L_4[i0, i1, i2] -> MemRef_12[i2, i1] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_L_4[i0, i1, i2] -> MemRef_19[i1, i0] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [p_0, p_1, p_2] -> { Stmt_L_4[i0, i1, i2] -> MemRef_25[] };
; CHECK-NEXT: }
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -92,12 +92,12 @@
; CHECK-NEXT: { Stmt_bb12[i0, i1, i2] -> [i0, 2, i1, 2, i2, 3] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb12[i0, i1, i2] -> MemRef_x_3__phi[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb12[i0, i1, i2] -> MemRef_x_3[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_bb12[i0, i1, i2] -> MemRef_a[i0, i1] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_bb12[i0, i1, i2] -> MemRef_a[i0, i1] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb12[i0, i1, i2] -> MemRef_x_3[] };
; CHECK-NEXT: Stmt_bb16
; CHECK-NEXT: Domain :=
; CHECK-NEXT: { Stmt_bb16[i0, i1, i2] : 0 <= i0 <= 99 and 0 <= i1 <= 99 and 0 <= i2 <= 99 };

View File

@ -18,10 +18,10 @@ target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:
; CHECK-NEXT: [tmp180, tmp177, tmp183, tmp162, tmp157, tmp150, tmp146, tmp140, tmp] -> { Stmt_bb203[i0, i1, i2] -> [i0, 1, i1, i2] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [tmp180, tmp177, tmp183, tmp162, tmp157, tmp150, tmp146, tmp140, tmp] -> { Stmt_bb203[i0, i1, i2] -> MemRef_tmp192[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [tmp180, tmp177, tmp183, tmp162, tmp157, tmp150, tmp146, tmp140, tmp] -> { Stmt_bb203[i0, i1, i2] -> MemRef_tmp194[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [tmp180, tmp177, tmp183, tmp162, tmp157, tmp150, tmp146, tmp140, tmp] -> { Stmt_bb203[i0, i1, i2] -> MemRef_tmp173[o0, 1 + i1, 1 + i2] : 3*floor((-i0 + o0)/3) = -i0 + o0 and 0 <= o0 <= 2 };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [tmp180, tmp177, tmp183, tmp162, tmp157, tmp150, tmp146, tmp140, tmp] -> { Stmt_bb203[i0, i1, i2] -> MemRef_tmp194[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [tmp180, tmp177, tmp183, tmp162, tmp157, tmp150, tmp146, tmp140, tmp] -> { Stmt_bb203[i0, i1, i2] -> MemRef_tmp173[o0, 1 + i1, 1 + i2] : 3*floor((-2 - i0 + o0)/3) = -2 - i0 + o0 and 0 <= o0 <= 2 };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]

View File

@ -16,14 +16,14 @@
;
; CHECK: Arrays {
; CHECK-NEXT: i32 MemRef_A[*]; // Element size 4
; CHECK-NEXT: i32 MemRef_x; [BasePtrOrigin: MemRef_A] // Element size 4
; CHECK-NEXT: i32 MemRef_y__phi; // Element size 4
; CHECK-NEXT: i32 MemRef_x; [BasePtrOrigin: MemRef_A] // Element size 4
; CHECK-NEXT: }
;
; CHECK: Arrays (Bounds as pw_affs) {
; CHECK-NEXT: i32 MemRef_A[*]; // Element size 4
; CHECK-NEXT: i32 MemRef_x; [BasePtrOrigin: MemRef_A] // Element size 4
; CHECK-NEXT: i32 MemRef_y__phi; // Element size 4
; CHECK-NEXT: i32 MemRef_x; [BasePtrOrigin: MemRef_A] // Element size 4
; CHECK-NEXT: }
;
; CHECK: Statements {
@ -35,18 +35,18 @@
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_bb2__TO__bb7[i0] -> MemRef_A[i0] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb2__TO__bb7[i0] -> MemRef_x[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb2__TO__bb7[i0] -> MemRef_y__phi[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb2__TO__bb7[i0] -> MemRef_x[] };
; CHECK-NEXT: Stmt_bb7
; CHECK-NEXT: Domain :=
; CHECK-NEXT: { Stmt_bb7[i0] : 0 <= i0 <= 1023 };
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: { Stmt_bb7[i0] -> [i0, 1] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb7[i0] -> MemRef_x[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb7[i0] -> MemRef_y__phi[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb7[i0] -> MemRef_x[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_bb7[i0] -> MemRef_A[i0] };
; CHECK-NEXT: }

View File

@ -40,10 +40,10 @@
; CHECK-NEXT: [N, c] -> { Stmt_bb8b[i0] : 0 <= i0 < N };
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: [N, c] -> { Stmt_bb8b[i0] -> [i0, 3] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N, c] -> { Stmt_bb8b[i0] -> MemRef_tmp_0[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [N, c] -> { Stmt_bb8b[i0] -> MemRef_A[i0] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N, c] -> { Stmt_bb8b[i0] -> MemRef_tmp_0[] };
; CHECK-NEXT: }
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -23,10 +23,10 @@
; CHECK-NEXT: [N] -> { Stmt_bb4[i0] -> [i0, 1] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_bb4[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_bb4[i0] -> MemRef_tmp_0[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [N] -> { Stmt_bb4[i0] -> MemRef_A[i0] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_bb4[i0] -> MemRef_tmp_0[] };
; CHECK-NEXT: }
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -51,10 +51,10 @@
; CHECK-NEXT: [N] -> { Stmt_for_inc[i0, i1] -> [i0, 2, i1, 1] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1__phi[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [N] -> { Stmt_for_inc[i0, i1] -> MemRef_A[1 + i0] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1[] };
; CHECK-NEXT: Stmt_for_end
; CHECK-NEXT: Domain :=
; CHECK-NEXT: [N] -> { Stmt_for_end[i0] : N >= 3 and 0 <= i0 <= -2 + N };

View File

@ -52,10 +52,10 @@
; CHECK-NEXT: [N, c] -> { Stmt_if_then[i0, i1] : 0 <= i0 < c and i0 < N and 0 <= i1 < N };
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: [N, c] -> { Stmt_if_then[i0, i1] -> [i0, 2, i1, 2] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N, c] -> { Stmt_if_then[i0, i1] -> MemRef_x_addr_1[] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [N, c] -> { Stmt_if_then[i0, i1] -> MemRef_A[i0] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N, c] -> { Stmt_if_then[i0, i1] -> MemRef_x_addr_1[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N, c] -> { Stmt_if_then[i0, i1] -> MemRef_x_addr_2__phi[] };
; CHECK-NEXT: Stmt_if_end

View File

@ -55,8 +55,8 @@ return:
; CHECK-NEXT: [N] -> { Stmt_S2[i0] : 0 <= i0 < N };
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: [N] -> { Stmt_S2[i0] -> [i0, 1] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_S2[i0] -> MemRef_val[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [N] -> { Stmt_S2[i0] -> MemRef_a[i0] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_S2[i0] -> MemRef_val[] };
; CHECK-NEXT: }

View File

@ -33,10 +33,10 @@
; CHECK-NEXT: [N] -> { Stmt_for_j[i0, i1] : 0 <= i0 < N and 0 <= i1 < N };
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: [N] -> { Stmt_for_j[i0, i1] -> [i0, i1] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_for_j[i0, i1] -> MemRef_init[] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [N] -> { Stmt_for_j[i0, i1] -> MemRef_A[i1] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [N] -> { Stmt_for_j[i0, i1] -> MemRef_init[] };
; CHECK-NEXT: }
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"