Skip to content

Commit da42b28

Browse files
committed
[CodeGen] Support allocating of arguments by decreasing offsets
Previously, `CCState::AllocateStack` always allocated stack space by increasing offsets. For targets with stack growing up (away from zero) it is more convenient to allocate arguments by decreasing offsets, so that the first argument is at the top of the stack. This is important when calling a function with variable number of arguments: the callee does not know the size of the stack, but must be able to access "fixed" arguments. For that to work, the "fixed" arguments should have fixed offsets relative to the stack top, i.e. the variadic arguments area should be at the stack bottom (at lowest addresses). The in-tree target with stack growing up is AMDGPU, but it allocates arguments by increasing addresses. It does not support variadic arguments. A drive-by change is to promote stack size/offset to 64-bit integer. This is what MachineFrameInfo expects. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D149575
1 parent 01a7967 commit da42b28

File tree

7 files changed

+91
-30
lines changed

7 files changed

+91
-30
lines changed

llvm/include/llvm/CodeGen/CallingConvLower.h

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,14 @@ class CCValAssign {
9191
return getReg(ValNo, ValVT, RegNo, LocVT, HTP, /*IsCustom=*/true);
9292
}
9393

94-
static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset,
94+
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset,
9595
MVT LocVT, LocInfo HTP, bool IsCustom = false) {
9696
CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom);
97-
Ret.Data = int64_t(Offset);
97+
Ret.Data = Offset;
9898
return Ret;
9999
}
100100

101-
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, unsigned Offset,
101+
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset,
102102
MVT LocVT, LocInfo HTP) {
103103
return getMem(ValNo, ValVT, Offset, LocVT, HTP, /*IsCustom=*/true);
104104
}
@@ -112,7 +112,7 @@ class CCValAssign {
112112

113113
void convertToReg(unsigned RegNo) { Data = Register(RegNo); }
114114

115-
void convertToMem(unsigned Offset) { Data = int64_t(Offset); }
115+
void convertToMem(int64_t Offset) { Data = Offset; }
116116

117117
unsigned getValNo() const { return ValNo; }
118118
MVT getValVT() const { return ValVT; }
@@ -124,7 +124,7 @@ class CCValAssign {
124124
bool needsCustom() const { return isCustom; }
125125

126126
Register getLocReg() const { return std::get<Register>(Data); }
127-
unsigned getLocMemOffset() const { return std::get<int64_t>(Data); }
127+
int64_t getLocMemOffset() const { return std::get<int64_t>(Data); }
128128
unsigned getExtraInfo() const { return std::get<unsigned>(Data); }
129129

130130
MVT getLocVT() const { return LocVT; }
@@ -174,8 +174,10 @@ class CCState {
174174
const TargetRegisterInfo &TRI;
175175
SmallVectorImpl<CCValAssign> &Locs;
176176
LLVMContext &Context;
177+
// True if arguments should be allocated at negative offsets.
178+
bool NegativeOffsets;
177179

178-
unsigned StackSize;
180+
uint64_t StackSize;
179181
Align MaxStackArgAlign;
180182
SmallVector<uint32_t, 16> UsedRegs;
181183
SmallVector<CCValAssign, 4> PendingLocs;
@@ -224,8 +226,9 @@ class CCState {
224226
unsigned InRegsParamsProcessed;
225227

226228
public:
227-
CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
228-
SmallVectorImpl<CCValAssign> &locs, LLVMContext &C);
229+
CCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,
230+
SmallVectorImpl<CCValAssign> &Locs, LLVMContext &Context,
231+
bool NegativeOffsets = false);
229232

230233
void addLoc(const CCValAssign &V) {
231234
Locs.push_back(V);
@@ -237,12 +240,12 @@ class CCState {
237240
bool isVarArg() const { return IsVarArg; }
238241

239242
/// Returns the size of the currently allocated portion of the stack.
240-
unsigned getStackSize() const { return StackSize; }
243+
uint64_t getStackSize() const { return StackSize; }
241244

242245
/// getAlignedCallFrameSize - Return the size of the call frame needed to
243246
/// be able to store all arguments and such that the alignment requirement
244247
/// of each of the arguments is satisfied.
245-
unsigned getAlignedCallFrameSize() const {
248+
uint64_t getAlignedCallFrameSize() const {
246249
return alignTo(StackSize, MaxStackArgAlign);
247250
}
248251

@@ -396,21 +399,26 @@ class CCState {
396399

397400
/// AllocateStack - Allocate a chunk of stack space with the specified size
398401
/// and alignment.
399-
unsigned AllocateStack(unsigned Size, Align Alignment) {
400-
StackSize = alignTo(StackSize, Alignment);
401-
unsigned Result = StackSize;
402-
StackSize += Size;
402+
int64_t AllocateStack(unsigned Size, Align Alignment) {
403+
int64_t Offset;
404+
if (NegativeOffsets) {
405+
StackSize = alignTo(StackSize + Size, Alignment);
406+
Offset = -StackSize;
407+
} else {
408+
Offset = alignTo(StackSize, Alignment);
409+
StackSize = Offset + Size;
410+
}
403411
MaxStackArgAlign = std::max(Alignment, MaxStackArgAlign);
404412
ensureMaxAlignment(Alignment);
405-
return Result;
413+
return Offset;
406414
}
407415

408416
void ensureMaxAlignment(Align Alignment);
409417

410418
/// Version of AllocateStack with list of extra registers to be shadowed.
411419
/// Note that, unlike AllocateReg, this shadows ALL of the shadow registers.
412-
unsigned AllocateStack(unsigned Size, Align Alignment,
413-
ArrayRef<MCPhysReg> ShadowRegs) {
420+
int64_t AllocateStack(unsigned Size, Align Alignment,
421+
ArrayRef<MCPhysReg> ShadowRegs) {
414422
for (MCPhysReg Reg : ShadowRegs)
415423
MarkAllocated(Reg);
416424
return AllocateStack(Size, Alignment);

llvm/lib/CodeGen/CallingConvLower.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525

2626
using namespace llvm;
2727

28-
CCState::CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &mf,
29-
SmallVectorImpl<CCValAssign> &locs, LLVMContext &C)
30-
: CallingConv(CC), IsVarArg(isVarArg), MF(mf),
31-
TRI(*MF.getSubtarget().getRegisterInfo()), Locs(locs), Context(C) {
28+
CCState::CCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,
29+
SmallVectorImpl<CCValAssign> &Locs, LLVMContext &Context,
30+
bool NegativeOffsets)
31+
: CallingConv(CC), IsVarArg(IsVarArg), MF(MF),
32+
TRI(*MF.getSubtarget().getRegisterInfo()), Locs(Locs), Context(Context),
33+
NegativeOffsets(NegativeOffsets) {
34+
3235
// No stack is used.
3336
StackSize = 0;
3437

@@ -51,7 +54,7 @@ void CCState::HandleByVal(unsigned ValNo, MVT ValVT, MVT LocVT,
5154
ensureMaxAlignment(Alignment);
5255
MF.getSubtarget().getTargetLowering()->HandleByVal(this, Size, Alignment);
5356
Size = unsigned(alignTo(Size, MinAlign));
54-
unsigned Offset = AllocateStack(Size, Alignment);
57+
uint64_t Offset = AllocateStack(Size, Alignment);
5558
addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
5659
}
5760

@@ -197,7 +200,7 @@ static bool isValueTypeInRegForCC(CallingConv::ID CC, MVT VT) {
197200

198201
void CCState::getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs,
199202
MVT VT, CCAssignFn Fn) {
200-
unsigned SavedStackSize = StackSize;
203+
uint64_t SavedStackSize = StackSize;
201204
Align SavedMaxStackArgAlign = MaxStackArgAlign;
202205
unsigned NumLocs = Locs.size();
203206

llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7224,8 +7224,8 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
72247224
// On AIX a minimum of 8 words is saved to the parameter save area.
72257225
const unsigned MinParameterSaveArea = 8 * PtrByteSize;
72267226
// Area that is at least reserved in the caller of this function.
7227-
unsigned CallerReservedArea =
7228-
std::max(CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
7227+
unsigned CallerReservedArea = std::max<unsigned>(
7228+
CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
72297229

72307230
// Set the size that is at least reserved in caller of this function. Tail
72317231
// call optimized function's reserved stack space needs to be aligned so
@@ -7317,8 +7317,8 @@ SDValue PPCTargetLowering::LowerCall_AIX(
73177317
// conservatively assume that it is needed. As such, make sure we have at
73187318
// least enough stack space for the caller to store the 8 GPRs.
73197319
const unsigned MinParameterSaveAreaSize = 8 * PtrByteSize;
7320-
const unsigned NumBytes =
7321-
std::max(LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
7320+
const unsigned NumBytes = std::max<unsigned>(
7321+
LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
73227322

73237323
// Adjust the stack pointer for the new arguments...
73247324
// These operations are automatically eliminated by the prolog/epilog pass.

llvm/lib/Target/Sparc/SparcISelLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
12041204
// Called functions expect 6 argument words to exist in the stack frame, used
12051205
// or not.
12061206
unsigned StackReserved = 6 * 8u;
1207-
unsigned ArgsSize = std::max(StackReserved, CCInfo.getStackSize());
1207+
unsigned ArgsSize = std::max<unsigned>(StackReserved, CCInfo.getStackSize());
12081208

12091209
// Keep stack frames 16-byte aligned.
12101210
ArgsSize = alignTo(ArgsSize, 16);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===- CCStateTest.cpp ----------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/CodeGen/CallingConvLower.h"
10+
#include "llvm/CodeGen/MachineFunction.h"
11+
#include "llvm/CodeGen/MachineModuleInfo.h"
12+
#include "llvm/CodeGen/TargetFrameLowering.h"
13+
#include "llvm/CodeGen/TargetInstrInfo.h"
14+
#include "llvm/CodeGen/TargetLowering.h"
15+
#include "llvm/CodeGen/TargetRegisterInfo.h"
16+
#include "llvm/CodeGen/TargetSubtargetInfo.h"
17+
#include "llvm/IR/Module.h"
18+
#include "llvm/MC/TargetRegistry.h"
19+
#include "llvm/Target/TargetMachine.h"
20+
#include "gtest/gtest.h"
21+
22+
using namespace llvm;
23+
24+
namespace {
25+
26+
#include "MFCommon.inc"
27+
28+
TEST(CCStateTest, NegativeOffsets) {
29+
LLVMContext Ctx;
30+
Module Mod("Module", Ctx);
31+
auto MF = createMachineFunction(Ctx, Mod);
32+
33+
SmallVector<CCValAssign, 8> Locs;
34+
CCState Info(CallingConv::C, /*IsVarArg=*/false, *MF, Locs, Ctx,
35+
/*NegativeOffsets=*/true);
36+
37+
ASSERT_EQ(Info.AllocateStack(1, Align(1)), -1);
38+
ASSERT_EQ(Info.AllocateStack(1, Align(2)), -2);
39+
ASSERT_EQ(Info.AllocateStack(1, Align(2)), -4);
40+
ASSERT_EQ(Info.AllocateStack(1, Align(1)), -5);
41+
ASSERT_EQ(Info.AllocateStack(2, Align(2)), -8);
42+
ASSERT_EQ(Info.AllocateStack(2, Align(2)), -10);
43+
ASSERT_EQ(Info.AllocateStack(2, Align(1)), -12);
44+
ASSERT_EQ(Info.AllocateStack(1, Align(1)), -13);
45+
ASSERT_EQ(Info.getStackSize(), 13u);
46+
ASSERT_EQ(Info.getAlignedCallFrameSize(), 14u);
47+
}
48+
49+
} // namespace

llvm/unittests/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_llvm_unittest(CodeGenTests
2121
AllocationOrderTest.cpp
2222
AMDGPUMetadataTest.cpp
2323
AsmPrinterDwarfTest.cpp
24+
CCStateTest.cpp
2425
DIEHashTest.cpp
2526
DIETest.cpp
2627
DwarfStringPoolEntryRefTest.cpp

llvm/utils/TableGen/CallingConvEmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
251251
int Size = Action->getValueAsInt("Size");
252252
int Align = Action->getValueAsInt("Align");
253253

254-
O << IndentStr << "unsigned Offset" << ++Counter
254+
O << IndentStr << "int64_t Offset" << ++Counter
255255
<< " = State.AllocateStack(";
256256
if (Size)
257257
O << Size << ", ";
@@ -287,7 +287,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
287287
O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
288288
O << "\n" << IndentStr << "};\n";
289289

290-
O << IndentStr << "unsigned Offset" << ++Counter
290+
O << IndentStr << "int64_t Offset" << ++Counter
291291
<< " = State.AllocateStack(" << Size << ", Align(" << Align << "), "
292292
<< "ShadowRegList" << ShadowRegListNumber << ");\n";
293293
O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"

0 commit comments

Comments
 (0)