Port DemandedBits to the new pass manager.

Differential Revision: http://reviews.llvm.org/D18679

llvm-svn: 266699
This commit is contained in:
Michael Kuperstein 2016-04-18 23:55:01 +00:00
parent 2526fca8d8
commit de16b44f74
11 changed files with 119 additions and 54 deletions

View File

@ -26,6 +26,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
@ -35,31 +36,31 @@ class Instruction;
class DominatorTree;
class AssumptionCache;
struct DemandedBits : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
DemandedBits();
class DemandedBits {
public:
DemandedBits(Function &F, AssumptionCache &AC, DominatorTree &DT) :
F(F), AC(AC), DT(DT), Analyzed(false) {}
bool runOnFunction(Function& F) override;
void getAnalysisUsage(AnalysisUsage& AU) const override;
void print(raw_ostream &OS, const Module *M) const override;
/// Return the bits demanded from instruction I.
APInt getDemandedBits(Instruction *I);
/// Return true if, during analysis, I could not be reached.
bool isInstructionDead(Instruction *I);
void print(raw_ostream &OS);
private:
Function &F;
AssumptionCache ∾
DominatorTree &DT;
void performAnalysis();
void determineLiveOperandBits(const Instruction *UserI,
const Instruction *I, unsigned OperandNo,
const APInt &AOut, APInt &AB,
APInt &KnownZero, APInt &KnownOne,
APInt &KnownZero2, APInt &KnownOne2);
const Instruction *I, unsigned OperandNo,
const APInt &AOut, APInt &AB,
APInt &KnownZero, APInt &KnownOne,
APInt &KnownZero2, APInt &KnownOne2);
AssumptionCache *AC;
DominatorTree *DT;
Function *F;
bool Analyzed;
// The set of visited instructions (non-integer-typed only).
@ -67,8 +68,49 @@ private:
DenseMap<Instruction *, APInt> AliveBits;
};
class DemandedBitsWrapperPass : public FunctionPass {
private:
mutable Optional<DemandedBits> DB;
public:
static char ID; // Pass identification, replacement for typeid
DemandedBitsWrapperPass();
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// Clean up memory in between runs
void releaseMemory() override;
DemandedBits &getDemandedBits() { return *DB; }
void print(raw_ostream &OS, const Module *M) const override;
};
/// An analysis that produces \c DemandedBits for a function.
class DemandedBitsAnalysis : public AnalysisInfoMixin<DemandedBitsAnalysis> {
friend AnalysisInfoMixin<DemandedBitsAnalysis>;
static char PassID;
public:
/// \brief Provide the result typedef for this analysis pass.
typedef DemandedBits Result;
/// \brief Run the analysis pass over a function and produce demanded bits
/// information.
DemandedBits run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for DemandedBits
class DemandedBitsPrinterPass : public PassInfoMixin<DemandedBitsPrinterPass> {
raw_ostream &OS;
public:
explicit DemandedBitsPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// Create a demanded bits analysis pass.
FunctionPass *createDemandedBitsPass();
FunctionPass *createDemandedBitsWrapperPass();
} // End llvm namespace

View File

@ -22,7 +22,7 @@
namespace llvm {
template <typename T> class ArrayRef;
struct DemandedBits;
class DemandedBits;
class GetElementPtrInst;
class Loop;
class ScalarEvolution;

View File

@ -323,7 +323,7 @@ void initializeDwarfEHPreparePass(PassRegistry&);
void initializeFloat2IntPass(PassRegistry&);
void initializeLoopDistributePass(PassRegistry&);
void initializeSjLjEHPreparePass(PassRegistry&);
void initializeDemandedBitsPass(PassRegistry&);
void initializeDemandedBitsWrapperPassPass(PassRegistry&);
void initializeFuncletLayoutPass(PassRegistry &);
void initializeLoopLoadEliminationPass(PassRegistry&);
void initializeFunctionImportPassPass(PassRegistry &);

View File

@ -37,7 +37,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
initializeCFLAAWrapperPassPass(Registry);
initializeDependenceAnalysisPass(Registry);
initializeDelinearizationPass(Registry);
initializeDemandedBitsPass(Registry);
initializeDemandedBitsWrapperPassPass(Registry);
initializeDivergenceAnalysisPass(Registry);
initializeDominanceFrontierWrapperPassPass(Registry);
initializeDomViewerPass(Registry);

View File

@ -42,25 +42,29 @@ using namespace llvm;
#define DEBUG_TYPE "demanded-bits"
char DemandedBits::ID = 0;
INITIALIZE_PASS_BEGIN(DemandedBits, "demanded-bits", "Demanded bits analysis",
false, false)
char DemandedBitsWrapperPass::ID = 0;
INITIALIZE_PASS_BEGIN(DemandedBitsWrapperPass, "demanded-bits",
"Demanded bits analysis", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_END(DemandedBits, "demanded-bits", "Demanded bits analysis",
false, false)
INITIALIZE_PASS_END(DemandedBitsWrapperPass, "demanded-bits",
"Demanded bits analysis", false, false)
DemandedBits::DemandedBits() : FunctionPass(ID), F(nullptr), Analyzed(false) {
initializeDemandedBitsPass(*PassRegistry::getPassRegistry());
DemandedBitsWrapperPass::DemandedBitsWrapperPass() : FunctionPass(ID) {
initializeDemandedBitsWrapperPassPass(*PassRegistry::getPassRegistry());
}
void DemandedBits::getAnalysisUsage(AnalysisUsage &AU) const {
void DemandedBitsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<AssumptionCacheTracker>();
AU.addRequired<DominatorTreeWrapperPass>();
AU.setPreservesAll();
}
void DemandedBitsWrapperPass::print(raw_ostream &OS, const Module *M) const {
DB->print(OS);
}
static bool isAlwaysLive(Instruction *I) {
return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) ||
I->isEHPad() || I->mayHaveSideEffects();
@ -84,13 +88,13 @@ void DemandedBits::determineLiveOperandBits(
KnownZero = APInt(BitWidth, 0);
KnownOne = APInt(BitWidth, 0);
computeKnownBits(const_cast<Value *>(V1), KnownZero, KnownOne, DL, 0,
AC, UserI, DT);
&AC, UserI, &DT);
if (V2) {
KnownZero2 = APInt(BitWidth, 0);
KnownOne2 = APInt(BitWidth, 0);
computeKnownBits(const_cast<Value *>(V2), KnownZero2, KnownOne2, DL,
0, AC, UserI, DT);
0, &AC, UserI, &DT);
}
};
@ -243,19 +247,22 @@ void DemandedBits::determineLiveOperandBits(
}
}
bool DemandedBits::runOnFunction(Function& Fn) {
F = &Fn;
Analyzed = false;
bool DemandedBitsWrapperPass::runOnFunction(Function &F) {
auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
DB.emplace(F, AC, DT);
return false;
}
void DemandedBitsWrapperPass::releaseMemory() {
DB.reset();
}
void DemandedBits::performAnalysis() {
if (Analyzed)
// Analysis already completed for this function.
return;
Analyzed = true;
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F);
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Visited.clear();
AliveBits.clear();
@ -263,7 +270,7 @@ void DemandedBits::performAnalysis() {
SmallVector<Instruction*, 128> Worklist;
// Collect the set of "root" instructions that are known live.
for (Instruction &I : instructions(*F)) {
for (Instruction &I : instructions(F)) {
if (!isAlwaysLive(&I))
continue;
@ -368,16 +375,29 @@ bool DemandedBits::isInstructionDead(Instruction *I) {
!isAlwaysLive(I);
}
void DemandedBits::print(raw_ostream &OS, const Module *M) const {
// This is gross. But the alternative is making all the state mutable
// just because of this one debugging method.
const_cast<DemandedBits*>(this)->performAnalysis();
void DemandedBits::print(raw_ostream &OS) {
performAnalysis();
for (auto &KV : AliveBits) {
OS << "DemandedBits: 0x" << utohexstr(KV.second.getLimitedValue()) << " for "
<< *KV.first << "\n";
}
}
FunctionPass *llvm::createDemandedBitsPass() {
return new DemandedBits();
FunctionPass *llvm::createDemandedBitsWrapperPass() {
return new DemandedBitsWrapperPass();
}
char DemandedBitsAnalysis::PassID;
DemandedBits DemandedBitsAnalysis::run(Function &F,
AnalysisManager<Function> &AM) {
auto &AC = AM.getResult<AssumptionAnalysis>(F);
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
return DemandedBits(F, AC, DT);
}
PreservedAnalyses DemandedBitsPrinterPass::run(Function &F,
FunctionAnalysisManager &AM) {
AM.getResult<DemandedBitsAnalysis>(F).print(OS);
return PreservedAnalyses::all();
}

View File

@ -24,6 +24,7 @@
#include "llvm/Analysis/CFLAliasAnalysis.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LazyCallGraph.h"

View File

@ -68,6 +68,7 @@ FUNCTION_ANALYSIS("aa", AAManager())
FUNCTION_ANALYSIS("assumptions", AssumptionAnalysis())
FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis())
FUNCTION_ANALYSIS("postdomtree", PostDominatorTreeAnalysis())
FUNCTION_ANALYSIS("demanded-bits", DemandedBitsAnalysis())
FUNCTION_ANALYSIS("domfrontier", DominanceFrontierAnalysis())
FUNCTION_ANALYSIS("loops", LoopAnalysis())
FUNCTION_ANALYSIS("memdep", MemoryDependenceAnalysis())
@ -105,6 +106,7 @@ FUNCTION_PASS("print", PrintFunctionPass(dbgs()))
FUNCTION_PASS("print<assumptions>", AssumptionPrinterPass(dbgs()))
FUNCTION_PASS("print<domtree>", DominatorTreePrinterPass(dbgs()))
FUNCTION_PASS("print<postdomtree>", PostDominatorTreePrinterPass(dbgs()))
FUNCTION_PASS("print<demanded-bits>", DemandedBitsPrinterPass(dbgs()))
FUNCTION_PASS("print<domfrontier>", DominanceFrontierPrinterPass(dbgs()))
FUNCTION_PASS("print<loops>", LoopPrinterPass(dbgs()))
FUNCTION_PASS("print<regions>", RegionInfoPrinterPass(dbgs()))

View File

@ -45,7 +45,7 @@ struct BDCE : public FunctionPass {
void getAnalysisUsage(AnalysisUsage& AU) const override {
AU.setPreservesCFG();
AU.addRequired<DemandedBits>();
AU.addRequired<DemandedBitsWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
}
};
@ -54,14 +54,14 @@ struct BDCE : public FunctionPass {
char BDCE::ID = 0;
INITIALIZE_PASS_BEGIN(BDCE, "bdce", "Bit-Tracking Dead Code Elimination",
false, false)
INITIALIZE_PASS_DEPENDENCY(DemandedBits)
INITIALIZE_PASS_DEPENDENCY(DemandedBitsWrapperPass)
INITIALIZE_PASS_END(BDCE, "bdce", "Bit-Tracking Dead Code Elimination",
false, false)
bool BDCE::runOnFunction(Function& F) {
if (skipOptnoneFunction(F))
return false;
DemandedBits &DB = getAnalysis<DemandedBits>();
auto &DB = getAnalysis<DemandedBitsWrapperPass>().getDemandedBits();
SmallVector<Instruction*, 128> Worklist;
bool Changed = false;

View File

@ -1498,9 +1498,9 @@ public:
LoopVectorizationCostModel(Loop *L, ScalarEvolution *SE, LoopInfo *LI,
LoopVectorizationLegality *Legal,
const TargetTransformInfo &TTI,
const TargetLibraryInfo *TLI, DemandedBits *DB,
AssumptionCache *AC, const Function *F,
const LoopVectorizeHints *Hints,
const TargetLibraryInfo *TLI,
DemandedBits *DB, AssumptionCache *AC,
const Function *F, const LoopVectorizeHints *Hints,
SmallPtrSetImpl<const Value *> &ValuesToIgnore)
: TheLoop(L), SE(SE), LI(LI), Legal(Legal), TTI(TTI), TLI(TLI), DB(DB),
TheFunction(F), Hints(Hints), ValuesToIgnore(ValuesToIgnore) {}
@ -1717,7 +1717,7 @@ struct LoopVectorize : public FunctionPass {
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
LAA = &getAnalysis<LoopAccessAnalysis>();
DB = &getAnalysis<DemandedBits>();
DB = &getAnalysis<DemandedBitsWrapperPass>().getDemandedBits();
// Compute some weights outside of the loop over the loops. Compute this
// using a BranchProbability to re-use its scaling math.
@ -2035,7 +2035,7 @@ struct LoopVectorize : public FunctionPass {
AU.addRequired<TargetTransformInfoWrapperPass>();
AU.addRequired<AAResultsWrapperPass>();
AU.addRequired<LoopAccessAnalysis>();
AU.addRequired<DemandedBits>();
AU.addRequired<DemandedBitsWrapperPass>();
AU.addPreserved<LoopInfoWrapperPass>();
AU.addPreserved<DominatorTreeWrapperPass>();
AU.addPreserved<BasicAAWrapperPass>();
@ -6064,7 +6064,7 @@ INITIALIZE_PASS_DEPENDENCY(LCSSA)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
INITIALIZE_PASS_DEPENDENCY(LoopAccessAnalysis)
INITIALIZE_PASS_DEPENDENCY(DemandedBits)
INITIALIZE_PASS_DEPENDENCY(DemandedBitsWrapperPass)
INITIALIZE_PASS_END(LoopVectorize, LV_NAME, lv_name, false, false)
namespace llvm {

View File

@ -3407,7 +3407,7 @@ struct SLPVectorizer : public FunctionPass {
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
DB = &getAnalysis<DemandedBits>();
DB = &getAnalysis<DemandedBitsWrapperPass>().getDemandedBits();
Stores.clear();
GEPs.clear();
@ -3484,7 +3484,7 @@ struct SLPVectorizer : public FunctionPass {
AU.addRequired<TargetTransformInfoWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<DemandedBits>();
AU.addRequired<DemandedBitsWrapperPass>();
AU.addPreserved<LoopInfoWrapperPass>();
AU.addPreserved<DominatorTreeWrapperPass>();
AU.addPreserved<AAResultsWrapperPass>();
@ -4575,7 +4575,7 @@ INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
INITIALIZE_PASS_DEPENDENCY(DemandedBits)
INITIALIZE_PASS_DEPENDENCY(DemandedBitsWrapperPass)
INITIALIZE_PASS_END(SLPVectorizer, SV_NAME, lv_name, false, false)
namespace llvm {

View File

@ -1,6 +1,6 @@
; RUN: opt -S -demanded-bits -analyze < %s | FileCheck %s
; CHECK-LABEL: 'test_mul'
; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
; CHECK-DAG: DemandedBits: 0xFF for %1 = add nsw i32 %a, 5
; CHECK-DAG: DemandedBits: 0xFF for %3 = trunc i32 %2 to i8
; CHECK-DAG: DemandedBits: 0xFF for %2 = mul nsw i32 %1, %b