Skip to content

Commit 2dcf051

Browse files
committed
[CodeGen] Store call frame size in MachineBasicBlock
Record the call frame size on entry to each basic block. This is usually zero except when a basic block has been split in the middle of a call sequence. This simplifies PEI::replaceFrameIndices which previously had to visit basic blocks in a specific order and had special handling for unreachable blocks. More importantly it paves the way for an equally simple implementation of a backwards version of replaceFrameIndices, which is required to fully convert PrologEpilogInserter to backwards register scavenging, which is preferred because it does not rely on accurate kill flags. Differential Revision: https://reviews.llvm.org/D156113
1 parent 77ef88d commit 2dcf051

17 files changed

+141
-32
lines changed

llvm/include/llvm/CodeGen/MachineBasicBlock.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ class MachineBasicBlock
111111

112112
const BasicBlock *BB;
113113
int Number;
114+
115+
/// The call frame size on entry to this basic block due to call frame setup
116+
/// instructions in a predecessor. This is usually zero, unless basic blocks
117+
/// are split in the middle of a call sequence.
118+
///
119+
/// This information is only maintained until PrologEpilogInserter eliminates
120+
/// call frame pseudos.
121+
unsigned CallFrameSize = 0;
122+
114123
MachineFunction *xParent;
115124
Instructions Insts;
116125

@@ -1148,6 +1157,11 @@ class MachineBasicBlock
11481157
int getNumber() const { return Number; }
11491158
void setNumber(int N) { Number = N; }
11501159

1160+
/// Return the call frame size on entry to this basic block.
1161+
unsigned getCallFrameSize() const { return CallFrameSize; }
1162+
/// Set the call frame size on entry to this basic block.
1163+
void setCallFrameSize(unsigned N) { CallFrameSize = N; }
1164+
11511165
/// Return the MCSymbol for this basic block.
11521166
MCSymbol *getSymbol() const;
11531167

llvm/include/llvm/CodeGen/TargetInstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,9 @@ class TargetInstrInfo : public MCInstrInfo {
21152115
return false;
21162116
}
21172117

2118+
// Get the call frame size just before MI.
2119+
unsigned getCallFrameSizeAt(MachineInstr &MI) const;
2120+
21182121
private:
21192122
mutable std::unique_ptr<MIRFormatter> Formatter;
21202123
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;

llvm/lib/CodeGen/MIRParser/MILexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
281281
.Case("ir-block-address-taken", MIToken::kw_ir_block_address_taken)
282282
.Case("machine-block-address-taken",
283283
MIToken::kw_machine_block_address_taken)
284+
.Case("call-frame-size", MIToken::kw_call_frame_size)
284285
.Default(MIToken::Identifier);
285286
}
286287

