10
10
// This pass inserts the necessary instructions to adjust for the inconsistency
11
11
// of the call-frame information caused by final machine basic block layout.
12
12
// The pass relies in constraints LLVM imposes on the placement of
13
- // save/restore points (cf. ShrinkWrap):
14
- // * there is a single basic block, containing the function prologue
13
+ // save/restore points (cf. ShrinkWrap) and has certain preconditions about
14
+ // placement of CFI instructions:
15
+ // * for any two CFI instructions of the function prologue one dominates
16
+ // and is post-dominated by the other
15
17
// * possibly multiple epilogue blocks, where each epilogue block is
16
18
// complete and self-contained, i.e. CSR restore instructions (and the
17
19
// corresponding CFI instructions are not split across two or more blocks.
18
- // * prologue and epilogue blocks are outside of any loops
19
- // Thus, during execution, at the beginning and at the end of each basic block
20
- // the function can be in one of two states:
20
+ // * CFI instructions are not contained in any loops
21
+ // Thus, during execution, at the beginning and at the end of each basic block,
22
+ // following the prologue, the function can be in one of two states:
21
23
// - "has a call frame", if the function has executed the prologue, and
22
24
// has not executed any epilogue
23
25
// - "does not have a call frame", if the function has not executed the
24
26
// prologue, or has executed an epilogue
25
27
// which can be computed by a single RPO traversal.
26
28
29
+ // The location of the prologue is determined by finding the first block in the
30
+ // post-order traversal which contains CFI instructions.
31
+
27
32
// In order to accommodate backends which do not generate unwind info in
28
33
// epilogues we compute an additional property "strong no call frame on entry",
29
34
// which is set for the entry point of the function and for every block
@@ -85,17 +90,32 @@ static bool isPrologueCFIInstruction(const MachineInstr &MI) {
85
90
MI.getFlag (MachineInstr::FrameSetup);
86
91
}
87
92
88
- static bool containsPrologue (const MachineBasicBlock &MBB) {
89
- return llvm::any_of (MBB.instrs (), isPrologueCFIInstruction);
90
- }
91
-
92
93
static bool containsEpilogue (const MachineBasicBlock &MBB) {
93
94
return llvm::any_of (llvm::reverse (MBB), [](const auto &MI) {
94
95
return MI.getOpcode () == TargetOpcode::CFI_INSTRUCTION &&
95
96
MI.getFlag (MachineInstr::FrameDestroy);
96
97
});
97
98
}
98
99
100
+ static MachineBasicBlock *
101
+ findPrologueEnd (MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) {
102
+ MachineBasicBlock *PrologueBlock = nullptr ;
103
+ for (auto It = po_begin (&MF.front ()), End = po_end (&MF.front ()); It != End;
104
+ ++It) {
105
+ MachineBasicBlock *MBB = *It;
106
+ llvm::for_each (MBB->instrs (), [&](MachineInstr &MI) {
107
+ if (isPrologueCFIInstruction (MI)) {
108
+ PrologueBlock = MBB;
109
+ PrologueEnd = std::next (MI.getIterator ());
110
+ }
111
+ });
112
+ if (PrologueBlock)
113
+ return PrologueBlock;
114
+ }
115
+
116
+ return nullptr ;
117
+ }
118
+
99
119
bool CFIFixup::runOnMachineFunction (MachineFunction &MF) {
100
120
const TargetFrameLowering &TFL = *MF.getSubtarget ().getFrameLowering ();
101
121
if (!TFL.enableCFIFixup (MF))
@@ -105,6 +125,14 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
105
125
if (NumBlocks < 2 )
106
126
return false ;
107
127
128
+ // Find the prologue and the point where we can issue the first
129
+ // `.cfi_remember_state`.
130
+
131
+ MachineBasicBlock::iterator PrologueEnd;
132
+ MachineBasicBlock *PrologueBlock = findPrologueEnd (MF, PrologueEnd);
133
+ if (PrologueBlock == nullptr )
134
+ return false ;
135
+
108
136
struct BlockFlags {
109
137
bool Reachable : 1 ;
110
138
bool StrongNoFrameOnEntry : 1 ;
@@ -116,21 +144,15 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
116
144
BlockInfo[0 ].StrongNoFrameOnEntry = true ;
117
145
118
146
// Compute the presence/absence of frame at each basic block.
119
- MachineBasicBlock *PrologueBlock = nullptr ;
120
147
ReversePostOrderTraversal<MachineBasicBlock *> RPOT (&*MF.begin ());
121
148
for (MachineBasicBlock *MBB : RPOT) {
122
149
BlockFlags &Info = BlockInfo[MBB->getNumber ()];
123
150
124
151
// Set to true if the current block contains the prologue or the epilogue,
125
152
// respectively.
126
- bool HasPrologue = false ;
153
+ bool HasPrologue = MBB == PrologueBlock ;
127
154
bool HasEpilogue = false ;
128
155
129
- if (!PrologueBlock && !Info.HasFrameOnEntry && containsPrologue (*MBB)) {
130
- PrologueBlock = MBB;
131
- HasPrologue = true ;
132
- }
133
-
134
156
if (Info.HasFrameOnEntry || HasPrologue)
135
157
HasEpilogue = containsEpilogue (*MBB);
136
158
@@ -149,9 +171,6 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
149
171
}
150
172
}
151
173
152
- if (!PrologueBlock)
153
- return false ;
154
-
155
174
// Walk the blocks of the function in "physical" order.
156
175
// Every block inherits the frame state (as recorded in the unwind tables)
157
176
// of the previous block. If the intended frame state is different, insert
@@ -162,10 +181,7 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
162
181
// insert a `.cfi_remember_state`, in the case that the current block needs a
163
182
// `.cfi_restore_state`.
164
183
MachineBasicBlock *InsertMBB = PrologueBlock;
165
- MachineBasicBlock::iterator InsertPt = PrologueBlock->begin ();
166
- for (MachineInstr &MI : *PrologueBlock)
167
- if (isPrologueCFIInstruction (MI))
168
- InsertPt = std::next (MI.getIterator ());
184
+ MachineBasicBlock::iterator InsertPt = PrologueEnd;
169
185
170
186
assert (InsertPt != PrologueBlock->begin () &&
171
187
" Inconsistent notion of \" prologue block\" " );
0 commit comments