20#include "llvm/ADT/Statistic.h"
21#include "llvm/InitializePasses.h"
22#include "llvm/Support/Debug.h"
26#define DEBUG_TYPE "polly-simplify"
33#define TWO_STATISTICS(VARNAME, DESC) \
34 static llvm::Statistic VARNAME[2] = { \
35 {DEBUG_TYPE, #VARNAME "0", DESC " (first)"}, \
36 {DEBUG_TYPE, #VARNAME "1", DESC " (second)"}}
42static unsigned const SimplifyMaxDisjuncts = 4;
48 "Number of statement with empty domains removed in any SCoP");
49TWO_STATISTICS(TotalOverwritesRemoved,
"Number of removed overwritten writes");
50TWO_STATISTICS(TotalWritesCoalesced,
"Number of writes coalesced with another");
52 "Number of writes of same value removed in any SCoP");
54 "Number of empty partial accesses removed");
55TWO_STATISTICS(TotalDeadAccessesRemoved,
"Number of dead accesses removed");
57 "Number of unused instructions removed");
58TWO_STATISTICS(TotalStmtsRemoved,
"Number of statements removed in any SCoP");
60TWO_STATISTICS(NumValueWrites,
"Number of scalar value writes after Simplify");
62 NumValueWritesInLoops,
63 "Number of scalar value writes nested in affine loops after Simplify");
65 "Number of scalar phi writes after the first simplification");
68 "Number of scalar phi writes nested in affine loops after Simplify");
69TWO_STATISTICS(NumSingletonWrites,
"Number of singleton writes after Simplify");
71 NumSingletonWritesInLoops,
72 "Number of singleton writes nested in affine loops after Simplify");
102 SimplifyMaxDisjuncts)
103 return UMap.
unite(Map);
109 Result = Result.
unite(BMap);
114 Result = Result.
unite(BMap);
119 UResult.
unite(Result);
124class SimplifyImpl final {
134 int EmptyDomainsRemoved = 0;
137 int OverwritesRemoved = 0;
140 int WritesCoalesced = 0;
143 int RedundantWritesRemoved = 0;
146 int EmptyPartialAccessesRemoved = 0;
149 int DeadAccessesRemoved = 0;
152 int DeadInstructionsRemoved = 0;
155 int StmtsRemoved = 0;
165 void removeEmptyDomainStmts();
172 void removeOverwrites();
181 void coalesceWrites();
185 void removeRedundantWrites();
188 void removeUnnecessaryStmts();
191 void removeEmptyPartialAccesses();
195 void markAndSweep(LoopInfo *LI);
198 void printStatistics(llvm::raw_ostream &OS,
int Indent = 0)
const;
201 void printAccesses(llvm::raw_ostream &OS,
int Indent = 0)
const;
204 explicit SimplifyImpl(
int CallNo = 0) : CallNo(CallNo) {}
206 void run(
Scop &
S, LoopInfo *LI);
208 void printScop(raw_ostream &OS,
Scop &
S)
const;
211 bool isModified()
const;
215bool SimplifyImpl::isModified()
const {
216 return EmptyDomainsRemoved > 0 || OverwritesRemoved > 0 ||
217 WritesCoalesced > 0 || RedundantWritesRemoved > 0 ||
218 EmptyPartialAccessesRemoved > 0 || DeadAccessesRemoved > 0 ||
219 DeadInstructionsRemoved > 0 || StmtsRemoved > 0;
230void SimplifyImpl::removeEmptyDomainStmts() {
231 size_t NumStmtsBefore =
S->getSize();
233 S->removeStmts([](
ScopStmt &Stmt) ->
bool {
234 auto EffectiveDomain =
239 assert(NumStmtsBefore >=
S->getSize());
240 EmptyDomainsRemoved = NumStmtsBefore -
S->getSize();
241 POLLY_DEBUG(dbgs() <<
"Removed " << EmptyDomainsRemoved <<
" (of "
242 << NumStmtsBefore <<
") statements with empty domains \n");
243 TotalEmptyDomainsRemoved[CallNo] += EmptyDomainsRemoved;
251void SimplifyImpl::removeOverwrites() {
252 for (
auto &Stmt : *
S) {
260 for (
auto *MA : reverse(Accesses)) {
277 WillBeOverwritten = WillBeOverwritten.
subtract(AccRelUniv);
283 if (AccRelUnion.
is_subset(WillBeOverwritten)) {
285 <<
" which will be overwritten anyway\n");
289 TotalOverwritesRemoved[CallNo]++;
296 WillBeOverwritten = underapproximatedAddMap(WillBeOverwritten, AccRel);
309void SimplifyImpl::coalesceWrites() {
310 for (
auto &Stmt : *
S) {
318 SmallDenseMap<Value *, isl::set> ValueSets;
319 auto makeValueSet = [&ValueSets,
this](
Value *V) ->
isl::set {
368 ValSet = makeValueSet(StoredVal);
425 TotalWritesCoalesced[CallNo]++;
438 SmallPtrSet<MemoryAccess *, 2> TouchedAccesses;
446 TouchedAccesses.insert(MA);
456 if (!TouchedAccesses.count(MA))
457 NewFutureWrites = NewFutureWrites.
unite(FutureWrite);
459 FutureWrites = NewFutureWrites;
473 FutureWrites = FutureWrites.
unite(AccRelValAcc);
481void SimplifyImpl::removeRedundantWrites() {
482 for (
auto &Stmt : *
S) {
483 SmallDenseMap<Value *, isl::set> ValueSets;
484 auto makeValueSet = [&ValueSets,
this](
Value *V) ->
isl::set {
534 AccRelWrapped, makeValueSet(StoredVal));
536 POLLY_DEBUG(dbgs() <<
"Cleanup of " << MA <<
":\n");
537 POLLY_DEBUG(dbgs() <<
" Scalar: " << *StoredVal <<
"\n");
538 POLLY_DEBUG(dbgs() <<
" AccRel: " << AccRel <<
"\n");
542 RedundantWritesRemoved++;
543 TotalRedundantWritesRemoved[CallNo]++;
553 if (LoadedVal && IsOrdered) {
555 AccRelWrapped, makeValueSet(LoadedVal));
557 Known = Known.
unite(AccRelVal);
575void SimplifyImpl::removeUnnecessaryStmts() {
576 auto NumStmtsBefore =
S->getSize();
577 S->simplifySCoP(
true);
578 assert(NumStmtsBefore >=
S->getSize());
579 StmtsRemoved = NumStmtsBefore -
S->getSize();
580 POLLY_DEBUG(dbgs() <<
"Removed " << StmtsRemoved <<
" (of " << NumStmtsBefore
581 <<
") statements\n");
582 TotalStmtsRemoved[CallNo] += StmtsRemoved;
586void SimplifyImpl::removeEmptyPartialAccesses() {
589 SmallVector<MemoryAccess *, 8> DeferredRemove;
600 dbgs() <<
"Removing " << MA
601 <<
" because it's a partial access that never occurs\n");
602 DeferredRemove.push_back(MA);
606 Stmt.removeSingleMemoryAccess(MA);
607 EmptyPartialAccessesRemoved++;
608 TotalEmptyPartialAccessesRemoved[CallNo]++;
615void SimplifyImpl::markAndSweep(LoopInfo *LI) {
616 DenseSet<MemoryAccess *> UsedMA;
617 DenseSet<VirtualInstruction> UsedInsts;
625 SmallVector<MemoryAccess *, 64> AllMAs;
627 AllMAs.append(Stmt.begin(), Stmt.end());
630 if (UsedMA.count(MA))
633 <<
" because its value is not used\n");
637 DeadAccessesRemoved++;
638 TotalDeadAccessesRemoved[CallNo]++;
647 SmallVector<Instruction *, 32> AllInsts(Stmt.
insts_begin(),
649 SmallVector<Instruction *, 32> RemainInsts;
651 for (Instruction *Inst : AllInsts) {
652 auto It = UsedInsts.find({&Stmt, Inst});
653 if (It == UsedInsts.end()) {
654 POLLY_DEBUG(dbgs() <<
"Removing "; Inst->print(dbgs());
655 dbgs() <<
" because it is not used\n");
656 DeadInstructionsRemoved++;
657 TotalDeadInstructionsRemoved[CallNo]++;
661 RemainInsts.push_back(Inst);
673void SimplifyImpl::printStatistics(llvm::raw_ostream &OS,
int Indent)
const {
674 OS.indent(Indent) <<
"Statistics {\n";
675 OS.indent(Indent + 4) <<
"Empty domains removed: " << EmptyDomainsRemoved
677 OS.indent(Indent + 4) <<
"Overwrites removed: " << OverwritesRemoved <<
'\n';
678 OS.indent(Indent + 4) <<
"Partial writes coalesced: " << WritesCoalesced
680 OS.indent(Indent + 4) <<
"Redundant writes removed: "
681 << RedundantWritesRemoved <<
"\n";
682 OS.indent(Indent + 4) <<
"Accesses with empty domains removed: "
683 << EmptyPartialAccessesRemoved <<
"\n";
684 OS.indent(Indent + 4) <<
"Dead accesses removed: " << DeadAccessesRemoved
686 OS.indent(Indent + 4) <<
"Dead instructions removed: "
687 << DeadInstructionsRemoved <<
'\n';
688 OS.indent(Indent + 4) <<
"Stmts removed: " << StmtsRemoved <<
"\n";
689 OS.indent(Indent) <<
"}\n";
693void SimplifyImpl::printAccesses(llvm::raw_ostream &OS,
int Indent)
const {
694 OS.indent(Indent) <<
"After accesses {\n";
695 for (
auto &Stmt : *
S) {
696 OS.indent(Indent + 4) << Stmt.
getBaseName() <<
"\n";
697 for (
auto *MA : Stmt)
700 OS.indent(Indent) <<
"}\n";
703void SimplifyImpl::run(
Scop &
S, LoopInfo *LI) {
710 ScopsProcessed[CallNo]++;
712 POLLY_DEBUG(dbgs() <<
"Removing statements that are never executed...\n");
713 removeEmptyDomainStmts();
715 POLLY_DEBUG(dbgs() <<
"Removing partial writes that never happen...\n");
716 removeEmptyPartialAccesses();
721 POLLY_DEBUG(dbgs() <<
"Coalesce partial writes...\n");
724 POLLY_DEBUG(dbgs() <<
"Removing redundant writes...\n");
725 removeRedundantWrites();
727 POLLY_DEBUG(dbgs() <<
"Cleanup unused accesses...\n");
730 POLLY_DEBUG(dbgs() <<
"Removing statements without side effects...\n");
731 removeUnnecessaryStmts();
734 ScopsModified[CallNo]++;
738 auto ScopStats =
S.getStatistics();
739 NumValueWrites[CallNo] += ScopStats.NumValueWrites;
740 NumValueWritesInLoops[CallNo] += ScopStats.NumValueWritesInLoops;
741 NumPHIWrites[CallNo] += ScopStats.NumPHIWrites;
742 NumPHIWritesInLoops[CallNo] += ScopStats.NumPHIWritesInLoops;
743 NumSingletonWrites[CallNo] += ScopStats.NumSingletonWrites;
744 NumSingletonWritesInLoops[CallNo] += ScopStats.NumSingletonWritesInLoops;
747void SimplifyImpl::printScop(raw_ostream &OS,
Scop &
S)
const {
749 "Can only print analysis for the last processed SCoP");
753 OS <<
"SCoP could not be simplified\n";
759class SimplifyWrapperPass final :
public ScopPass {
763 std::optional<SimplifyImpl> Impl;
765 explicit SimplifyWrapperPass(
int CallNo = 0) :
ScopPass(ID), CallNo(CallNo) {}
769 AU.addRequired<LoopInfoWrapperPass>();
770 AU.setPreservesAll();
774 LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
776 Impl.emplace(CallNo);
784 Impl->printScop(OS,
S);
787 void releaseMemory()
override { Impl.reset(); }
790char SimplifyWrapperPass::ID;
792static llvm::PreservedAnalyses
796 SimplifyImpl Impl(CallNo);
797 Impl.run(
S, &SAR.
LI);
799 *OS <<
"Printing analysis 'Polly - Simplify' for region: '" <<
S.getName()
800 <<
"' in function '" <<
S.getFunction().getName() <<
"':\n";
801 Impl.printScop(*OS,
S);
804 if (!Impl.isModified())
805 return llvm::PreservedAnalyses::all();
807 PreservedAnalyses PA;
808 PA.preserveSet<AllAnalysesOn<Module>>();
809 PA.preserveSet<AllAnalysesOn<Function>>();
810 PA.preserveSet<AllAnalysesOn<Loop>>();
819 return runSimplifyUsingNPM(
S, SAM, SAR, U,
CallNo,
nullptr);
822llvm::PreservedAnalyses
825 return runSimplifyUsingNPM(
S, SAM, SAR, U,
CallNo, &
OS);
829 SmallVector<MemoryAccess *, 32> Accesses;
832 if (isImplicitRead(
MemAcc))
833 Accesses.push_back(
MemAcc);
836 if (isExplicitAccess(
MemAcc))
837 Accesses.push_back(
MemAcc);
840 if (isImplicitWrite(
MemAcc))
841 Accesses.push_back(
MemAcc);
847 return new SimplifyWrapperPass(CallNo);
869 SimplifyWrapperPass &P = getAnalysis<SimplifyWrapperPass>();
871 OS <<
"Printing analysis '" << P.getPassName() <<
"' for region: '"
872 <<
S.getRegion().getNameStr() <<
"' in function '"
873 <<
S.getFunction().getName() <<
"':\n";
881 AU.addRequired<SimplifyWrapperPass>();
882 AU.setPreservesAll();
886 llvm::raw_ostream &
OS;
889char SimplifyPrinterLegacyPass::ID = 0;
893 return new SimplifyPrinterLegacyPass(OS);
897 "Polly - Print Simplify actions",
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)
polly print Polly Print Simplify actions
#define TWO_STATISTICS(VARNAME, DESC)
Print result from SimplifyWrapperPass.
SimplifyPrinterLegacyPass()
bool runOnScop(Scop &S) override
runOnScop - This method must be overloaded to perform the desired Polyhedral transformation or analys...
void getAnalysisUsage(AnalysisUsage &AU) const override
SimplifyPrinterLegacyPass(llvm::raw_ostream &OS)
static isl::id alloc(isl::ctx ctx, const std::string &name, void *user)
isl::basic_map_list get_basic_map_list() const
static isl::map universe(isl::space space)
isl::map intersect_params(isl::set params) const
boolean is_subset(const isl::map &map2) const
class size n_basic_map() const
static isl::map from_domain_and_range(isl::set domain, isl::set range)
isl::map unite(isl::map map2) const
isl::space get_space() const
static isl::map empty(isl::space space)
isl::map intersect_domain(isl::set set) const
static isl::set universe(isl::space space)
isl::set intersect_params(isl::set params) const
isl::space get_space() const
isl::space set_tuple_id(isl::dim type, isl::id id) const
isl::id get_tuple_id(isl::dim type) const
isl::space unwrap() const
isl::map extract_map(isl::space space) const
isl::union_map uncurry() const
isl::union_map unite(isl::union_map umap2) const
isl::map_list get_map_list() const
isl::union_map subtract_domain(isl::union_set dom) const
boolean is_subset(const isl::union_map &umap2) const
static isl::union_map empty(isl::ctx ctx)
isl::union_map subtract(isl::union_map umap2) const
isl::union_map intersect_domain(isl::space space) const
Represent memory accesses in statements.
bool isOriginalArrayKind() const
Whether this is an access of an explicit load or store in the IR.
isl::map getLatestAccessRelation() const
Return the newest access relation of this access.
bool isWrite() const
Is this a write memory access?
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
Value * tryGetValueStored()
Return llvm::Value that is stored by this access, if available.
bool isRead() const
Is this a read memory access?
isl::id getId() const
Get identifier for the memory access.
bool isMustWrite() const
Is this a must-write memory access?
void print(raw_ostream &OS) const
Print the MemoryAccess.
bool isOriginalScalarKind() const
Whether this access is an array to a scalar memory object, without considering changes by setNewAcces...
ScopStmt * getStatement() const
Get the statement that contains this memory access.
isl::map getAccessRelation() const
Old name of getLatestAccessRelation().
Value * getAccessValue() const
Return the access value of this memory access.
void setNewAccessRelation(isl::map NewAccessRelation)
Set the updated access relation read from JSCOP file.
The legacy pass manager's analysis pass to compute scop information for a region.
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.
BasicBlock * getEntryBlock() const
Return a BasicBlock from this statement.
std::vector< Instruction * >::const_iterator insts_end() const
bool isBlockStmt() const
Return true if this statement represents a single basic block.
void removeSingleMemoryAccess(MemoryAccess *MA, bool AfterHoisting=true)
Remove MA from this statement.
void setInstructions(ArrayRef< Instruction * > Range)
Set the list of instructions for this statement.
std::vector< Instruction * >::const_iterator insts_begin() const
const char * getBaseName() const
bool isRegionStmt() const
Return true if this statement represents a whole region.
isl::set getDomain() const
Get the iteration domain of this ScopStmt.
isl::set getContext() const
Get the constraint on parameter of this Scop.
__isl_give isl_id * isl_id_alloc(isl_ctx *ctx, __isl_keep const char *name, void *user)
boolean manage(isl_bool val)
This file contains the declaration of the PolyhedralInfo class, which will provide an interface to ex...
std::string getIslCompatibleName(const std::string &Prefix, const llvm::Value *Val, long Number, const std::string &Suffix, bool UseInstructionNames)
Combine Prefix, Val (or Number) and Suffix to an isl-compatible name.
llvm::SmallVector< MemoryAccess *, 32 > getAccessesInOrder(ScopStmt &Stmt)
Return a vector that contains MemoryAccesses in the order in which they are executed.
@ Value
MemoryKind::Value: Models an llvm::Value.
llvm::Pass * createSimplifyWrapperPass(int)
Create a Simplify pass.
void markReachable(Scop *S, LoopInfo *LI, DenseSet< VirtualInstruction > &UsedInsts, DenseSet< MemoryAccess * > &UsedAccs, ScopStmt *OnlyLocal=nullptr)
Find all reachable instructions and accesses.
llvm::Pass * createSimplifyPrinterLegacyPass(llvm::raw_ostream &OS)
AnalysisManager< Scop, ScopStandardAnalysisResults & > ScopAnalysisManager
llvm::PreservedAnalyses run(Scop &S, ScopAnalysisManager &SAM, ScopStandardAnalysisResults &AR, SPMUpdater &U)
PreservedAnalyses run(Scop &S, ScopAnalysisManager &, ScopStandardAnalysisResults &, SPMUpdater &)
static TupleKindPtr Domain("Domain")