[Polly] Port DeadCodeElim to the NewPM.

This commit is contained in:
Michael Kruse
2021-03-24 00:54:37 -05:00
parent 3b83590cb2
commit 8796451d6e
7 changed files with 117 additions and 47 deletions

View File

@@ -0,0 +1,41 @@
//===- DeadCodeElimination.h ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Eliminate dead iterations.
//
//===----------------------------------------------------------------------===//
#ifndef POLLY_DEADCODEELIMINATION_H
#define POLLY_DEADCODEELIMINATION_H
#include "polly/ScopPass.h"
namespace llvm {
class PassRegistry;
class Pass;
class raw_ostream;
} // namespace llvm
namespace polly {
llvm::Pass *createDeadCodeElimWrapperPass();
struct DeadCodeElimPass : llvm::PassInfoMixin<DeadCodeElimPass> {
DeadCodeElimPass() {}
llvm::PreservedAnalyses run(Scop &S, ScopAnalysisManager &SAM, ScopStandardAnalysisResults &SAR, SPMUpdater &U);
};
} // namespace polly
namespace llvm {
void initializeDeadCodeElimWrapperPassPass(llvm::PassRegistry &);
} // namespace llvm
#endif /* POLLY_DEADCODEELIMINATION_H */

View File

@@ -28,7 +28,7 @@ class PassRegistry;
namespace polly {
llvm::Pass *createCodePreparationPass();
llvm::Pass *createScopInlinerPass();
llvm::Pass *createDeadCodeElimPass();
llvm::Pass *createDeadCodeElimWrapperPass();
llvm::Pass *createDependenceInfoPass();
llvm::Pass *createDependenceInfoWrapperPassPass();
llvm::Pass *createDOTOnlyPrinterPass();
@@ -75,7 +75,7 @@ struct PollyForcePassLinking {
return;
polly::createCodePreparationPass();
polly::createDeadCodeElimPass();
polly::createDeadCodeElimWrapperPass();
polly::createDependenceInfoPass();
polly::createDOTOnlyPrinterPass();
polly::createDOTOnlyViewerPass();
@@ -109,7 +109,7 @@ namespace llvm {
class PassRegistry;
void initializeCodePreparationPass(llvm::PassRegistry &);
void initializeScopInlinerPass(llvm::PassRegistry &);
void initializeDeadCodeElimPass(llvm::PassRegistry &);
void initializeDeadCodeElimWrapperPassPass(llvm::PassRegistry &);
void initializeJSONExporterPass(llvm::PassRegistry &);
void initializeJSONImporterPass(llvm::PassRegistry &);
void initializeIslAstInfoWrapperPassPass(llvm::PassRegistry &);

View File

@@ -38,4 +38,5 @@ SCOP_PASS("print<polly-delicm>", DeLICMPrinterPass(outs()))
SCOP_PASS("polly-prune-unprofitable", PruneUnprofitablePass())
SCOP_PASS("polly-opt-isl", IslScheduleOptimizerPass())
SCOP_PASS("print<polly-opt-isl>", IslScheduleOptimizerPrinterPass(outs()))
SCOP_PASS("polly-dce", DeadCodeElimPass())
#undef SCOP_PASS

View File

@@ -25,6 +25,7 @@
#include "polly/CodeGen/IslAst.h"
#include "polly/CodePreparation.h"
#include "polly/DeLICM.h"
#include "polly/DeadCodeElimination.h"
#include "polly/DependenceInfo.h"
#include "polly/ForwardOpTree.h"
#include "polly/JSONExporter.h"
@@ -248,7 +249,7 @@ void initializePollyPasses(PassRegistry &Registry) {
LLVMInitializeNVPTXAsmPrinter();
#endif
initializeCodePreparationPass(Registry);
initializeDeadCodeElimPass(Registry);
initializeDeadCodeElimWrapperPassPass(Registry);
initializeDependenceInfoPass(Registry);
initializeDependenceInfoWrapperPassPass(Registry);
initializeJSONExporterPass(Registry);
@@ -336,7 +337,7 @@ static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
PM.add(polly::createJSONImporterPass());
if (DeadCodeElim)
PM.add(polly::createDeadCodeElimPass());
PM.add(polly::createDeadCodeElimWrapperPass());
if (FullyIndexedStaticExpansion)
PM.add(polly::createMaximalStaticExpansionPass());
@@ -517,7 +518,7 @@ static void buildDefaultPollyPipeline(FunctionPassManager &PM,
SPM.addPass(JSONImportPass());
if (DeadCodeElim)
report_fatal_error("Option -polly-run-dce not supported with NPM", false);
SPM.addPass(DeadCodeElimPass());
if (FullyIndexedStaticExpansion)
report_fatal_error("Option -polly-enable-mse not supported with NPM",

View File

@@ -31,6 +31,7 @@
//
//===----------------------------------------------------------------------===//
#include "polly/DeadCodeElimination.h"
#include "polly/DependenceInfo.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
@@ -50,43 +51,38 @@ cl::opt<int> DCEPreciseSteps(
"before the actual dead code elimination."),
cl::ZeroOrMore, cl::init(-1), cl::cat(PollyCategory));
class DeadCodeElim : public ScopPass {
class DeadCodeElimWrapperPass : public ScopPass {
public:
static char ID;
explicit DeadCodeElim() : ScopPass(ID) {}
explicit DeadCodeElimWrapperPass() : ScopPass(ID) {}
/// Remove dead iterations from the schedule of @p S.
bool runOnScop(Scop &S) override;
/// Register all analyses and transformation required.
void getAnalysisUsage(AnalysisUsage &AU) const override;
private:
/// Return the set of live iterations.
///
/// The set of live iterations are all iterations that write to memory and for
/// which we can not prove that there will be a later write that _must_
/// overwrite the same memory location and is consequently the only one that
/// is visible after the execution of the SCoP.
///
isl::union_set getLiveOut(Scop &S);
bool eliminateDeadCode(Scop &S, int PreciseSteps);
};
} // namespace
char DeadCodeElim::ID = 0;
char DeadCodeElimWrapperPass::ID = 0;
// To compute the live outs, we compute for the data-locations that are
// must-written to the last statement that touches these locations. On top of
// this we add all statements that perform may-write accesses.
//
// We could be more precise by removing may-write accesses for which we know
// that they are overwritten by a must-write after. However, at the moment the
// only may-writes we introduce access the full (unbounded) array, such that
// bounded write accesses can not overwrite all of the data-locations. As
// this means may-writes are in the current situation always live, there is
// no point in trying to remove them from the live-out set.
isl::union_set DeadCodeElim::getLiveOut(Scop &S) {
/// Return the set of live iterations.
///
/// The set of live iterations are all iterations that write to memory and for
/// which we can not prove that there will be a later write that _must_
/// overwrite the same memory location and is consequently the only one that
/// is visible after the execution of the SCoP.
///
/// To compute the live outs, we compute for the data-locations that are
/// must-written to the last statement that touches these locations. On top of
/// this we add all statements that perform may-write accesses.
///
/// We could be more precise by removing may-write accesses for which we know
/// that they are overwritten by a must-write after. However, at the moment the
/// only may-writes we introduce access the full (unbounded) array, such that
/// bounded write accesses can not overwrite all of the data-locations. As
/// this means may-writes are in the current situation always live, there is
/// no point in trying to remove them from the live-out set.
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();
@@ -110,10 +106,8 @@ isl::union_set DeadCodeElim::getLiveOut(Scop &S) {
/// To ensure the set of live iterations does not get too complex we always
/// combine a certain number of precise steps with one approximating step that
/// simplifies the life set with an affine hull.
bool DeadCodeElim::eliminateDeadCode(Scop &S, int PreciseSteps) {
DependenceInfo &DI = getAnalysis<DependenceInfo>();
const Dependences &D = DI.getDependences(Dependences::AL_Statement);
static bool runDeadCodeElimination(Scop &S, int PreciseSteps,
const Dependences &D) {
if (!D.hasValidDependences())
return false;
@@ -147,29 +141,60 @@ bool DeadCodeElim::eliminateDeadCode(Scop &S, int PreciseSteps) {
Live = Live.coalesce();
bool Changed = S.restrictDomains(Live);
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);
// FIXME: We can probably avoid the recomputation of all dependences by
// updating them explicitly.
if (Changed)
DI.recomputeDependences(Dependences::AL_Statement);
return Changed;
return false;
}
bool DeadCodeElim::runOnScop(Scop &S) {
return eliminateDeadCode(S, DCEPreciseSteps);
}
void DeadCodeElim::getAnalysisUsage(AnalysisUsage &AU) const {
void DeadCodeElimWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
ScopPass::getAnalysisUsage(AU);
AU.addRequired<DependenceInfo>();
}
Pass *polly::createDeadCodeElimPass() { return new DeadCodeElim(); }
} // namespace
INITIALIZE_PASS_BEGIN(DeadCodeElim, "polly-dce",
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);
// FIXME: We can probably avoid the recomputation of all dependences by
// updating them explicitly.
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(DeadCodeElim, "polly-dce", "Polly - Remove dead iterations",
false, false)
INITIALIZE_PASS_END(DeadCodeElimWrapperPass, "polly-dce",
"Polly - Remove dead iterations", false, false)

View File

@@ -1,4 +1,5 @@
; RUN: opt -S %loadPolly -basic-aa -polly-dce -polly-ast -analyze < %s | FileCheck %s
; RUN: opt -S %loadPolly "-passes=scop(polly-dce,print<polly-ast>)" < %s | FileCheck %s
; RUN: opt -S %loadPolly -basic-aa -polly-dce -polly-ast -analyze -polly-dependences-computeout=1 < %s | FileCheck %s -check-prefix=TIMEOUT
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"

View File

@@ -1,4 +1,5 @@
; RUN: opt -S %loadPolly -basic-aa -polly-dependences-analysis-type=value-based -polly-dce -polly-dce-precise-steps=2 -polly-ast -analyze < %s | FileCheck %s
; RUN: opt -S %loadPolly "-passes=scop(polly-dce,print<polly-ast>)" -polly-dependences-analysis-type=value-based -polly-dce-precise-steps=2 < %s | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
;
; for(i = 0; i < 200; i++ )