27#define DEBUG_TYPE "gi-combiner"
31STATISTIC(NumOneIteration,
"Number of functions with one iteration");
32STATISTIC(NumTwoIterations,
"Number of functions with two iterations");
34 "Number of functions with three or more iterations");
38 "GlobalISel Combiner",
39 "Control the rules which are enabled. These options all take a comma "
40 "separated list of rules to disable and may be specified by number "
41 "or number range (e.g. 1-10)."
43 " They may also be specified by name."
62 static std::unique_ptr<WorkListMaintainer>
70 dbgs() <<
"Created: " << *
MI;
83template <CombinerInfo::ObserverLevel Lvl>
96 : WorkList(WorkList), MRI(MRI) {}
108 WorkList.remove(&
MI);
109 if constexpr (Lvl != Level::Basic) {
110 DeferList.remove(&
MI);
117 if constexpr (Lvl == Level::Basic)
118 WorkList.insert(&
MI);
123 DeferList.insert(&
MI);
132 if constexpr (Lvl != Level::Basic)
138 if constexpr (Lvl == Level::Basic)
139 WorkList.insert(&
MI);
142 DeferList.insert(&
MI);
150 if constexpr (Lvl == Level::Basic)
154 while (!DeferList.empty()) {
159 if constexpr (Lvl >= Level::SinglePass)
162 WorkList.insert(&
MI);
166 while (!LostUses.empty()) {
174 if (tryDCE(*
UseMI, MRI))
177 if constexpr (Lvl >= Level::SinglePass) {
180 if (MRI.hasOneNonDBGUser(
Use))
181 WorkList.insert(&*MRI.use_instr_nodbg_begin(
Use));
183 WorkList.insert(
UseMI);
189 for (
auto &
Use :
MI.explicit_uses()) {
190 if (!
Use.isReg() || !
Use.getReg().isVirtual())
192 LostUses.insert(
Use.getReg());
197 for (
auto &Def :
MI.defs()) {
201 for (
auto &
UseMI : MRI.use_nodbg_instructions(DefReg)) {
202 WorkList.insert(&
UseMI);
208std::unique_ptr<Combiner::WorkListMaintainer>
213 return std::make_unique<WorkListMaintainerImpl<Level::Basic>>(WorkList,
216 return std::make_unique<WorkListMaintainerImpl<Level::DCE>>(WorkList,
MRI);
217 case Level::SinglePass:
218 return std::make_unique<WorkListMaintainerImpl<Level::SinglePass>>(WorkList,
238 B.setChangeObserver(*ObserverWrapper);
248 MI.eraseFromParent();
255 if (
MF.getProperties().hasFailedISel())
269 bool MFChanged =
false;
272 unsigned Iteration = 0;
275 LLVM_DEBUG(
dbgs() <<
"\n\nCombiner iteration #" << Iteration <<
'\n');
280 ObserverWrapper->clearObservers();
282 ObserverWrapper->addObserver(
CSEInfo);
287 ?
CInfo.EnableFullDCE && Iteration == 1
288 :
CInfo.EnableFullDCE;
298 if (EnableDCE && tryDCE(CurMI,
MRI))
300 WorkList.deferred_insert(&CurMI);
306 ObserverWrapper->addObserver(WLObserver.get());
308 while (!WorkList.empty()) {
312 LLVM_DEBUG(WLObserver->reportFullyCreatedInstrs());
315 WLObserver->appliedCombine();
320 LLVM_DEBUG(
dbgs() <<
"\nCombiner reached fixed-point after iteration #"
321 << Iteration <<
'\n');
326 if (
CInfo.MaxIterations && Iteration >=
CInfo.MaxIterations) {
328 dbgs() <<
"\nCombiner reached iteration limit after iteration #"
329 << Iteration <<
'\n');
336 else if (Iteration == 2)
339 ++NumThreeOrMoreIterations;
343 if (
auto E =
CSEInfo->verify()) {
345 assert(
false &&
"CSEInfo is not consistent. Likely missing calls to "
346 "observer on mutations.");
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides analysis for continuously CSEing during GISel passes.
This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.
Option class for Targets to specify which operations are combined how and when.
This contains the base class for all Combiners generated by TableGen.
This contains common code to allow clients to notify changes to machine instr.
This file declares the MachineIRBuilder class.
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file implements a set that has insertion order iteration characteristics.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
~WorkListMaintainerImpl() override=default
void appliedCombine() override
void erasingInstr(MachineInstr &MI) override
An instruction is about to be erased.
void noteLostUses(MachineInstr &MI)
void changedInstr(MachineInstr &MI) override
This instruction was mutated in some way.
void changingInstr(MachineInstr &MI) override
This instruction is about to be mutated in some way.
WorkListMaintainerImpl(WorkListTy &WorkList, MachineRegisterInfo &MRI)
void createdInstr(MachineInstr &MI) override
An instruction has been created and inserted into the function.
void addUsersToWorkList(MachineInstr &MI)
This class acts as the glue that joins the CombinerHelper to the overall Combine algorithm.
void reportFullyCreatedInstrs()
virtual void appliedCombine()=0
~WorkListMaintainer() override=default
SmallSetVector< const MachineInstr *, 32 > CreatedInstrs
The instructions that have been created but we want to report once they have their operands.
static std::unique_ptr< WorkListMaintainer > create(Level Lvl, WorkListTy &WorkList, MachineRegisterInfo &MRI)
CombinerInfo::ObserverLevel Level
Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
bool combineMachineInstrs()
MachineRegisterInfo & MRI
Combiner(MachineFunction &MF, const CombinerInfo &CInfo, GISelValueTracking *VT, GISelCSEInfo *CSEInfo=nullptr)
If CSEInfo is not null, then the Combiner will use CSEInfo as the observer and also create a CSEMIRBu...
const CombinerInfo & CInfo
GISelChangeObserver & Observer
virtual bool tryCombineAll(MachineInstr &I) const =0
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
Abstract class that contains various methods for clients to notify about changes.
Simple wrapper observer that takes several observers, and calls each one for each event.
Helper class to build MachineInstr.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Class to install both of the above.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
A SetVector that performs no allocations if smaller than a certain size.
A Use represents the edge between a Value definition and its users.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
iterator_range< po_iterator< T > > post_order(const T &G)
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
cl::OptionCategory GICombinerOptionCategory("GlobalISel Combiner", "Control the rules which are enabled. These options all take a comma " "separated list of rules to disable and may be specified by number " "or number range (e.g. 1-10)." " They may also be specified by name.")
LLVM_ABI bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Check whether an instruction MI is dead: it only defines dead virtual registers, and doesn't have oth...
Implement std::hash so that hash_code can be used in STL containers.
@ DCE
Enables Observer-based detection of dead instructions.