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