#include "polly/ScopDetection.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
#include "polly/ScopDetectionDiagnostic.h"
#include "polly/Support/SCEVValidator.h"
#include "polly/Support/ScopHelper.h"
#include "polly/Support/ScopLocation.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Delinearization.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Value.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <stack>
#include <string>
#include <utility>
#include <vector>
usingnamespacellvm;
usingnamespacepolly;
#include "polly/Support/PollyDebug.h"
#define DEBUG_TYPE …
static cl::opt<int> ProfitabilityMinPerLoopInstructions(
"polly-detect-profitability-min-per-loop-insts",
cl::desc("The minimal number of per-loop instructions before a single loop "
"region is considered profitable"),
cl::Hidden, cl::ValueRequired, cl::init(100000000), cl::cat(PollyCategory));
bool polly::PollyProcessUnprofitable;
static cl::opt<bool, true> XPollyProcessUnprofitable(
"polly-process-unprofitable",
cl::desc(
"Process scops that are unlikely to benefit from Polly optimizations."),
cl::location(PollyProcessUnprofitable), cl::cat(PollyCategory));
static cl::list<std::string> OnlyFunctions(
"polly-only-func",
cl::desc("Only run on functions that match a regex. "
"Multiple regexes can be comma separated. "
"Scop detection will run on all functions that match "
"ANY of the regexes provided."),
cl::CommaSeparated, cl::cat(PollyCategory));
static cl::list<std::string> IgnoredFunctions(
"polly-ignore-func",
cl::desc("Ignore functions that match a regex. "
"Multiple regexes can be comma separated. "
"Scop detection will ignore all functions that match "
"ANY of the regexes provided."),
cl::CommaSeparated, cl::cat(PollyCategory));
bool polly::PollyAllowFullFunction;
static cl::opt<bool, true>
XAllowFullFunction("polly-detect-full-functions",
cl::desc("Allow the detection of full functions"),
cl::location(polly::PollyAllowFullFunction),
cl::init(false), cl::cat(PollyCategory));
static cl::opt<std::string> OnlyRegion(
"polly-only-region",
cl::desc("Only run on certain regions (The provided identifier must "
"appear in the name of the region's entry block"),
cl::value_desc("identifier"), cl::ValueRequired, cl::init(""),
cl::cat(PollyCategory));
static cl::opt<bool>
IgnoreAliasing("polly-ignore-aliasing",
cl::desc("Ignore possible aliasing of the array bases"),
cl::Hidden, cl::cat(PollyCategory));
bool polly::PollyAllowUnsignedOperations;
static cl::opt<bool, true> XPollyAllowUnsignedOperations(
"polly-allow-unsigned-operations",
cl::desc("Allow unsigned operations such as comparisons or zero-extends."),
cl::location(PollyAllowUnsignedOperations), cl::Hidden, cl::init(true),
cl::cat(PollyCategory));
bool polly::PollyUseRuntimeAliasChecks;
static cl::opt<bool, true> XPollyUseRuntimeAliasChecks(
"polly-use-runtime-alias-checks",
cl::desc("Use runtime alias checks to resolve possible aliasing."),
cl::location(PollyUseRuntimeAliasChecks), cl::Hidden, cl::init(true),
cl::cat(PollyCategory));
static cl::opt<bool>
ReportLevel("polly-report",
cl::desc("Print information about the activities of Polly"),
cl::cat(PollyCategory));
static cl::opt<bool> AllowDifferentTypes(
"polly-allow-differing-element-types",
cl::desc("Allow different element types for array accesses"), cl::Hidden,
cl::init(true), cl::cat(PollyCategory));
static cl::opt<bool>
AllowNonAffine("polly-allow-nonaffine",
cl::desc("Allow non affine access functions in arrays"),
cl::Hidden, cl::cat(PollyCategory));
static cl::opt<bool>
AllowModrefCall("polly-allow-modref-calls",
cl::desc("Allow functions with known modref behavior"),
cl::Hidden, cl::cat(PollyCategory));
static cl::opt<bool> AllowNonAffineSubRegions(
"polly-allow-nonaffine-branches",
cl::desc("Allow non affine conditions for branches"), cl::Hidden,
cl::init(true), cl::cat(PollyCategory));
static cl::opt<bool>
AllowNonAffineSubLoops("polly-allow-nonaffine-loops",
cl::desc("Allow non affine conditions for loops"),
cl::Hidden, cl::cat(PollyCategory));
static cl::opt<bool, true>
TrackFailures("polly-detect-track-failures",
cl::desc("Track failure strings in detecting scop regions"),
cl::location(PollyTrackFailures), cl::Hidden, cl::init(true),
cl::cat(PollyCategory));
static cl::opt<bool> KeepGoing("polly-detect-keep-going",
cl::desc("Do not fail on the first error."),
cl::Hidden, cl::cat(PollyCategory));
static cl::opt<bool, true>
PollyDelinearizeX("polly-delinearize",
cl::desc("Delinearize array access functions"),
cl::location(PollyDelinearize), cl::Hidden,
cl::init(true), cl::cat(PollyCategory));
static cl::opt<bool>
VerifyScops("polly-detect-verify",
cl::desc("Verify the detected SCoPs after each transformation"),
cl::Hidden, cl::cat(PollyCategory));
bool polly::PollyInvariantLoadHoisting;
static cl::opt<bool, true>
XPollyInvariantLoadHoisting("polly-invariant-load-hoisting",
cl::desc("Hoist invariant loads."),
cl::location(PollyInvariantLoadHoisting),
cl::Hidden, cl::cat(PollyCategory));
static cl::opt<bool> PollyAllowErrorBlocks(
"polly-allow-error-blocks",
cl::desc("Allow to speculate on the execution of 'error blocks'."),
cl::Hidden, cl::init(true), cl::cat(PollyCategory));
static const unsigned MIN_LOOP_TRIP_COUNT = …;
bool polly::PollyTrackFailures = …;
bool polly::PollyDelinearize = …;
StringRef polly::PollySkipFnAttr = …;
STATISTIC(NumScopRegions, "Number of scops");
STATISTIC(NumLoopsInScop, "Number of loops in scops");
STATISTIC(NumScopsDepthZero, "Number of scops with maximal loop depth 0");
STATISTIC(NumScopsDepthOne, "Number of scops with maximal loop depth 1");
STATISTIC(NumScopsDepthTwo, "Number of scops with maximal loop depth 2");
STATISTIC(NumScopsDepthThree, "Number of scops with maximal loop depth 3");
STATISTIC(NumScopsDepthFour, "Number of scops with maximal loop depth 4");
STATISTIC(NumScopsDepthFive, "Number of scops with maximal loop depth 5");
STATISTIC(NumScopsDepthLarger,
"Number of scops with maximal loop depth 6 and larger");
STATISTIC(NumProfScopRegions, "Number of scops (profitable scops only)");
STATISTIC(NumLoopsInProfScop,
"Number of loops in scops (profitable scops only)");
STATISTIC(NumLoopsOverall, "Number of total loops");
STATISTIC(NumProfScopsDepthZero,
"Number of scops with maximal loop depth 0 (profitable scops only)");
STATISTIC(NumProfScopsDepthOne,
"Number of scops with maximal loop depth 1 (profitable scops only)");
STATISTIC(NumProfScopsDepthTwo,
"Number of scops with maximal loop depth 2 (profitable scops only)");
STATISTIC(NumProfScopsDepthThree,
"Number of scops with maximal loop depth 3 (profitable scops only)");
STATISTIC(NumProfScopsDepthFour,
"Number of scops with maximal loop depth 4 (profitable scops only)");
STATISTIC(NumProfScopsDepthFive,
"Number of scops with maximal loop depth 5 (profitable scops only)");
STATISTIC(NumProfScopsDepthLarger,
"Number of scops with maximal loop depth 6 and larger "
"(profitable scops only)");
STATISTIC(MaxNumLoopsInScop, "Maximal number of loops in scops");
STATISTIC(MaxNumLoopsInProfScop,
"Maximal number of loops in scops (profitable scops only)");
static void updateLoopCountStatistic(ScopDetection::LoopStats Stats,
bool OnlyProfitable);
namespace {
class DiagnosticScopFound final : public DiagnosticInfo { … };
}
int DiagnosticScopFound::PluginDiagnosticKind = …;
void DiagnosticScopFound::print(DiagnosticPrinter &DP) const { … }
static bool doesStringMatchAnyRegex(StringRef Str,
const cl::list<std::string> &RegexList) { … }
ScopDetection::ScopDetection(const DominatorTree &DT, ScalarEvolution &SE,
LoopInfo &LI, RegionInfo &RI, AAResults &AA,
OptimizationRemarkEmitter &ORE)
: … { … }
void ScopDetection::detect(Function &F) { … }
template <class RR, typename... Args>
inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert,
Args &&...Arguments) const { … }
bool ScopDetection::isMaxRegionInScop(const Region &R, bool Verify) { … }
std::string ScopDetection::regionIsInvalidBecause(const Region *R) const { … }
bool ScopDetection::addOverApproximatedRegion(Region *AR,
DetectionContext &Context) const { … }
bool ScopDetection::onlyValidRequiredInvariantLoads(
InvariantLoadsSetTy &RequiredILS, DetectionContext &Context) const { … }
bool ScopDetection::involvesMultiplePtrs(const SCEV *S0, const SCEV *S1,
Loop *Scope) const { … }
bool ScopDetection::isAffine(const SCEV *S, Loop *Scope,
DetectionContext &Context) const { … }
bool ScopDetection::isValidSwitch(BasicBlock &BB, SwitchInst *SI,
Value *Condition, bool IsLoopBranch,
DetectionContext &Context) const { … }
bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
Value *Condition, bool IsLoopBranch,
DetectionContext &Context) { … }
bool ScopDetection::isValidCFG(BasicBlock &BB, bool IsLoopBranch,
bool AllowUnreachable,
DetectionContext &Context) { … }
bool ScopDetection::isValidCallInst(CallInst &CI,
DetectionContext &Context) const { … }
bool ScopDetection::isValidIntrinsicInst(IntrinsicInst &II,
DetectionContext &Context) const { … }
bool ScopDetection::isInvariant(Value &Val, const Region &Reg,
DetectionContext &Ctx) const { … }
namespace {
class SCEVRemoveMax final : public SCEVRewriteVisitor<SCEVRemoveMax> { … };
}
SmallVector<const SCEV *, 4>
ScopDetection::getDelinearizationTerms(DetectionContext &Context,
const SCEVUnknown *BasePointer) const { … }
bool ScopDetection::hasValidArraySizes(DetectionContext &Context,
SmallVectorImpl<const SCEV *> &Sizes,
const SCEVUnknown *BasePointer,
Loop *Scope) const { … }
bool ScopDetection::computeAccessFunctions(
DetectionContext &Context, const SCEVUnknown *BasePointer,
std::shared_ptr<ArrayShape> Shape) const { … }
bool ScopDetection::hasBaseAffineAccesses(DetectionContext &Context,
const SCEVUnknown *BasePointer,
Loop *Scope) const { … }
bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const { … }
bool ScopDetection::isValidAccess(Instruction *Inst, const SCEV *AF,
const SCEVUnknown *BP,
DetectionContext &Context) const { … }
bool ScopDetection::isValidMemoryAccess(MemAccInst Inst,
DetectionContext &Context) const { … }
bool ScopDetection::isValidInstruction(Instruction &Inst,
DetectionContext &Context) { … }
static bool hasExitingBlocks(Loop *L) { … }
bool ScopDetection::canUseISLTripCount(Loop *L, DetectionContext &Context) { … }
bool ScopDetection::isValidLoop(Loop *L, DetectionContext &Context) { … }
ScopDetection::LoopStats
ScopDetection::countBeneficialSubLoops(Loop *L, ScalarEvolution &SE,
unsigned MinProfitableTrips) { … }
ScopDetection::LoopStats
ScopDetection::countBeneficialLoops(Region *R, ScalarEvolution &SE,
LoopInfo &LI, unsigned MinProfitableTrips) { … }
static bool isErrorBlockImpl(BasicBlock &BB, const Region &R, LoopInfo &LI,
const DominatorTree &DT) { … }
bool ScopDetection::isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R) { … }
Region *ScopDetection::expandRegion(Region &R) { … }
static bool regionWithoutLoops(Region &R, LoopInfo &LI) { … }
void ScopDetection::removeCachedResultsRecursively(const Region &R) { … }
void ScopDetection::removeCachedResults(const Region &R) { … }
void ScopDetection::findScops(Region &R) { … }
bool ScopDetection::allBlocksValid(DetectionContext &Context) { … }
bool ScopDetection::hasSufficientCompute(DetectionContext &Context,
int NumLoops) const { … }
bool ScopDetection::hasPossiblyDistributableLoop(
DetectionContext &Context) const { … }
bool ScopDetection::isProfitableRegion(DetectionContext &Context) const { … }
bool ScopDetection::isValidRegion(DetectionContext &Context) { … }
void ScopDetection::markFunctionAsInvalid(Function *F) { … }
bool ScopDetection::isValidFunction(Function &F) { … }
void ScopDetection::printLocations(Function &F) { … }
void ScopDetection::emitMissedRemarks(const Function &F) { … }
bool ScopDetection::isReducibleRegion(Region &R, DebugLoc &DbgLoc) const { … }
static void updateLoopCountStatistic(ScopDetection::LoopStats Stats,
bool OnlyProfitable) { … }
ScopDetection::DetectionContext *
ScopDetection::getDetectionContext(const Region *R) const { … }
const RejectLog *ScopDetection::lookupRejectionLog(const Region *R) const { … }
void ScopDetection::verifyRegion(const Region &R) { … }
void ScopDetection::verifyAnalysis() { … }
bool ScopDetectionWrapperPass::runOnFunction(Function &F) { … }
void ScopDetectionWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { … }
void ScopDetectionWrapperPass::print(raw_ostream &OS, const Module *) const { … }
ScopDetectionWrapperPass::ScopDetectionWrapperPass() : … { … }
ScopAnalysis::ScopAnalysis() { … }
void ScopDetectionWrapperPass::releaseMemory() { … }
char ScopDetectionWrapperPass::ID;
AnalysisKey ScopAnalysis::Key;
ScopDetection ScopAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { … }
PreservedAnalyses ScopAnalysisPrinterPass::run(Function &F,
FunctionAnalysisManager &FAM) { … }
Pass *polly::createScopDetectionWrapperPassPass() { … }
INITIALIZE_PASS_BEGIN(ScopDetectionWrapperPass, "polly-detect",
"Polly - Detect static control parts (SCoPs)", false,
false);
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass);
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass);
INITIALIZE_PASS_END(ScopDetectionWrapperPass, "polly-detect",
"Polly - Detect static control parts (SCoPs)", false, false)
namespace {
class ScopDetectionPrinterLegacyPass final : public FunctionPass { … };
char ScopDetectionPrinterLegacyPass::ID = …;
}
Pass *polly::createScopDetectionPrinterLegacyPass(raw_ostream &OS) { … }
INITIALIZE_PASS_BEGIN(ScopDetectionPrinterLegacyPass, "polly-print-detect",
"Polly - Print static control parts (SCoPs)", false,
false);
INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass);
INITIALIZE_PASS_END(ScopDetectionPrinterLegacyPass, "polly-print-detect",
"Polly - Print static control parts (SCoPs)", false, false)