llvm/lib/CodeGen/MIRParser/MILexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct MIToken {
135135
kw_unknown_address,
136136
kw_ir_block_address_taken,
137137
kw_machine_block_address_taken,
138+
kw_call_frame_size,
138139

139140
// Metadata types.
140141
kw_distinct,

llvm/lib/CodeGen/MIRParser/MIParser.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ class MIParser {
501501
bool parseAddrspace(unsigned &Addrspace);
502502
bool parseSectionID(std::optional<MBBSectionID> &SID);
503503
bool parseBBID(std::optional<unsigned> &BBID);
504+
bool parseCallFrameSize(unsigned &CallFrameSize);
504505
bool parseOperandsOffset(MachineOperand &Op);
505506
bool parseIRValue(const Value *&V);
506507
bool parseMemoryOperandFlag(MachineMemOperand::Flags &Flags);
@@ -676,6 +677,18 @@ bool MIParser::parseBBID(std::optional<unsigned> &BBID) {
676677
return false;
677678
}
678679

680+
// Parse basic block call frame size.
681+
bool MIParser::parseCallFrameSize(unsigned &CallFrameSize) {
682+
assert(Token.is(MIToken::kw_call_frame_size));
683+
lex();
684+
unsigned Value = 0;
685+
if (getUnsigned(Value))
686+
return error("Unknown call frame size");
687+
CallFrameSize = Value;
688+
lex();
689+
return false;
690+
}
691+
679692
bool MIParser::parseBasicBlockDefinition(
680693
DenseMap<unsigned, MachineBasicBlock *> &MBBSlots) {
681694
assert(Token.is(MIToken::MachineBasicBlockLabel));
@@ -693,6 +706,7 @@ bool MIParser::parseBasicBlockDefinition(
693706
std::optional<MBBSectionID> SectionID;
694707
uint64_t Alignment = 0;
695708
std::optional<unsigned> BBID;
709+
unsigned CallFrameSize = 0;
696710
BasicBlock *BB = nullptr;
697711
if (consumeIfPresent(MIToken::lparen)) {
698712
do {
@@ -737,6 +751,10 @@ bool MIParser::parseBasicBlockDefinition(
737751
if (parseBBID(BBID))
738752
return true;
739753
break;
754+
case MIToken::kw_call_frame_size:
755+
if (parseCallFrameSize(CallFrameSize))
756+
return true;
757+
break;
740758
default:
741759
break;
742760
}
@@ -781,6 +799,7 @@ bool MIParser::parseBasicBlockDefinition(
781799
MF.setBBSectionsType(BasicBlockSection::Labels);
782800
MBB->setBBID(BBID.value());
783801
}
802+
MBB->setCallFrameSize(CallFrameSize);
784803
return false;
785804
}
786805

llvm/lib/CodeGen/MachineBasicBlock.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,11 @@ void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags,
570570
os << "bb_id " << *getBBID();
571571
hasAttributes = true;
572572
}
573+
if (CallFrameSize != 0) {
574+
os << (hasAttributes ? ", " : " (");
575+
os << "call-frame-size " << CallFrameSize;
576+
hasAttributes = true;
577+
}
573578
}
574579

575580
if (hasAttributes)
@@ -1099,6 +1104,7 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
10991104
DebugLoc DL; // FIXME: this is nowhere
11001105

11011106
MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock();
1107+
NMBB->setCallFrameSize(Succ->getCallFrameSize());
11021108

11031109
// Is there an indirect jump with jump table?
11041110
bool ChangedIndirectJump = false;

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3398,6 +3398,15 @@ void MachineVerifier::verifyStackFrame() {
33983398
BBState.ExitIsSetup = BBState.EntryIsSetup;
33993399
}
34003400

3401+
if ((int)MBB->getCallFrameSize() != -BBState.EntryValue) {
3402+
report("Call frame size on entry does not match value computed from "
3403+
"predecessor",
3404+
MBB);
3405+
errs() << "Call frame size on entry " << MBB->getCallFrameSize()
3406+
<< " does not match value computed from predecessor "
3407+
<< -BBState.EntryValue << '\n';
3408+
}
3409+
34013410
// Update stack state by checking contents of MBB.
34023411
for (const auto &I : *MBB) {
34033412
if (I.getOpcode() == FrameSetupOpcode) {

llvm/lib/CodeGen/PrologEpilogInserter.cpp

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
#include "llvm/ADT/ArrayRef.h"
1919
#include "llvm/ADT/BitVector.h"
20-
#include "llvm/ADT/DepthFirstIterator.h"
2120
#include "llvm/ADT/STLExtras.h"
2221
#include "llvm/ADT/SetVector.h"
2322
#include "llvm/ADT/SmallPtrSet.h"
@@ -381,13 +380,18 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) {
381380
MFI.setAdjustsStack(AdjustsStack);
382381
MFI.setMaxCallFrameSize(MaxCallFrameSize);
383382

384-
for (MachineBasicBlock::iterator I : FrameSDOps) {
383+
if (TFI->canSimplifyCallFramePseudos(MF)) {
385384
// If call frames are not being included as part of the stack frame, and
386385
// the target doesn't indicate otherwise, remove the call frame pseudos
387386
// here. The sub/add sp instruction pairs are still inserted, but we don't
388387
// need to track the SP adjustment for frame index elimination.
389-
if (TFI->canSimplifyCallFramePseudos(MF))
388+
for (MachineBasicBlock::iterator I : FrameSDOps)
390389
TFI->eliminateCallFramePseudoInstr(MF, *I->getParent(), I);
390+
391+
// We can't track the call frame size after call frame pseudos have been
392+
// eliminated. Set it to zero everywhere to keep MachineVerifier happy.
393+
for (MachineBasicBlock &MBB : MF)
394+
MBB.setCallFrameSize(0);
391395
}
392396
}
393397

@@ -1341,34 +1345,16 @@ void PEI::replaceFrameIndices(MachineFunction &MF) {
13411345
FrameIndexEliminationScavenging = (RS && !FrameIndexVirtualScavenging) ||
13421346
TRI->requiresFrameIndexReplacementScavenging(MF);
13431347

1344-
// Store SPAdj at exit of a basic block.
1345-
SmallVector<int, 8> SPState;
1346-
SPState.resize(MF.getNumBlockIDs());
1347-
df_iterator_default_set<MachineBasicBlock*> Reachable;
1348-
1349-
// Iterate over the reachable blocks in DFS order.
1350-
for (auto DFI = df_ext_begin(&MF, Reachable), DFE = df_ext_end(&MF, Reachable);
1351-
DFI != DFE; ++DFI) {
1352-
int SPAdj = 0;
1353-
// Check the exit state of the DFS stack predecessor.
1354-
if (DFI.getPathLength() >= 2) {
1355-
MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2);
1356-
assert(Reachable.count(StackPred) &&
1357-
"DFS stack predecessor is already visited.\n");
1358-
SPAdj = SPState[StackPred->getNumber()];
1359-
}
1360-
MachineBasicBlock *BB = *DFI;
1361-
replaceFrameIndices(BB, MF, SPAdj);
1362-
SPState[BB->getNumber()] = SPAdj;
1363-
}
1348+
for (auto &MBB : MF) {
1349+
int SPAdj = TFI.alignSPAdjust(MBB.getCallFrameSize());
1350+
if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp)
1351+
SPAdj = -SPAdj;
13641352

1365-
// Handle the unreachable blocks.
1366-
for (auto &BB : MF) {
1367-
if (Reachable.count(&BB))
1368-
// Already handled in DFS traversal.
1369-
continue;
1370-
int SPAdj = 0;
1371-
replaceFrameIndices(&BB, MF, SPAdj);
1353+
replaceFrameIndices(&MBB, MF, SPAdj);
1354+
1355+
// We can't track the call frame size after call frame pseudos have been
1356+
// eliminated. Set it to zero everywhere to keep MachineVerifier happy.
1357+
MBB.setCallFrameSize(0);
13721358
}
13731359
}
13741360

llvm/lib/CodeGen/TargetInstrInfo.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,22 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
14501450
return std::nullopt;
14511451
}
14521452

1453+
// Get the call frame size just before MI.
1454+
unsigned TargetInstrInfo::getCallFrameSizeAt(MachineInstr &MI) const {
1455+
// Search backwards from MI for the most recent call frame instruction.
1456+
MachineBasicBlock *MBB = MI.getParent();
1457+
for (auto &AdjI : reverse(make_range(MBB->instr_begin(), MI.getIterator()))) {
1458+
if (AdjI.getOpcode() == getCallFrameSetupOpcode())
1459+
return getFrameTotalSize(AdjI);
1460+
if (AdjI.getOpcode() == getCallFrameDestroyOpcode())
1461+
return 0;
1462+
}
1463+
1464+
// If none was found, use the call frame size from the start of the basic
1465+
// block.
1466+
return MBB->getCallFrameSize();
1467+
}
1468+
14531469
/// Both DefMI and UseMI must be valid. By default, call directly to the
14541470
/// itinerary. This may be overriden by the target.
14551471
int TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11485,6 +11485,11 @@ ARMTargetLowering::EmitStructByval(MachineInstr &MI,
1148511485
MF->insert(It, loopMBB);
1148611486
MF->insert(It, exitMBB);
1148711487

11488+
// Set the call frame size on entry to the new basic blocks.
11489+
unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
11490+
loopMBB->setCallFrameSize(CallFrameSize);
11491+
exitMBB->setCallFrameSize(CallFrameSize);
11492+
1148811493
// Transfer the remainder of BB and its successor edges to exitMBB.
1148911494
exitMBB->splice(exitMBB->begin(), BB,
1149011495
std::next(MachineBasicBlock::iterator(MI)), BB->end());
@@ -12081,6 +12086,11 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1208112086
F->insert(It, copy0MBB);
1208212087
F->insert(It, sinkMBB);
1208312088

12089+
// Set the call frame size on entry to the new basic blocks.
12090+
unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
12091+
copy0MBB->setCallFrameSize(CallFrameSize);
12092+
sinkMBB->setCallFrameSize(CallFrameSize);
12093+
1208412094
// Check whether CPSR is live past the tMOVCCr_pseudo.
1208512095
const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
1208612096
if (!MI.killsRegister(ARM::CPSR) &&

llvm/lib/Target/AVR/AVRISelLowering.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,6 +2440,11 @@ AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
24402440
MF->insert(I, trueMBB);
24412441
MF->insert(I, falseMBB);
24422442

2443+
// Set the call frame size on entry to the new basic blocks.
2444+
unsigned CallFrameSize = TII.getCallFrameSizeAt(MI);
2445+
trueMBB->setCallFrameSize(CallFrameSize);
2446+
falseMBB->setCallFrameSize(CallFrameSize);
2447+
24432448
// Transfer remaining instructions and all successors of the current
24442449
// block to the block which will contain the Phi node for the
24452450
// select.

llvm/lib/Target/M68k/M68kISelLowering.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3204,6 +3204,11 @@ M68kTargetLowering::EmitLoweredSelect(MachineInstr &MI,
32043204
F->insert(It, Copy0MBB);
32053205
F->insert(It, SinkMBB);
32063206

3207+
// Set the call frame size on entry to the new basic blocks.
3208+
unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
3209+
Copy0MBB->setCallFrameSize(CallFrameSize);
3210+
SinkMBB->setCallFrameSize(CallFrameSize);
3211+
32073212
// If the CCR register isn't dead in the terminator, then claim that it's
32083213
// live into the sink and copy blocks.
32093214
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37244,6 +37244,11 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr &MI,
3724437244
F->insert(It, FalseMBB);
3724537245
F->insert(It, SinkMBB);
3724637246

37247+
// Set the call frame size on entry to the new basic blocks.
37248+
unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
37249+
FalseMBB->setCallFrameSize(CallFrameSize);
37250+
SinkMBB->setCallFrameSize(CallFrameSize);
37251+
3724737252
// If the EFLAGS register isn't dead in the terminator, then claim that it's
3724837253
// live into the sink and copy blocks.
3724937254
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();

llvm/test/CodeGen/ARM/2013-06-03-ByVal-2Kbytes.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
; RUN: llc < %s -mcpu=cortex-a15 | FileCheck %s
2+
; RUN: llc < %s -mcpu=cortex-a15 -stop-after=finalize-isel -o %t.mir
3+
; RUN: llc %t.mir -mcpu=cortex-a15 -start-after=finalize-isel -o - | FileCheck %s
24
; ModuleID = 'attri_16.c'
35
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
46
target triple = "armv4t--linux-gnueabihf"

llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ body: |
121121
%61:gpr = COPY killed %29
122122
%62:gpr = COPY killed %4
123123
%63:gpr = COPY killed %27
124-
bb.2:
124+
bb.2 (call-frame-size 72):
125125
%35:gpr = COPY killed %63
126126
%33:gpr = COPY killed %62
127127
%31:gpr = COPY killed %61
@@ -134,7 +134,7 @@ body: |
134134
%62:gpr = COPY killed %32
135135
%63:gpr = COPY killed %34
136136
Bcc %bb.2, 1, killed $cpsr
137-
bb.3:
137+
bb.3 (call-frame-size 72):
138138
successors:
139139
%28:gpr = ADDri %stack.1.jb1, 0, 14, $noreg, $noreg
140140
$r0 = COPY killed %28
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
2+
# RUN: llc -march=arm -run-pass none -o - %s | FileCheck %s
3+
# This test ensures that the MIR parser parses machine functions correctly.
4+
5+
---
6+
name: callframesize
7+
body: |
8+
; CHECK-LABEL: name: callframesize
9+
; CHECK: bb.0:
10+
; CHECK-NEXT: successors: %bb.1(0x80000000)
11+
; CHECK-NEXT: {{ $}}
12+
; CHECK-NEXT: ADJCALLSTACKDOWN 100, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
13+
; CHECK-NEXT: {{ $}}
14+
; CHECK-NEXT: bb.1 (call-frame-size 100):
15+
; CHECK-NEXT: successors: %bb.2(0x80000000)
16+
; CHECK-NEXT: {{ $}}
17+
; CHECK-NEXT: ADJCALLSTACKUP 100, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
18+
; CHECK-NEXT: {{ $}}
19+
; CHECK-NEXT: bb.2:
20+
bb.0:
21+
ADJCALLSTACKDOWN 100, 0, 14, $noreg, implicit-def $sp, implicit $sp
22+
bb.1 (call-frame-size 100):
23+
ADJCALLSTACKUP 100, 0, 14, $noreg, implicit-def $sp, implicit $sp
24+
bb.2:
25+
...

llvm/tools/llvm-reduce/ReducerWorkItem.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ static std::unique_ptr<MachineFunction> cloneMF(MachineFunction *SrcMF,
225225
DstMF->CreateMachineBasicBlock(SrcMBB.getBasicBlock());
226226
Src2DstMBB[&SrcMBB] = DstMBB;
227227

228+
DstMBB->setCallFrameSize(SrcMBB.getCallFrameSize());
229+
228230
if (SrcMBB.isIRBlockAddressTaken())
229231
DstMBB->setAddressTakenIRBlock(SrcMBB.getAddressTakenIRBlock());
230232
if (SrcMBB.isMachineBlockAddressTaken())

0 commit comments

Comments
 (0)