7070#include " llvm/ADT/DenseMap.h"
7171#include " llvm/ADT/PostOrderIterator.h"
7272#include " llvm/ADT/STLExtras.h"
73+ #include " llvm/ADT/SmallVector.h"
7374#include " llvm/ADT/iterator_range.h"
7475#include " llvm/CodeGen/MachineBasicBlock.h"
7576#include " llvm/CodeGen/MachineFunction.h"
@@ -122,6 +123,59 @@ findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) {
122123 return nullptr ;
123124}
124125
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+
125179// Represents the point within a basic block where we can insert an instruction.
126180// Note that we need the MachineBasicBlock* as well as the iterator since the
127181// iterator can point to the end of the block. Instructions are inserted
@@ -181,13 +235,69 @@ static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd,
181235 return DstInsertPt;
182236}
183237
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 ();
185246 const TargetFrameLowering &TFL = *MF.getSubtarget ().getFrameLowering ();
186- if (!TFL.enableCFIFixup (MF))
247+ const BlockFlags &Info = BlockInfo[CurrBB.getNumber ()];
248+
249+ if (!Info.Reachable )
187250 return false ;
188251
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 )
191301 return false ;
192302
193303 // Find the prologue and the point where we can issue the first
@@ -197,44 +307,7 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
197307 if (PrologueBlock == nullptr )
198308 return false ;
199309
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);
238311
239312 // Walk the blocks of the function in "physical" order.
240313 // Every block inherits the frame state (as recorded in the unwind tables)
@@ -253,57 +326,10 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
253326 // No point starting before the prologue block.
254327 // TODO: the unwind tables will still be incorrect if an epilogue physically
255328 // 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});
307333 }
308334
309335 return Change;
0 commit comments