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 Reads.insert_range(
S.getValueUses(SAI));
145 auto Read =
S.getPHIRead(SAI);
147 auto StmtDomain =
isl::union_set(Read->getStatement()->getDomain());
149 auto Writes =
S.getPHIIncomings(SAI);
154 for (
auto Write : Writes) {
155 auto MapDeps = filterDependences(
Dependences, Write);
156 for (
isl::map Map : MapDeps.get_map_list())
157 WriteDomain = WriteDomain.unite(Map.range());
161 if (!StmtDomain.is_equal(WriteDomain)) {
162 emitRemark(SAI->
getName() +
" read from its original value.",
163 Read->getAccessInstruction());
170 emitRemark(SAI->
getName() +
" is a ExitPhi node.",
171 &*
S.getEnteringBlock()->getFirstNonPHIIt());
175 int NumberWrites = 0;
190 if (!StmtWrites.is_disjoint(AccRel)) {
191 emitRemark(SAI->
getName() +
" has read after write to the same "
192 "element in same statement. The "
193 "dependences found during analysis may "
194 "be wrong because Polly is not able to "
195 "handle such case for now.",
200 StmtReads = StmtReads.unite(AccRel);
202 StmtWrites = StmtWrites.unite(AccRel);
207 emitRemark(SAI->
getName() +
" has a maywrite access.",
216 if (NumberWrites > 1) {
217 emitRemark(SAI->
getName() +
" has more than 1 write access.",
226 auto StmtDomain = Stmt.getDomain();
233 auto MapDependences = filterDependences(
Dependences.reverse(), MA);
236 if (NumberElementMap == 0) {
237 emitRemark(
"The expansion of " + SAI->
getName() +
238 " would lead to a read from the original array.",
243 auto DepsDomain = MapDependences.domain();
247 if (NumberElementMap != 1) {
249 " has too many dependences to be handle for now.",
254 auto DepsDomainSet =
isl::set(DepsDomain);
257 if (!StmtDomain.is_subset(DepsDomainSet)) {
258 emitRemark(
"The expansion of " + SAI->
getName() +
259 " would lead to a read from the original array.",
270 if (NumberWrites == 0) {
271 emitRemark(SAI->
getName() +
" has 0 write access.",
272 &*
S.getEnteringBlock()->getFirstNonPHIIt());
288 void mapAccess(SmallPtrSetImpl<MemoryAccess *> &Accesses,
291 for (
auto MA : Accesses) {
308 "There are more than one RAW dependencies in the union map.");
329 unsigned in_dimensions =
333 auto Domain = CurrentAccessMap.domain();
339 NewAccessMap = NewAccessMap.add_dims(
isl::dim::out, in_dimensions);
346 auto CurrentOutId = CurrentAccessMap.get_tuple_id(
isl::dim::out);
347 std::string CurrentOutIdString =
351 NewAccessMap = NewAccessMap.set_tuple_id(
isl::dim::out, CurrentOutId);
354 std::vector<unsigned> Sizes;
355 for (
unsigned i = 0; i < in_dimensions; i++) {
356 assert(isDimBoundedByConstant(CurrentStmtDomain, i) &&
357 "Domain boundary are not constant.");
358 auto UpperBound =
getConstant(CurrentStmtDomain.dim_max(i),
true,
false);
359 assert(!UpperBound.is_null() && UpperBound.is_pos() &&
360 !UpperBound.is_nan() &&
361 "The upper bound is not a positive integer.");
363 std::numeric_limits<int>::max() - 1)) &&
364 "The upper bound overflow a int.");
365 Sizes.push_back(UpperBound.get_num_si() + 1);
373 S.createScopArrayInfo(ElementType, CurrentOutIdString, Sizes);
380 NewAccessMap = NewAccessMap.set_tuple_id(
isl::dim::out, NewOutId);
383 auto SpaceMap = NewAccessMap.get_space();
386 NewAccessMap =
isl::map(ConstraintBasicMap);
401 SmallPtrSet<MemoryAccess *, 4> Writes(llvm::from_range,
402 S.getPHIIncomings(SAI));
403 auto Read =
S.getPHIRead(SAI);
404 auto ExpandedSAI = expandAccess(Read);
406 mapAccess(Writes,
Dependences, ExpandedSAI,
false);
411 OptimizationRemarkEmitter &ORE)
419 SmallVector<ScopArrayInfo *, 4> CurrentSAI(
S.arrays().begin(),
421 for (
auto SAI : CurrentSAI) {
422 SmallPtrSet<MemoryAccess *, 4> AllWrites;
423 SmallPtrSet<MemoryAccess *, 4> AllReads;
424 if (!isExpandable(SAI, AllWrites, AllReads,
S))
430 auto TheWrite = *(AllWrites.begin());
433 mapAccess(AllReads,
Dependences, ExpandedArray,
true);
441 void print(llvm::raw_ostream &OS) {
442 OS <<
"After arrays {\n";
444 for (
auto &
Array :
S.arrays())
449 OS <<
"After accesses {\n";
450 for (
auto &Stmt :
S) {
451 OS.indent(4) << Stmt.getBaseName() <<
"{\n";
452 for (
auto *MA : Stmt)
454 OS.indent(4) <<
"}\n";
460static std::unique_ptr<MaximalStaticExpansionImpl>
461runMaximalStaticExpansion(
Scop &
S, OptimizationRemarkEmitter &ORE,
465 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
466 std::make_unique<MaximalStaticExpansionImpl>(
S,
Dependences, ORE);
475 OptimizationRemarkEmitter ORE(&
S.getFunction());
480 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
481 runMaximalStaticExpansion(
S, ORE, D);
484 *OS <<
"Printing analysis 'Polly - Maximal static expansion of SCoP' for "
486 <<
S.getName() <<
"' in function '" <<
S.getFunction().getName()
490 *OS <<
"MSE result:\n";
495 return PreservedAnalyses::all();
504 return runMSEUsingNPM(
S, SAM, SAR,
nullptr);
511 return runMSEUsingNPM(
S, SAM, SAR, &
OS);
514char MaximalStaticExpanderWrapperPass::ID = 0;
516bool MaximalStaticExpanderWrapperPass::runOnScop(
Scop &
S) {
518 OptimizationRemarkEmitter *ORE =
519 &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
522 auto &DI = getAnalysis<DependenceInfo>();
525 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
526 runMaximalStaticExpansion(
S, *ORE, D);
531void MaximalStaticExpanderWrapperPass::printScop(raw_ostream &OS,
536void MaximalStaticExpanderWrapperPass::getAnalysisUsage(
537 AnalysisUsage &AU)
const {
540 AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
544 return new MaximalStaticExpanderWrapperPass();
548 "Polly - Maximal static expansion of SCoP",
false,
false);
552 "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)