Skip to content

Commit

Permalink
Extend the jscop interface to allow the user to declare new arrays an…
Browse files Browse the repository at this point in the history
…d to reference these arrays from access expressions

Extend the jscop interface to allow the user to export arrays. It is required
that already existing arrays of the list of arrays correspond to arrays
of the SCoP. Each array that is appended to the list will be newly created.
Furthermore, we allow the user to modify access expressions to reference
any array in case it has the same element type.

Reviewed-by: Tobias Grosser <tobias@grosser.es>

Differential Revision: https://reviews.llvm.org/D22828

llvm-svn: 277263
  • Loading branch information
gareevroman committed Jul 30, 2016
1 parent 5d304b2 commit d7754a1
Show file tree
Hide file tree
Showing 11 changed files with 458 additions and 42 deletions.
3 changes: 3 additions & 0 deletions polly/include/polly/CodeGen/IslNodeBuilder.h
Expand Up @@ -55,6 +55,9 @@ class IslNodeBuilder {
void addParameters(__isl_take isl_set *Context);
void create(__isl_take isl_ast_node *Node);

/// @brief Allocate memory for all new arrays created by Polly.
void allocateNewArrays();

/// @brief Preload all memory loads that are invariant.
bool preloadInvariantLoads();

Expand Down
59 changes: 46 additions & 13 deletions polly/include/polly/ScopInfo.h
Expand Up @@ -231,9 +231,10 @@ class ScopArrayInfo {
/// @param Kind The kind of the array object.
/// @param DL The data layout of the module.
/// @param S The scop this array object belongs to.
/// @param BaseName The optional name of this memory reference.
ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *IslCtx,
ArrayRef<const SCEV *> DimensionSizes, enum MemoryKind Kind,
const DataLayout &DL, Scop *S);
const DataLayout &DL, Scop *S, const char *BaseName = nullptr);

