Keep track of ScopArrayInfo objects that model PHI node storage

Summary:
When translating PHI nodes into memory dependences during code generation we
require two kinds of memory. 'Normal memory' as for all scalar dependences and
'PHI node memory' to store the incoming values of the PHI node. With this
patch we now mark and track these two kinds of memories, which we previously
incorrectly marked as a single memory object.

Being aware of PHI node storage makes code generation easier, as we do not need
to guess what kind of storage a scalar reference requires. This simplifies the
code nicely.

Reviewers: jdoerfert

Subscribers: pollydev, llvm-commits

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

llvm-svn: 243420
This commit is contained in:
Tobias Grosser 2015-07-28 14:53:44 +00:00
parent 280ee917d7
commit 922452285a
18 changed files with 140 additions and 175 deletions

View File

@ -162,12 +162,13 @@ protected:
/// memory location in the 'PHIOpMap' table. The memory locations in
/// 'PHIOpMap' end with '.phiops'.
///
/// An access to/from memory that belongs to a PHI node is in the ScopInfo
/// always modeled with the name of the PHI node. However, in reality PHI
/// nodes can introduce reads/writes to two different memory locations, the
/// normal '.s2a' locations and the special '.phiops' locations. We do not
/// track this difference in the polyhedral description, but only through
/// the content of the two maps 'ScalarMap' and 'PHIOpMap'.
/// The ScopArrayInfo objects of accesses that belong to a PHI node may have
/// identical base pointers, even though they refer to two different memory
/// locations, the normal '.s2a' locations and the special '.phiops'
/// locations. For historic reasons we keep such accesses in two maps
/// 'ScalarMap' and 'PHIOpMap', index by the BasePointer. An alternative
/// implemenation, could use a single map that uses the ScopArrayInfo object
/// as index.
///
/// Example:
///

View File

@ -76,8 +76,9 @@ public:
/// @param ElementType The type of the elements stored in the array.
/// @param IslCtx The isl context used to create the base pointer id.
/// @param DimensionSizes A vector containing the size of each dimension.
/// @param IsPHI Is this a PHI node specific array info object.
ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *IslCtx,
const SmallVector<const SCEV *, 4> &DimensionSizes);
const SmallVector<const SCEV *, 4> &DimensionSizes, bool IsPHI);
/// @brief Destructor to free the isl id of the base pointer.
~ScopArrayInfo();
@ -106,6 +107,18 @@ public:
/// @brief Return the isl id for the base pointer.
__isl_give isl_id *getBasePtrId() const;
/// @brief Is this array info modeling special PHI node memory?
///
/// During code generation of PHI nodes, there is a need for two kinds of
/// virtual storage. The normal one as it is used for all scalar dependences,
/// where the result of the PHI node is stored and later loaded from as well
/// as a second one where the incoming values of the PHI nodes are stored
/// into and reloaded when the PHI is executed. As both memories use the
/// original PHI node as virtual base pointer, we have this additional
/// attribute to distinguish the PHI node specific array modeling from the
/// normal scalar array modeling.
bool isPHI() const { return IsPHI; };
/// @brief Dump a readable representation to stderr.
void dump() const;
@ -131,6 +144,9 @@ private:
/// @brief The sizes of each dimension.
SmallVector<const SCEV *, 4> DimensionSizes;
/// @brief Is this PHI node specific storage?
bool IsPHI;
};
/// @brief Represent memory accesses in statements.
@ -757,9 +773,13 @@ private:
/// Constraints on parameters.
isl_set *Context;
typedef MapVector<const Value *, std::unique_ptr<ScopArrayInfo>>
ArrayInfoMapTy;
typedef MapVector<std::pair<const Value *, int>,
std::unique_ptr<ScopArrayInfo>> ArrayInfoMapTy;
/// @brief A map to remember ScopArrayInfo objects for all base pointers.
///
/// As PHI nodes may have two array info objects associated, we add a flag
/// that distinguishes between the PHI node specific ArrayInfo object
/// and the normal one.
ArrayInfoMapTy ScopArrayInfoMap;
/// @brief The assumptions under which this scop was built.
@ -1031,12 +1051,18 @@ public:
/// @brief Return the (possibly new) ScopArrayInfo object for @p Access.
///
/// @param ElementType The type of the elements stored in this array.
/// @param IsPHI Is this ScopArrayInfo object modeling special
/// PHI node storage.
const ScopArrayInfo *
getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType,
const SmallVector<const SCEV *, 4> &Sizes);
const SmallVector<const SCEV *, 4> &Sizes,
bool IsPHI = false);
/// @brief Return the cached ScopArrayInfo object for @p BasePtr.
const ScopArrayInfo *getScopArrayInfo(Value *BasePtr);
///
/// @param BasePtr The base pointer the object has been stored for
/// @param IsPHI Are we looking for special PHI storage.
const ScopArrayInfo *getScopArrayInfo(Value *BasePtr, bool IsPHI = false);
void setContext(isl_set *NewContext);

