Index: include/llvm/Analysis/DemandedBits.h =================================================================== --- include/llvm/Analysis/DemandedBits.h +++ 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 DemandedBitsResult { +public: + DemandedBitsResult(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 DemandedBitsLegacyPass : public FunctionPass { +private: + mutable Optional DB; +public: + static char ID; // Pass identification, replacement for typeid + DemandedBitsLegacyPass(); + + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Clean up memory in between runs + void releaseMemory() override; + + DemandedBitsResult &getDemandedBitsResult() { return *DB; } + + void print(raw_ostream &OS, const Module *M) const override; +}; + +/// An analysis that produces \c DemandedBitsResult for a function. +class DemandedBitsAnalysis : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static char PassID; + +public: + /// \brief Provide the result typedef for this analysis pass. + typedef DemandedBitsResult Result; + + /// \brief Run the analysis pass over a function and produce demanded bits + /// information. + DemandedBitsResult 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 *createDemandedBitsLegacyPass(); } // End llvm namespace Index: include/llvm/Analysis/VectorUtils.h =================================================================== --- include/llvm/Analysis/VectorUtils.h +++ include/llvm/Analysis/VectorUtils.h @@ -22,7 +22,7 @@ namespace llvm { -struct DemandedBits; +class DemandedBitsResult; class GetElementPtrInst; class Loop; class ScalarEvolution; @@ -124,7 +124,7 @@ /// to do less work by only looking at illegal types. MapVector computeMinimumValueSizes(ArrayRef Blocks, - DemandedBits &DB, + DemandedBitsResult &DB, const TargetTransformInfo *TTI=nullptr); } // llvm namespace Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -318,7 +318,7 @@ void initializeFloat2IntPass(PassRegistry&); void initializeLoopDistributePass(PassRegistry&); void initializeSjLjEHPreparePass(PassRegistry&); -void initializeDemandedBitsPass(PassRegistry&); +void initializeDemandedBitsLegacyPassPass(PassRegistry&); void initializeFuncletLayoutPass(PassRegistry &); void initializeLoopLoadEliminationPass(PassRegistry&); void initializeFunctionImportPassPass(PassRegistry &); Index: lib/Analysis/Analysis.cpp =================================================================== --- lib/Analysis/Analysis.cpp +++ lib/Analysis/Analysis.cpp @@ -37,7 +37,7 @@ initializeCFLAAWrapperPassPass(Registry); initializeDependenceAnalysisPass(Registry); initializeDelinearizationPass(Registry); - initializeDemandedBitsPass(Registry); + initializeDemandedBitsLegacyPassPass(Registry); initializeDivergenceAnalysisPass(Registry); initializeDominanceFrontierWrapperPassPass(Registry); initializeDomViewerPass(Registry); Index: lib/Analysis/DemandedBits.cpp =================================================================== --- lib/Analysis/DemandedBits.cpp +++ lib/Analysis/DemandedBits.cpp @@ -43,31 +43,35 @@ #define DEBUG_TYPE "demanded-bits" -char DemandedBits::ID = 0; -INITIALIZE_PASS_BEGIN(DemandedBits, "demanded-bits", "Demanded bits analysis", - false, false) +char DemandedBitsLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(DemandedBitsLegacyPass, "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(DemandedBitsLegacyPass, "demanded-bits", + "Demanded bits analysis", false, false) -DemandedBits::DemandedBits() : FunctionPass(ID), F(nullptr), Analyzed(false) { - initializeDemandedBitsPass(*PassRegistry::getPassRegistry()); +DemandedBitsLegacyPass::DemandedBitsLegacyPass() : FunctionPass(ID) { + initializeDemandedBitsLegacyPassPass(*PassRegistry::getPassRegistry()); } -void DemandedBits::getAnalysisUsage(AnalysisUsage &AU) const { +void DemandedBitsLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); AU.addRequired(); AU.addRequired(); AU.setPreservesAll(); } +void DemandedBitsLegacyPass::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(); } -void DemandedBits::determineLiveOperandBits( +void DemandedBitsResult::determineLiveOperandBits( const Instruction *UserI, const Instruction *I, unsigned OperandNo, const APInt &AOut, APInt &AB, APInt &KnownZero, APInt &KnownOne, APInt &KnownZero2, APInt &KnownOne2) { @@ -85,13 +89,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); } }; @@ -244,19 +248,22 @@ } } -bool DemandedBits::runOnFunction(Function& Fn) { - F = &Fn; - Analyzed = false; +bool DemandedBitsLegacyPass::runOnFunction(Function &F) { + auto &AC = getAnalysis().getAssumptionCache(F); + auto &DT = getAnalysis().getDomTree(); + DB.emplace(F, AC, DT); return false; } -void DemandedBits::performAnalysis() { +void DemandedBitsLegacyPass::releaseMemory() { + DB.reset(); +} + +void DemandedBitsResult::performAnalysis() { if (Analyzed) // Analysis already completed for this function. return; Analyzed = true; - AC = &getAnalysis().getAssumptionCache(*F); - DT = &getAnalysis().getDomTree(); Visited.clear(); AliveBits.clear(); @@ -264,7 +271,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; @@ -353,7 +360,7 @@ } } -APInt DemandedBits::getDemandedBits(Instruction *I) { +APInt DemandedBitsResult::getDemandedBits(Instruction *I) { performAnalysis(); const DataLayout &DL = I->getParent()->getModule()->getDataLayout(); @@ -362,23 +369,36 @@ return APInt::getAllOnesValue(DL.getTypeSizeInBits(I->getType())); } -bool DemandedBits::isInstructionDead(Instruction *I) { +bool DemandedBitsResult::isInstructionDead(Instruction *I) { performAnalysis(); return !Visited.count(I) && AliveBits.find(I) == AliveBits.end() && !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 DemandedBitsResult::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::createDemandedBitsLegacyPass() { + return new DemandedBitsLegacyPass(); } + +char DemandedBitsAnalysis::PassID; + +DemandedBitsResult DemandedBitsAnalysis::run(Function &F, + AnalysisManager &AM) { + auto &AC = AM.getResult(F); + auto &DT = AM.getResult(F); + return DemandedBitsResult(F, AC, DT); +} + +PreservedAnalyses DemandedBitsPrinterPass::run(Function &F, + FunctionAnalysisManager &AM) { + AM.getResult(F).print(OS); + return PreservedAnalyses::all(); +} \ No newline at end of file Index: lib/Analysis/VectorUtils.cpp =================================================================== --- lib/Analysis/VectorUtils.cpp +++ lib/Analysis/VectorUtils.cpp @@ -437,7 +437,8 @@ } MapVector -llvm::computeMinimumValueSizes(ArrayRef Blocks, DemandedBits &DB, +llvm::computeMinimumValueSizes(ArrayRef Blocks, + DemandedBitsResult &DB, const TargetTransformInfo *TTI) { // DemandedBits will give us every value's live-out bits. But we want Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ 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: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -67,6 +67,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()) @@ -104,6 +105,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: lib/Transforms/Scalar/BDCE.cpp =================================================================== --- lib/Transforms/Scalar/BDCE.cpp +++ 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(DemandedBitsLegacyPass) 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().getDemandedBitsResult(); SmallVector Worklist; bool Changed = false; Index: lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/LoopVectorize.cpp +++ lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1478,9 +1478,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, + DemandedBitsResult *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) {} @@ -1584,7 +1584,7 @@ /// Target Library Info. const TargetLibraryInfo *TLI; /// Demanded bits analysis - DemandedBits *DB; + DemandedBitsResult *DB; const Function *TheFunction; // Loop Vectorize Hint. const LoopVectorizeHints *Hints; @@ -1677,7 +1677,7 @@ DominatorTree *DT; BlockFrequencyInfo *BFI; TargetLibraryInfo *TLI; - DemandedBits *DB; + DemandedBitsResult *DB; AliasAnalysis *AA; AssumptionCache *AC; LoopAccessAnalysis *LAA; @@ -1697,7 +1697,7 @@ AA = &getAnalysis().getAAResults(); AC = &getAnalysis().getAssumptionCache(F); LAA = &getAnalysis(); - DB = &getAnalysis(); + DB = &getAnalysis().getDemandedBitsResult(); // Compute some weights outside of the loop over the loops. Compute this // using a BranchProbability to re-use its scaling math. @@ -2000,7 +2000,7 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); @@ -5994,7 +5994,7 @@ INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(LoopSimplify) INITIALIZE_PASS_DEPENDENCY(LoopAccessAnalysis) -INITIALIZE_PASS_DEPENDENCY(DemandedBits) +INITIALIZE_PASS_DEPENDENCY(DemandedBitsLegacyPass) INITIALIZE_PASS_END(LoopVectorize, LV_NAME, lv_name, false, false) namespace llvm { Index: lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- lib/Transforms/Vectorize/SLPVectorizer.cpp +++ lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -368,7 +368,7 @@ BoUpSLP(Function *Func, ScalarEvolution *Se, TargetTransformInfo *Tti, TargetLibraryInfo *TLi, AliasAnalysis *Aa, LoopInfo *Li, - DominatorTree *Dt, AssumptionCache *AC, DemandedBits *DB, + DominatorTree *Dt, AssumptionCache *AC, DemandedBitsResult *DB, const DataLayout *DL) : NumLoadsWantToKeepOrder(0), NumLoadsWantToChangeOrder(0), F(Func), SE(Se), TTI(Tti), TLI(TLi), AA(Aa), LI(Li), DT(Dt), AC(AC), DB(DB), @@ -925,7 +925,7 @@ LoopInfo *LI; DominatorTree *DT; AssumptionCache *AC; - DemandedBits *DB; + DemandedBitsResult *DB; const DataLayout *DL; /// Instruction builder to construct the vectorized tree. IRBuilder<> Builder; @@ -3377,7 +3377,7 @@ LoopInfo *LI; DominatorTree *DT; AssumptionCache *AC; - DemandedBits *DB; + DemandedBitsResult *DB; const DataLayout *DL; bool doInitialization(Module &M) override { @@ -3397,7 +3397,7 @@ LI = &getAnalysis().getLoopInfo(); DT = &getAnalysis().getDomTree(); AC = &getAnalysis().getAssumptionCache(F); - DB = &getAnalysis(); + DB = &getAnalysis().getDemandedBitsResult(); Stores.clear(); GEPs.clear(); @@ -3474,7 +3474,7 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); @@ -4565,7 +4565,7 @@ INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) INITIALIZE_PASS_DEPENDENCY(LoopSimplify) -INITIALIZE_PASS_DEPENDENCY(DemandedBits) +INITIALIZE_PASS_DEPENDENCY(DemandedBitsLegacyPass) INITIALIZE_PASS_END(SLPVectorizer, SV_NAME, lv_name, false, false) namespace llvm { Index: test/Analysis/DemandedBits/basic.ll =================================================================== --- test/Analysis/DemandedBits/basic.ll +++ 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