70
70
#include " llvm/ADT/DenseMap.h"
71
71
#include " llvm/ADT/PostOrderIterator.h"
72
72
#include " llvm/ADT/STLExtras.h"
73
- #include " llvm/ADT/SmallVector.h"
74
73
#include " llvm/ADT/iterator_range.h"
75
74
#include " llvm/CodeGen/MachineBasicBlock.h"
76
75
#include " llvm/CodeGen/MachineFunction.h"
@@ -123,57 +122,6 @@ findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) {
123
122
return nullptr ;
124
123
}
125
124
126
- // Represents a basic block's relationship to the call frame. This metadata
127
- // reflects what the state *should* be, which may differ from the actual state
128
- // after final machine basic block layout.
129
- struct BlockFlags {
130
- bool Reachable : 1 ;
131
- bool StrongNoFrameOnEntry : 1 ;
132
- bool HasFrameOnEntry : 1 ;
133
- bool HasFrameOnExit : 1 ;
134
- };
135
-
136
- // Computes the frame information for each block in the function. Frame info
137
- // for a block is inferred from its predecessors.
138
- static SmallVector<BlockFlags>
139
- computeBlockInfo (const MachineFunction &MF,
140
- const MachineBasicBlock *PrologueBlock) {
141
- SmallVector<BlockFlags, 32 > BlockInfo (MF.getNumBlockIDs (),
142
- {false , false , false , false });
143
- BlockInfo[0 ].Reachable = true ;
144
- BlockInfo[0 ].StrongNoFrameOnEntry = true ;
145
-
146
- // Compute the presence/absence of frame at each basic block.
147
- ReversePostOrderTraversal<const MachineBasicBlock *> RPOT (&*MF.begin ());
148
- for (const MachineBasicBlock *MBB : RPOT) {
149
- BlockFlags &Info = BlockInfo[MBB->getNumber ()];
150
-
151
- // Set to true if the current block contains the prologue or the epilogue,
152
- // respectively.
153
- bool HasPrologue = MBB == PrologueBlock;
154
- bool HasEpilogue = false ;
155
-
156
- if (Info.HasFrameOnEntry || HasPrologue)
157
- HasEpilogue = containsEpilogue (*MBB);
158
-
159
- // If the function has a call frame at the entry of the current block or the
160
- // current block contains the prologue, then the function has a call frame
161
- // at the exit of the block, unless the block contains the epilogue.
162
- Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue;
163
-
164
- // Set the successors' state on entry.
165
- for (MachineBasicBlock *Succ : MBB->successors ()) {
166
- BlockFlags &SuccInfo = BlockInfo[Succ->getNumber ()];
167
- SuccInfo.Reachable = true ;
168
- SuccInfo.StrongNoFrameOnEntry |=
169
- Info.StrongNoFrameOnEntry && !HasPrologue;
170
- SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit ;
171
- }
172
- }
173
-
174
- return BlockInfo;
175
- }
176
-
177
125
// Represents the point within a basic block where we can insert an instruction.
178
126
// Note that we need the MachineBasicBlock* as well as the iterator since the
179
127
// iterator can point to the end of the block. Instructions are inserted
@@ -233,69 +181,13 @@ static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd,
233
181
return DstInsertPt;
234
182
}
235
183
236
- // Fixes up the CFI instructions in a basic block to be consistent with the
237
- // intended frame state, adding or removing CFI instructions as necessary.
238
- // Returns true if a change was made and false otherwise.
239
- static bool
240
- fixupBlock (MachineBasicBlock &CurrBB, const SmallVector<BlockFlags> &BlockInfo,
241
- SmallDenseMap<MBBSectionID, InsertionPoint> &InsertionPts,
242
- const InsertionPoint &Prologue) {
243
- const MachineFunction &MF = *CurrBB.getParent ();
244
- const TargetFrameLowering &TFL = *MF.getSubtarget ().getFrameLowering ();
245
- const BlockFlags &Info = BlockInfo[CurrBB.getNumber ()];
246
-
247
- if (!Info.Reachable )
248
- return false ;
249
-
250
- // If the previous block and the current block are in the same section,
251
- // the frame info will propagate from the previous block to the current one.
252
- const BlockFlags &PrevInfo =
253
- BlockInfo[std::prev (CurrBB.getIterator ())->getNumber ()];
254
- bool HasFrame = PrevInfo.HasFrameOnExit && !CurrBB.isBeginSection ();
255
- bool NeedsFrame = Info.HasFrameOnEntry && !Info.StrongNoFrameOnEntry ;
256
-
257
- #ifndef NDEBUG
258
- if (!Info.StrongNoFrameOnEntry ) {
259
- for (auto *Pred : CurrBB.predecessors ()) {
260
- const BlockFlags &PredInfo = BlockInfo[Pred->getNumber ()];
261
- assert ((!PredInfo.Reachable ||
262
- Info.HasFrameOnEntry == PredInfo.HasFrameOnExit ) &&
263
- " Inconsistent call frame state" );
264
- }
265
- }
266
- #endif
267
-
268
- if (HasFrame == NeedsFrame)
269
- return false ;
270
-
271
- if (!NeedsFrame) {
272
- // Reset to the state upon function entry.
273
- TFL.resetCFIToInitialState (CurrBB);
274
- return true ;
275
- }
276
-
277
- // Reset to the "after prologue" state.
278
- InsertionPoint &InsertPt = InsertionPts[CurrBB.getSectionID ()];
279
- if (InsertPt.MBB == nullptr ) {
280
- // CurBB is the first block in its section, so there is no "after
281
- // prologue" state. Clone the CFI instructions from the prologue block
282
- // to create it.
283
- InsertPt = cloneCfiPrologue (Prologue, {&CurrBB, CurrBB.begin ()});
284
- } else {
285
- // There's an earlier block known to have a stack frame. Insert a
286
- // `.cfi_remember_state` instruction into that block and a
287
- // `.cfi_restore_state` instruction at the beginning of the current
288
- // block.
289
- InsertPt = insertRememberRestorePair (InsertPt, {&CurrBB, CurrBB.begin ()});
290
- }
291
- return true ;
292
- }
293
-
294
184
bool CFIFixup::runOnMachineFunction (MachineFunction &MF) {
295
- if (!MF.getSubtarget ().getFrameLowering ()->enableCFIFixup (MF))
185
+ const TargetFrameLowering &TFL = *MF.getSubtarget ().getFrameLowering ();
186
+ if (!TFL.enableCFIFixup (MF))
296
187
return false ;
297
188
298
- if (MF.getNumBlockIDs () < 2 )
189
+ const unsigned NumBlocks = MF.getNumBlockIDs ();
190
+ if (NumBlocks < 2 )
299
191
return false ;
300
192
301
193
// Find the prologue and the point where we can issue the first
@@ -305,7 +197,44 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
305
197
if (PrologueBlock == nullptr )
306
198
return false ;
307
199
308
- SmallVector<BlockFlags> BlockInfo = computeBlockInfo (MF, PrologueBlock);
200
+ struct BlockFlags {
201
+ bool Reachable : 1 ;
202
+ bool StrongNoFrameOnEntry : 1 ;
203
+ bool HasFrameOnEntry : 1 ;
204
+ bool HasFrameOnExit : 1 ;
205
+ };
206
+ SmallVector<BlockFlags, 32 > BlockInfo (NumBlocks,
207
+ {false , false , false , false });
208
+ BlockInfo[0 ].Reachable = true ;
209
+ BlockInfo[0 ].StrongNoFrameOnEntry = true ;
210
+
211
+ // Compute the presence/absence of frame at each basic block.
212
+ ReversePostOrderTraversal<MachineBasicBlock *> RPOT (&*MF.begin ());
213
+ for (MachineBasicBlock *MBB : RPOT) {
214
+ BlockFlags &Info = BlockInfo[MBB->getNumber ()];
215
+
216
+ // Set to true if the current block contains the prologue or the epilogue,
217
+ // respectively.
218
+ bool HasPrologue = MBB == PrologueBlock;
219
+ bool HasEpilogue = false ;
220
+
221
+ if (Info.HasFrameOnEntry || HasPrologue)
222
+ HasEpilogue = containsEpilogue (*MBB);
223
+
224
+ // If the function has a call frame at the entry of the current block or the
225
+ // current block contains the prologue, then the function has a call frame
226
+ // at the exit of the block, unless the block contains the epilogue.
227
+ Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue;
228
+
229
+ // Set the successors' state on entry.
230
+ for (MachineBasicBlock *Succ : MBB->successors ()) {
231
+ BlockFlags &SuccInfo = BlockInfo[Succ->getNumber ()];
232
+ SuccInfo.Reachable = true ;
233
+ SuccInfo.StrongNoFrameOnEntry |=
234
+ Info.StrongNoFrameOnEntry && !HasPrologue;
235
+ SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit ;
236
+ }
237
+ }
309
238
310
239
// Walk the blocks of the function in "physical" order.
311
240
// Every block inherits the frame state (as recorded in the unwind tables)
@@ -324,10 +253,57 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
324
253
// No point starting before the prologue block.
325
254
// TODO: the unwind tables will still be incorrect if an epilogue physically
326
255
// preceeds the prologue.
327
- for (MachineBasicBlock &MBB :
328
- make_range (std::next (PrologueBlock->getIterator ()), MF.end ())) {
329
- Change |=
330
- fixupBlock (MBB, BlockInfo, InsertionPts, {PrologueBlock, PrologueEnd});
256
+ MachineFunction::iterator CurrBB = std::next (PrologueBlock->getIterator ());
257
+ bool HasFrame = BlockInfo[PrologueBlock->getNumber ()].HasFrameOnExit ;
258
+ while (CurrBB != MF.end ()) {
259
+ const BlockFlags &Info = BlockInfo[CurrBB->getNumber ()];
260
+ if (!Info.Reachable ) {
261
+ ++CurrBB;
262
+ continue ;
263
+ }
264
+
265
+ #ifndef NDEBUG
266
+ if (!Info.StrongNoFrameOnEntry ) {
267
+ for (auto *Pred : CurrBB->predecessors ()) {
268
+ BlockFlags &PredInfo = BlockInfo[Pred->getNumber ()];
269
+ assert ((!PredInfo.Reachable ||
270
+ Info.HasFrameOnEntry == PredInfo.HasFrameOnExit ) &&
271
+ " Inconsistent call frame state" );
272
+ }
273
+ }
274
+ #endif
275
+
276
+ // If the block is the first block in its section, then it doesn't have a
277
+ // frame on entry.
278
+ HasFrame &= !CurrBB->isBeginSection ();
279
+ if (!Info.StrongNoFrameOnEntry && Info.HasFrameOnEntry && !HasFrame) {
280
+ // Reset to the "after prologue" state.
281
+
282
+ InsertionPoint &InsertPt = InsertionPts[CurrBB->getSectionID ()];
283
+ if (InsertPt.MBB == nullptr ) {
284
+ // CurBB is the first block in its section, so there is no "after
285
+ // prologue" state. Clone the CFI instructions from the prologue block
286
+ // to create it.
287
+ InsertPt = cloneCfiPrologue ({PrologueBlock, PrologueEnd},
288
+ {&*CurrBB, CurrBB->begin ()});
289
+ } else {
290
+ // There's an earlier block known to have a stack frame. Insert a
291
+ // `.cfi_remember_state` instruction into that block and a
292
+ // `.cfi_restore_state` instruction at the beginning of the current
293
+ // block.
294
+ InsertPt =
295
+ insertRememberRestorePair (InsertPt, {&*CurrBB, CurrBB->begin ()});
296
+ }
297
+ Change = true ;
298
+ } else if ((Info.StrongNoFrameOnEntry || !Info.HasFrameOnEntry ) &&
299
+ HasFrame) {
300
+ // Reset to the state upon function entry.
301
+ TFL.resetCFIToInitialState (*CurrBB);
302
+ Change = true ;
303
+ }
304
+
305
+ HasFrame = Info.HasFrameOnExit ;
306
+ ++CurrBB;
331
307
}
332
308
333
309
return Change;
0 commit comments