mirror of
https://github.com/intel/llvm.git
synced 2026-02-06 23:31:50 +08:00
[Polly] Port DeadCodeElim to the NewPM.
This commit is contained in:
41
polly/include/polly/DeadCodeElimination.h
Normal file
41
polly/include/polly/DeadCodeElimination.h
Normal 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 */
|
||||
@@ -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 &);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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++ )
|
||||
|
||||
Reference in New Issue
Block a user