View File

@ -48,20 +48,27 @@ private:
TypeKind Type;
bool IsAffine;
/// @brief Is this IRAccess modeling special PHI node accesses?
bool IsPHI;
public:
SmallVector<const SCEV *, 4> Subscripts, Sizes;
/// @brief Create a new IRAccess
///
/// @param IsPHI Are we modeling special PHI node accesses?
explicit IRAccess(TypeKind Type, Value *BaseAddress, const SCEV *Offset,
unsigned elemBytes, bool Affine)
unsigned elemBytes, bool Affine, bool IsPHI = false)
: BaseAddress(BaseAddress), Offset(Offset), ElemBytes(elemBytes),
Type(Type), IsAffine(Affine) {}
Type(Type), IsAffine(Affine), IsPHI(IsPHI) {}
explicit IRAccess(TypeKind Type, Value *BaseAddress, const SCEV *Offset,
unsigned elemBytes, bool Affine,
SmallVector<const SCEV *, 4> Subscripts,
SmallVector<const SCEV *, 4> Sizes)
: BaseAddress(BaseAddress), Offset(Offset), ElemBytes(elemBytes),
Type(Type), IsAffine(Affine), Subscripts(Subscripts), Sizes(Sizes) {}
Type(Type), IsAffine(Affine), IsPHI(false), Subscripts(Subscripts),
Sizes(Sizes) {}
enum TypeKind getType() const { return Type; }
@ -83,6 +90,9 @@ public:
bool isScalar() const { return Subscripts.size() == 0; }
// @brief Is this IRAccess modeling special PHI node accesses?
bool isPHI() const { return IsPHI; }
void print(raw_ostream &OS) const;
};

View File

@ -350,10 +350,12 @@ static __isl_give isl_set *addRangeBoundsToSet(__isl_take isl_set *S,
}
ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx,
const SmallVector<const SCEV *, 4> &DimensionSizes)
const SmallVector<const SCEV *, 4> &DimensionSizes,
bool IsPHI)
: BasePtr(BasePtr), ElementType(ElementType),
DimensionSizes(DimensionSizes) {
const std::string BasePtrName = getIslCompatibleName("MemRef_", BasePtr, "");
DimensionSizes(DimensionSizes), IsPHI(IsPHI) {
std::string BasePtrName =
getIslCompatibleName("MemRef_", BasePtr, IsPHI ? "__phi" : "");
Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);
}
@ -890,7 +892,7 @@ void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block,
Type *ElementType = getAccessInstType(AccessInst);
const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo(
Access.getBase(), ElementType, Access.Sizes);
Access.getBase(), ElementType, Access.Sizes, Access.isPHI());
if (isApproximated && Access.isWrite())
Access.setMayWrite();
@ -1705,15 +1707,17 @@ Scop::~Scop() {
const ScopArrayInfo *
Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *AccessType,
const SmallVector<const SCEV *, 4> &Sizes) {
auto &SAI = ScopArrayInfoMap[BasePtr];
const SmallVector<const SCEV *, 4> &Sizes,
bool IsPHI) {
auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, IsPHI)];
if (!SAI)
SAI.reset(new ScopArrayInfo(BasePtr, AccessType, getIslCtx(), Sizes));
SAI.reset(
new ScopArrayInfo(BasePtr, AccessType, getIslCtx(), Sizes, IsPHI));
return SAI.get();
}
const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr) {
const ScopArrayInfo *SAI = ScopArrayInfoMap[BasePtr].get();
const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, bool IsPHI) {
auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, IsPHI)].get();
assert(SAI && "No ScopArrayInfo available for this base pointer");
return SAI;
}

