Skip to content

Commit c063b0b

Browse files
Petar AvramovicPetar Avramovic
Petar Avramovic
authored and
Petar Avramovic
committedSep 23, 2019
[MIPS GlobalISel] VarArg argument lowering, select G_VASTART and vacopy
CC_Mips doesn't accept vararg functions for O32, so we have to explicitly use CC_Mips_FixedArg. For lowerCall we now properly figure out whether callee function is vararg or not, this has no effect for O32 since we always use CC_Mips_FixedArg. For lower formal arguments we need to copy arguments in register to stack and save pointer to start for argument list into MipsMachineFunction object so that G_VASTART could use it during instruction select. For vacopy we need to copy content from one vreg to another, load and store are used for that purpose. Differential Revision: https://reviews.llvm.org/D67756 llvm-svn: 372555
1 parent 0e490ae commit c063b0b

File tree

10 files changed

+588
-6
lines changed

10 files changed

+588
-6
lines changed
 

‎llvm/lib/Target/Mips/MipsCallLowering.cpp

+40-5
Original file line numberDiff line numberDiff line change
@@ -454,10 +454,6 @@ bool MipsCallLowering::lowerFormalArguments(
454454
if (F.arg_empty())
455455
return true;
456456

457-
if (F.isVarArg()) {
458-
return false;
459-
}
460-
461457
for (auto &Arg : F.args()) {
462458
if (!isSupportedType(Arg.getType()))
463459
return false;
@@ -496,6 +492,40 @@ bool MipsCallLowering::lowerFormalArguments(
496492
if (!Handler.handle(ArgLocs, ArgInfos))
497493
return false;
498494

495+
if (F.isVarArg()) {
496+
ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs();
497+
unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
498+
499+
int VaArgOffset;
500+
unsigned RegSize = 4;
501+
if (ArgRegs.size() == Idx)
502+
VaArgOffset = alignTo(CCInfo.getNextStackOffset(), RegSize);
503+
else {
504+
VaArgOffset =
505+
(int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) -
506+
(int)(RegSize * (ArgRegs.size() - Idx));
507+
}
508+
509+
MachineFrameInfo &MFI = MF.getFrameInfo();
510+
int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
511+
MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);
512+
513+
for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {
514+
MIRBuilder.getMBB().addLiveIn(ArgRegs[I]);
515+
516+
MachineInstrBuilder Copy =
517+
MIRBuilder.buildCopy(LLT::scalar(RegSize * 8), Register(ArgRegs[I]));
518+
FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
519+
MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);
520+
MachineInstrBuilder FrameIndex =
521+
MIRBuilder.buildFrameIndex(LLT::pointer(MPO.getAddrSpace(), 32), FI);
522+
MachineMemOperand *MMO =
523+
MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, RegSize,
524+
/* Alignment */ RegSize);
525+
MIRBuilder.buildStore(Copy, FrameIndex, *MMO);
526+
}
527+
}
528+
499529
return true;
500530
}
501531

@@ -566,7 +596,12 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
566596
subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs);
567597

568598
SmallVector<CCValAssign, 8> ArgLocs;
569-
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
599+
bool IsCalleeVarArg = false;
600+
if (Info.Callee.isGlobal()) {
601+
const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());
602+
IsCalleeVarArg = CF->isVarArg();
603+
}
604+
MipsCCState CCInfo(F.getCallingConv(), IsCalleeVarArg, MF, ArgLocs,
570605
F.getContext());
571606

572607
CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv), 1);

‎llvm/lib/Target/Mips/MipsISelLowering.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2869,7 +2869,7 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
28692869
#include "MipsGenCallingConv.inc"
28702870

28712871
CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{
2872-
return CC_Mips;
2872+
return CC_Mips_FixedArg;
28732873
}
28742874

28752875
CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{

‎llvm/lib/Target/Mips/MipsInstructionSelector.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,29 @@ bool MipsInstructionSelector::select(MachineInstr &I) {
773773
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
774774
break;
775775
}
776+
case G_VASTART: {
777+
MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
778+
int FI = FuncInfo->getVarArgsFrameIndex();
779+
780+
Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
781+
MachineInstr *LEA_ADDiu =
782+
BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
783+
.addDef(LeaReg)
784+
.addFrameIndex(FI)
785+
.addImm(0);
786+
if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
787+
return false;
788+
789+
MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
790+
.addUse(LeaReg)
791+
.addUse(I.getOperand(0).getReg())
792+
.addImm(0);
793+
if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
794+
return false;
795+
796+
I.eraseFromParent();
797+
return true;
798+
}
776799
default:
777800
return false;
778801
}

