Skip to content

Commit f14f197

Browse files
authored
[CFIFixup] Factor logic into helpers and use range-based loops (NFC) (#125137)
`runOnMachineFunction` is getting long (>100 lines), and the logic for computing block info and performing block fixup can be abstracted away. Reduce nesting in the main block fixup loop and name conditions to reflect their purpose. Replace manual usage of iterators with a range-based for loop. Source: - https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code - https://llvm.org/docs/CodingStandards.html#use-range-based-for-loops-wherever-possible - https://llvm.org/docs/CodingStandards.html#don-t-evaluate-end-every-time-through-a-loop
1 parent 2bfb3ba commit f14f197

File tree

1 file changed

+117
-93
lines changed

1 file changed

+117
-93
lines changed

llvm/lib/CodeGen/CFIFixup.cpp

Lines changed: 117 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
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

Comments
 (0)