View File

@ -141,12 +141,14 @@ void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
Written = true;
IRAccess ScalarAccess(IRAccess::MUST_WRITE, PHI, ZeroOffset, 1, true);
IRAccess ScalarAccess(IRAccess::MUST_WRITE, PHI, ZeroOffset, 1, true,
/* IsPHI */ true);
AccFuncMap[OpBB].push_back(std::make_pair(ScalarAccess, OpI));
}
if (Written) {
IRAccess ScalarAccess(IRAccess::READ, PHI, ZeroOffset, 1, true);
IRAccess ScalarAccess(IRAccess::READ, PHI, ZeroOffset, 1, true,
/* IsPHI */ true);
Functions.push_back(std::make_pair(ScalarAccess, PHI));
}
}

View File

@ -440,9 +440,7 @@ void BlockGenerator::generateScalarLoads(ScopStmt &Stmt,
auto Base = cast<Instruction>(MA.getBaseAddr());
// This is either a common scalar use (second case) or the use of a phi
// operand by the PHI node (first case).
if (isa<PHINode>(Base) && Base == MA.getAccessInstruction())
if (MA.getScopArrayInfo()->isPHI())
Address = getOrCreateAlloca(Base, PHIOpMap, ".phiops");
else
Address = getOrCreateAlloca(Base, ScalarMap, ".s2a");
@ -501,74 +499,27 @@ void BlockGenerator::generateScalarStores(ScopStmt &Stmt, BasicBlock *BB,
"Region statements need to use the generateScalarStores() "
"function in the RegionGenerator");
// Set to remember a store to the phiops alloca of a PHINode. It is needed as
// we might have multiple write accesses to the same PHI and while one is the
// self write of the PHI (to the ScalarMap alloca) the other is the write to
// the operand alloca (PHIOpMap).
SmallPtrSet<PHINode *, 4> SeenPHIs;
// Iterate over all accesses in the given statement.
for (MemoryAccess *MA : Stmt) {
// Skip non-scalar and read accesses.
if (!MA->isScalar() || MA->isRead())
continue;
Instruction *ScalarBase = cast<Instruction>(MA->getBaseAddr());
Instruction *ScalarInst = MA->getAccessInstruction();
PHINode *ScalarBasePHI = dyn_cast<PHINode>(ScalarBase);
Instruction *Base = cast<Instruction>(MA->getBaseAddr());
Instruction *Inst = MA->getAccessInstruction();
// Get the alloca node for the base instruction and the value we want to
// store. In total there are 4 options:
// (1) The base is no PHI, hence it is a simple scalar def-use chain.
// (2) The base is a PHI,
// (a) and the write is caused by an operand in the block.
// (b) and it is the PHI self write (same as case (1)).
// (c) (2a) and (2b) are not distinguishable.
// For case (1) and (2b) we get the alloca from the scalar map and the value
// we want to store is initialized with the instruction attached to the
// memory access. For case (2a) we get the alloca from the PHI operand map
// and the value we want to store is initialized with the incoming value for
// this block. The tricky case (2c) is when both (2a) and (2b) match. This
// happens if the PHI operand is in the same block as the PHI. To handle
// that we choose the alloca of (2a) first and (2b) for the next write
// access to that PHI (there must be 2).
Value *ScalarValue = nullptr;
AllocaInst *ScalarAddr = nullptr;
Value *Val = nullptr;
AllocaInst *Address = nullptr;
if (!ScalarBasePHI) {
// Case (1)
ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a");
ScalarValue = ScalarInst;
if (MA->getScopArrayInfo()->isPHI()) {
PHINode *BasePHI = dyn_cast<PHINode>(Base);
int PHIIdx = BasePHI->getBasicBlockIndex(BB);
Address = getOrCreateAlloca(Base, PHIOpMap, ".phiops");
Val = BasePHI->getIncomingValue(PHIIdx);
} else {
int PHIIdx = ScalarBasePHI->getBasicBlockIndex(BB);
if (ScalarBasePHI != ScalarInst) {
// Case (2a)
assert(PHIIdx >= 0 && "Bad scalar write to PHI operand");
SeenPHIs.insert(ScalarBasePHI);
ScalarAddr = getOrCreateAlloca(ScalarBase, PHIOpMap, ".phiops");
ScalarValue = ScalarBasePHI->getIncomingValue(PHIIdx);
} else if (PHIIdx < 0) {
// Case (2b)
ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a");
ScalarValue = ScalarInst;
} else {
// Case (2c)
if (SeenPHIs.insert(ScalarBasePHI).second) {
// First access ==> same as (2a)
ScalarAddr = getOrCreateAlloca(ScalarBase, PHIOpMap, ".phiops");
ScalarValue = ScalarBasePHI->getIncomingValue(PHIIdx);
} else {
// Second access ==> same as (2b)
ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a");
ScalarValue = ScalarInst;
}
}
Address = getOrCreateAlloca(Base, ScalarMap, ".s2a");
Val = Inst;
}
ScalarValue =
getNewScalarValue(ScalarValue, R, ScalarMap, BBMap, GlobalMap);
Builder.CreateStore(ScalarValue, ScalarAddr);
Val = getNewScalarValue(Val, R, ScalarMap, BBMap, GlobalMap);
Builder.CreateStore(Val, Address);
}
}
@ -1174,21 +1125,8 @@ void RegionGenerator::generateScalarStores(ScopStmt &Stmt, BasicBlock *BB,
assert(StmtR && "Block statements need to use the generateScalarStores() "
"function in the BlockGenerator");
BasicBlock *ExitBB = StmtR->getExit();
// For region statements three kinds of scalar stores exists:
// (1) A definition used by a non-phi instruction outside the region.
// (2) A phi-instruction in the region entry.
// (3) A write to a phi instruction in the region exit.
// The last case is the tricky one since we do not know anymore which
// predecessor of the exit needs to store the operand value that doesn't
// have a definition in the region. Therefore, we have to check in each
// block in the region if we should store the value or not.
// Iterate over all accesses in the given statement.
for (MemoryAccess *MA : Stmt) {
// Skip non-scalar and read accesses.
if (!MA->isScalar() || MA->isRead())
continue;
@ -1196,36 +1134,20 @@ void RegionGenerator::generateScalarStores(ScopStmt &Stmt, BasicBlock *BB,
Instruction *ScalarInst = MA->getAccessInstruction();
PHINode *ScalarBasePHI = dyn_cast<PHINode>(ScalarBase);
Value *ScalarValue = nullptr;
Value *Val = nullptr;
AllocaInst *ScalarAddr = nullptr;
if (!ScalarBasePHI) {
// Case (1)
ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a");
ScalarValue = ScalarInst;
} else if (ScalarBasePHI->getParent() != ExitBB) {
// Case (2)
assert(ScalarBasePHI->getParent() == StmtR->getEntry() &&
"Bad PHI self write in non-affine region");
assert(ScalarBase == ScalarInst &&
"Bad PHI self write in non-affine region");
ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a");
ScalarValue = ScalarInst;
} else {
if (MA->getScopArrayInfo()->isPHI()) {
int PHIIdx = ScalarBasePHI->getBasicBlockIndex(BB);
// Skip accesses we will not handle in this basic block but in another one
// in the statement region.
if (PHIIdx < 0)
continue;
// Case (3)
ScalarAddr = getOrCreateAlloca(ScalarBase, PHIOpMap, ".phiops");
ScalarValue = ScalarBasePHI->getIncomingValue(PHIIdx);
Val = ScalarBasePHI->getIncomingValue(PHIIdx);
} else {
ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a");
Val = ScalarInst;
}
ScalarValue =
getNewScalarValue(ScalarValue, R, ScalarMap, BBMap, GlobalMap);
Builder.CreateStore(ScalarValue, ScalarAddr);
Val = getNewScalarValue(Val, R, ScalarMap, BBMap, GlobalMap);
Builder.CreateStore(Val, ScalarAddr);
}
}

View File

@ -20,7 +20,7 @@
; CHECK: Schedule :=
; CHECK: [N] -> { Stmt_bb2[i0] -> [i0, 0] : i0 <= N and N >= 1; Stmt_bb2[0] -> [0, 0] : N <= 0 }
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb2[i0] -> MemRef_j_0[] };
; CHECK: [N] -> { Stmt_bb2[i0] -> MemRef_j_0__phi[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb2[i0] -> MemRef_j_0[] };
; CHECK: Stmt_bb4__TO__bb18
@ -33,7 +33,7 @@
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb4__TO__bb18[i0] -> MemRef_j_0[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb4__TO__bb18[i0] -> MemRef_j_2[] };
; CHECK: [N] -> { Stmt_bb4__TO__bb18[i0] -> MemRef_j_2__phi[] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [N] -> { Stmt_bb4__TO__bb18[i0] -> MemRef_A[i0] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 0]
@ -41,7 +41,7 @@
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb4__TO__bb18[i0] -> MemRef_smax[] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb4__TO__bb18[i0] -> MemRef_j_2[] };
; CHECK: [N] -> { Stmt_bb4__TO__bb18[i0] -> MemRef_j_2__phi[] };
; CHECK: Stmt_bb18
; CHECK: Domain :=
; CHECK: [N] -> { Stmt_bb18[i0] : i0 >= 0 and N >= 1 and i0 <= -1 + N };
@ -50,7 +50,7 @@
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb18[i0] -> MemRef_j_2[] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb18[i0] -> MemRef_j_2[] };
; CHECK: [N] -> { Stmt_bb18[i0] -> MemRef_j_2__phi[] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [N] -> { Stmt_bb18[i0] -> MemRef_A[o0] : o0 >= -2147483648 and o0 <= 2147483645 };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
@ -63,7 +63,7 @@
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb23[i0] -> MemRef_j_2[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_bb23[i0] -> MemRef_j_0[] };
; CHECK: [N] -> { Stmt_bb23[i0] -> MemRef_j_0__phi[] };
; CHECK: }
;
; void f(int *A, int N, int M) {

View File

@ -54,13 +54,13 @@ bb2: ; preds = %bb, %entry
; CHECK: Schedule :=
; CHECK: [n] -> { Stmt_bb[i0] -> [i0] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_1[] };
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_1__phi[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_k_05[] };
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_k_05__phi[] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_1[] };
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_1__phi[] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_k_05[] };
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_k_05__phi[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [n] -> { Stmt_bb[i0] -> MemRef_a[1 + i0] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]

View File

@ -21,20 +21,20 @@
; CHECK: Region: %bb1---%bb21
; CHECK: Stmt_bb3
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [b] -> { Stmt_bb3[i0] -> MemRef_x_1[] };
; CHECK: [b] -> { Stmt_bb3[i0] -> MemRef_x_1__phi[] };
; CHECK: Stmt_bb7
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [b] -> { Stmt_bb7[i0] -> MemRef_x_1[] };
; CHECK: [b] -> { Stmt_bb7[i0] -> MemRef_x_1__phi[] };
; CHECK: Stmt_bb8
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [b] -> { Stmt_bb8[i0] -> MemRef_x_1[] };
; CHECK: [b] -> { Stmt_bb8[i0] -> MemRef_x_1__phi[] };
; CHECK: Stmt_bb10__TO__bb18
; CHECK-NEXT: Domain :=
; CHECK-NEXT: [b] -> { Stmt_bb10__TO__bb18[i0] : i0 >= 0 and i0 <= 1023 };
; CHECK-NEXT: Schedule :=
; CHECK-NEXT: [b] -> { Stmt_bb10__TO__bb18[i0] -> [i0, 3] };
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [b] -> { Stmt_bb10__TO__bb18[i0] -> MemRef_x_1[] }
; CHECK-NEXT: [b] -> { Stmt_bb10__TO__bb18[i0] -> MemRef_x_1__phi[] }
; CHECK-NOT: [Scalar: 1]
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -32,11 +32,11 @@
; CHECK-NOT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_0[] };
; CHECK-NOT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_1[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2[] };
; CHECK-NEXT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2__phi[] };
; CHECK-NOT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_0[] };
; CHECK-NOT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_1[] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2[] };
; CHECK-NEXT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2__phi[] };
; CHECK-NOT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_0[] };
; CHECK-NOT: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_1[] };
; CHECK: Stmt_bb18
@ -45,7 +45,7 @@
; CHECK: Schedule :=
; CHECK: { Stmt_bb18[i0] -> [i0, 1] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb18[i0] -> MemRef_x_2[] };
; CHECK: { Stmt_bb18[i0] -> MemRef_x_2__phi[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: { Stmt_bb18[i0] -> MemRef_A[i0] };
;

View File

@ -28,20 +28,20 @@
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_A[i0] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2[] };
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2__phi[] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2[] };
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2__phi[] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2[] };
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2__phi[] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2[] };
; CHECK: { Stmt_bb3__TO__bb18[i0] -> MemRef_x_2__phi[] };
; CHECK: Stmt_bb18
; CHECK: Domain :=
; CHECK: { Stmt_bb18[i0] : i0 >= 0 and i0 <= 1023 };
; CHECK: Schedule :=
; CHECK: { Stmt_bb18[i0] -> [i0, 1] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb18[i0] -> MemRef_x_2[] };
; CHECK: { Stmt_bb18[i0] -> MemRef_x_2__phi[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: { Stmt_bb18[i0] -> MemRef_A[i0] };
;

View File

@ -23,9 +23,9 @@
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb2__TO__bb7[i0] -> MemRef_x[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb2__TO__bb7[i0] -> MemRef_y[] };
; CHECK: { Stmt_bb2__TO__bb7[i0] -> MemRef_y__phi[] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb2__TO__bb7[i0] -> MemRef_y[] };
; CHECK: { Stmt_bb2__TO__bb7[i0] -> MemRef_y__phi[] };
; CHECK: Stmt_bb7
; CHECK: Domain :=
; CHECK: { Stmt_bb7[i0] : i0 >= 0 and i0 <= 1023 };
@ -34,7 +34,7 @@
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb7[i0] -> MemRef_x[] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: { Stmt_bb7[i0] -> MemRef_y[] };
; CHECK: { Stmt_bb7[i0] -> MemRef_y__phi[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: { Stmt_bb7[i0] -> MemRef_A[i0] };
;

View File

@ -15,17 +15,17 @@
; CHECK-LABEL: Stmt_bb6
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_bb6[i0] -> MemRef_tmp_0[] };
; CHECK: [N, c] -> { Stmt_bb6[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK-LABEL: Stmt_bb7
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_bb7[i0] -> MemRef_tmp_0[] };
; CHECK: [N, c] -> { Stmt_bb7[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK-LABEL: Stmt_bb8
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_bb8[i0] -> MemRef_tmp_0[] };
; CHECK: [N, c] -> { Stmt_bb8[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [N, c] -> { Stmt_bb8[i0] -> MemRef_A[i0] };

View File

@ -15,17 +15,17 @@
; CHECK-LABEL: Stmt_bb6
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_bb6[i0] -> MemRef_tmp_0[] };
; CHECK: [N, c] -> { Stmt_bb6[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK-LABEL: Stmt_bb7
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_bb7[i0] -> MemRef_tmp_0[] };
; CHECK: [N, c] -> { Stmt_bb7[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK-LABEL: Stmt_bb8
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_bb8[i0] -> MemRef_tmp_0[] };
; CHECK: [N, c] -> { Stmt_bb8[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_bb8[i0] -> MemRef_tmp_0[] };

View File

@ -13,17 +13,17 @@
; CHECK-LABEL: Stmt_if_else
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [c] -> { Stmt_if_else[i0] -> MemRef_phi[] };
; CHECK: [c] -> { Stmt_if_else[i0] -> MemRef_phi__phi[] };
; CHECK-NOT: Access
; CHECK-LABEL: Stmt_if_then
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [c] -> { Stmt_if_then[i0] -> MemRef_phi[] };
; CHECK: [c] -> { Stmt_if_then[i0] -> MemRef_phi__phi[] };
; CHECK-NOT: Access
; CHECK-LABEL: Stmt_if_end
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [c] -> { Stmt_if_end[i0] -> MemRef_phi[] };
; CHECK: [c] -> { Stmt_if_end[i0] -> MemRef_phi__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [c] -> { Stmt_if_end[i0] -> MemRef_A[i0] };

View File

@ -10,7 +10,7 @@
; CHECK-LABEL: Stmt_bb1
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE]
; CHECK: [N] -> { Stmt_bb1[i0] -> MemRef_tmp_0[] };
; CHECK: [N] -> { Stmt_bb1[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE]
; CHECK: [N] -> { Stmt_bb1[i0] -> MemRef_tmp_0[] };
@ -18,7 +18,7 @@
; CHECK-LABEL: Stmt_bb4
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE]
; CHECK: [N] -> { Stmt_bb4[i0] -> MemRef_tmp_0[] };
; CHECK: [N] -> { Stmt_bb4[i0] -> MemRef_tmp_0__phi[] };
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE]
; CHECK: [N] -> { Stmt_bb4[i0] -> MemRef_tmp_0[] };

View File

@ -17,7 +17,7 @@ entry:
for.cond: ; preds = %for.inc4, %entry
; CHECK-LABEL: Stmt_for_cond
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0[] };
; CHECK: [N] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0[] };
@ -36,20 +36,20 @@ for.body: ; preds = %for.cond
; CHECK: [N] -> { Stmt_for_body[i0] -> MemRef_x_addr_0[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_body[i0] -> MemRef_x_addr_1[] };
; CHECK: [N] -> { Stmt_for_body[i0] -> MemRef_x_addr_1__phi[] };
; CHECK-NOT: Access
br label %for.cond1
for.cond1: ; preds = %for.inc, %for.body
; CHECK-LABEL: Stmt_for_cond1
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1[] };
; CHECK: [N] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1_lcssa[] };
; CHECK: [N] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1_lcssa__phi[] };
; CHECK-NOT: Access
%x.addr.1 = phi i32 [ %x.addr.0, %for.body ], [ %add, %for.inc ]
%j.0 = phi i32 [ 3, %for.body ], [ %inc, %for.inc ]
@ -62,7 +62,7 @@ for.body3: ; preds = %for.cond1
for.inc: ; preds = %for.body3
; CHECK-LABEL: Stmt_for_inc
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1[] };
; CHECK: [N] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1__phi[] };
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1[] };
@ -83,7 +83,7 @@ for.end: ; preds = %for.cond1
; CHECK: [N] -> { Stmt_for_end[i0] -> MemRef_x_addr_1_lcssa[] };
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_end[i0] -> MemRef_x_addr_1_lcssa[] };
; CHECK: [N] -> { Stmt_for_end[i0] -> MemRef_x_addr_1_lcssa__phi[] };
; CHECK-NOT: Access
%x.addr.1.lcssa = phi i32 [ %x.addr.1, %for.cond1 ]
br label %for.inc4
@ -95,7 +95,7 @@ for.inc4: ; preds = %for.end
; CHECK: [N] -> { Stmt_for_inc4[i0] -> MemRef_x_addr_1_lcssa[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N] -> { Stmt_for_inc4[i0] -> MemRef_x_addr_0[] };
; CHECK: [N] -> { Stmt_for_inc4[i0] -> MemRef_x_addr_0__phi[] };
; CHECK-NOT: Access
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond

View File

@ -20,7 +20,7 @@ for.cond: ; preds = %for.inc5, %entry
; CHECK-LABEL: Stmt_for_cond
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0[] };
; CHECK: [N, c] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0[] };
@ -45,7 +45,7 @@ for.body: ; preds = %for.cond
; CHECK: [N, c] -> { Stmt_for_body[i0] -> MemRef_x_addr_0[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_body[i0] -> MemRef_x_addr_1[] };
; CHECK: [N, c] -> { Stmt_for_body[i0] -> MemRef_x_addr_1__phi[] };
; CHECK-NOT: Access
br label %for.cond1
@ -56,7 +56,7 @@ for.cond1: ; preds = %for.inc, %for.body
; CHECK: [N, c] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1[] };
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1[] };
; CHECK: [N, c] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1__phi[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1[] };
@ -76,7 +76,7 @@ for.body3: ; preds = %for.cond1
; CHECK: [N, c] -> { Stmt_for_body3[i0, i1] -> MemRef_x_addr_1[] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_body3[i0, i1] -> MemRef_x_addr_2[] };
; CHECK: [N, c] -> { Stmt_for_body3[i0, i1] -> MemRef_x_addr_2__phi[] };
; CHECK-NOT: Access
%cmp4 = icmp slt i64 %indvars.iv, %tmp1
br i1 %cmp4, label %if.then, label %if.end
@ -91,7 +91,7 @@ if.then: ; preds = %for.body3
; CHECK: [N, c] -> { Stmt_if_then[i0, i1] -> MemRef_A[i0] };
; CHECK-NOT: Access
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_if_then[i0, i1] -> MemRef_x_addr_2[] };
; CHECK: [N, c] -> { Stmt_if_then[i0, i1] -> MemRef_x_addr_2__phi[] };
; CHECK-NOT: Access
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
%tmp2 = load i32, i32* %arrayidx, align 4
@ -105,7 +105,7 @@ if.end: ; preds = %if.then, %for.body3
; CHECK: [N, c] -> { Stmt_if_end[i0, i1] -> MemRef_x_addr_2[] };
; CHECK-NOT: Access
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_if_end[i0, i1] -> MemRef_x_addr_2[] };
; CHECK: [N, c] -> { Stmt_if_end[i0, i1] -> MemRef_x_addr_2__phi[] };
; CHECK-NOT: Access
%x.addr.2 = phi i32 [ %add, %if.then ], [ %x.addr.1, %for.body3 ]
br label %for.inc
@ -115,7 +115,7 @@ for.inc: ; preds = %if.end
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_2[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1[] };
; CHECK: [N, c] -> { Stmt_for_inc[i0, i1] -> MemRef_x_addr_1__phi[] };
%inc = add nsw i32 %j.0, 1
br label %for.cond1
@ -127,7 +127,7 @@ for.inc5: ; preds = %for.end
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_inc5[i0] -> MemRef_x_addr_1[] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [N, c] -> { Stmt_for_inc5[i0] -> MemRef_x_addr_0[] };
; CHECK: [N, c] -> { Stmt_for_inc5[i0] -> MemRef_x_addr_0__phi[] };
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond