1212#include " llvm/CodeGen/GlobalISel/InstructionSelect.h"
1313#include " llvm/ADT/PostOrderIterator.h"
1414#include " llvm/ADT/ScopeExit.h"
15+ #include " llvm/ADT/SetVector.h"
1516#include " llvm/Analysis/LazyBlockFrequencyInfo.h"
1617#include " llvm/Analysis/ProfileSummaryInfo.h"
18+ #include " llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
1719#include " llvm/CodeGen/GlobalISel/GISelKnownBits.h"
1820#include " llvm/CodeGen/GlobalISel/InstructionSelector.h"
1921#include " llvm/CodeGen/GlobalISel/LegalizerInfo.h"
@@ -65,6 +67,52 @@ INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
6567InstructionSelect::InstructionSelect(CodeGenOptLevel OL, char &PassID)
6668 : MachineFunctionPass(PassID), OptLevel(OL) {}
6769
70+ // / This class observes instruction insertions/removals.
71+ // / InstructionSelect stores an iterator of the instruction prior to the one
72+ // / that is currently being selected to determine which instruction to select
73+ // / next. Previously this meant that selecting multiple instructions at once was
74+ // / illegal behavior due to potential invalidation of this iterator. This is
75+ // / a non-obvious limitation for selector implementers. Therefore, to allow
76+ // / deletion of arbitrary instructions, we detect this case and continue
77+ // / selection with the predecessor of the deleted instruction.
78+ class InstructionSelect ::MIIteratorMaintainer
79+ : public MachineFunction::Delegate {
80+ #ifndef NDEBUG
81+ SmallSetVector<const MachineInstr *, 32 > CreatedInstrs;
82+ #endif
83+ public:
84+ MachineBasicBlock::reverse_iterator MII;
85+
86+ void MF_HandleInsertion (MachineInstr &MI) override {
87+ LLVM_DEBUG (dbgs () << " Creating: " << MI; CreatedInstrs.insert (&MI));
88+ }
89+
90+ void MF_HandleRemoval (MachineInstr &MI) override {
91+ LLVM_DEBUG (dbgs () << " Erasing: " << MI; CreatedInstrs.remove (&MI));
92+ if (MII.getInstrIterator ().getNodePtr () == &MI) {
93+ // If the iterator points to the MI that will be erased (i.e. the MI prior
94+ // to the MI that is currently being selected), the iterator would be
95+ // invalidated. Continue selection with its predecessor.
96+ ++MII;
97+ LLVM_DEBUG (dbgs () << " Instruction removal updated iterator.\n " );
98+ }
99+ }
100+
101+ void reportFullyCreatedInstrs () {
102+ LLVM_DEBUG ({
103+ if (CreatedInstrs.empty ()) {
104+ dbgs () << " Created no instructions.\n " ;
105+ } else {
106+ dbgs () << " Created:\n " ;
107+ for (const auto *MI : CreatedInstrs) {
108+ dbgs () << " " << *MI;
109+ }
110+ CreatedInstrs.clear ();
111+ }
112+ });
113+ }
114+ };
115+
68116void InstructionSelect::getAnalysisUsage (AnalysisUsage &AU) const {
69117 AU.addRequired <TargetPassConfig>();
70118 AU.addRequired <GISelKnownBitsAnalysis>();
@@ -84,31 +132,36 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
84132 MachineFunctionProperties::Property::FailedISel))
85133 return false ;
86134
87- LLVM_DEBUG (dbgs () << " Selecting function: " << MF.getName () << ' \n ' );
88-
89- const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
90- InstructionSelector *ISel = MF.getSubtarget ().getInstructionSelector ();
91- ISel->setTargetPassConfig (&TPC);
135+ ISel = MF.getSubtarget ().getInstructionSelector ();
136+ ISel->TPC = &getAnalysis<TargetPassConfig>();
92137
138+ // FIXME: Properly override OptLevel in TargetMachine. See OptLevelChanger
93139 CodeGenOptLevel OldOptLevel = OptLevel;
94140 auto RestoreOptLevel = make_scope_exit ([=]() { OptLevel = OldOptLevel; });
95141 OptLevel = MF.getFunction ().hasOptNone () ? CodeGenOptLevel::None
96142 : MF.getTarget ().getOptLevel ();
97143
98- GISelKnownBits * KB = &getAnalysis<GISelKnownBitsAnalysis>().get (MF);
144+ KB = &getAnalysis<GISelKnownBitsAnalysis>().get (MF);
99145 if (OptLevel != CodeGenOptLevel::None) {
100146 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI ();
101147 if (PSI && PSI->hasProfileSummary ())
102148 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI ();
103149 }
104150
105- CodeGenCoverage CoverageInfo;
151+ return selectMachineFunction (MF);
152+ }
153+
154+ bool InstructionSelect::selectMachineFunction (MachineFunction &MF) {
155+ LLVM_DEBUG (dbgs () << " Selecting function: " << MF.getName () << ' \n ' );
106156 assert (ISel && " Cannot work without InstructionSelector" );
157+
158+ const TargetPassConfig &TPC = *ISel->TPC ;
159+ CodeGenCoverage CoverageInfo;
107160 ISel->setupMF (MF, KB, &CoverageInfo, PSI, BFI);
108161
109162 // An optimization remark emitter. Used to report failures.
110163 MachineOptimizationRemarkEmitter MORE (MF, /* MBFI=*/ nullptr );
111- ISel->setRemarkEmitter ( &MORE) ;
164+ ISel->MORE = &MORE;
112165
113166 // FIXME: There are many other MF/MFI fields we need to initialize.
114167
@@ -131,80 +184,36 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
131184 // Keep track of selected blocks, so we can delete unreachable ones later.
132185 DenseSet<MachineBasicBlock *> SelectedBlocks;
133186
134- for (MachineBasicBlock *MBB : post_order (&MF)) {
135- ISel->CurMBB = MBB;
136- SelectedBlocks.insert (MBB);
137- if (MBB->empty ())
138- continue ;
139-
140- // Select instructions in reverse block order. We permit erasing so have
141- // to resort to manually iterating and recognizing the begin (rend) case.
142- bool ReachedBegin = false ;
143- for (auto MII = std::prev (MBB->end ()), Begin = MBB->begin ();
144- !ReachedBegin;) {
145- #ifndef NDEBUG
146- // Keep track of the insertion range for debug printing.
147- const auto AfterIt = std::next (MII);
148- #endif
149- // Select this instruction.
150- MachineInstr &MI = *MII;
151-
152- // And have our iterator point to the next instruction, if there is one.
153- if (MII == Begin)
154- ReachedBegin = true ;
155- else
156- --MII;
157-
158- LLVM_DEBUG (dbgs () << " Selecting: \n " << MI);
159-
160- // We could have folded this instruction away already, making it dead.
161- // If so, erase it.
162- if (isTriviallyDead (MI, MRI)) {
163- LLVM_DEBUG (dbgs () << " Is dead; erasing.\n " );
164- salvageDebugInfo (MRI, MI);
165- MI.eraseFromParent ();
166- continue ;
167- }
168-
169- // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
170- if (isPreISelGenericOptimizationHint (MI.getOpcode ()) ||
171- MI.getOpcode () == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
172- auto [DstReg, SrcReg] = MI.getFirst2Regs ();
173-
174- // At this point, the destination register class of the op may have
175- // been decided.
176- //
177- // Propagate that through to the source register.
178- const TargetRegisterClass *DstRC = MRI.getRegClassOrNull (DstReg);
179- if (DstRC)
180- MRI.setRegClass (SrcReg, DstRC);
181- assert (canReplaceReg (DstReg, SrcReg, MRI) &&
182- " Must be able to replace dst with src!" );
183- MI.eraseFromParent ();
184- MRI.replaceRegWith (DstReg, SrcReg);
185- continue ;
186- }
187-
188- if (MI.getOpcode () == TargetOpcode::G_INVOKE_REGION_START) {
189- MI.eraseFromParent ();
190- continue ;
191- }
192-
193- if (!ISel->select (MI)) {
194- // FIXME: It would be nice to dump all inserted instructions. It's
195- // not obvious how, esp. considering select() can insert after MI.
196- reportGISelFailure (MF, TPC, MORE, " gisel-select" , " cannot select" , MI);
197- return false ;
187+ {
188+ // Observe IR insertions and removals during selection.
189+ // We only install a MachineFunction::Delegate instead of a
190+ // GISelChangeObserver, because we do not want notifications about changed
191+ // instructions. This prevents significant compile-time regressions from
192+ // e.g. constrainOperandRegClass().
193+ MIIteratorMaintainer MIIMaintainer;
194+ RAIIDelegateInstaller DelInstaller (MF, &MIIMaintainer);
195+
196+ for (MachineBasicBlock *MBB : post_order (&MF)) {
197+ ISel->CurMBB = MBB;
198+ SelectedBlocks.insert (MBB);
199+
200+ // Select instructions in reverse block order.
201+ MIIMaintainer.MII = MBB->rbegin ();
202+ for (auto End = MBB->rend (); MIIMaintainer.MII != End;) {
203+ MachineInstr &MI = *MIIMaintainer.MII ;
204+ // Increment early to skip instructions inserted by select().
205+ ++MIIMaintainer.MII ;
206+
207+ LLVM_DEBUG (dbgs () << " \n Select: " << MI);
208+ if (!selectInstr (MI)) {
209+ LLVM_DEBUG (dbgs () << " Selection failed!\n " ;
210+ MIIMaintainer.reportFullyCreatedInstrs ());
211+ reportGISelFailure (MF, TPC, MORE, " gisel-select" , " cannot select" ,
212+ MI);
213+ return false ;
214+ }
215+ LLVM_DEBUG (MIIMaintainer.reportFullyCreatedInstrs ());
198216 }
199-
200- // Dump the range of instructions that MI expanded into.
201- LLVM_DEBUG ({
202- auto InsertedBegin = ReachedBegin ? MBB->begin () : std::next (MII);
203- dbgs () << " Into:\n " ;
204- for (auto &InsertedMI : make_range (InsertedBegin, AfterIt))
205- dbgs () << " " << InsertedMI;
206- dbgs () << ' \n ' ;
207- });
208217 }
209218 }
210219
@@ -222,16 +231,10 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
222231 continue ;
223232 }
224233 // Try to find redundant copies b/w vregs of the same register class.
225- bool ReachedBegin = false ;
226- for (auto MII = std::prev (MBB.end ()), Begin = MBB.begin (); !ReachedBegin;) {
227- // Select this instruction.
234+ for (auto MII = MBB.rbegin (), End = MBB.rend (); MII != End;) {
228235 MachineInstr &MI = *MII;
236+ ++MII;
229237
230- // And have our iterator point to the next instruction, if there is one.
231- if (MII == Begin)
232- ReachedBegin = true ;
233- else
234- --MII;
235238 if (MI.getOpcode () != TargetOpcode::COPY)
236239 continue ;
237240 Register SrcReg = MI.getOperand (1 ).getReg ();
@@ -336,3 +339,42 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
336339 // FIXME: Should we accurately track changes?
337340 return true ;
338341}
342+
343+ bool InstructionSelect::selectInstr (MachineInstr &MI) {
344+ MachineRegisterInfo &MRI = ISel->MF ->getRegInfo ();
345+
346+ // We could have folded this instruction away already, making it dead.
347+ // If so, erase it.
348+ if (isTriviallyDead (MI, MRI)) {
349+ LLVM_DEBUG (dbgs () << " Is dead.\n " );
350+ salvageDebugInfo (MRI, MI);
351+ MI.eraseFromParent ();
352+ return true ;
353+ }
354+
355+ // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
356+ if (isPreISelGenericOptimizationHint (MI.getOpcode ()) ||
357+ MI.getOpcode () == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
358+ auto [DstReg, SrcReg] = MI.getFirst2Regs ();
359+
360+ // At this point, the destination register class of the op may have
361+ // been decided.
362+ //
363+ // Propagate that through to the source register.
364+ const TargetRegisterClass *DstRC = MRI.getRegClassOrNull (DstReg);
365+ if (DstRC)
366+ MRI.setRegClass (SrcReg, DstRC);
367+ assert (canReplaceReg (DstReg, SrcReg, MRI) &&
368+ " Must be able to replace dst with src!" );
369+ MI.eraseFromParent ();
370+ MRI.replaceRegWith (DstReg, SrcReg);
371+ return true ;
372+ }
373+
374+ if (MI.getOpcode () == TargetOpcode::G_INVOKE_REGION_START) {
375+ MI.eraseFromParent ();
376+ return true ;
377+ }
378+
379+ return ISel->select (MI);
380+ }
0 commit comments