Skip to content

File tree

1 file changed

+93
-117
lines changed

1 file changed

+93
-117
lines changed

llvm/lib/CodeGen/CFIFixup.cpp

+93-117
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
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-
294184
bool 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

Comments
 (0)