12
12
#include " llvm/CodeGen/GlobalISel/InstructionSelect.h"
13
13
#include " llvm/ADT/PostOrderIterator.h"
14
14
#include " llvm/ADT/ScopeExit.h"
15
+ #include " llvm/ADT/SetVector.h"
15
16
#include " llvm/Analysis/LazyBlockFrequencyInfo.h"
16
17
#include " llvm/Analysis/ProfileSummaryInfo.h"
18
+ #include " llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
17
19
#include " llvm/CodeGen/GlobalISel/GISelKnownBits.h"
18
20
#include " llvm/CodeGen/GlobalISel/InstructionSelector.h"
19
21
#include " llvm/CodeGen/GlobalISel/LegalizerInfo.h"
@@ -62,6 +64,52 @@ INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
62
64
" Select target instructions out of generic instructions" ,
63
65
false , false )
64
66
67
+ // / This class observes instruction insertions/removals.
68
+ // / InstructionSelect stores an iterator of the instruction prior to the one
69
+ // / that is currently being selected to determine which instruction to select
70
+ // / next. Previously this meant that selecting multiple instructions at once was
71
+ // / illegal behavior due to potential invalidation of this iterator. This is
72
+ // / a non-obvious limitation for selector implementers. Therefore, to allow
73
+ // / deletion of arbitrary instructions, we detect this case and continue
74
+ // / selection with the predecessor of the deleted instruction.
75
+ class InstructionSelect::MIIteratorMaintainer
76
+ : public MachineFunction::Delegate {
77
+ #ifndef NDEBUG
78
+ SetVector<const MachineInstr *> CreatedInstrs;
79
+ #endif
80
+ public:
81
+ MachineBasicBlock::reverse_iterator MII;
82
+
83
+ void MF_HandleInsertion (MachineInstr &MI) override {
84
+ LLVM_DEBUG (dbgs () << " Creating: " << MI; CreatedInstrs.insert (&MI));
85
+ }
86
+
87
+ void MF_HandleRemoval (MachineInstr &MI) override {
88
+ LLVM_DEBUG (dbgs () << " Erasing: " << MI; CreatedInstrs.remove (&MI));
89
+ if (MII.getInstrIterator ().getNodePtr () == &MI) {
90
+ // If the iterator points to the MI that will be erased (i.e. the MI prior
91
+ // to the MI that is currently being selected), the iterator would be
92
+ // invalidated. Continue selection with its predecessor.
93
+ ++MII;
94
+ LLVM_DEBUG (dbgs () << " Instruction removal updated iterator.\n " );
95
+ }
96
+ }
97
+
98
+ void reportFullyCreatedInstrs () {
99
+ LLVM_DEBUG ({
100
+ if (CreatedInstrs.empty ()) {
101
+ dbgs () << " Created no instructions.\n " ;
102
+ } else {
103
+ dbgs () << " Created:\n " ;
104
+ for (const auto *MI : CreatedInstrs) {
105
+ dbgs () << " " << *MI;
106
+ }
107
+ CreatedInstrs.clear ();
108
+ }
109
+ });
110
+ }
111
+ };
112
+
65
113
InstructionSelect::InstructionSelect (CodeGenOptLevel OL)
66
114
: MachineFunctionPass(ID), OptLevel(OL) {}
67
115
@@ -93,7 +141,7 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
93
141
LLVM_DEBUG (dbgs () << " Selecting function: " << MF.getName () << ' \n ' );
94
142
95
143
const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
96
- InstructionSelector * ISel = MF.getSubtarget ().getInstructionSelector ();
144
+ ISel = MF.getSubtarget ().getInstructionSelector ();
97
145
ISel->setTargetPassConfig (&TPC);
98
146
99
147
CodeGenOptLevel OldOptLevel = OptLevel;
@@ -137,80 +185,36 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
137
185
// Keep track of selected blocks, so we can delete unreachable ones later.
138
186
DenseSet<MachineBasicBlock *> SelectedBlocks;
139
187
140
- for (MachineBasicBlock *MBB : post_order (&MF)) {
141
- ISel->CurMBB = MBB;
142
- SelectedBlocks.insert (MBB);
143
- if (MBB->empty ())
144
- continue ;
145
-
146
- // Select instructions in reverse block order. We permit erasing so have
147
- // to resort to manually iterating and recognizing the begin (rend) case.
148
- bool ReachedBegin = false ;
149
- for (auto MII = std::prev (MBB->end ()), Begin = MBB->begin ();
150
- !ReachedBegin;) {
151
- #ifndef NDEBUG
152
- // Keep track of the insertion range for debug printing.
153
- const auto AfterIt = std::next (MII);
154
- #endif
155
- // Select this instruction.
156
- MachineInstr &MI = *MII;
157
-
158
- // And have our iterator point to the next instruction, if there is one.
159
- if (MII == Begin)
160
- ReachedBegin = true ;
161
- else
162
- --MII;
163
-
164
- LLVM_DEBUG (dbgs () << " Selecting: \n " << MI);
165
-
166
- // We could have folded this instruction away already, making it dead.
167
- // If so, erase it.
168
- if (isTriviallyDead (MI, MRI)) {
169
- LLVM_DEBUG (dbgs () << " Is dead; erasing.\n " );
170
- salvageDebugInfo (MRI, MI);
171
- MI.eraseFromParent ();
172
- continue ;
173
- }
174
-
175
- // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
176
- if (isPreISelGenericOptimizationHint (MI.getOpcode ()) ||
177
- MI.getOpcode () == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
178
- auto [DstReg, SrcReg] = MI.getFirst2Regs ();
179
-
180
- // At this point, the destination register class of the op may have
181
- // been decided.
182
- //
183
- // Propagate that through to the source register.
184
- const TargetRegisterClass *DstRC = MRI.getRegClassOrNull (DstReg);
185
- if (DstRC)
186
- MRI.setRegClass (SrcReg, DstRC);
187
- assert (canReplaceReg (DstReg, SrcReg, MRI) &&
188
- " Must be able to replace dst with src!" );
189
- MI.eraseFromParent ();
190
- MRI.replaceRegWith (DstReg, SrcReg);
191
- continue ;
192
- }
193
-
194
- if (MI.getOpcode () == TargetOpcode::G_INVOKE_REGION_START) {
195
- MI.eraseFromParent ();
196
- continue ;
197
- }
198
-
199
- if (!ISel->select (MI)) {
200
- // FIXME: It would be nice to dump all inserted instructions. It's
201
- // not obvious how, esp. considering select() can insert after MI.
202
- reportGISelFailure (MF, TPC, MORE, " gisel-select" , " cannot select" , MI);
203
- return false ;
188
+ {
189
+ // Observe IR insertions and removals during selection.
190
+ // We only install a MachineFunction::Delegate instead of a
191
+ // GISelChangeObserver, because we do not want notifications about changed
192
+ // instructions. This prevents significant compile-time regressions from
193
+ // e.g. constrainOperandRegClass().
194
+ MIIteratorMaintainer MIIMaintainer;
195
+ RAIIDelegateInstaller DelInstaller (MF, &MIIMaintainer);
196
+
197
+ for (MachineBasicBlock *MBB : post_order (&MF)) {
198
+ ISel->CurMBB = MBB;
199
+ SelectedBlocks.insert (MBB);
200
+
201
+ // Select instructions in reverse block order.
202
+ MIIMaintainer.MII = MBB->rbegin ();
203
+ for (auto End = MBB->rend (); MIIMaintainer.MII != End;) {
204
+ MachineInstr &MI = *MIIMaintainer.MII ;
205
+ // Increment early to skip instructions inserted by select().
206
+ ++MIIMaintainer.MII ;
207
+
208
+ LLVM_DEBUG (dbgs () << " \n Select: " << MI);
209
+ if (!select (MI)) {
210
+ LLVM_DEBUG (dbgs () << " Selection failed!\n " ;
211
+ MIIMaintainer.reportFullyCreatedInstrs ());
212
+ reportGISelFailure (MF, TPC, MORE, " gisel-select" , " cannot select" ,
213
+ MI);
214
+ return false ;
215
+ }
216
+ LLVM_DEBUG (MIIMaintainer.reportFullyCreatedInstrs ());
204
217
}
205
-
206
- // Dump the range of instructions that MI expanded into.
207
- LLVM_DEBUG ({
208
- auto InsertedBegin = ReachedBegin ? MBB->begin () : std::next (MII);
209
- dbgs () << " Into:\n " ;
210
- for (auto &InsertedMI : make_range (InsertedBegin, AfterIt))
211
- dbgs () << " " << InsertedMI;
212
- dbgs () << ' \n ' ;
213
- });
214
218
}
215
219
}
216
220
@@ -228,16 +232,10 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
228
232
continue ;
229
233
}
230
234
// Try to find redundant copies b/w vregs of the same register class.
231
- bool ReachedBegin = false ;
232
- for (auto MII = std::prev (MBB.end ()), Begin = MBB.begin (); !ReachedBegin;) {
233
- // Select this instruction.
235
+ for (auto MII = MBB.rbegin (), End = MBB.rend (); MII != End;) {
234
236
MachineInstr &MI = *MII;
237
+ ++MII;
235
238
236
- // And have our iterator point to the next instruction, if there is one.
237
- if (MII == Begin)
238
- ReachedBegin = true ;
239
- else
240
- --MII;
241
239
if (MI.getOpcode () != TargetOpcode::COPY)
242
240
continue ;
243
241
Register SrcReg = MI.getOperand (1 ).getReg ();
@@ -342,3 +340,42 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
342
340
// FIXME: Should we accurately track changes?
343
341
return true ;
344
342
}
343
+
344
+ bool InstructionSelect::select (MachineInstr &MI) {
345
+ MachineRegisterInfo &MRI = ISel->MF ->getRegInfo ();
346
+
347
+ // We could have folded this instruction away already, making it dead.
348
+ // If so, erase it.
349
+ if (isTriviallyDead (MI, MRI)) {
350
+ LLVM_DEBUG (dbgs () << " Is dead.\n " );
351
+ salvageDebugInfo (MRI, MI);
352
+ MI.eraseFromParent ();
353
+ return true ;
354
+ }
355
+
356
+ // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
357
+ if (isPreISelGenericOptimizationHint (MI.getOpcode ()) ||
358
+ MI.getOpcode () == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
359
+ auto [DstReg, SrcReg] = MI.getFirst2Regs ();
360
+
361
+ // At this point, the destination register class of the op may have
362
+ // been decided.
363
+ //
364
+ // Propagate that through to the source register.
365
+ const TargetRegisterClass *DstRC = MRI.getRegClassOrNull (DstReg);
366
+ if (DstRC)
367
+ MRI.setRegClass (SrcReg, DstRC);
368
+ assert (canReplaceReg (DstReg, SrcReg, MRI) &&
369
+ " Must be able to replace dst with src!" );
370
+ MI.eraseFromParent ();
371
+ MRI.replaceRegWith (DstReg, SrcReg);
372
+ return true ;
373
+ }
374
+
375
+ if (MI.getOpcode () == TargetOpcode::G_INVOKE_REGION_START) {
376
+ MI.eraseFromParent ();
377
+ return true ;
378
+ }
379
+
380
+ return ISel->select (MI);
381
+ }
0 commit comments