forked from OSchip/llvm-project
Add a field to the memory access class for a related value.
The new field in the MemoryAccess allows us to track a value related to that access: - For real memory accesses the value is the loaded result or the stored value. - For straigt line scalar accesses it is the access instruction itself. - For PHI operand accesses it is the operand value. We use this value to simplify code which deduced information about the value later in the Polly pipeline and was known to be error prone. Reviewers: grosser, Meinsersbur Subscribers: #polly Differential Revision: http://reviews.llvm.org/D12062 llvm-svn: 245213
This commit is contained in:
parent
58fdd88751
commit
d86f2157e5
|
@ -244,7 +244,15 @@ private:
|
|||
ReductionType RedType = RT_NONE;
|
||||
|
||||
/// @brief The access instruction of this memory access.
|
||||
Instruction *Inst;
|
||||
Instruction *AccessInstruction;
|
||||
|
||||
/// @brief The value associated with this memory access.
|
||||
///
|
||||
/// - For real memory accesses it is the loaded result or the stored value.
|
||||
/// - For straigt line scalar accesses it is the access instruction itself.
|
||||
/// - For PHI operand accesses it is the operand value.
|
||||
///
|
||||
Value *AccessValue;
|
||||
|
||||
/// Updated access relation read from JSCOP file.
|
||||
isl_map *newAccessRelation;
|
||||
|
@ -377,8 +385,11 @@ public:
|
|||
|
||||
const std::string &getBaseName() const { return BaseName; }
|
||||
|
||||
/// @brief Return the access value of this memory access.
|
||||
Value *getAccessValue() const { return AccessValue; }
|
||||
|
||||
/// @brief Return the access instruction of this memory access.
|
||||
Instruction *getAccessInstruction() const { return Inst; }
|
||||
Instruction *getAccessInstruction() const { return AccessInstruction; }
|
||||
|
||||
/// Get the stride of this memory access in the specified Schedule. Schedule
|
||||
/// is a map from the statement to a schedule where the innermost dimension is
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace polly {
|
|||
class IRAccess {
|
||||
public:
|
||||
Value *BaseAddress;
|
||||
Value *AccessValue;
|
||||
|
||||
const SCEV *Offset;
|
||||
|
||||
|
@ -58,22 +59,25 @@ public:
|
|||
///
|
||||
/// @param IsPHI Are we modeling special PHI node accesses?
|
||||
explicit IRAccess(TypeKind Type, Value *BaseAddress, const SCEV *Offset,
|
||||
unsigned elemBytes, bool Affine, bool IsPHI = false)
|
||||
: BaseAddress(BaseAddress), Offset(Offset), ElemBytes(elemBytes),
|
||||
Type(Type), IsAffine(Affine), IsPHI(IsPHI) {}
|
||||
unsigned elemBytes, bool Affine, Value *AccessValue,
|
||||
bool IsPHI = false)
|
||||
: BaseAddress(BaseAddress), AccessValue(AccessValue), Offset(Offset),
|
||||
ElemBytes(elemBytes), 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), IsPHI(false), Subscripts(Subscripts),
|
||||
Sizes(Sizes) {}
|
||||
SmallVector<const SCEV *, 4> Sizes, Value *AccessValue)
|
||||
: BaseAddress(BaseAddress), AccessValue(AccessValue), Offset(Offset),
|
||||
ElemBytes(elemBytes), Type(Type), IsAffine(Affine), IsPHI(false),
|
||||
Subscripts(Subscripts), Sizes(Sizes) {}
|
||||
|
||||
enum TypeKind getType() const { return Type; }
|
||||
|
||||
Value *getBase() const { return BaseAddress; }
|
||||
|
||||
Value *getAccessValue() const { return AccessValue; }
|
||||
|
||||
const SCEV *getOffset() const { return Offset; }
|
||||
|
||||
unsigned getElemSizeInBytes() const { return ElemBytes; }
|
||||
|
|
|
@ -447,7 +447,8 @@ __isl_give isl_map *MemoryAccess::foldAccess(const IRAccess &Access,
|
|||
MemoryAccess::MemoryAccess(const IRAccess &Access, Instruction *AccInst,
|
||||
ScopStmt *Statement, const ScopArrayInfo *SAI,
|
||||
int Identifier)
|
||||
: AccType(getMemoryAccessType(Access)), Statement(Statement), Inst(AccInst),
|
||||
: AccType(getMemoryAccessType(Access)), Statement(Statement),
|
||||
AccessInstruction(AccInst), AccessValue(Access.getAccessValue()),
|
||||
newAccessRelation(nullptr) {
|
||||
|
||||
isl_ctx *Ctx = Statement->getIslCtx();
|
||||
|
@ -669,18 +670,6 @@ void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) {
|
|||
Domain = NewDomain;
|
||||
}
|
||||
|
||||
// @brief Get the data-type of the elements accessed
|
||||
static Type *getAccessType(IRAccess &Access, Instruction *AccessInst) {
|
||||
if (Access.isPHI())
|
||||
return Access.getBase()->getType();
|
||||
|
||||
if (StoreInst *Store = dyn_cast<StoreInst>(AccessInst))
|
||||
return Store->getValueOperand()->getType();
|
||||
if (BranchInst *Branch = dyn_cast<BranchInst>(AccessInst))
|
||||
return Branch->getCondition()->getType();
|
||||
return AccessInst->getType();
|
||||
}
|
||||
|
||||
void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block,
|
||||
bool isApproximated) {
|
||||
AccFuncSetType *AFS = tempScop.getAccessFunctions(Block);
|
||||
|
@ -690,7 +679,7 @@ void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block,
|
|||
for (auto &AccessPair : *AFS) {
|
||||
IRAccess &Access = AccessPair.first;
|
||||
Instruction *AccessInst = AccessPair.second;
|
||||
Type *ElementType = getAccessType(Access, AccessInst);
|
||||
Type *ElementType = Access.getAccessValue()->getType();
|
||||
|
||||
const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo(
|
||||
Access.getBase(), ElementType, Access.Sizes, Access.isPHI());
|
||||
|
|
|
@ -135,9 +135,10 @@ void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
|
|||
// we have to insert a scalar dependence from the definition of OpI to
|
||||
// OpBB if the definition is not in OpBB.
|
||||
if (OpIBB != OpBB) {
|
||||
IRAccess ScalarRead(IRAccess::READ, OpI, ZeroOffset, 1, true);
|
||||
IRAccess ScalarRead(IRAccess::READ, OpI, ZeroOffset, 1, true, OpI);
|
||||
AccFuncMap[OpBB].push_back(std::make_pair(ScalarRead, PHI));
|
||||
IRAccess ScalarWrite(IRAccess::MUST_WRITE, OpI, ZeroOffset, 1, true);
|
||||
IRAccess ScalarWrite(IRAccess::MUST_WRITE, OpI, ZeroOffset, 1, true,
|
||||
OpI);
|
||||
AccFuncMap[OpIBB].push_back(std::make_pair(ScalarWrite, OpI));
|
||||
}
|
||||
}
|
||||
|
@ -147,13 +148,13 @@ void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
|
|||
if (!OpI)
|
||||
OpI = OpBB->getTerminator();
|
||||
|
||||
IRAccess ScalarAccess(IRAccess::MUST_WRITE, PHI, ZeroOffset, 1, true,
|
||||
IRAccess ScalarAccess(IRAccess::MUST_WRITE, PHI, ZeroOffset, 1, true, Op,
|
||||
/* IsPHI */ true);
|
||||
AccFuncMap[OpBB].push_back(std::make_pair(ScalarAccess, OpI));
|
||||
}
|
||||
|
||||
if (!OnlyNonAffineSubRegionOperands) {
|
||||
IRAccess ScalarAccess(IRAccess::READ, PHI, ZeroOffset, 1, true,
|
||||
IRAccess ScalarAccess(IRAccess::READ, PHI, ZeroOffset, 1, true, PHI,
|
||||
/* IsPHI */ true);
|
||||
Functions.push_back(std::make_pair(ScalarAccess, PHI));
|
||||
}
|
||||
|
@ -211,7 +212,7 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R,
|
|||
// Do not build a read access that is not in the current SCoP
|
||||
// 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);
|
||||
IRAccess ScalarAccess(IRAccess::READ, Inst, ZeroOffset, 1, true, Inst);
|
||||
AccFuncMap[UseParent].push_back(std::make_pair(ScalarAccess, UI));
|
||||
}
|
||||
|
||||
|
@ -224,7 +225,7 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R,
|
|||
if (R->contains(OpInst))
|
||||
continue;
|
||||
|
||||
IRAccess ScalarAccess(IRAccess::READ, Op, ZeroOffset, 1, true);
|
||||
IRAccess ScalarAccess(IRAccess::READ, Op, ZeroOffset, 1, true, Op);
|
||||
AccFuncMap[Inst->getParent()].push_back(
|
||||
std::make_pair(ScalarAccess, Inst));
|
||||
}
|
||||
|
@ -240,17 +241,20 @@ TempScopInfo::buildIRAccess(Instruction *Inst, Loop *L, Region *R,
|
|||
const ScopDetection::BoxedLoopsSetTy *BoxedLoops) {
|
||||
unsigned Size;
|
||||
Type *SizeType;
|
||||
Value *Val;
|
||||
enum IRAccess::TypeKind Type;
|
||||
|
||||
if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
|
||||
SizeType = Load->getType();
|
||||
Size = TD->getTypeStoreSize(SizeType);
|
||||
Type = IRAccess::READ;
|
||||
Val = Load;
|
||||
} else {
|
||||
StoreInst *Store = cast<StoreInst>(Inst);
|
||||
SizeType = Store->getValueOperand()->getType();
|
||||
Size = TD->getTypeStoreSize(SizeType);
|
||||
Type = IRAccess::MUST_WRITE;
|
||||
Val = Store->getValueOperand();
|
||||
}
|
||||
|
||||
const SCEV *AccessFunction = SE->getSCEVAtScope(getPointerOperand(*Inst), L);
|
||||
|
@ -264,7 +268,7 @@ TempScopInfo::buildIRAccess(Instruction *Inst, Loop *L, Region *R,
|
|||
if (PollyDelinearize && AccItr != InsnToMemAcc.end())
|
||||
return IRAccess(Type, BasePointer->getValue(), AccessFunction, Size, true,
|
||||
AccItr->second.DelinearizedSubscripts,
|
||||
AccItr->second.Shape->DelinearizedSizes);
|
||||
AccItr->second.Shape->DelinearizedSizes, Val);
|
||||
|
||||
// Check if the access depends on a loop contained in a non-affine subregion.
|
||||
bool isVariantInNonAffineLoop = false;
|
||||
|
@ -287,7 +291,7 @@ TempScopInfo::buildIRAccess(Instruction *Inst, Loop *L, Region *R,
|
|||
Type = IRAccess::MAY_WRITE;
|
||||
|
||||
return IRAccess(Type, BasePointer->getValue(), AccessFunction, Size, IsAffine,
|
||||
Subscripts, Sizes);
|
||||
Subscripts, Sizes, Val);
|
||||
}
|
||||
|
||||
void TempScopInfo::buildAccessFunctions(Region &R, Region &SR) {
|
||||
|
@ -326,7 +330,8 @@ void TempScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB,
|
|||
buildScalarDependences(Inst, &R, NonAffineSubRegion)) {
|
||||
// If the Instruction is used outside the statement, we need to build the
|
||||
// write access.
|
||||
IRAccess ScalarAccess(IRAccess::MUST_WRITE, Inst, ZeroOffset, 1, true);
|
||||
IRAccess ScalarAccess(IRAccess::MUST_WRITE, Inst, ZeroOffset, 1, true,
|
||||
Inst);
|
||||
Functions.push_back(std::make_pair(ScalarAccess, Inst));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -495,21 +495,14 @@ void BlockGenerator::generateScalarStores(ScopStmt &Stmt, BasicBlock *BB,
|
|||
continue;
|
||||
|
||||
Instruction *Base = cast<Instruction>(MA->getBaseAddr());
|
||||
Instruction *Inst = MA->getAccessInstruction();
|
||||
Value *Val = MA->getAccessValue();
|
||||
|
||||
Value *Val = nullptr;
|
||||
AllocaInst *Address = nullptr;
|
||||
|
||||
if (MA->getScopArrayInfo()->isPHI()) {
|
||||
PHINode *BasePHI = dyn_cast<PHINode>(Base);
|
||||
int PHIIdx = BasePHI->getBasicBlockIndex(BB);
|
||||
assert(PHIIdx >= 0);
|
||||
if (MA->getScopArrayInfo()->isPHI())
|
||||
Address = getOrCreateAlloca(Base, PHIOpMap, ".phiops");
|
||||
Val = BasePHI->getIncomingValue(PHIIdx);
|
||||
} else {
|
||||
else
|
||||
Address = getOrCreateAlloca(Base, ScalarMap, ".s2a");
|
||||
Val = Inst;
|
||||
}
|
||||
|
||||
Val = getNewScalarValue(Val, R, ScalarMap, BBMap, GlobalMap);
|
||||
Builder.CreateStore(Val, Address);
|
||||
}
|
||||
|
@ -1124,23 +1117,18 @@ void RegionGenerator::generateScalarStores(ScopStmt &Stmt, BasicBlock *BB,
|
|||
|
||||
Instruction *ScalarBase = cast<Instruction>(MA->getBaseAddr());
|
||||
Instruction *ScalarInst = MA->getAccessInstruction();
|
||||
PHINode *ScalarBasePHI = dyn_cast<PHINode>(ScalarBase);
|
||||
|
||||
// Only generate accesses that belong to this basic block.
|
||||
if (ScalarInst->getParent() != BB)
|
||||
continue;
|
||||
|
||||
Value *Val = nullptr;
|
||||
Value *Val = MA->getAccessValue();
|
||||
AllocaInst *ScalarAddr = nullptr;
|
||||
|
||||
if (MA->getScopArrayInfo()->isPHI()) {
|
||||
int PHIIdx = ScalarBasePHI->getBasicBlockIndex(BB);
|
||||
if (MA->getScopArrayInfo()->isPHI())
|
||||
ScalarAddr = getOrCreateAlloca(ScalarBase, PHIOpMap, ".phiops");
|
||||
Val = ScalarBasePHI->getIncomingValue(PHIIdx);
|
||||
} else {
|
||||
else
|
||||
ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a");
|
||||
Val = ScalarInst;
|
||||
}
|
||||
|
||||
Val = getNewScalarValue(Val, R, ScalarMap, BBMap, GlobalMap);
|
||||
Builder.CreateStore(Val, ScalarAddr);
|
||||
|
|
Loading…
Reference in New Issue