/// @brief Update the element type of the ScopArrayInfo object.
///
Expand Down Expand Up @@ -1398,16 +1399,29 @@ class Scop {
/// @brief The affinator used to translate SCEVs to isl expressions.
SCEVAffinator Affinator;

typedef MapVector<std::pair<AssertingVH<const Value>, int>,
std::unique_ptr<ScopArrayInfo>>
typedef std::map<std::pair<AssertingVH<const Value>, int>,
std::unique_ptr<ScopArrayInfo>>
ArrayInfoMapTy;

typedef StringMap<std::unique_ptr<ScopArrayInfo>> ArrayNameMapTy;

typedef SetVector<ScopArrayInfo *> ArrayInfoSetTy;

/// @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 A map to remember ScopArrayInfo objects for all names of memory
/// references.
ArrayNameMapTy ScopArrayNameMap;

/// @brief A set to remember ScopArrayInfo objects.
/// @see Scop::ScopArrayInfoMap
ArrayInfoSetTy ScopArrayInfoSet;

/// @brief The assumptions under which this scop was built.
///
/// When constructing a scop sometimes the exact representation of a statement
Expand Down Expand Up @@ -1855,21 +1869,21 @@ class Scop {
/// could be executed.
bool isEmpty() const { return Stmts.empty(); }

typedef ArrayInfoMapTy::iterator array_iterator;
typedef ArrayInfoMapTy::const_iterator const_array_iterator;
typedef iterator_range<ArrayInfoMapTy::iterator> array_range;
typedef iterator_range<ArrayInfoMapTy::const_iterator> const_array_range;
typedef ArrayInfoSetTy::iterator array_iterator;
typedef ArrayInfoSetTy::const_iterator const_array_iterator;
typedef iterator_range<ArrayInfoSetTy::iterator> array_range;
typedef iterator_range<ArrayInfoSetTy::const_iterator> const_array_range;

inline array_iterator array_begin() { return ScopArrayInfoMap.begin(); }
inline array_iterator array_begin() { return ScopArrayInfoSet.begin(); }

inline array_iterator array_end() { return ScopArrayInfoMap.end(); }
inline array_iterator array_end() { return ScopArrayInfoSet.end(); }

inline const_array_iterator array_begin() const {
return ScopArrayInfoMap.begin();
return ScopArrayInfoSet.begin();
}

inline const_array_iterator array_end() const {
return ScopArrayInfoMap.end();
return ScopArrayInfoSet.end();
}

inline array_range arrays() {
Expand Down Expand Up @@ -2148,10 +2162,21 @@ class Scop {
///
/// @param ElementType The type of the elements stored in this array.
/// @param Kind The kind of the array info object.
/// @param BaseName The optional name of this memory reference.
const ScopArrayInfo *getOrCreateScopArrayInfo(Value *BasePtr,
Type *ElementType,
ArrayRef<const SCEV *> Sizes,
ScopArrayInfo::MemoryKind Kind);
ScopArrayInfo::MemoryKind Kind,
const char *BaseName = nullptr);

/// @brief Create an array and return the corresponding ScopArrayInfo object.
///
/// @param ElementType The type of the elements stored in this array.
/// @param BaseName The name of this memory reference.
/// @param Sizes The sizes of dimensions.
const ScopArrayInfo *createScopArrayInfo(Type *ElementType,
const std::string &BaseName,
const std::vector<unsigned> &Sizes);

/// @brief Return the cached ScopArrayInfo object for @p BasePtr.
///
Expand All @@ -2165,7 +2190,11 @@ class Scop {
/// @param BasePtr The base pointer of the ScopArrayInfo object to invalidate.
/// @param Kind The Kind of the ScopArrayInfo object.
void invalidateScopArrayInfo(Value *BasePtr, ScopArrayInfo::MemoryKind Kind) {
ScopArrayInfoMap.erase(std::make_pair(BasePtr, Kind));
auto It = ScopArrayInfoMap.find(std::make_pair(BasePtr, Kind));
if (It == ScopArrayInfoMap.end())
return;
ScopArrayInfoSet.remove(It->second.get());
ScopArrayInfoMap.erase(It);
}

void setContext(isl_set *NewContext);
Expand Down Expand Up @@ -2275,6 +2304,10 @@ class Scop {
/// >0 for other loops in the SCoP
/// -1 if @p L is nullptr or there is no outermost loop in the SCoP
int getRelativeLoopDepth(const Loop *L) const;

/// @brief Find the ScopArrayInfo associated with an isl Id
/// that has name @p Name.
ScopArrayInfo *getArrayInfoByName(const std::string BaseName);
};

/// @brief Print Scop scop to raw_ostream O.
Expand Down
57 changes: 47 additions & 10 deletions polly/lib/Analysis/ScopInfo.cpp
Expand Up @@ -169,13 +169,21 @@ static const ScopArrayInfo *identifyBasePtrOriginSAI(Scop *S, Value *BasePtr) {

ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx,
ArrayRef<const SCEV *> Sizes, enum MemoryKind Kind,
const DataLayout &DL, Scop *S)
const DataLayout &DL, Scop *S,
const char *BaseName)
: BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) {
std::string BasePtrName =
getIslCompatibleName("MemRef_", BasePtr, Kind == MK_PHI ? "__phi" : "");
BaseName ? BaseName : getIslCompatibleName("MemRef_", BasePtr,
Kind == MK_PHI ? "__phi" : "");
Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);

updateSizes(Sizes);

if (!BasePtr) {
BasePtrOriginSAI = nullptr;
return;
}

BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr);
if (BasePtrOriginSAI)
const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this);
Expand Down Expand Up @@ -3133,7 +3141,9 @@ Scop::~Scop() {
// Explicitly release all Scop objects and the underlying isl objects before
// we relase the isl context.
Stmts.clear();
ScopArrayInfoSet.clear();
ScopArrayInfoMap.clear();
ScopArrayNameMap.clear();
AccFuncMap.clear();
}

