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,57 @@ 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+ // 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+
125177// Represents the point within a basic block where we can insert an instruction.
126178// Note that we need the MachineBasicBlock* as well as the iterator since the
127179// iterator can point to the end of the block. Instructions are inserted
@@ -181,13 +233,69 @@ static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd,
181233 return DstInsertPt;
182234}
183235
184- bool CFIFixup::runOnMachineFunction (MachineFunction &MF) {
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 ();
185244 const TargetFrameLowering &TFL = *MF.getSubtarget ().getFrameLowering ();
186- if (!TFL.enableCFIFixup (MF))
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+ bool CFIFixup::runOnMachineFunction (MachineFunction &MF) {
295+ if (!MF.getSubtarget ().getFrameLowering ()->enableCFIFixup (MF))
187296 return false ;
188297
189- const unsigned NumBlocks = MF.getNumBlockIDs ();
190- if (NumBlocks < 2 )
298+ if (MF.getNumBlockIDs () < 2 )
191299 return false ;
192300
193301 // Find the prologue and the point where we can issue the first
@@ -197,44 +305,7 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
197305 if (PrologueBlock == nullptr )
198306 return false ;
199307
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- }
308+ SmallVector<BlockFlags> BlockInfo = computeBlockInfo (MF, PrologueBlock);
238309
239310 // Walk the blocks of the function in "physical" order.
240311 // Every block inherits the frame state (as recorded in the unwind tables)
@@ -253,57 +324,10 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
253324 // No point starting before the prologue block.
254325 // TODO: the unwind tables will still be incorrect if an epilogue physically
255326 // 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;
327+ for (MachineBasicBlock &MBB :
328+ make_range (std::next (PrologueBlock->getIterator ()), MF.end ())) {
329+ Change |=
330+ fixupBlock (MBB, BlockInfo, InsertionPts, {PrologueBlock, PrologueEnd});
307331 }
308332
309333 return Change;
0 commit comments