#include "polly/DeadCodeElimination.h"
#include "polly/DependenceInfo.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
#include "polly/ScopInfo.h"
#include "llvm/Support/CommandLine.h"
#include "isl/isl-noexceptions.h"
using namespace llvm;
using namespace polly;
namespace {
cl::opt<int> DCEPreciseSteps(
"polly-dce-precise-steps",
cl::desc("The number of precise steps between two approximating "
"iterations. (A value of -1 schedules another approximation stage "
"before the actual dead code elimination."),
cl::init(-1), cl::cat(PollyCategory));
class DeadCodeElimWrapperPass final : public ScopPass {
public:
static char ID;
explicit DeadCodeElimWrapperPass() : ScopPass(ID) {}
bool runOnScop(Scop &S) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
char DeadCodeElimWrapperPass::ID = 0;
static isl::union_set getLiveOut(Scop &S) {
isl::union_map Schedule = S.getSchedule();
isl::union_map MustWrites = S.getMustWrites();
isl::union_map WriteIterations = MustWrites.reverse();
isl::union_map WriteTimes = WriteIterations.apply_range(Schedule);
isl::union_map LastWriteTimes = WriteTimes.lexmax();
isl::union_map LastWriteIterations =
LastWriteTimes.apply_range(Schedule.reverse());
isl::union_set Live = LastWriteIterations.range();
isl::union_map MayWrites = S.getMayWrites();
Live = Live.unite(MayWrites.domain());
return Live.coalesce();
}
static bool runDeadCodeElimination(Scop &S, int PreciseSteps,
const Dependences &D) {
if (!D.hasValidDependences())
return false;
isl::union_set Live = getLiveOut(S);
isl::union_map Dep =
D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED);
Dep = Dep.reverse();
if (PreciseSteps == -1)
Live = Live.affine_hull();
isl::union_set OriginalDomain = S.getDomains();
int Steps = 0;
while (true) {
Steps++;
isl::union_set Extra = Live.apply(Dep);
if (Extra.is_subset(Live))
break;
Live = Live.unite(Extra);
if (Steps > PreciseSteps) {
Steps = 0;
Live = Live.affine_hull();
}
Live = Live.intersect(OriginalDomain);
}
Live = Live.coalesce();
return S.restrictDomains(Live);
}
bool DeadCodeElimWrapperPass::runOnScop(Scop &S) {
auto &DI = getAnalysis<DependenceInfo>();
const Dependences &Deps = DI.getDependences(Dependences::AL_Statement);
bool Changed = runDeadCodeElimination(S, DCEPreciseSteps, Deps);
if (Changed)
DI.recomputeDependences(Dependences::AL_Statement);
return false;
}
void DeadCodeElimWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
ScopPass::getAnalysisUsage(AU);
AU.addRequired<DependenceInfo>();
}
}
Pass *polly::createDeadCodeElimWrapperPass() {
return new DeadCodeElimWrapperPass();
}
llvm::PreservedAnalyses DeadCodeElimPass::run(Scop &S, ScopAnalysisManager &SAM,
ScopStandardAnalysisResults &SAR,
SPMUpdater &U) {
DependenceAnalysis::Result &DA = SAM.getResult<DependenceAnalysis>(S, SAR);
const Dependences &Deps = DA.getDependences(Dependences::AL_Statement);
bool Changed = runDeadCodeElimination(S, DCEPreciseSteps, Deps);
if (Changed)
DA.recomputeDependences(Dependences::AL_Statement);
if (!Changed)
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserveSet<AllAnalysesOn<Module>>();
PA.preserveSet<AllAnalysesOn<Function>>();
PA.preserveSet<AllAnalysesOn<Loop>>();
return PA;
}
INITIALIZE_PASS_BEGIN(DeadCodeElimWrapperPass, "polly-dce",
"Polly - Remove dead iterations", false, false)
INITIALIZE_PASS_DEPENDENCY(DependenceInfo)
INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass)
INITIALIZE_PASS_END(DeadCodeElimWrapperPass, "polly-dce",
"Polly - Remove dead iterations", false, false)