diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h --- a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h @@ -6,38 +6,70 @@ // //===----------------------------------------------------------------------===// /// \file -/// This contains common code to drive combines. Combiner Passes will need to -/// setup a CombinerInfo and call combineMachineFunction. +/// This contains the base class for all Combiners generated by TableGen. +/// Backends need to create class that inherits from "Combiner" and put all of +/// the TableGen-erated code in there, as it implements the virtual functions. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_H #define LLVM_CODEGEN_GLOBALISEL_COMBINER_H +#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" namespace llvm { class MachineRegisterInfo; -class CombinerInfo; +struct CombinerInfo; class GISelCSEInfo; class TargetPassConfig; class MachineFunction; +class MachineIRBuilder; + +/// Combiner implementation. This is per-function, so passes need to recreate +/// one of these each time they enter a new function. +/// +/// TODO: Is it worth making this module-wide? +class Combiner : public GIMatchTableExecutor { +private: + class WorkListMaintainer; + GISelWorkList<512> WorkList; + + // We have a little hack here where keep the owned pointers private, and only + // expose a reference. This has two purposes: + // - Avoid derived classes messing with those pointers. + // - Keep the API consistent. CInfo, MF, MRI, etc. are all accessed as + // references. Accessing Observer/B as pointers unnecessarily leaks + // implementation details into derived classes. + std::unique_ptr Builder; + std::unique_ptr WLObserver; + std::unique_ptr ObserverWrapper; + + bool HasSetupMF = false; -class Combiner { public: - Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC); + /// If CSEInfo is not null, then the Combiner will use CSEInfo as the observer + /// and also create a CSEMIRBuilder. Pass nullptr if CSE is not needed. + Combiner(MachineFunction &MF, CombinerInfo &CInfo, + const TargetPassConfig *TPC, GISelKnownBits *KB, + GISelCSEInfo *CSEInfo = nullptr); + virtual ~Combiner(); + + virtual bool tryCombineAll(MachineInstr &I) const = 0; - /// If CSEInfo is not null, then the Combiner will setup observer for - /// CSEInfo and instantiate a CSEMIRBuilder. Pass nullptr if CSE is not - /// needed. - bool combineMachineInstrs(MachineFunction &MF, GISelCSEInfo *CSEInfo); + bool combineMachineInstrs(); protected: CombinerInfo &CInfo; + GISelChangeObserver &Observer; + MachineIRBuilder &B; + MachineFunction &MF; + MachineRegisterInfo &MRI; + GISelKnownBits *KB; - MachineRegisterInfo *MRI = nullptr; const TargetPassConfig *TPC; - std::unique_ptr Builder; + GISelCSEInfo *CSEInfo; }; } // End namespace llvm. diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// /// \file -/// Interface for Targets to specify which operations are combined how and when. +/// Option class for Targets to specify which operations are combined how and +/// when. /// //===----------------------------------------------------------------------===// @@ -16,15 +17,11 @@ #include namespace llvm { -class GISelChangeObserver; class LegalizerInfo; -class MachineInstr; -class MachineIRBuilder; // Contains information relevant to enabling/disabling various combines for a // pass. -class CombinerInfo { -public: +struct CombinerInfo { CombinerInfo(bool AllowIllegalOps, bool ShouldLegalizeIllegal, const LegalizerInfo *LInfo, bool OptEnabled, bool OptSize, bool MinSize) @@ -52,19 +49,6 @@ bool EnableOptSize; /// Whether we're optimizing for minsize (-Oz). bool EnableMinSize; - - /// Attempt to combine instructions using MI as the root. - /// - /// Use Observer to report the creation, modification, and erasure of - /// instructions. GISelChangeObserver will automatically report certain - /// kinds of operations. These operations are: - /// * Instructions that are newly inserted into the MachineFunction - /// * Instructions that are erased from the MachineFunction. - /// - /// However, it is important to report instruction modification and this is - /// not automatic. - virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const = 0; }; } // namespace llvm diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h @@ -463,9 +463,7 @@ // For some predicates, we need to track the current MBB. MachineBasicBlock *CurMBB = nullptr; - virtual void setupGeneratedPerFunctionState(MachineFunction &MF) { - llvm_unreachable("TableGen should have emitted implementation"); - } + virtual void setupGeneratedPerFunctionState(MachineFunction &MF) = 0; /// Setup per-MF executor state. virtual void setupMF(MachineFunction &mf, GISelKnownBits *kb, diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -37,6 +37,9 @@ : GICombineGroup { // The class name to use in the generated output. string Classname = classname; + // Combiners can use this so they're free to define tryCombineAll themselves + // and do extra work before/after calling the TableGen-erated code. + string CombineAllMethodName = "tryCombineAll"; // The name of a run-time compiler option that will be generated to disable // specific rules within this combiner. string DisableRuleOption = ?; diff --git a/llvm/lib/CodeGen/GlobalISel/Combiner.cpp b/llvm/lib/CodeGen/GlobalISel/Combiner.cpp --- a/llvm/lib/CodeGen/GlobalISel/Combiner.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Combiner.cpp @@ -39,7 +39,6 @@ ); } // end namespace llvm -namespace { /// This class acts as the glue the joins the CombinerHelper to the overall /// Combine algorithm. The CombinerHelper is intended to report the /// modifications it makes to the MIR to the GISelChangeObserver and the @@ -48,7 +47,7 @@ /// instruction creation will schedule that instruction for a future visit. /// Other Combiner implementations may require more complex behaviour from /// their GISelChangeObserver subclass. -class WorkListMaintainer : public GISelChangeObserver { +class Combiner::WorkListMaintainer : public GISelChangeObserver { using WorkListTy = GISelWorkList<512>; WorkListTy &WorkList; /// The instructions that have been created but we want to report once they @@ -88,27 +87,46 @@ LLVM_DEBUG(CreatedInstrs.clear()); } }; -} -Combiner::Combiner(CombinerInfo &Info, const TargetPassConfig *TPC) - : CInfo(Info), TPC(TPC) { +Combiner::Combiner(MachineFunction &MF, CombinerInfo &CInfo, + const TargetPassConfig *TPC, GISelKnownBits *KB, + GISelCSEInfo *CSEInfo) + : Builder(CSEInfo ? std::make_unique() + : std::make_unique()), + WLObserver(std::make_unique(WorkList)), + ObserverWrapper(std::make_unique()), CInfo(CInfo), + Observer(*ObserverWrapper), B(*Builder), MF(MF), MRI(MF.getRegInfo()), + KB(KB), TPC(TPC), CSEInfo(CSEInfo) { (void)this->TPC; // FIXME: Remove when used. + + // Setup builder. + B.setMF(MF); + if (CSEInfo) + B.setCSEInfo(CSEInfo); + + // Setup observer. + ObserverWrapper->addObserver(WLObserver.get()); + if (CSEInfo) + ObserverWrapper->addObserver(CSEInfo); + + B.setChangeObserver(*ObserverWrapper); } -bool Combiner::combineMachineInstrs(MachineFunction &MF, - GISelCSEInfo *CSEInfo) { +Combiner::~Combiner() = default; + +bool Combiner::combineMachineInstrs() { // If the ISel pipeline failed, do not bother running this pass. // FIXME: Should this be here or in individual combiner passes. if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) return false; - Builder = - CSEInfo ? std::make_unique() : std::make_unique(); - MRI = &MF.getRegInfo(); - Builder->setMF(MF); - if (CSEInfo) - Builder->setCSEInfo(CSEInfo); + // We can't call this in the constructor because the derived class is + // uninitialized at that time. + if (!HasSetupMF) { + HasSetupMF = true; + setupMF(MF, KB); + } LLVM_DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n'); @@ -116,26 +134,23 @@ bool MFChanged = false; bool Changed; - MachineIRBuilder &B = *Builder; do { + WorkList.clear(); + // Collect all instructions. Do a post order traversal for basic blocks and // insert with list bottom up, so while we pop_back_val, we'll traverse top // down RPOT. Changed = false; - GISelWorkList<512> WorkList; - WorkListMaintainer Observer(WorkList); - GISelObserverWrapper WrapperObserver(&Observer); - if (CSEInfo) - WrapperObserver.addObserver(CSEInfo); - RAIIDelegateInstaller DelInstall(MF, &WrapperObserver); + + RAIIDelegateInstaller DelInstall(MF, ObserverWrapper.get()); for (MachineBasicBlock *MBB : post_order(&MF)) { for (MachineInstr &CurMI : llvm::make_early_inc_range(llvm::reverse(*MBB))) { // Erase dead insts before even adding to the list. - if (isTriviallyDead(CurMI, *MRI)) { + if (isTriviallyDead(CurMI, MRI)) { LLVM_DEBUG(dbgs() << CurMI << "Is dead; erasing.\n"); - llvm::salvageDebugInfo(*MRI, CurMI); + llvm::salvageDebugInfo(MRI, CurMI); CurMI.eraseFromParent(); continue; } @@ -147,8 +162,8 @@ while (!WorkList.empty()) { MachineInstr *CurrInst = WorkList.pop_back_val(); LLVM_DEBUG(dbgs() << "\nTry combining " << *CurrInst;); - Changed |= CInfo.combine(WrapperObserver, *CurrInst, B); - Observer.reportFullyCreatedInstrs(); + Changed |= tryCombineAll(*CurrInst); + WLObserver->reportFullyCreatedInstrs(); } MFChanged |= Changed; } while (Changed); diff --git a/llvm/lib/Target/AArch64/AArch64Combine.td b/llvm/lib/Target/AArch64/AArch64Combine.td --- a/llvm/lib/Target/AArch64/AArch64Combine.td +++ b/llvm/lib/Target/AArch64/AArch64Combine.td @@ -38,10 +38,12 @@ fconstant_to_constant, icmp_redundant_trunc, fold_global_offset]> { + let CombineAllMethodName = "tryCombineAllImpl"; } def AArch64O0PreLegalizerCombiner: GICombinerHelper< "AArch64O0PreLegalizerCombinerImpl", [optnone_combines]> { + let CombineAllMethodName = "tryCombineAllImpl"; } // Matchdata for combines which replace a G_SHUFFLE_VECTOR with a diff --git a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp @@ -16,7 +16,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" @@ -42,27 +41,25 @@ #include "AArch64GenO0PreLegalizeGICombiner.inc" #undef GET_GICOMBINER_TYPES -class AArch64O0PreLegalizerCombinerImpl : public GIMatchTableExecutor { +class AArch64O0PreLegalizerCombinerImpl : public Combiner { protected: - CombinerHelper &Helper; + // TODO: Make CombinerHelper methods const. + mutable CombinerHelper Helper; const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig; - const AArch64Subtarget &STI; - GISelChangeObserver &Observer; - MachineIRBuilder &B; - MachineFunction &MF; - - MachineRegisterInfo &MRI; public: AArch64O0PreLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig, - GISelChangeObserver &Observer, MachineIRBuilder &B, - CombinerHelper &Helper); + const AArch64Subtarget &STI); static const char *getName() { return "AArch64O0PreLegalizerCombiner"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAll(MachineInstr &I) const override; + + bool tryCombineAllImpl(MachineInstr &I) const; private: #define GET_GICOMBINER_CLASS_MEMBERS @@ -75,45 +72,21 @@ #undef GET_GICOMBINER_IMPL AArch64O0PreLegalizerCombinerImpl::AArch64O0PreLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig, - GISelChangeObserver &Observer, MachineIRBuilder &B, CombinerHelper &Helper) - : Helper(Helper), RuleConfig(RuleConfig), - STI(B.getMF().getSubtarget()), Observer(Observer), B(B), - MF(B.getMF()), MRI(*B.getMRI()), + const AArch64Subtarget &STI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), + Helper(Observer, B, /*IsPreLegalize*/ true, &KB), RuleConfig(RuleConfig), + STI(STI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "AArch64GenO0PreLegalizeGICombiner.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS { } -class AArch64O0PreLegalizerCombinerInfo : public CombinerInfo { - GISelKnownBits *KB; - MachineDominatorTree *MDT; - AArch64O0PreLegalizerCombinerImplRuleConfig RuleConfig; - -public: - AArch64O0PreLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, - GISelKnownBits *KB, - MachineDominatorTree *MDT) - : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, - /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize), - KB(KB), MDT(MDT) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool AArch64O0PreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - CombinerHelper Helper(Observer, B, /*IsPreLegalize*/ true, KB, MDT); - AArch64O0PreLegalizerCombinerImpl Impl(RuleConfig, Observer, B, Helper); - Impl.setupMF(*MI.getMF(), KB); - - if (Impl.tryCombineAll(MI)) +bool AArch64O0PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const { + if (tryCombineAllImpl(MI)) return true; unsigned Opc = MI.getOpcode(); @@ -133,7 +106,7 @@ if (Helper.tryCombineMemCpyFamily(MI, MaxLen)) return true; if (Opc == TargetOpcode::G_MEMSET) - return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, EnableMinSize); + return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, CInfo.EnableMinSize); return false; } } @@ -157,6 +130,9 @@ bool runOnMachineFunction(MachineFunction &MF) override; void getAnalysisUsage(AnalysisUsage &AU) const override; + +private: + AArch64O0PreLegalizerCombinerImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -172,6 +148,9 @@ AArch64O0PreLegalizerCombiner::AArch64O0PreLegalizerCombiner() : MachineFunctionPass(ID) { initializeAArch64O0PreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool AArch64O0PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { @@ -182,10 +161,15 @@ const Function &F = MF.getFunction(); GISelKnownBits *KB = &getAnalysis().get(MF); - AArch64O0PreLegalizerCombinerInfo PCInfo( - false, F.hasOptSize(), F.hasMinSize(), KB, nullptr /* MDT */); - Combiner C(PCInfo, &TPC); - return C.combineMachineInstrs(MF, nullptr /* CSEInfo */); + + const AArch64Subtarget &ST = MF.getSubtarget(); + + CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, + /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false, + F.hasOptSize(), F.hasMinSize()); + AArch64O0PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *KB, + /*CSEInfo*/ nullptr, RuleConfig, ST); + return Impl.combineMachineInstrs(); } char AArch64O0PreLegalizerCombiner::ID = 0; diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp @@ -24,7 +24,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" @@ -339,26 +338,24 @@ Store.eraseFromParent(); } -class AArch64PostLegalizerCombinerImpl : public GIMatchTableExecutor { +class AArch64PostLegalizerCombinerImpl : public Combiner { protected: - CombinerHelper &Helper; + // TODO: Make CombinerHelper methods const. + mutable CombinerHelper Helper; const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig; - const AArch64Subtarget &STI; - MachineRegisterInfo &MRI; - GISelChangeObserver &Observer; - MachineIRBuilder &B; - MachineFunction &MF; public: AArch64PostLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig, - const AArch64Subtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper); + const AArch64Subtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI); static const char *getName() { return "AArch64PostLegalizerCombiner"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAll(MachineInstr &I) const override; private: #define GET_GICOMBINER_CLASS_MEMBERS @@ -371,49 +368,20 @@ #undef GET_GICOMBINER_IMPL AArch64PostLegalizerCombinerImpl::AArch64PostLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig, - const AArch64Subtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper) - : Helper(Helper), RuleConfig(RuleConfig), STI(STI), MRI(*B.getMRI()), - Observer(Observer), B(B), MF(B.getMF()), + const AArch64Subtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), + Helper(Observer, B, /*IsPreLegalize*/ false, &KB, MDT, LI), + RuleConfig(RuleConfig), STI(STI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "AArch64GenPostLegalizeGICombiner.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS { } -class AArch64PostLegalizerCombinerInfo : public CombinerInfo { - GISelKnownBits *KB; - MachineDominatorTree *MDT; - -public: - AArch64PostLegalizerCombinerImplRuleConfig RuleConfig; - - AArch64PostLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, - GISelKnownBits *KB, - MachineDominatorTree *MDT) - : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, - /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize), - KB(KB), MDT(MDT) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool AArch64PostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - const auto &STI = MI.getMF()->getSubtarget(); - const auto *LI = STI.getLegalizerInfo(); - CombinerHelper Helper(Observer, B, /*IsPreLegalize*/ false, KB, MDT, LI); - AArch64PostLegalizerCombinerImpl Impl(RuleConfig, STI, Observer, B, Helper); - Impl.setupMF(*MI.getMF(), KB); - return Impl.tryCombineAll(MI); -} - class AArch64PostLegalizerCombiner : public MachineFunctionPass { public: static char ID; @@ -429,6 +397,7 @@ private: bool IsOptNone; + AArch64PostLegalizerCombinerImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -450,6 +419,9 @@ AArch64PostLegalizerCombiner::AArch64PostLegalizerCombiner(bool IsOptNone) : MachineFunctionPass(ID), IsOptNone(IsOptNone) { initializeAArch64PostLegalizerCombinerPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool AArch64PostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { @@ -463,16 +435,23 @@ const Function &F = MF.getFunction(); bool EnableOpt = MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F); + + const AArch64Subtarget &ST = MF.getSubtarget(); + const auto *LI = ST.getLegalizerInfo(); + GISelKnownBits *KB = &getAnalysis().get(MF); MachineDominatorTree *MDT = IsOptNone ? nullptr : &getAnalysis(); - AArch64PostLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(), - F.hasMinSize(), KB, MDT); GISelCSEAnalysisWrapper &Wrapper = getAnalysis().getCSEWrapper(); auto *CSEInfo = &Wrapper.get(TPC->getCSEConfig()); - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, CSEInfo); + + CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, + /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(), + F.hasMinSize()); + AArch64PostLegalizerCombinerImpl Impl(MF, CInfo, TPC, *KB, CSEInfo, + RuleConfig, ST, MDT, LI); + return Impl.combineMachineInstrs(); } char AArch64PostLegalizerCombiner::ID = 0; diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp @@ -29,7 +29,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" @@ -1067,27 +1066,23 @@ Helper.lower(MI, 0, /* Unused hint type */ LLT()); } -class AArch64PostLegalizerLoweringImpl : public GIMatchTableExecutor { +class AArch64PostLegalizerLoweringImpl : public Combiner { protected: - CombinerHelper &Helper; + // TODO: Make CombinerHelper methods const. + mutable CombinerHelper Helper; const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig; - const AArch64Subtarget &STI; - GISelChangeObserver &Observer; - MachineIRBuilder &B; - MachineFunction &MF; - - MachineRegisterInfo &MRI; public: AArch64PostLegalizerLoweringImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelCSEInfo *CSEInfo, const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig, - const AArch64Subtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper); + const AArch64Subtarget &STI); static const char *getName() { return "AArch6400PreLegalizerCombiner"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAll(MachineInstr &I) const override; private: #define GET_GICOMBINER_CLASS_MEMBERS @@ -1100,42 +1095,19 @@ #undef GET_GICOMBINER_IMPL AArch64PostLegalizerLoweringImpl::AArch64PostLegalizerLoweringImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelCSEInfo *CSEInfo, const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig, - const AArch64Subtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper) - : Helper(Helper), RuleConfig(RuleConfig), STI(STI), Observer(Observer), - B(B), MF(B.getMF()), MRI(*B.getMRI()), + const AArch64Subtarget &STI) + : Combiner(MF, CInfo, TPC, /*KB*/ nullptr, CSEInfo), + Helper(Observer, B, /*IsPreLegalize*/ true), RuleConfig(RuleConfig), + STI(STI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "AArch64GenPostLegalizeGILowering.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS { } -class AArch64PostLegalizerLoweringInfo : public CombinerInfo { -public: - AArch64PostLegalizerLoweringImplRuleConfig RuleConfig; - - AArch64PostLegalizerLoweringInfo(bool OptSize, bool MinSize) - : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, - /*LegalizerInfo*/ nullptr, /*OptEnabled = */ true, OptSize, - MinSize) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool AArch64PostLegalizerLoweringInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - const auto &STI = MI.getMF()->getSubtarget(); - CombinerHelper Helper(Observer, B, /* IsPreLegalize*/ false); - AArch64PostLegalizerLoweringImpl Impl(RuleConfig, STI, Observer, B, Helper); - Impl.setupMF(*MI.getMF(), Helper.getKnownBits()); - return Impl.tryCombineAll(MI); -} class AArch64PostLegalizerLowering : public MachineFunctionPass { public: static char ID; @@ -1148,6 +1120,9 @@ bool runOnMachineFunction(MachineFunction &MF) override; void getAnalysisUsage(AnalysisUsage &AU) const override; + +private: + AArch64PostLegalizerLoweringImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -1161,6 +1136,9 @@ AArch64PostLegalizerLowering::AArch64PostLegalizerLowering() : MachineFunctionPass(ID) { initializeAArch64PostLegalizerLoweringPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool AArch64PostLegalizerLowering::runOnMachineFunction(MachineFunction &MF) { @@ -1172,9 +1150,14 @@ "Expected a legalized function?"); auto *TPC = &getAnalysis(); const Function &F = MF.getFunction(); - AArch64PostLegalizerLoweringInfo PCInfo(F.hasOptSize(), F.hasMinSize()); - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr); + + const AArch64Subtarget &ST = MF.getSubtarget(); + CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, + /*LegalizerInfo*/ nullptr, /*OptEnabled=*/true, + F.hasOptSize(), F.hasMinSize()); + AArch64PostLegalizerLoweringImpl Impl(MF, CInfo, TPC, /*CSEInfo*/ nullptr, + RuleConfig, ST); + return Impl.combineMachineInstrs(); } char AArch64PostLegalizerLowering::ID = 0; diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp @@ -17,7 +17,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" @@ -343,27 +342,26 @@ return true; } -class AArch64PreLegalizerCombinerImpl : public GIMatchTableExecutor { +class AArch64PreLegalizerCombinerImpl : public Combiner { protected: - CombinerHelper &Helper; + // TODO: Make CombinerHelper methods const. + mutable CombinerHelper Helper; const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig; - const AArch64Subtarget &STI; - GISelChangeObserver &Observer; - MachineIRBuilder &B; - MachineFunction &MF; - - MachineRegisterInfo &MRI; public: AArch64PreLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig, - const AArch64Subtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper); + const AArch64Subtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI); static const char *getName() { return "AArch6400PreLegalizerCombiner"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAll(MachineInstr &I) const override; + + bool tryCombineAllImpl(MachineInstr &I) const; private: #define GET_GICOMBINER_CLASS_MEMBERS @@ -376,46 +374,22 @@ #undef GET_GICOMBINER_IMPL AArch64PreLegalizerCombinerImpl::AArch64PreLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig, - const AArch64Subtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper) - : Helper(Helper), RuleConfig(RuleConfig), STI(STI), Observer(Observer), - B(B), MF(B.getMF()), MRI(*B.getMRI()), + const AArch64Subtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), + Helper(Observer, B, /*IsPreLegalize*/ true, &KB, MDT, LI), + RuleConfig(RuleConfig), STI(STI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "AArch64GenPreLegalizeGICombiner.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS { } -class AArch64PreLegalizerCombinerInfo : public CombinerInfo { - GISelKnownBits *KB; - MachineDominatorTree *MDT; - AArch64PreLegalizerCombinerImplRuleConfig RuleConfig; - -public: - AArch64PreLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, - GISelKnownBits *KB, MachineDominatorTree *MDT) - : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, - /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize), - KB(KB), MDT(MDT) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool AArch64PreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - const auto &STI = MI.getMF()->getSubtarget(); - const auto *LI = STI.getLegalizerInfo(); - CombinerHelper Helper(Observer, B, /* IsPreLegalize*/ true, KB, MDT, LI); - AArch64PreLegalizerCombinerImpl Impl(RuleConfig, STI, Observer, B, Helper); - Impl.setupMF(*MI.getMF(), KB); - - if (Impl.tryCombineAll(MI)) +bool AArch64PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const { + if (tryCombineAllImpl(MI)) return true; unsigned Opc = MI.getOpcode(); @@ -433,12 +407,12 @@ case TargetOpcode::G_MEMSET: { // If we're at -O0 set a maxlen of 32 to inline, otherwise let the other // heuristics decide. - unsigned MaxLen = EnableOpt ? 0 : 32; + unsigned MaxLen = CInfo.EnableOpt ? 0 : 32; // Try to inline memcpy type calls if optimizations are enabled. if (Helper.tryCombineMemCpyFamily(MI, MaxLen)) return true; if (Opc == TargetOpcode::G_MEMSET) - return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, EnableMinSize); + return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, CInfo.EnableMinSize); return false; } } @@ -462,6 +436,9 @@ bool runOnMachineFunction(MachineFunction &MF) override; void getAnalysisUsage(AnalysisUsage &AU) const override; + +private: + AArch64PreLegalizerCombinerImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -481,6 +458,9 @@ AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner() : MachineFunctionPass(ID) { initializeAArch64PreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { @@ -494,15 +474,20 @@ getAnalysis().getCSEWrapper(); auto *CSEInfo = &Wrapper.get(TPC.getCSEConfig()); + const AArch64Subtarget &ST = MF.getSubtarget(); + const auto *LI = ST.getLegalizerInfo(); + const Function &F = MF.getFunction(); bool EnableOpt = MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F); GISelKnownBits *KB = &getAnalysis().get(MF); MachineDominatorTree *MDT = &getAnalysis(); - AArch64PreLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(), - F.hasMinSize(), KB, MDT); - Combiner C(PCInfo, &TPC); - return C.combineMachineInstrs(MF, CSEInfo); + CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, + /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(), + F.hasMinSize()); + AArch64PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *KB, CSEInfo, + RuleConfig, ST, MDT, LI); + return Impl.combineMachineInstrs(); } char AArch64PreLegalizerCombiner::ID = 0; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCombine.td b/llvm/lib/Target/AMDGPU/AMDGPUCombine.td --- a/llvm/lib/Target/AMDGPU/AMDGPUCombine.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUCombine.td @@ -142,6 +142,7 @@ def AMDGPUPreLegalizerCombiner: GICombinerHelper< "AMDGPUPreLegalizerCombinerImpl", [all_combines, clamp_i64_to_i16, foldable_fneg]> { + let CombineAllMethodName = "tryCombineAllImpl"; } def AMDGPUPostLegalizerCombiner: GICombinerHelper< @@ -149,6 +150,7 @@ [all_combines, gfx6gfx7_combines, gfx8_combines, uchar_to_float, cvt_f32_ubyteN, remove_fcanonicalize, foldable_fneg, rcp_sqrt_to_rsq, sign_extension_in_reg]> { + let CombineAllMethodName = "tryCombineAllImpl"; } def AMDGPURegBankCombiner : GICombinerHelper< diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPostLegalizerCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPostLegalizerCombiner.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUPostLegalizerCombiner.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUPostLegalizerCombiner.cpp @@ -19,7 +19,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" @@ -43,27 +42,26 @@ #include "AMDGPUGenPostLegalizeGICombiner.inc" #undef GET_GICOMBINER_TYPES -class AMDGPUPostLegalizerCombinerImpl : public GIMatchTableExecutor { +class AMDGPUPostLegalizerCombinerImpl : public Combiner { protected: const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig; - - MachineIRBuilder &B; - MachineFunction &MF; - MachineRegisterInfo &MRI; const GCNSubtarget &STI; const SIInstrInfo &TII; - AMDGPUCombinerHelper &Helper; - GISelChangeObserver &Observer; + // TODO: Make CombinerHelper methods const. + mutable AMDGPUCombinerHelper Helper; public: AMDGPUPostLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig, - MachineIRBuilder &B, AMDGPUCombinerHelper &Helper, - GISelChangeObserver &Observer); + const GCNSubtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI); static const char *getName() { return "AMDGPUPostLegalizerCombinerImpl"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAllImpl(MachineInstr &I) const; + bool tryCombineAll(MachineInstr &I) const override; struct FMinFMaxLegacyInfo { Register LHS; @@ -121,18 +119,36 @@ #undef GET_GICOMBINER_IMPL AMDGPUPostLegalizerCombinerImpl::AMDGPUPostLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig, - MachineIRBuilder &B, AMDGPUCombinerHelper &Helper, - GISelChangeObserver &Observer) - : RuleConfig(RuleConfig), B(B), MF(B.getMF()), MRI(*B.getMRI()), - STI(MF.getSubtarget()), TII(*STI.getInstrInfo()), - Helper(Helper), Observer(Observer), + const GCNSubtarget &STI, MachineDominatorTree *MDT, const LegalizerInfo *LI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), RuleConfig(RuleConfig), STI(STI), + TII(*STI.getInstrInfo()), + Helper(Observer, B, /*IsPreLegalize*/ false, &KB, MDT, LI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "AMDGPUGenPostLegalizeGICombiner.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS { } +bool AMDGPUPostLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const { + if (tryCombineAllImpl(MI)) + return true; + + switch (MI.getOpcode()) { + case TargetOpcode::G_SHL: + case TargetOpcode::G_LSHR: + case TargetOpcode::G_ASHR: + // On some subtargets, 64-bit shift is a quarter rate instruction. In the + // common case, splitting this into a move and a 32-bit shift is faster and + // the same code size. + return Helper.tryCombineShiftToUnmerge(MI, 32); + } + + return false; +} + bool AMDGPUPostLegalizerCombinerImpl::matchFMinFMaxLegacy( MachineInstr &MI, FMinFMaxLegacyInfo &Info) const { // FIXME: Type predicate on pattern @@ -403,51 +419,6 @@ MI.eraseFromParent(); } -class AMDGPUPostLegalizerCombinerInfo final : public CombinerInfo { - GISelKnownBits *KB; - MachineDominatorTree *MDT; - AMDGPUPostLegalizerCombinerImplRuleConfig RuleConfig; - -public: - AMDGPUPostLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, - const AMDGPULegalizerInfo *LI, - GISelKnownBits *KB, MachineDominatorTree *MDT) - : CombinerInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true, - /*LegalizerInfo*/ LI, EnableOpt, OptSize, MinSize), - KB(KB), MDT(MDT) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool AMDGPUPostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - AMDGPUCombinerHelper Helper(Observer, B, /*IsPreLegalize*/ false, KB, MDT, - LInfo); - // TODO: Do not re-create the Impl on every inst, it should be per function. - AMDGPUPostLegalizerCombinerImpl Impl(RuleConfig, B, Helper, Observer); - Impl.setupMF(*MI.getMF(), KB); - - if (Impl.tryCombineAll(MI)) - return true; - - switch (MI.getOpcode()) { - case TargetOpcode::G_SHL: - case TargetOpcode::G_LSHR: - case TargetOpcode::G_ASHR: - // On some subtargets, 64-bit shift is a quarter rate instruction. In the - // common case, splitting this into a move and a 32-bit shift is faster and - // the same code size. - return Helper.tryCombineShiftToUnmerge(MI, 32); - } - - return false; -} - // Pass boilerplate // ================ @@ -464,8 +435,10 @@ bool runOnMachineFunction(MachineFunction &MF) override; void getAnalysisUsage(AnalysisUsage &AU) const override; + private: bool IsOptNone; + AMDGPUPostLegalizerCombinerImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -485,6 +458,9 @@ AMDGPUPostLegalizerCombiner::AMDGPUPostLegalizerCombiner(bool IsOptNone) : MachineFunctionPass(ID), IsOptNone(IsOptNone) { initializeAMDGPUPostLegalizerCombinerPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool AMDGPUPostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { @@ -503,10 +479,13 @@ GISelKnownBits *KB = &getAnalysis().get(MF); MachineDominatorTree *MDT = IsOptNone ? nullptr : &getAnalysis(); - AMDGPUPostLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(), - F.hasMinSize(), LI, KB, MDT); - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr); + + CombinerInfo CInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true, + LI, EnableOpt, F.hasOptSize(), F.hasMinSize()); + + AMDGPUPostLegalizerCombinerImpl Impl(MF, CInfo, TPC, *KB, /*CSEInfo*/ nullptr, + RuleConfig, ST, MDT, LI); + return Impl.combineMachineInstrs(); } char AMDGPUPostLegalizerCombiner::ID = 0; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPreLegalizerCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPreLegalizerCombiner.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUPreLegalizerCombiner.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUPreLegalizerCombiner.cpp @@ -20,7 +20,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" @@ -42,26 +41,25 @@ #include "AMDGPUGenPreLegalizeGICombiner.inc" #undef GET_GICOMBINER_TYPES -class AMDGPUPreLegalizerCombinerImpl : public GIMatchTableExecutor { +class AMDGPUPreLegalizerCombinerImpl : public Combiner { protected: const AMDGPUPreLegalizerCombinerImplRuleConfig &RuleConfig; const GCNSubtarget &STI; - - GISelChangeObserver &Observer; - MachineIRBuilder &B; - MachineFunction &MF; - MachineRegisterInfo &MRI; - AMDGPUCombinerHelper &Helper; + // TODO: Make CombinerHelper methods const. + mutable AMDGPUCombinerHelper Helper; public: AMDGPUPreLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AMDGPUPreLegalizerCombinerImplRuleConfig &RuleConfig, - const GCNSubtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, AMDGPUCombinerHelper &Helper); + const GCNSubtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI); static const char *getName() { return "AMDGPUPreLegalizerCombinerImpl"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAllImpl(MachineInstr &MI) const; + bool tryCombineAll(MachineInstr &I) const override; struct ClampI64ToI16MatchInfo { int64_t Cmp1 = 0; @@ -91,17 +89,32 @@ #undef GET_GICOMBINER_IMPL AMDGPUPreLegalizerCombinerImpl::AMDGPUPreLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AMDGPUPreLegalizerCombinerImplRuleConfig &RuleConfig, - const GCNSubtarget &STI, GISelChangeObserver &Observer, MachineIRBuilder &B, - AMDGPUCombinerHelper &Helper) - : RuleConfig(RuleConfig), STI(STI), Observer(Observer), B(B), MF(B.getMF()), - MRI(*B.getMRI()), Helper(Helper), + const GCNSubtarget &STI, MachineDominatorTree *MDT, const LegalizerInfo *LI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), RuleConfig(RuleConfig), STI(STI), + Helper(Observer, B, /*IsPreLegalize*/ true, &KB, MDT, LI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "AMDGPUGenPreLegalizeGICombiner.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS { } +bool AMDGPUPreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const { + if (tryCombineAllImpl(MI)) + return true; + + switch (MI.getOpcode()) { + case TargetOpcode::G_CONCAT_VECTORS: + return Helper.tryCombineConcatVectors(MI); + case TargetOpcode::G_SHUFFLE_VECTOR: + return Helper.tryCombineShuffleVector(MI); + } + + return false; +} + bool AMDGPUPreLegalizerCombinerImpl::matchClampI64ToI16( MachineInstr &MI, const MachineRegisterInfo &MRI, const MachineFunction &MF, ClampI64ToI16MatchInfo &MatchInfo) const { @@ -199,49 +212,6 @@ MI.eraseFromParent(); } -class AMDGPUPreLegalizerCombinerInfo final : public CombinerInfo { - GISelKnownBits *KB; - MachineDominatorTree *MDT; - AMDGPUPreLegalizerCombinerImplRuleConfig RuleConfig; - -public: - AMDGPUPreLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, - GISelKnownBits *KB, MachineDominatorTree *MDT) - : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, - /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize), - KB(KB), MDT(MDT) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool AMDGPUPreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - const auto *LI = MI.getMF()->getSubtarget().getLegalizerInfo(); - AMDGPUCombinerHelper Helper(Observer, B, /*IsPreLegalize*/ true, KB, MDT, LI); - - const GCNSubtarget &STI = MI.getMF()->getSubtarget(); - // TODO: Do not re-create the Impl on every inst, it should be per function. - AMDGPUPreLegalizerCombinerImpl Impl(RuleConfig, STI, Observer, B, Helper); - Impl.setupMF(*MI.getMF(), KB); - - if (Impl.tryCombineAll(MI)) - return true; - - switch (MI.getOpcode()) { - case TargetOpcode::G_CONCAT_VECTORS: - return Helper.tryCombineConcatVectors(MI); - case TargetOpcode::G_SHUFFLE_VECTOR: - return Helper.tryCombineShuffleVector(MI); - } - - return false; -} - // Pass boilerplate // ================ @@ -261,6 +231,7 @@ private: bool IsOptNone; + AMDGPUPreLegalizerCombinerImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -283,6 +254,9 @@ AMDGPUPreLegalizerCombiner::AMDGPUPreLegalizerCombiner(bool IsOptNone) : MachineFunctionPass(ID), IsOptNone(IsOptNone) { initializeAMDGPUPreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool AMDGPUPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { @@ -294,17 +268,20 @@ bool EnableOpt = MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F); GISelKnownBits *KB = &getAnalysis().get(MF); - MachineDominatorTree *MDT = - IsOptNone ? nullptr : &getAnalysis(); - AMDGPUPreLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(), - F.hasMinSize(), KB, MDT); + // Enable CSE. GISelCSEAnalysisWrapper &Wrapper = getAnalysis().getCSEWrapper(); auto *CSEInfo = &Wrapper.get(TPC->getCSEConfig()); - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, CSEInfo); + const GCNSubtarget &STI = MF.getSubtarget(); + MachineDominatorTree *MDT = + IsOptNone ? nullptr : &getAnalysis(); + CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, + nullptr, EnableOpt, F.hasOptSize(), F.hasMinSize()); + AMDGPUPreLegalizerCombinerImpl Impl(MF, CInfo, TPC, *KB, CSEInfo, RuleConfig, + STI, MDT, STI.getLegalizerInfo()); + return Impl.combineMachineInstrs(); } char AMDGPUPreLegalizerCombiner::ID = 0; diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp @@ -20,7 +20,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" @@ -43,29 +42,27 @@ #include "AMDGPUGenRegBankGICombiner.inc" #undef GET_GICOMBINER_TYPES -class AMDGPURegBankCombinerImpl : public GIMatchTableExecutor { +class AMDGPURegBankCombinerImpl : public Combiner { protected: const AMDGPURegBankCombinerImplRuleConfig &RuleConfig; - - MachineIRBuilder &B; - MachineFunction &MF; - MachineRegisterInfo &MRI; const GCNSubtarget &STI; const RegisterBankInfo &RBI; const TargetRegisterInfo &TRI; const SIInstrInfo &TII; - CombinerHelper &Helper; - GISelChangeObserver &Observer; + // TODO: Make CombinerHelper methods const. + mutable CombinerHelper Helper; public: AMDGPURegBankCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const AMDGPURegBankCombinerImplRuleConfig &RuleConfig, - MachineIRBuilder &B, CombinerHelper &Helper, - GISelChangeObserver &Observer); + const GCNSubtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI); static const char *getName() { return "AMDGPURegBankCombinerImpl"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAll(MachineInstr &I) const override; bool isVgprRegBank(Register Reg) const; Register getAsVgpr(Register Reg) const; @@ -114,12 +111,14 @@ #undef GET_GICOMBINER_IMPL AMDGPURegBankCombinerImpl::AMDGPURegBankCombinerImpl( - const AMDGPURegBankCombinerImplRuleConfig &RuleConfig, MachineIRBuilder &B, - CombinerHelper &Helper, GISelChangeObserver &Observer) - : RuleConfig(RuleConfig), B(B), MF(B.getMF()), MRI(*B.getMRI()), - STI(MF.getSubtarget()), RBI(*STI.getRegBankInfo()), - TRI(*STI.getRegisterInfo()), TII(*STI.getInstrInfo()), Helper(Helper), - Observer(Observer), + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, + const AMDGPURegBankCombinerImplRuleConfig &RuleConfig, + const GCNSubtarget &STI, MachineDominatorTree *MDT, const LegalizerInfo *LI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), RuleConfig(RuleConfig), STI(STI), + RBI(*STI.getRegBankInfo()), TRI(*STI.getRegisterInfo()), + TII(*STI.getInstrInfo()), + Helper(Observer, B, /*IsPreLegalize*/ false, &KB, MDT, LI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "AMDGPUGenRegBankGICombiner.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS @@ -396,36 +395,6 @@ return false; } -class AMDGPURegBankCombinerInfo final : public CombinerInfo { - GISelKnownBits *KB; - MachineDominatorTree *MDT; - AMDGPURegBankCombinerImplRuleConfig RuleConfig; - -public: - AMDGPURegBankCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, - const AMDGPULegalizerInfo *LI, GISelKnownBits *KB, - MachineDominatorTree *MDT) - : CombinerInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true, - /*LegalizerInfo*/ LI, EnableOpt, OptSize, MinSize), - KB(KB), MDT(MDT) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool AMDGPURegBankCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - CombinerHelper Helper(Observer, B, /* IsPreLegalize*/ false, KB, MDT); - // TODO: Do not re-create the Impl on every inst, it should be per function. - AMDGPURegBankCombinerImpl Impl(RuleConfig, B, Helper, Observer); - Impl.setupMF(*MI.getMF(), KB); - return Impl.tryCombineAll(MI); -} - // Pass boilerplate // ================ @@ -440,8 +409,10 @@ bool runOnMachineFunction(MachineFunction &MF) override; void getAnalysisUsage(AnalysisUsage &AU) const override; + private: bool IsOptNone; + AMDGPURegBankCombinerImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -461,6 +432,9 @@ AMDGPURegBankCombiner::AMDGPURegBankCombiner(bool IsOptNone) : MachineFunctionPass(ID), IsOptNone(IsOptNone) { initializeAMDGPURegBankCombinerPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool AMDGPURegBankCombiner::runOnMachineFunction(MachineFunction &MF) { @@ -473,16 +447,17 @@ MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F); const GCNSubtarget &ST = MF.getSubtarget(); - const AMDGPULegalizerInfo *LI = - static_cast(ST.getLegalizerInfo()); - GISelKnownBits *KB = &getAnalysis().get(MF); + + const auto *LI = ST.getLegalizerInfo(); MachineDominatorTree *MDT = IsOptNone ? nullptr : &getAnalysis(); - AMDGPURegBankCombinerInfo PCInfo(EnableOpt, F.hasOptSize(), F.hasMinSize(), - LI, KB, MDT); - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr); + + CombinerInfo CInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true, + LI, EnableOpt, F.hasOptSize(), F.hasMinSize()); + AMDGPURegBankCombinerImpl Impl(MF, CInfo, TPC, *KB, /*CSEInfo*/ nullptr, + RuleConfig, ST, MDT, LI); + return Impl.combineMachineInstrs(); } char AMDGPURegBankCombiner::ID = 0; diff --git a/llvm/lib/Target/Mips/MipsPostLegalizerCombiner.cpp b/llvm/lib/Target/Mips/MipsPostLegalizerCombiner.cpp --- a/llvm/lib/Target/Mips/MipsPostLegalizerCombiner.cpp +++ b/llvm/lib/Target/Mips/MipsPostLegalizerCombiner.cpp @@ -18,7 +18,6 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" @@ -40,27 +39,24 @@ #include "MipsGenPostLegalizeGICombiner.inc" #undef GET_GICOMBINER_TYPES -class MipsPostLegalizerCombinerImpl : public GIMatchTableExecutor { +class MipsPostLegalizerCombinerImpl : public Combiner { protected: - CombinerHelper &Helper; const MipsPostLegalizerCombinerImplRuleConfig &RuleConfig; - const MipsSubtarget &STI; - GISelChangeObserver &Observer; - MachineIRBuilder &B; - MachineFunction &MF; - - MachineRegisterInfo &MRI; + // TODO: Make CombinerHelper methods const. + mutable CombinerHelper Helper; public: MipsPostLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const MipsPostLegalizerCombinerImplRuleConfig &RuleConfig, - const MipsSubtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper); + const MipsSubtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI); static const char *getName() { return "MipsPostLegalizerCombiner"; } - bool tryCombineAll(MachineInstr &I) const; + bool tryCombineAll(MachineInstr &I) const override; private: #define GET_GICOMBINER_CLASS_MEMBERS @@ -73,47 +69,19 @@ #undef GET_GICOMBINER_IMPL MipsPostLegalizerCombinerImpl::MipsPostLegalizerCombinerImpl( + MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, + GISelKnownBits &KB, GISelCSEInfo *CSEInfo, const MipsPostLegalizerCombinerImplRuleConfig &RuleConfig, - const MipsSubtarget &STI, GISelChangeObserver &Observer, - MachineIRBuilder &B, CombinerHelper &Helper) - : Helper(Helper), RuleConfig(RuleConfig), STI(STI), Observer(Observer), - B(B), MF(B.getMF()), MRI(*B.getMRI()), + const MipsSubtarget &STI, MachineDominatorTree *MDT, + const LegalizerInfo *LI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), RuleConfig(RuleConfig), STI(STI), + Helper(Observer, B, /*IsPreLegalize*/ false, &KB, MDT, LI), #define GET_GICOMBINER_CONSTRUCTOR_INITS #include "MipsGenPostLegalizeGICombiner.inc" #undef GET_GICOMBINER_CONSTRUCTOR_INITS { } -class MipsPostLegalizerCombinerInfo final : public CombinerInfo { - GISelKnownBits *KB; - -public: - MipsPostLegalizerCombinerImplRuleConfig RuleConfig; - - MipsPostLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, - GISelKnownBits *KB, const MipsLegalizerInfo *LI) - : CombinerInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true, - /*LegalizerInfo*/ LI, EnableOpt, OptSize, MinSize), - KB(KB) { - if (!RuleConfig.parseCommandLineOption()) - report_fatal_error("Invalid rule identifier"); - } - - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool MipsPostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - const auto &STI = MI.getMF()->getSubtarget(); - CombinerHelper Helper(Observer, B, /* IsPreLegalize*/ false, KB, - /*DominatorTree*/ nullptr, LInfo); - MipsPostLegalizerCombinerImpl Impl(RuleConfig, STI, Observer, B, Helper); - Impl.setupMF(*MI.getMF(), KB); - return Impl.tryCombineAll(MI); -} - // Pass boilerplate // ================ @@ -123,9 +91,7 @@ MipsPostLegalizerCombiner(bool IsOptNone = false); - StringRef getPassName() const override { - return "MipsPostLegalizerCombiner"; - } + StringRef getPassName() const override { return "MipsPostLegalizerCombiner"; } bool runOnMachineFunction(MachineFunction &MF) override; @@ -133,6 +99,7 @@ private: bool IsOptNone; + MipsPostLegalizerCombinerImplRuleConfig RuleConfig; }; } // end anonymous namespace @@ -152,6 +119,9 @@ MipsPostLegalizerCombiner::MipsPostLegalizerCombiner(bool IsOptNone) : MachineFunctionPass(ID), IsOptNone(IsOptNone) { initializeMipsPostLegalizerCombinerPass(*PassRegistry::getPassRegistry()); + + if (!RuleConfig.parseCommandLineOption()) + report_fatal_error("Invalid rule identifier"); } bool MipsPostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { @@ -168,10 +138,13 @@ static_cast(ST.getLegalizerInfo()); GISelKnownBits *KB = &getAnalysis().get(MF); - MipsPostLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(), - F.hasMinSize(), KB, LI); - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr); + MachineDominatorTree *MDT = + IsOptNone ? nullptr : &getAnalysis(); + CombinerInfo CInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true, + LI, EnableOpt, F.hasOptSize(), F.hasMinSize()); + MipsPostLegalizerCombinerImpl Impl(MF, CInfo, TPC, *KB, /*CSEInfo*/ nullptr, + RuleConfig, ST, MDT, LI); + return Impl.combineMachineInstrs(); } char MipsPostLegalizerCombiner::ID = 0; diff --git a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp --- a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp +++ b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp @@ -11,10 +11,12 @@ // //===----------------------------------------------------------------------===// +#include "MipsLegalizerInfo.h" #include "MipsTargetMachine.h" #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" +#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -25,45 +27,62 @@ using namespace llvm; namespace { -class MipsPreLegalizerCombinerInfo : public CombinerInfo { +struct MipsPreLegalizerCombinerInfo : public CombinerInfo { public: MipsPreLegalizerCombinerInfo() : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false, /*EnableOptSize*/ false, /*EnableMinSize*/ false) {} - bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; }; -bool MipsPreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - CombinerHelper Helper(Observer, B, /*IsPreLegalize*/ true); +class MipsPreLegalizerCombinerImpl : public Combiner { +protected: + const MipsSubtarget &STI; + // TODO: Make CombinerHelper methods const. + mutable CombinerHelper Helper; - switch (MI.getOpcode()) { - default: - return false; - case TargetOpcode::G_MEMCPY_INLINE: - return Helper.tryEmitMemcpyInline(MI); - case TargetOpcode::G_LOAD: - case TargetOpcode::G_SEXTLOAD: - case TargetOpcode::G_ZEXTLOAD: { - // Don't attempt to combine non power of 2 loads or unaligned loads when - // subtarget doesn't support them. - auto MMO = *MI.memoperands_begin(); - const MipsSubtarget &STI = MI.getMF()->getSubtarget(); - if (!isPowerOf2_64(MMO->getSize())) - return false; - bool isUnaligned = MMO->getAlign() < MMO->getSize(); - if (!STI.systemSupportsUnalignedAccess() && isUnaligned) +public: + MipsPreLegalizerCombinerImpl(MachineFunction &MF, CombinerInfo &CInfo, + const TargetPassConfig *TPC, GISelKnownBits &KB, + GISelCSEInfo *CSEInfo, const MipsSubtarget &STI, + MachineDominatorTree *MDT, + const LegalizerInfo *LI) + : Combiner(MF, CInfo, TPC, &KB, CSEInfo), STI(STI), + Helper(Observer, B, /*IsPreLegalize*/ true, &KB, MDT, LI) {} + + static const char *getName() { return "MipsPreLegalizerCombiner"; } + + void setupGeneratedPerFunctionState(MachineFunction &MF) override { + // TODO: TableGen-erate this class' impl. + } + + bool tryCombineAll(MachineInstr &MI) const override { + + switch (MI.getOpcode()) { + default: return false; + case TargetOpcode::G_MEMCPY_INLINE: + return Helper.tryEmitMemcpyInline(MI); + case TargetOpcode::G_LOAD: + case TargetOpcode::G_SEXTLOAD: + case TargetOpcode::G_ZEXTLOAD: { + // Don't attempt to combine non power of 2 loads or unaligned loads when + // subtarget doesn't support them. + auto MMO = *MI.memoperands_begin(); + const MipsSubtarget &STI = MI.getMF()->getSubtarget(); + if (!isPowerOf2_64(MMO->getSize())) + return false; + bool isUnaligned = MMO->getAlign() < MMO->getSize(); + if (!STI.systemSupportsUnalignedAccess() && isUnaligned) + return false; + + return Helper.tryCombineExtendingLoads(MI); + } + } - return Helper.tryCombineExtendingLoads(MI); - } + return false; } - - return false; -} +}; // Pass boilerplate // ================ @@ -84,6 +103,8 @@ void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); AU.setPreservesCFG(); getSelectionDAGFallbackAnalysisUsage(AU); MachineFunctionPass::getAnalysisUsage(AU); @@ -97,10 +118,17 @@ if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) return false; + auto *TPC = &getAnalysis(); + const MipsSubtarget &ST = MF.getSubtarget(); + const MipsLegalizerInfo *LI = + static_cast(ST.getLegalizerInfo()); + + GISelKnownBits *KB = &getAnalysis().get(MF); MipsPreLegalizerCombinerInfo PCInfo; - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, nullptr); + MipsPreLegalizerCombinerImpl Impl(MF, PCInfo, TPC, *KB, /*CSEInfo*/ nullptr, + ST, /*MDT*/ nullptr, LI); + return Impl.combineMachineInstrs(); } char MipsPreLegalizerCombiner::ID = 0; @@ -108,6 +136,7 @@ "Combine Mips machine instrs before legalization", false, false) INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) +INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis) INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE, "Combine Mips machine instrs before legalization", false, false) diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -3097,6 +3097,10 @@ return Combiner->getValueAsString("Classname"); } + StringRef getCombineAllMethodName() const { + return Combiner->getValueAsString("CombineAllMethodName"); + } + std::string getRuleConfigClassName() const { return getClassName().str() + "RuleConfig"; } @@ -3222,8 +3226,8 @@ } void GICombinerEmitter::emitAdditionalImpl(raw_ostream &OS) { - OS << "bool " << getClassName() - << "::tryCombineAll(MachineInstr &I) const {\n" + OS << "bool " << getClassName() << "::" << getCombineAllMethodName() + << "(MachineInstr &I) const {\n" << " const TargetSubtargetInfo &ST = MF.getSubtarget();\n" << " const PredicateBitset AvailableFeatures = " "getAvailableFeatures();\n"