20#include "llvm/ADT/SmallPtrSet.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Analysis/OptimizationRemarkEmitter.h"
23#include "llvm/InitializePasses.h"
34#define DEBUG_TYPE "polly-mse"
38class MaximalStaticExpanderWrapperPass final :
public ScopPass {
42 explicit MaximalStaticExpanderWrapperPass() :
ScopPass(ID) {}
44 ~MaximalStaticExpanderWrapperPass()
override =
default;
65static bool isDimBoundedByConstant(
isl::set Set,
unsigned dim) {
76class MaximalStaticExpansionImpl {
77 OptimizationRemarkEmitter &ORE;
82 void emitRemark(StringRef Msg, Instruction *Inst) {
83 ORE.emit(OptimizationRemarkAnalysis(
DEBUG_TYPE,
"ExpansionRejection", Inst)
103 if (!Map.can_curry())
107 auto TmpMapDomainId =
108 Map.get_space().domain().unwrap().range().get_tuple_id(
isl::dim::set);
117 auto NewMap = Map.factor_domain();
118 auto NewMapDomainId = NewMap.domain().get_tuple_id();
120 if (AccessDomainId.get() != NewMapDomainId.get())
124 MapDependences = MapDependences.
unite(NewMap);
127 return MapDependences;
138 SmallPtrSetImpl<MemoryAccess *> &Writes,
139 SmallPtrSetImpl<MemoryAccess *> &Reads,
Scop &
S) {
141 Writes.insert(
S.getValueDef(SAI));
142 for (
auto MA :
S.getValueUses(SAI))
146 auto Read =
S.getPHIRead(SAI);
148 auto StmtDomain =
isl::union_set(Read->getStatement()->getDomain());
150 auto Writes =
S.getPHIIncomings(SAI);
155 for (
auto Write : Writes) {
156 auto MapDeps = filterDependences(
Dependences, Write);
157 for (
isl::map Map : MapDeps.get_map_list())
158 WriteDomain = WriteDomain.unite(Map.range());
162 if (!StmtDomain.is_equal(WriteDomain)) {
163 emitRemark(SAI->
getName() +
" read from its original value.",
164 Read->getAccessInstruction());
171 emitRemark(SAI->
getName() +
" is a ExitPhi node.",
172 S.getEnteringBlock()->getFirstNonPHI());
176 int NumberWrites = 0;
191 if (!StmtWrites.is_disjoint(AccRel)) {
192 emitRemark(SAI->
getName() +
" has read after write to the same "
193 "element in same statement. The "
194 "dependences found during analysis may "
195 "be wrong because Polly is not able to "
196 "handle such case for now.",
201 StmtReads = StmtReads.unite(AccRel);
203 StmtWrites = StmtWrites.unite(AccRel);
208 emitRemark(SAI->
getName() +
" has a maywrite access.",
217 if (NumberWrites > 1) {
218 emitRemark(SAI->
getName() +
" has more than 1 write access.",
227 auto StmtDomain = Stmt.getDomain();
234 auto MapDependences = filterDependences(
Dependences.reverse(), MA);
237 if (NumberElementMap == 0) {
238 emitRemark(
"The expansion of " + SAI->
getName() +
239 " would lead to a read from the original array.",
244 auto DepsDomain = MapDependences.domain();
248 if (NumberElementMap != 1) {
250 " has too many dependences to be handle for now.",
255 auto DepsDomainSet =
isl::set(DepsDomain);
258 if (!StmtDomain.is_subset(DepsDomainSet)) {
259 emitRemark(
"The expansion of " + SAI->
getName() +
260 " would lead to a read from the original array.",
271 if (NumberWrites == 0) {
272 emitRemark(SAI->
getName() +
" has 0 write access.",
273 S.getEnteringBlock()->getFirstNonPHI());
289 void mapAccess(SmallPtrSetImpl<MemoryAccess *> &Accesses,
292 for (
auto MA : Accesses) {
309 "There are more than one RAW dependencies in the union map.");
330 unsigned in_dimensions =
334 auto Domain = CurrentAccessMap.domain();
340 NewAccessMap = NewAccessMap.add_dims(
isl::dim::out, in_dimensions);
347 auto CurrentOutId = CurrentAccessMap.get_tuple_id(
isl::dim::out);
348 std::string CurrentOutIdString =
352 NewAccessMap = NewAccessMap.set_tuple_id(
isl::dim::out, CurrentOutId);
355 std::vector<unsigned> Sizes;
356 for (
unsigned i = 0; i < in_dimensions; i++) {
357 assert(isDimBoundedByConstant(CurrentStmtDomain, i) &&
358 "Domain boundary are not constant.");
359 auto UpperBound =
getConstant(CurrentStmtDomain.dim_max(i),
true,
false);
360 assert(!UpperBound.is_null() && UpperBound.is_pos() &&
361 !UpperBound.is_nan() &&
362 "The upper bound is not a positive integer.");
364 std::numeric_limits<int>::max() - 1)) &&
365 "The upper bound overflow a int.");
366 Sizes.push_back(UpperBound.get_num_si() + 1);
374 S.createScopArrayInfo(ElementType, CurrentOutIdString, Sizes);
381 NewAccessMap = NewAccessMap.set_tuple_id(
isl::dim::out, NewOutId);
384 auto SpaceMap = NewAccessMap.get_space();
387 NewAccessMap =
isl::map(ConstraintBasicMap);
402 SmallPtrSet<MemoryAccess *, 4> Writes;
403 for (
auto MA :
S.getPHIIncomings(SAI))
405 auto Read =
S.getPHIRead(SAI);
406 auto ExpandedSAI = expandAccess(Read);
408 mapAccess(Writes,
Dependences, ExpandedSAI,
false);
413 OptimizationRemarkEmitter &ORE)
421 SmallVector<ScopArrayInfo *, 4> CurrentSAI(
S.arrays().begin(),
423 for (
auto SAI : CurrentSAI) {
424 SmallPtrSet<MemoryAccess *, 4> AllWrites;
425 SmallPtrSet<MemoryAccess *, 4> AllReads;
426 if (!isExpandable(SAI, AllWrites, AllReads,
S))
432 auto TheWrite = *(AllWrites.begin());
435 mapAccess(AllReads,
Dependences, ExpandedArray,
true);
443 void print(llvm::raw_ostream &OS) {
444 OS <<
"After arrays {\n";
446 for (
auto &
Array :
S.arrays())
451 OS <<
"After accesses {\n";
452 for (
auto &Stmt :
S) {
453 OS.indent(4) << Stmt.getBaseName() <<
"{\n";
454 for (
auto *MA : Stmt)
456 OS.indent(4) <<
"}\n";
462static std::unique_ptr<MaximalStaticExpansionImpl>
463runMaximalStaticExpansion(
Scop &
S, OptimizationRemarkEmitter &ORE,
467 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
468 std::make_unique<MaximalStaticExpansionImpl>(
S,
Dependences, ORE);
477 OptimizationRemarkEmitter ORE(&
S.getFunction());
482 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
483 runMaximalStaticExpansion(
S, ORE, D);
486 *OS <<
"Printing analysis 'Polly - Maximal static expansion of SCoP' for "
488 <<
S.getName() <<
"' in function '" <<
S.getFunction().getName()
492 *OS <<
"MSE result:\n";
497 return PreservedAnalyses::all();
506 return runMSEUsingNPM(
S, SAM, SAR,
nullptr);
513 return runMSEUsingNPM(
S, SAM, SAR, &
OS);
516char MaximalStaticExpanderWrapperPass::ID = 0;
518bool MaximalStaticExpanderWrapperPass::runOnScop(
Scop &
S) {
520 OptimizationRemarkEmitter *ORE =
521 &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
524 auto &DI = getAnalysis<DependenceInfo>();
527 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
528 runMaximalStaticExpansion(
S, *ORE, D);
533void MaximalStaticExpanderWrapperPass::printScop(raw_ostream &OS,
538void MaximalStaticExpanderWrapperPass::getAnalysisUsage(
539 AnalysisUsage &AU)
const {
542 AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
546 return new MaximalStaticExpanderWrapperPass();
550 "Polly - Maximal static expansion of SCoP",
false,
false);
554 "Polly - Maximal static expansion of SCoP",
false,
false)
INITIALIZE_PASS_BEGIN(DependenceInfo, "polly-dependences", "Polly - Calculate dependences", false, false)
INITIALIZE_PASS_END(DependenceInfo, "polly-dependences", "Polly - Calculate dependences", false, false) namespace
INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass)
static isl::basic_map equal(isl::space space, unsigned int n_equal)
static isl::map from_union_map(isl::union_map umap)
static isl::map from_domain(isl::set set)
isl::set project_out(isl::dim type, unsigned int first, unsigned int n) const
isl::id get_tuple_id() const
boolean is_bounded() const
class size tuple_dim() const
class size dim(isl::dim type) const
std::string get_tuple_name() const
isl::union_map unite(isl::union_map umap2) const
__isl_keep isl_union_map * get() const
static isl::union_map empty(isl::ctx ctx)
static isl::union_set empty(isl::ctx ctx)
The accumulated dependence information for a SCoP.
isl::union_map getDependences(int Kinds) const
Get the dependences of type Kinds.
llvm::PreservedAnalyses run(Scop &, ScopAnalysisManager &, ScopStandardAnalysisResults &, SPMUpdater &)
Represent memory accesses in statements.
const ScopArrayInfo * getLatestScopArrayInfo() const
Get the ScopArrayInfo object for the base address, or the one set by setNewAccessRelation().
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
bool isRead() const
Is this a read memory access?
bool isMustWrite() const
Is this a must-write memory access?
void print(raw_ostream &OS) const
Print the MemoryAccess.
const ScopArrayInfo * getScopArrayInfo() const
Legacy name of getOriginalScopArrayInfo().
ScopStmt * getStatement() const
Get the statement that contains this memory access.
bool isMayWrite() const
Is this a may-write memory access?
isl::map getAccessRelation() const
Old name of getLatestAccessRelation().
void setNewAccessRelation(isl::map NewAccessRelation)
Set the updated access relation read from JSCOP file.
A class to store information about arrays in the SCoP.
bool isExitPHIKind() const
Is this array info modeling an MemoryKind::ExitPHI?
bool isArrayKind() const
Is this array info modeling an array?
bool isValueKind() const
Is this array info modeling an llvm::Value?
void setIsOnHeap(bool value)
std::string getName() const
Get the name of this memory reference.
bool isPHIKind() const
Is this array info modeling special PHI node memory?
isl::id getBasePtrId() const
Return the isl id for the base pointer.
Type * getElementType() const
Get the canonical element type of this array.
ScopPass - This class adapts the RegionPass interface to allow convenient creation of passes that ope...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnScop(Scop &S)=0
runOnScop - This method must be overloaded to perform the desired Polyhedral transformation or analys...
virtual void printScop(raw_ostream &OS, Scop &S) const
Print method for SCoPs.
isl::set getDomain() const
Get the iteration domain of this ScopStmt.
static __isl_give isl_poly * expand(__isl_take isl_poly *poly, int *exp, int first)
This file contains the declaration of the PolyhedralInfo class, which will provide an interface to ex...
llvm::Pass * createMaximalStaticExpansionPass()
@ Array
MemoryKind::Array: Models a one or multi-dimensional array.
isl::val getConstant(isl::pw_aff PwAff, bool Max, bool Min)
If PwAff maps to a constant, return said constant.
AnalysisManager< Scop, ScopStandardAnalysisResults & > ScopAnalysisManager
PreservedAnalyses run(Scop &S, ScopAnalysisManager &, ScopStandardAnalysisResults &SAR, SPMUpdater &)
static TupleKindPtr Domain("Domain")
isl_size isl_union_map_n_map(__isl_keep isl_union_map *umap)