diff --git a/llvm/include/llvm/Transforms/Scalar/GVN.h b/llvm/include/llvm/Transforms/Scalar/GVN.h --- a/llvm/include/llvm/Transforms/Scalar/GVN.h +++ b/llvm/include/llvm/Transforms/Scalar/GVN.h @@ -61,14 +61,51 @@ } // end namespace gvn +/// A set of parameters to control various transforms performed by GVN pass. +// Each of the optional boolean parameters can be set to: +/// true - enabling the transformation. +/// false - disabling the transformation. +/// None - relying on a global default. +/// Intended use is to create a default object, modify parameters with +/// additional setters and then pass it to GVN. +struct GVNOptions { + Optional AllowPRE = None; + Optional AllowLoadPRE = None; + Optional AllowMemDep = None; + + GVNOptions() = default; + + /// Enables or disables PRE in GVN. + GVNOptions &setPRE(bool PRE) { + AllowPRE = PRE; + return *this; + } + + /// Enables or disables PRE of loads in GVN. + GVNOptions &setLoadPRE(bool LoadPRE) { + AllowLoadPRE = LoadPRE; + return *this; + } + + /// Enables or disables use of MemDepAnalysis. + GVNOptions &setMemDep(bool MemDep) { + AllowMemDep = MemDep; + return *this; + } +}; + /// The core GVN pass object. /// /// FIXME: We should have a good summary of the GVN algorithm implemented by /// this particular pass here. class GVN : public PassInfoMixin { + GVNOptions Options; + public: struct Expression; + GVN(GVNOptions Options = {}) : Options(Options) {} + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); @@ -83,6 +120,10 @@ AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); } MemoryDependenceResults &getMemDep() const { return *MD; } + bool isPREEnabled() const; + bool isLoadPREEnabled() const; + bool isMemDepEnabled() const; + /// This class holds the mapping between values and value numbers. It is used /// as an efficient mechanism to determine the expression-wise equivalence of /// two values. diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -97,10 +97,9 @@ STATISTIC(NumGVNEqProp, "Number of equalities propagated"); STATISTIC(NumPRELoad, "Number of loads PRE'd"); -static cl::opt EnablePRE("enable-pre", - cl::init(true), cl::Hidden); -static cl::opt EnableLoadPRE("enable-load-pre", cl::init(true)); -static cl::opt EnableMemDep("enable-gvn-memdep", cl::init(true)); +static cl::opt GVNEnablePRE("enable-pre", cl::init(true), cl::Hidden); +static cl::opt GVNEnableLoadPRE("enable-load-pre", cl::init(true)); +static cl::opt GVNEnableMemDep("enable-gvn-memdep", cl::init(true)); // Maximum allowed recursion depth. static cl::opt @@ -610,6 +609,17 @@ // GVN Pass //===----------------------------------------------------------------------===// +bool GVN::isPREEnabled() const { + return Options.AllowPRE.getValueOr(GVNEnablePRE); +} + +bool GVN::isLoadPREEnabled() const { + return Options.AllowLoadPRE.getValueOr(GVNEnableLoadPRE); +} +bool GVN::isMemDepEnabled() const { + return Options.AllowMemDep.getValueOr(GVNEnableMemDep); +} + PreservedAnalyses GVN::run(Function &F, FunctionAnalysisManager &AM) { // FIXME: The order of evaluation of these 'getResult' calls is very // significant! Re-ordering these variables will cause GVN when run alone to @@ -619,10 +629,11 @@ auto &DT = AM.getResult(F); auto &TLI = AM.getResult(F); auto &AA = AM.getResult(F); - auto &MemDep = AM.getResult(F); + auto *MemDep = + isMemDepEnabled() ? &AM.getResult(F) : nullptr; auto *LI = AM.getCachedResult(F); auto &ORE = AM.getResult(F); - bool Changed = runImpl(F, AC, DT, TLI, AA, &MemDep, LI, &ORE); + bool Changed = runImpl(F, AC, DT, TLI, AA, MemDep, LI, &ORE); if (!Changed) return PreservedAnalyses::all(); PreservedAnalyses PA; @@ -1383,7 +1394,7 @@ } // Step 4: Eliminate partial redundancy. - if (!EnablePRE || !EnableLoadPRE) + if (!isPREEnabled() || !isLoadPREEnabled()) return false; return PerformLoadPRE(LI, ValuesPerBlock, UnavailableBlocks); @@ -2148,7 +2159,7 @@ ++Iteration; } - if (EnablePRE) { + if (isPREEnabled()) { // Fabricate val-num for dead-code in order to suppress assertion in // performPRE(). assignValNumForDeadCode(); @@ -2682,8 +2693,8 @@ public: static char ID; // Pass identification, replacement for typeid - explicit GVNLegacyPass(bool NoMemDepAnalysis = !EnableMemDep) - : FunctionPass(ID), NoMemDepAnalysis(NoMemDepAnalysis) { + explicit GVNLegacyPass(bool NoMemDepAnalysis = !GVNEnableMemDep) + : FunctionPass(ID), Impl(GVNOptions().setMemDep(!NoMemDepAnalysis)) { initializeGVNLegacyPassPass(*PassRegistry::getPassRegistry()); } @@ -2698,9 +2709,9 @@ getAnalysis().getDomTree(), getAnalysis().getTLI(F), getAnalysis().getAAResults(), - NoMemDepAnalysis - ? nullptr - : &getAnalysis().getMemDep(), + Impl.isMemDepEnabled() + ? &getAnalysis().getMemDep() + : nullptr, LIWP ? &LIWP->getLoopInfo() : nullptr, &getAnalysis().getORE()); } @@ -2710,7 +2721,7 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); - if (!NoMemDepAnalysis) + if (Impl.isMemDepEnabled()) AU.addRequired(); AU.addRequired(); @@ -2723,7 +2734,6 @@ } private: - bool NoMemDepAnalysis; GVN Impl; };