‎llvm/lib/Target/Mips/MipsLegalizerInfo.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
122122
getActionDefinitionsBuilder(G_DYN_STACKALLOC)
123123
.lowerFor({{p0, s32}});
124124

125+
getActionDefinitionsBuilder(G_VASTART)
126+
.legalFor({p0});
127+
125128
// FP instructions
126129
getActionDefinitionsBuilder(G_FCONSTANT)
127130
.legalFor({s32, s64});
@@ -252,6 +255,18 @@ bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
252255
MI.eraseFromParent();
253256
return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
254257
}
258+
case Intrinsic::vacopy: {
259+
Register Tmp = MRI.createGenericVirtualRegister(LLT::pointer(0, 32));
260+
MachinePointerInfo MPO;
261+
MIRBuilder.buildLoad(Tmp, MI.getOperand(2),
262+
*MI.getMF()->getMachineMemOperand(
263+
MPO, MachineMemOperand::MOLoad, 4, 4));
264+
MIRBuilder.buildStore(Tmp, MI.getOperand(1),
265+
*MI.getMF()->getMachineMemOperand(
266+
MPO, MachineMemOperand::MOStore, 4, 4));
267+
MI.eraseFromParent();
268+
return true;
269+
}
255270
default:
256271
break;
257272
}

‎llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
403403
case G_SREM:
404404
case G_UREM:
405405
case G_BRINDIRECT:
406+
case G_VASTART:
406407
OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
407408
break;
408409
case G_LOAD: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
3+
--- |
4+
5+
@.str = private unnamed_addr constant [11 x i8] c"string %s\0A\00", align 1
6+
declare void @llvm.va_start(i8*) #0
7+
declare void @llvm.va_copy(i8*, i8*) #0
8+
declare i32 @printf(i8*, ...)
9+
10+
define void @testVaCopyArg(i8* %fmt, ...) {
11+
entry:
12+
%fmt.addr = alloca i8*, align 4
13+
%ap = alloca i8*, align 4
14+
%aq = alloca i8*, align 4
15+
%s = alloca i8*, align 4
16+
store i8* %fmt, i8** %fmt.addr, align 4
17+
%ap1 = bitcast i8** %ap to i8*
18+
call void @llvm.va_start(i8* %ap1)
19+
%0 = bitcast i8** %aq to i8*
20+
%1 = bitcast i8** %ap to i8*
21+
call void @llvm.va_copy(i8* %0, i8* %1)
22+
%argp.cur = load i8*, i8** %aq, align 4
23+
%argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
24+
store i8* %argp.next, i8** %aq, align 4
25+
%2 = bitcast i8* %argp.cur to i8**
26+
%3 = load i8*, i8** %2, align 4
27+
store i8* %3, i8** %s, align 4
28+
%4 = load i8*, i8** %s, align 4
29+
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i8* %4)
30+
ret void
31+
}
32+
33+
...
34+
---
35+
name: testVaCopyArg
36+
alignment: 4
37+
legalized: true
38+
regBankSelected: true
39+
tracksRegLiveness: true
40+
liveins:
41+
- { reg: '$a0' }
42+
fixedStack:
43+
- { id: 0, offset: 12, size: 4, alignment: 4, isImmutable: true }
44+
- { id: 1, offset: 8, size: 4, alignment: 8, isImmutable: true }
45+
- { id: 2, offset: 4, size: 4, alignment: 4, isImmutable: true }
46+
- { id: 3, offset: 4, size: 4, alignment: 4, isImmutable: true }
47+
stack:
48+
- { id: 0, name: fmt.addr, size: 4, alignment: 4 }
49+
- { id: 1, name: ap, size: 4, alignment: 4 }
50+
- { id: 2, name: aq, size: 4, alignment: 4 }
51+
- { id: 3, name: s, size: 4, alignment: 4 }
52+
machineFunctionInfo: {}
53+
body: |
54+
bb.1.entry:
55+
liveins: $a0, $a1, $a2, $a3
56+
57+
; MIPS32-LABEL: name: testVaCopyArg
58+
; MIPS32: liveins: $a0, $a1, $a2, $a3
59+
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
60+
; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
61+
; MIPS32: [[ADDiu:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.1, 0
62+
; MIPS32: SW [[COPY1]], [[ADDiu]], 0 :: (store 4 into %fixed-stack.1)
63+
; MIPS32: [[COPY2:%[0-9]+]]:gpr32 = COPY $a2
64+
; MIPS32: [[ADDiu1:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.2, 0
65+
; MIPS32: SW [[COPY2]], [[ADDiu1]], 0 :: (store 4 into %fixed-stack.2)
66+
; MIPS32: [[COPY3:%[0-9]+]]:gpr32 = COPY $a3
67+
; MIPS32: [[ADDiu2:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.3, 0
68+
; MIPS32: SW [[COPY3]], [[ADDiu2]], 0 :: (store 4 into %fixed-stack.3)
69+
; MIPS32: [[LUi:%[0-9]+]]:gpr32 = LUi target-flags(mips-abs-hi) @.str
70+
; MIPS32: [[ADDiu3:%[0-9]+]]:gpr32 = ADDiu [[LUi]], target-flags(mips-abs-lo) @.str
71+
; MIPS32: [[ADDiu4:%[0-9]+]]:gpr32 = ADDiu %stack.0.fmt.addr, 0
72+
; MIPS32: [[ADDiu5:%[0-9]+]]:gpr32 = ADDiu %stack.1.ap, 0
73+
; MIPS32: [[ADDiu6:%[0-9]+]]:gpr32 = ADDiu %stack.2.aq, 0
74+
; MIPS32: [[ADDiu7:%[0-9]+]]:gpr32 = ADDiu %stack.3.s, 0
75+
; MIPS32: SW [[COPY]], [[ADDiu4]], 0 :: (store 4 into %ir.fmt.addr)
76+
; MIPS32: [[LEA_ADDiu:%[0-9]+]]:gpr32 = LEA_ADDiu %stack.0.fmt.addr, 0
77+
; MIPS32: SW [[LEA_ADDiu]], [[ADDiu5]], 0
78+
; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDiu5]], 0 :: (load 4)
79+
; MIPS32: SW [[LW]], [[ADDiu6]], 0 :: (store 4)
80+
; MIPS32: [[LW1:%[0-9]+]]:gpr32 = LW [[ADDiu6]], 0 :: (load 4 from %ir.aq)
81+
; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 4
82+
; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[LW1]], [[ORi]]
83+
; MIPS32: SW [[ADDu]], [[ADDiu6]], 0 :: (store 4 into %ir.aq)
84+
; MIPS32: [[LW2:%[0-9]+]]:gpr32 = LW [[LW1]], 0 :: (load 4 from %ir.2)
85+
; MIPS32: SW [[LW2]], [[ADDiu7]], 0 :: (store 4 into %ir.s)
86+
; MIPS32: [[LW3:%[0-9]+]]:gpr32 = LW [[ADDiu7]], 0 :: (load 4 from %ir.s)
87+
; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
88+
; MIPS32: $a0 = COPY [[ADDiu3]]
89+
; MIPS32: $a1 = COPY [[LW3]]
90+
; MIPS32: JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
91+
; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
92+
; MIPS32: RetRA
93+
%0:gprb(p0) = COPY $a0
94+
%1:gprb(s32) = COPY $a1
95+
%2:gprb(p0) = G_FRAME_INDEX %fixed-stack.2
96+
G_STORE %1(s32), %2(p0) :: (store 4 into %fixed-stack.2)
97+
%3:gprb(s32) = COPY $a2
98+
%4:gprb(p0) = G_FRAME_INDEX %fixed-stack.1
99+
G_STORE %3(s32), %4(p0) :: (store 4 into %fixed-stack.1)
100+
%5:gprb(s32) = COPY $a3
101+
%6:gprb(p0) = G_FRAME_INDEX %fixed-stack.0
102+
G_STORE %5(s32), %6(p0) :: (store 4 into %fixed-stack.0)
103+
%18:gprb(p0) = G_GLOBAL_VALUE @.str
104+
%17:gprb(p0) = COPY %18(p0)
105+
%7:gprb(p0) = G_FRAME_INDEX %stack.0.fmt.addr
106+
%8:gpr32(p0) = G_FRAME_INDEX %stack.1.ap
107+
%9:gpr32(p0) = G_FRAME_INDEX %stack.2.aq
108+
%10:gprb(p0) = G_FRAME_INDEX %stack.3.s
109+
G_STORE %0(p0), %7(p0) :: (store 4 into %ir.fmt.addr)
110+
G_VASTART %8(p0) :: (store 4 into %ir.ap1, align 1)
111+
%19:gpr32 = LW %8(p0), 0 :: (load 4)
112+
SW %19, %9(p0), 0 :: (store 4)
113+
%11:gprb(p0) = G_LOAD %9(p0) :: (load 4 from %ir.aq)
114+
%12:gprb(s32) = G_CONSTANT i32 4
115+
%13:gprb(p0) = G_GEP %11, %12(s32)
116+
G_STORE %13(p0), %9(p0) :: (store 4 into %ir.aq)
117+
%14:gprb(p0) = G_LOAD %11(p0) :: (load 4 from %ir.2)
118+
G_STORE %14(p0), %10(p0) :: (store 4 into %ir.s)
119+
%15:gprb(p0) = G_LOAD %10(p0) :: (load 4 from %ir.s)
120+
ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
121+
$a0 = COPY %17(p0)
122+
$a1 = COPY %15(p0)
123+
JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
124+
ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
125+
RetRA
126+
127+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
3+
4+
@.str = private unnamed_addr constant [11 x i8] c"string %s\0A\00", align 1
5+
declare void @llvm.va_start(i8*)
6+
declare void @llvm.va_copy(i8*, i8*)
7+
declare i32 @printf(i8*, ...)
8+
9+
define void @testVaCopyArg(i8* %fmt, ...) {
10+
; MIPS32-LABEL: name: testVaCopyArg
11+
; MIPS32: bb.1.entry:
12+
; MIPS32: liveins: $a0, $a1, $a2, $a3
13+
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
14+
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
15+
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.2
16+
; MIPS32: G_STORE [[COPY1]](s32), [[FRAME_INDEX]](p0) :: (store 4 into %fixed-stack.2)
17+
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
18+
; MIPS32: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
19+
; MIPS32: G_STORE [[COPY2]](s32), [[FRAME_INDEX1]](p0) :: (store 4 into %fixed-stack.1)
20+
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
21+
; MIPS32: [[FRAME_INDEX2:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
22+
; MIPS32: G_STORE [[COPY3]](s32), [[FRAME_INDEX2]](p0) :: (store 4 into %fixed-stack.0)
23+
; MIPS32: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @.str
24+
; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY [[GV]](p0)
25+
; MIPS32: [[FRAME_INDEX3:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.fmt.addr
26+
; MIPS32: [[FRAME_INDEX4:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1.ap
27+
; MIPS32: [[FRAME_INDEX5:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.2.aq
28+
; MIPS32: [[FRAME_INDEX6:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.3.s
29+
; MIPS32: G_STORE [[COPY]](p0), [[FRAME_INDEX3]](p0) :: (store 4 into %ir.fmt.addr)
30+
; MIPS32: G_VASTART [[FRAME_INDEX4]](p0) :: (store 4 into %ir.ap1, align 1)
31+
; MIPS32: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.va_copy), [[FRAME_INDEX5]](p0), [[FRAME_INDEX4]](p0)
32+
; MIPS32: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX5]](p0) :: (load 4 from %ir.aq)
33+
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
34+
; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[LOAD]], [[C]](s32)
35+
; MIPS32: G_STORE [[GEP]](p0), [[FRAME_INDEX5]](p0) :: (store 4 into %ir.aq)
36+
; MIPS32: [[LOAD1:%[0-9]+]]:_(p0) = G_LOAD [[LOAD]](p0) :: (load 4 from %ir.2)
37+
; MIPS32: G_STORE [[LOAD1]](p0), [[FRAME_INDEX6]](p0) :: (store 4 into %ir.s)
38+
; MIPS32: [[LOAD2:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX6]](p0) :: (load 4 from %ir.s)
39+
; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
40+
; MIPS32: $a0 = COPY [[COPY4]](p0)
41+
; MIPS32: $a1 = COPY [[LOAD2]](p0)
42+
; MIPS32: JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
43+
; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0
44+
; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
45+
; MIPS32: RetRA
46+
entry:
47+
%fmt.addr = alloca i8*, align 4
48+
%ap = alloca i8*, align 4
49+
%aq = alloca i8*, align 4
50+
%s = alloca i8*, align 4
51+
store i8* %fmt, i8** %fmt.addr, align 4
52+
%ap1 = bitcast i8** %ap to i8*
53+
call void @llvm.va_start(i8* %ap1)
54+
%0 = bitcast i8** %aq to i8*
55+
%1 = bitcast i8** %ap to i8*
56+
call void @llvm.va_copy(i8* %0, i8* %1)
57+
%argp.cur = load i8*, i8** %aq, align 4
58+
%argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
59+
store i8* %argp.next, i8** %aq, align 4
60+
%2 = bitcast i8* %argp.cur to i8**
61+
%3 = load i8*, i8** %2, align 4
62+
store i8* %3, i8** %s, align 4
63+
%4 = load i8*, i8** %s, align 4
64+
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i8* %4)
65+
ret void
66+
}

0 commit comments

Comments
 (0)
Please sign in to comment.