Expand Down Expand Up @@ -3476,15 +3486,19 @@ void Scop::hoistInvariantLoads() {
isl_union_map_free(Writes);
}

const ScopArrayInfo *
Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType,
ArrayRef<const SCEV *> Sizes,
ScopArrayInfo::MemoryKind Kind) {
auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)];
const ScopArrayInfo *Scop::getOrCreateScopArrayInfo(
Value *BasePtr, Type *ElementType, ArrayRef<const SCEV *> Sizes,
ScopArrayInfo::MemoryKind Kind, const char *BaseName) {
assert((BasePtr || BaseName) &&
"BasePtr and BaseName can not be nullptr at the same time.");
assert(!(BasePtr && BaseName) && "BaseName is redundant.");
auto &SAI = BasePtr ? ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]
: ScopArrayNameMap[BaseName];
if (!SAI) {
auto &DL = getFunction().getParent()->getDataLayout();
SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind,
DL, this));
DL, this, BaseName));
ScopArrayInfoSet.insert(SAI.get());
} else {
SAI->updateElementType(ElementType);
// In case of mismatching array sizes, we bail out by setting the run-time
Expand All @@ -3495,6 +3509,21 @@ Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType,
return SAI.get();
}

const ScopArrayInfo *
Scop::createScopArrayInfo(Type *ElementType, const std::string &BaseName,
const std::vector<unsigned> &Sizes) {
auto *DimSizeType = Type::getInt64Ty(getSE()->getContext());
std::vector<const SCEV *> SCEVSizes;

for (auto size : Sizes)
SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false));

auto *SAI =
getOrCreateScopArrayInfo(nullptr, ElementType, SCEVSizes,
ScopArrayInfo::MK_Array, BaseName.c_str());
return SAI;
}

