#include "llvm/Transforms/Scalar/LoopFuse.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/DependenceAnalysis.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/CodeMoverUtils.h"
#include "llvm/Transforms/Utils/LoopPeel.h"
#include "llvm/Transforms/Utils/LoopSimplify.h"
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(FuseCounter, "Loops fused");
STATISTIC(NumFusionCandidates, "Number of candidates for loop fusion");
STATISTIC(InvalidPreheader, "Loop has invalid preheader");
STATISTIC(InvalidHeader, "Loop has invalid header");
STATISTIC(InvalidExitingBlock, "Loop has invalid exiting blocks");
STATISTIC(InvalidExitBlock, "Loop has invalid exit block");
STATISTIC(InvalidLatch, "Loop has invalid latch");
STATISTIC(InvalidLoop, "Loop is invalid");
STATISTIC(AddressTakenBB, "Basic block has address taken");
STATISTIC(MayThrowException, "Loop may throw an exception");
STATISTIC(ContainsVolatileAccess, "Loop contains a volatile access");
STATISTIC(NotSimplifiedForm, "Loop is not in simplified form");
STATISTIC(InvalidDependencies, "Dependencies prevent fusion");
STATISTIC(UnknownTripCount, "Loop has unknown trip count");
STATISTIC(UncomputableTripCount, "SCEV cannot compute trip count of loop");
STATISTIC(NonEqualTripCount, "Loop trip counts are not the same");
STATISTIC(NonAdjacent, "Loops are not adjacent");
STATISTIC(
NonEmptyPreheader,
"Loop has a non-empty preheader with instructions that cannot be moved");
STATISTIC(FusionNotBeneficial, "Fusion is not beneficial");
STATISTIC(NonIdenticalGuards, "Candidates have different guards");
STATISTIC(NonEmptyExitBlock, "Candidate has a non-empty exit block with "
"instructions that cannot be moved");
STATISTIC(NonEmptyGuardBlock, "Candidate has a non-empty guard block with "
"instructions that cannot be moved");
STATISTIC(NotRotated, "Candidate is not rotated");
STATISTIC(OnlySecondCandidateIsGuarded,
"The second candidate is guarded while the first one is not");
STATISTIC(NumHoistedInsts, "Number of hoisted preheader instructions.");
STATISTIC(NumSunkInsts, "Number of hoisted preheader instructions.");
enum FusionDependenceAnalysisChoice { … };
static cl::opt<FusionDependenceAnalysisChoice> FusionDependenceAnalysis(
"loop-fusion-dependence-analysis",
cl::desc("Which dependence analysis should loop fusion use?"),
cl::values(clEnumValN(FUSION_DEPENDENCE_ANALYSIS_SCEV, "scev",
"Use the scalar evolution interface"),
clEnumValN(FUSION_DEPENDENCE_ANALYSIS_DA, "da",
"Use the dependence analysis interface"),
clEnumValN(FUSION_DEPENDENCE_ANALYSIS_ALL, "all",
"Use all available analyses")),
cl::Hidden, cl::init(FUSION_DEPENDENCE_ANALYSIS_ALL));
static cl::opt<unsigned> FusionPeelMaxCount(
"loop-fusion-peel-max-count", cl::init(0), cl::Hidden,
cl::desc("Max number of iterations to be peeled from a loop, such that "
"fusion can take place"));
#ifndef NDEBUG
static cl::opt<bool>
VerboseFusionDebugging("loop-fusion-verbose-debug",
cl::desc("Enable verbose debugging for Loop Fusion"),
cl::Hidden, cl::init(false));
#endif
namespace {
struct FusionCandidate { … };
struct FusionCandidateCompare { … };
LoopVector;
FusionCandidateSet;
FusionCandidateCollection;
#if !defined(NDEBUG)
static llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const FusionCandidate &FC) {
if (FC.isValid())
OS << FC.Preheader->getName();
else
OS << "<Invalid>";
return OS;
}
static llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const FusionCandidateSet &CandSet) {
for (const FusionCandidate &FC : CandSet)
OS << FC << '\n';
return OS;
}
static void
printFusionCandidates(const FusionCandidateCollection &FusionCandidates) {
dbgs() << "Fusion Candidates: \n";
for (const auto &CandidateSet : FusionCandidates) {
dbgs() << "*** Fusion Candidate Set ***\n";
dbgs() << CandidateSet;
dbgs() << "****************************\n";
}
}
#endif
struct LoopDepthTree { … };
#ifndef NDEBUG
static void printLoopVector(const LoopVector &LV) {
dbgs() << "****************************\n";
for (auto *L : LV)
printLoop(*L, dbgs());
dbgs() << "****************************\n";
}
#endif
struct LoopFuser { … };
}
PreservedAnalyses LoopFusePass::run(Function &F, FunctionAnalysisManager &AM) { … }