Skip to content

Commit 82b923d

Browse files
committed
Reland "[CFIFixup] Factor logic into helpers and use range-based loops (NFC) #125137"
This patch was breaking tests due to inconsistent use of SmallVector. After consolidating SmallVector usages, everything should work as intended.
1 parent d841c88 commit 82b923d

File tree

1 file changed

+119
-93
lines changed

1 file changed

+119
-93
lines changed

llvm/lib/CodeGen/CFIFixup.cpp

Lines changed: 119 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,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

Comments
 (0)