const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr,
ScopArrayInfo::MemoryKind Kind) {
auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get();
Expand Down Expand Up @@ -3781,14 +3810,14 @@ void Scop::printArrayInfo(raw_ostream &OS) const {
OS << "Arrays {\n";

for (auto &Array : arrays())
Array.second->print(OS);
Array->print(OS);

OS.indent(4) << "}\n";

OS.indent(4) << "Arrays (Bounds as pw_affs) {\n";

for (auto &Array : arrays())
Array.second->print(OS, /* SizeAsPwAff */ true);
Array->print(OS, /* SizeAsPwAff */ true);

OS.indent(4) << "}\n";
}
Expand Down Expand Up @@ -4187,6 +4216,14 @@ int Scop::getRelativeLoopDepth(const Loop *L) const {
return L->getLoopDepth() - OuterLoop->getLoopDepth();
}

ScopArrayInfo *Scop::getArrayInfoByName(const std::string BaseName) {
for (auto &SAI : arrays()) {
if (SAI->getName() == BaseName)
return SAI;
}
return nullptr;
}

//===----------------------------------------------------------------------===//
void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LoopInfoWrapperPass>();
Expand Down
9 changes: 3 additions & 6 deletions polly/lib/CodeGen/BlockGenerators.cpp
Expand Up @@ -485,8 +485,7 @@ void BlockGenerator::createScalarInitialization(Scop &S) {

Builder.SetInsertPoint(StartBB->getTerminator());

for (auto &Pair : S.arrays()) {
auto &Array = Pair.second;
for (auto &Array : S.arrays()) {
if (Array->getNumberOfDimensions() != 0)
continue;
if (Array->isPHIKind()) {
Expand Down Expand Up @@ -576,8 +575,7 @@ void BlockGenerator::createScalarFinalization(Scop &S) {
}

void BlockGenerator::findOutsideUsers(Scop &S) {
for (auto &Pair : S.arrays()) {
auto &Array = Pair.second;
for (auto &Array : S.arrays()) {

if (Array->getNumberOfDimensions() != 0)
continue;
Expand Down Expand Up @@ -613,8 +611,7 @@ void BlockGenerator::createExitPHINodeMerges(Scop &S) {

Builder.SetInsertPoint(OptExitBB->getTerminator());

for (auto &Pair : S.arrays()) {
auto &SAI = Pair.second;
for (auto &SAI : S.arrays()) {
auto *Val = SAI->getBasePtr();

// Only Value-like scalars need a merge PHI. Exit block PHIs receive either
Expand Down
1 change: 1 addition & 0 deletions polly/lib/CodeGen/CodeGeneration.cpp
Expand Up @@ -189,6 +189,7 @@ class CodeGeneration : public ScopPass {

isl_ast_node_free(AstRoot);
} else {
NodeBuilder.allocateNewArrays();

NodeBuilder.addParameters(S.getContext());

Expand Down
26 changes: 26 additions & 0 deletions polly/lib/CodeGen/IslNodeBuilder.cpp
Expand Up @@ -1157,6 +1157,32 @@ bool IslNodeBuilder::preloadInvariantEquivClass(
return true;
}

void IslNodeBuilder::allocateNewArrays() {
for (auto &SAI : S.arrays()) {
if (SAI->getBasePtr())
continue;

Type *NewArrayType = nullptr;
for (unsigned i = SAI->getNumberOfDimensions() - 1; i >= 1; i--) {
auto *DimSize = SAI->getDimensionSize(i);
unsigned UnsignedDimSize = static_cast<const SCEVConstant *>(DimSize)
->getAPInt()
.getLimitedValue();

if (!NewArrayType)
NewArrayType = SAI->getElementType();

NewArrayType = ArrayType::get(NewArrayType, UnsignedDimSize);
}

auto InstIt =
Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator();
Value *CreatedArray =
new AllocaInst(NewArrayType, SAI->getName(), &*InstIt);
SAI->setBasePtr(CreatedArray);
}
}

bool IslNodeBuilder::preloadInvariantLoads() {

auto &InvariantEquivClasses = S.getInvariantAccesses();
Expand Down
11 changes: 4 additions & 7 deletions polly/lib/CodeGen/PPCGCodeGeneration.cpp
Expand Up @@ -794,7 +794,7 @@ SetVector<Value *> GPUNodeBuilder::getReferencesInKernel(ppcg_kernel *Kernel) {
findValues(Expr, SE, SubtreeValues);

for (auto &SAI : S.arrays())
SubtreeValues.remove(SAI.second->getBasePtr());
SubtreeValues.remove(SAI->getBasePtr());

isl_space *Space = S.getParamSpace();
for (long i = 0; i < isl_space_dim(Space, isl_dim_param); i++) {
Expand Down Expand Up @@ -1379,7 +1379,7 @@ class PPCGCodeGeneration : public ScopPass {
}

for (auto &Array : S->arrays()) {
auto Id = Array.second->getBasePtrId();
auto Id = Array->getBasePtrId();
Names = isl_id_to_ast_expr_set(Names, Id, isl_ast_expr_copy(Zero));
}

Expand Down Expand Up @@ -1550,9 +1550,7 @@ class PPCGCodeGeneration : public ScopPass {
/// @param PPCGProg The program to compute the arrays for.
void createArrays(gpu_prog *PPCGProg) {
int i = 0;
for (auto &Element : S->arrays()) {
ScopArrayInfo *Array = Element.second.get();

for (auto &Array : S->arrays()) {
std::string TypeName;
raw_string_ostream OS(TypeName);

Expand Down Expand Up @@ -1595,8 +1593,7 @@ class PPCGCodeGeneration : public ScopPass {
isl_union_map *getArrayIdentity() {
isl_union_map *Maps = isl_union_map_empty(S->getParamSpace());

for (auto &Item : S->arrays()) {
ScopArrayInfo *Array = Item.second.get();
for (auto &Array : S->arrays()) {
isl_space *Space = Array->getSpace();
Space = isl_space_map_from_set(Space);
isl_map *Identity = isl_map_identity(Space);
Expand Down

0 comments on commit d7754a1

Please sign in to comment.