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"
@@ -65,6 +67,52 @@ INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
65
67
InstructionSelect::InstructionSelect(CodeGenOptLevel OL, char &PassID)
66
68
: MachineFunctionPass(PassID), OptLevel(OL) {}
67
69
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
+
68
116
void InstructionSelect::getAnalysisUsage (AnalysisUsage &AU) const {
69
117
AU.addRequired <TargetPassConfig>();
70
118
AU.addRequired <GISelKnownBitsAnalysis>();
@@ -84,31 +132,36 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
84
132
MachineFunctionProperties::Property::FailedISel))
85
133
return false ;
86
134
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>();
92
137
138
+ // FIXME: Properly override OptLevel in TargetMachine. See OptLevelChanger
93
139
CodeGenOptLevel OldOptLevel = OptLevel;
94
140
auto RestoreOptLevel = make_scope_exit ([=]() { OptLevel = OldOptLevel; });
95
141
OptLevel = MF.getFunction ().hasOptNone () ? CodeGenOptLevel::None
96
142
: MF.getTarget ().getOptLevel ();
97
143
98
- GISelKnownBits * KB = &getAnalysis<GISelKnownBitsAnalysis>().get (MF);
144
+ KB = &getAnalysis<GISelKnownBitsAnalysis>().get (MF);
99
145
if (OptLevel != CodeGenOptLevel::None) {
100
146
PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI ();
101
147
if (PSI && PSI->hasProfileSummary ())
102
148
BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI ();
103
149
}
104
150
105
- CodeGenCoverage CoverageInfo;
151
+ return selectMachineFunction (MF);
152
+ }
153
+
154
+ bool InstructionSelect::selectMachineFunction (MachineFunction &MF) {
155
+ LLVM_DEBUG (dbgs () << " Selecting function: " << MF.getName () << ' \n ' );
106
156
assert (ISel && " Cannot work without InstructionSelector" );
157
+
158
+ const TargetPassConfig &TPC = *ISel->TPC ;
159
+ CodeGenCoverage CoverageInfo;
107
160
ISel->setupMF (MF, KB, &CoverageInfo, PSI, BFI);
108
161
109
162
// An optimization remark emitter. Used to report failures.
110
163
MachineOptimizationRemarkEmitter MORE (MF, /* MBFI=*/ nullptr );
111
- ISel->setRemarkEmitter ( &MORE) ;
164
+ ISel->MORE = &MORE;
112
165
113
166
// FIXME: There are many other MF/MFI fields we need to initialize.
114
167
@@ -131,80 +184,36 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
131
184
// Keep track of selected blocks, so we can delete unreachable ones later.
132
185
DenseSet<MachineBasicBlock *> SelectedBlocks;
133
186
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 ());
198
216
}
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
- });
208
217
}
209
218
}
210
219
@@ -222,16 +231,10 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
222
231
continue ;
223
232
}
224
233
// 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;) {
228
235
MachineInstr &MI = *MII;
236
+ ++MII;
229
237
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;
235
238
if (MI.getOpcode () != TargetOpcode::COPY)
236
239
continue ;
237
240
Register SrcReg = MI.getOperand (1 ).getReg ();
@@ -336,3 +339,42 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
336
339
// FIXME: Should we accurately track changes?
337
340
return true ;
338
341
}
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