Index: llvm/trunk/include/llvm/Analysis/DemandedBits.h =================================================================== --- llvm/trunk/include/llvm/Analysis/DemandedBits.h +++ llvm/trunk/include/llvm/Analysis/DemandedBits.h @@ -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 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 &AC; + 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); - - AssumptionCache *AC; - DominatorTree *DT; - Function *F; + const Instruction *I, unsigned OperandNo, + const APInt &AOut, APInt &AB, + APInt &KnownZero, APInt &KnownOne, + APInt &KnownZero2, APInt &KnownOne2); + bool Analyzed; // The set of visited instructions (non-integer-typed only). @@ -67,8 +68,49 @@ DenseMap AliveBits; }; +class DemandedBitsWrapperPass : public FunctionPass { +private: + mutable Optional 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 { + friend AnalysisInfoMixin; + 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 &AM); +}; + +/// \brief Printer pass for DemandedBits +class DemandedBitsPrinterPass : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit DemandedBitsPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager &AM); +}; + /// Create a demanded bits analysis pass. -FunctionPass *createDemandedBitsPass(); +FunctionPass *createDemandedBitsWrapperPass(); } // End llvm namespace Index: llvm/trunk/include/llvm/Analysis/VectorUtils.h =================================================================== --- llvm/trunk/include/llvm/Analysis/VectorUtils.h +++ llvm/trunk/include/llvm/Analysis/VectorUtils.h @@ -22,7 +22,7 @@ namespace llvm { template class ArrayRef; -struct DemandedBits; +class DemandedBits; class GetElementPtrInst; class Loop; class ScalarEvolution; Index: llvm/trunk/include/llvm/InitializePasses.h =================================================================== --- llvm/trunk/include/llvm/InitializePasses.h +++ llvm/trunk/include/llvm/InitializePasses.h @@ -323,7 +323,7 @@ void initializeFloat2IntPass(PassRegistry&); void initializeLoopDistributePass(PassRegistry&); void initializeSjLjEHPreparePass(PassRegistry&); -void initializeDemandedBitsPass(PassRegistry&); +void initializeDemandedBitsWrapperPassPass(PassRegistry&); void initializeFuncletLayoutPass(PassRegistry &); void initializeLoopLoadEliminationPass(PassRegistry&); void initializeFunctionImportPassPass(PassRegistry &); Index: llvm/trunk/lib/Analysis/Analysis.cpp =================================================================== --- llvm/trunk/lib/Analysis/Analysis.cpp +++ llvm/trunk/lib/Analysis/Analysis.cpp @@ -37,7 +37,7 @@ initializeCFLAAWrapperPassPass(Registry); initializeDependenceAnalysisPass(Registry); initializeDelinearizationPass(Registry); - initializeDemandedBitsPass(Registry); + initializeDemandedBitsWrapperPassPass(Registry); initializeDivergenceAnalysisPass(Registry); initializeDominanceFrontierWrapperPassPass(Registry); initializeDomViewerPass(Registry); Index: llvm/trunk/lib/Analysis/DemandedBits.cpp =================================================================== --- llvm/trunk/lib/Analysis/DemandedBits.cpp +++ llvm/trunk/lib/Analysis/DemandedBits.cpp @@ -42,25 +42,29 @@ #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(); AU.addRequired(); AU.setPreservesAll(); } +void DemandedBitsWrapperPass::print(raw_ostream &OS, const Module *M) const { + DB->print(OS); +} + static bool isAlwaysLive(Instruction *I) { return isa(I) || isa(I) || I->isEHPad() || I->mayHaveSideEffects(); @@ -84,13 +88,13 @@ KnownZero = APInt(BitWidth, 0); KnownOne = APInt(BitWidth, 0); computeKnownBits(const_cast(V1), KnownZero, KnownOne, DL, 0, - AC, UserI, DT); + &AC, UserI, &DT); if (V2) { KnownZero2 = APInt(BitWidth, 0); KnownOne2 = APInt(BitWidth, 0); computeKnownBits(const_cast(V2), KnownZero2, KnownOne2, DL, - 0, AC, UserI, DT); + 0, &AC, UserI, &DT); } }; @@ -243,19 +247,22 @@ } } -bool DemandedBits::runOnFunction(Function& Fn) { - F = &Fn; - Analyzed = false; +bool DemandedBitsWrapperPass::runOnFunction(Function &F) { + auto &AC = getAnalysis().getAssumptionCache(F); + auto &DT = getAnalysis().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().getAssumptionCache(*F); - DT = &getAnalysis().getDomTree(); Visited.clear(); AliveBits.clear(); @@ -263,7 +270,7 @@ SmallVector 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 @@ !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(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 &AM) { + auto &AC = AM.getResult(F); + auto &DT = AM.getResult(F); + return DemandedBits(F, AC, DT); +} + +PreservedAnalyses DemandedBitsPrinterPass::run(Function &F, + FunctionAnalysisManager &AM) { + AM.getResult(F).print(OS); + return PreservedAnalyses::all(); } Index: llvm/trunk/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/trunk/lib/Passes/PassBuilder.cpp +++ llvm/trunk/lib/Passes/PassBuilder.cpp @@ -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" Index: llvm/trunk/lib/Passes/PassRegistry.def =================================================================== --- llvm/trunk/lib/Passes/PassRegistry.def +++ llvm/trunk/lib/Passes/PassRegistry.def @@ -68,6 +68,7 @@ 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", AssumptionPrinterPass(dbgs())) FUNCTION_PASS("print", DominatorTreePrinterPass(dbgs())) FUNCTION_PASS("print", PostDominatorTreePrinterPass(dbgs())) +FUNCTION_PASS("print", DemandedBitsPrinterPass(dbgs())) FUNCTION_PASS("print", DominanceFrontierPrinterPass(dbgs())) FUNCTION_PASS("print", LoopPrinterPass(dbgs())) FUNCTION_PASS("print", RegionInfoPrinterPass(dbgs())) Index: llvm/trunk/lib/Transforms/Scalar/BDCE.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/BDCE.cpp +++ llvm/trunk/lib/Transforms/Scalar/BDCE.cpp @@ -45,7 +45,7 @@ void getAnalysisUsage(AnalysisUsage& AU) const override { AU.setPreservesCFG(); - AU.addRequired(); + AU.addRequired(); AU.addPreserved(); } }; @@ -54,14 +54,14 @@ 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(); + auto &DB = getAnalysis().getDemandedBits(); SmallVector Worklist; bool Changed = false; Index: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp +++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1498,9 +1498,9 @@ 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 &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 @@ AA = &getAnalysis().getAAResults(); AC = &getAnalysis().getAssumptionCache(F); LAA = &getAnalysis(); - DB = &getAnalysis(); + DB = &getAnalysis().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 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); @@ -6064,7 +6064,7 @@ 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 { Index: llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -3407,7 +3407,7 @@ LI = &getAnalysis().getLoopInfo(); DT = &getAnalysis().getDomTree(); AC = &getAnalysis().getAssumptionCache(F); - DB = &getAnalysis(); + DB = &getAnalysis().getDemandedBits(); Stores.clear(); GEPs.clear(); @@ -3484,7 +3484,7 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); @@ -4575,7 +4575,7 @@ 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 { Index: llvm/trunk/test/Analysis/DemandedBits/basic.ll =================================================================== --- llvm/trunk/test/Analysis/DemandedBits/basic.ll +++ llvm/trunk/test/Analysis/DemandedBits/basic.ll @@ -1,6 +1,6 @@ ; RUN: opt -S -demanded-bits -analyze < %s | FileCheck %s - -; CHECK-LABEL: 'test_mul' +; RUN: opt -S -disable-output -passes="print" < %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