7070#include " llvm/ADT/DenseMap.h"
7171#include " llvm/ADT/PostOrderIterator.h"
7272#include " llvm/ADT/STLExtras.h"
73- #include " llvm/ADT/SmallVector.h"
7473#include " llvm/ADT/iterator_range.h"
7574#include " llvm/CodeGen/MachineBasicBlock.h"
7675#include " llvm/CodeGen/MachineFunction.h"
@@ -123,57 +122,6 @@ findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) {
123122 return nullptr ;
124123}
125124
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-
177125// Represents the point within a basic block where we can insert an instruction.
178126// Note that we need the MachineBasicBlock* as well as the iterator since the
179127// iterator can point to the end of the block. Instructions are inserted
@@ -233,69 +181,13 @@ static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd,
233181 return DstInsertPt;
234182}
235183
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-
294184bool CFIFixup::runOnMachineFunction (MachineFunction &MF) {
295- if (!MF.getSubtarget ().getFrameLowering ()->enableCFIFixup (MF))
185+ const TargetFrameLowering &TFL = *MF.getSubtarget ().getFrameLowering ();
186+ if (!TFL.enableCFIFixup (MF))
296187 return false ;
297188
298- if (MF.getNumBlockIDs () < 2 )
189+ const unsigned NumBlocks = MF.getNumBlockIDs ();
190+ if (NumBlocks < 2 )
299191 return false ;
300192
301193 // Find the prologue and the point where we can issue the first
@@ -305,7 +197,44 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
305197 if (PrologueBlock == nullptr )
306198 return false ;
307199
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+ }
309238
310239 // Walk the blocks of the function in "physical" order.
311240 // Every block inherits the frame state (as recorded in the unwind tables)
@@ -324,10 +253,57 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
324253 // No point starting before the prologue block.
325254 // TODO: the unwind tables will still be incorrect if an epilogue physically
326255 // 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;
331307 }
332308
333309 return Change;
0 commit comments