[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
This commit is contained in:
Petar Avramovic 2019-09-23 08:11:41 +00:00
parent 0e490ae0a9
commit c063b0b0d3
10 changed files with 588 additions and 6 deletions

View File

@ -454,10 +454,6 @@ bool MipsCallLowering::lowerFormalArguments(
if (F.arg_empty())
return true;
if (F.isVarArg()) {
return false;
}
for (auto &Arg : F.args()) {
if (!isSupportedType(Arg.getType()))
return false;
@ -496,6 +492,40 @@ bool MipsCallLowering::lowerFormalArguments(
if (!Handler.handle(ArgLocs, ArgInfos))
return false;
if (F.isVarArg()) {
ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs();
unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
int VaArgOffset;
unsigned RegSize = 4;
if (ArgRegs.size() == Idx)
VaArgOffset = alignTo(CCInfo.getNextStackOffset(), RegSize);
else {
VaArgOffset =
(int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) -
(int)(RegSize * (ArgRegs.size() - Idx));
}
MachineFrameInfo &MFI = MF.getFrameInfo();
int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);
for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {
MIRBuilder.getMBB().addLiveIn(ArgRegs[I]);
MachineInstrBuilder Copy =
MIRBuilder.buildCopy(LLT::scalar(RegSize * 8), Register(ArgRegs[I]));
FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);
MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);
MachineInstrBuilder FrameIndex =
MIRBuilder.buildFrameIndex(LLT::pointer(MPO.getAddrSpace(), 32), FI);
MachineMemOperand *MMO =
MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, RegSize,
/* Alignment */ RegSize);
MIRBuilder.buildStore(Copy, FrameIndex, *MMO);
}
}
return true;
}
@ -566,7 +596,12 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs);
SmallVector<CCValAssign, 8> ArgLocs;
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
bool IsCalleeVarArg = false;
if (Info.Callee.isGlobal()) {
const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());
IsCalleeVarArg = CF->isVarArg();
}
MipsCCState CCInfo(F.getCallingConv(), IsCalleeVarArg, MF, ArgLocs,
F.getContext());
CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv), 1);

View File

@ -2869,7 +2869,7 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
#include "MipsGenCallingConv.inc"
CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{
return CC_Mips;
return CC_Mips_FixedArg;
}
CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{

View File

@ -773,6 +773,29 @@ bool MipsInstructionSelector::select(MachineInstr &I) {
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
break;
}
case G_VASTART: {
MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
int FI = FuncInfo->getVarArgsFrameIndex();
Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
MachineInstr *LEA_ADDiu =
BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
.addDef(LeaReg)
.addFrameIndex(FI)
.addImm(0);
if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
return false;
MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
.addUse(LeaReg)
.addUse(I.getOperand(0).getReg())
.addImm(0);
if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
return false;
I.eraseFromParent();
return true;
}
default:
return false;
}

View File

@ -122,6 +122,9 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
getActionDefinitionsBuilder(G_DYN_STACKALLOC)
.lowerFor({{p0, s32}});
getActionDefinitionsBuilder(G_VASTART)
.legalFor({p0});
// FP instructions
getActionDefinitionsBuilder(G_FCONSTANT)
.legalFor({s32, s64});
@ -252,6 +255,18 @@ bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
}
case Intrinsic::vacopy: {
Register Tmp = MRI.createGenericVirtualRegister(LLT::pointer(0, 32));
MachinePointerInfo MPO;
MIRBuilder.buildLoad(Tmp, MI.getOperand(2),
*MI.getMF()->getMachineMemOperand(
MPO, MachineMemOperand::MOLoad, 4, 4));
MIRBuilder.buildStore(Tmp, MI.getOperand(1),
*MI.getMF()->getMachineMemOperand(
MPO, MachineMemOperand::MOStore, 4, 4));
MI.eraseFromParent();
return true;
}
default:
break;
}

View File

@ -403,6 +403,7 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
case G_SREM:
case G_UREM:
case G_BRINDIRECT:
case G_VASTART:
OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
break;
case G_LOAD: {

View File

@ -0,0 +1,127 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
--- |
@.str = private unnamed_addr constant [11 x i8] c"string %s\0A\00", align 1
declare void @llvm.va_start(i8*) #0
declare void @llvm.va_copy(i8*, i8*) #0
declare i32 @printf(i8*, ...)
define void @testVaCopyArg(i8* %fmt, ...) {
entry:
%fmt.addr = alloca i8*, align 4
%ap = alloca i8*, align 4
%aq = alloca i8*, align 4
%s = alloca i8*, align 4
store i8* %fmt, i8** %fmt.addr, align 4
%ap1 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap1)
%0 = bitcast i8** %aq to i8*
%1 = bitcast i8** %ap to i8*
call void @llvm.va_copy(i8* %0, i8* %1)
%argp.cur = load i8*, i8** %aq, align 4
%argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
store i8* %argp.next, i8** %aq, align 4
%2 = bitcast i8* %argp.cur to i8**
%3 = load i8*, i8** %2, align 4
store i8* %3, i8** %s, align 4
%4 = load i8*, i8** %s, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i8* %4)
ret void
}
...
---
name: testVaCopyArg
alignment: 4
legalized: true
regBankSelected: true
tracksRegLiveness: true
liveins:
- { reg: '$a0' }
fixedStack:
- { id: 0, offset: 12, size: 4, alignment: 4, isImmutable: true }
- { id: 1, offset: 8, size: 4, alignment: 8, isImmutable: true }
- { id: 2, offset: 4, size: 4, alignment: 4, isImmutable: true }
- { id: 3, offset: 4, size: 4, alignment: 4, isImmutable: true }
stack:
- { id: 0, name: fmt.addr, size: 4, alignment: 4 }
- { id: 1, name: ap, size: 4, alignment: 4 }
- { id: 2, name: aq, size: 4, alignment: 4 }
- { id: 3, name: s, size: 4, alignment: 4 }
machineFunctionInfo: {}
body: |
bb.1.entry:
liveins: $a0, $a1, $a2, $a3
; MIPS32-LABEL: name: testVaCopyArg
; MIPS32: liveins: $a0, $a1, $a2, $a3
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
; MIPS32: [[ADDiu:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.1, 0
; MIPS32: SW [[COPY1]], [[ADDiu]], 0 :: (store 4 into %fixed-stack.1)
; MIPS32: [[COPY2:%[0-9]+]]:gpr32 = COPY $a2
; MIPS32: [[ADDiu1:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.2, 0
; MIPS32: SW [[COPY2]], [[ADDiu1]], 0 :: (store 4 into %fixed-stack.2)
; MIPS32: [[COPY3:%[0-9]+]]:gpr32 = COPY $a3
; MIPS32: [[ADDiu2:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.3, 0
; MIPS32: SW [[COPY3]], [[ADDiu2]], 0 :: (store 4 into %fixed-stack.3)
; MIPS32: [[LUi:%[0-9]+]]:gpr32 = LUi target-flags(mips-abs-hi) @.str
; MIPS32: [[ADDiu3:%[0-9]+]]:gpr32 = ADDiu [[LUi]], target-flags(mips-abs-lo) @.str
; MIPS32: [[ADDiu4:%[0-9]+]]:gpr32 = ADDiu %stack.0.fmt.addr, 0
; MIPS32: [[ADDiu5:%[0-9]+]]:gpr32 = ADDiu %stack.1.ap, 0
; MIPS32: [[ADDiu6:%[0-9]+]]:gpr32 = ADDiu %stack.2.aq, 0
; MIPS32: [[ADDiu7:%[0-9]+]]:gpr32 = ADDiu %stack.3.s, 0
; MIPS32: SW [[COPY]], [[ADDiu4]], 0 :: (store 4 into %ir.fmt.addr)
; MIPS32: [[LEA_ADDiu:%[0-9]+]]:gpr32 = LEA_ADDiu %stack.0.fmt.addr, 0
; MIPS32: SW [[LEA_ADDiu]], [[ADDiu5]], 0
; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDiu5]], 0 :: (load 4)
; MIPS32: SW [[LW]], [[ADDiu6]], 0 :: (store 4)
; MIPS32: [[LW1:%[0-9]+]]:gpr32 = LW [[ADDiu6]], 0 :: (load 4 from %ir.aq)
; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 4
; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[LW1]], [[ORi]]
; MIPS32: SW [[ADDu]], [[ADDiu6]], 0 :: (store 4 into %ir.aq)
; MIPS32: [[LW2:%[0-9]+]]:gpr32 = LW [[LW1]], 0 :: (load 4 from %ir.2)
; MIPS32: SW [[LW2]], [[ADDiu7]], 0 :: (store 4 into %ir.s)
; MIPS32: [[LW3:%[0-9]+]]:gpr32 = LW [[ADDiu7]], 0 :: (load 4 from %ir.s)
; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
; MIPS32: $a0 = COPY [[ADDiu3]]
; MIPS32: $a1 = COPY [[LW3]]
; MIPS32: JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
; MIPS32: RetRA
%0:gprb(p0) = COPY $a0
%1:gprb(s32) = COPY $a1
%2:gprb(p0) = G_FRAME_INDEX %fixed-stack.2
G_STORE %1(s32), %2(p0) :: (store 4 into %fixed-stack.2)
%3:gprb(s32) = COPY $a2
%4:gprb(p0) = G_FRAME_INDEX %fixed-stack.1
G_STORE %3(s32), %4(p0) :: (store 4 into %fixed-stack.1)
%5:gprb(s32) = COPY $a3
%6:gprb(p0) = G_FRAME_INDEX %fixed-stack.0
G_STORE %5(s32), %6(p0) :: (store 4 into %fixed-stack.0)
%18:gprb(p0) = G_GLOBAL_VALUE @.str
%17:gprb(p0) = COPY %18(p0)
%7:gprb(p0) = G_FRAME_INDEX %stack.0.fmt.addr
%8:gpr32(p0) = G_FRAME_INDEX %stack.1.ap
%9:gpr32(p0) = G_FRAME_INDEX %stack.2.aq
%10:gprb(p0) = G_FRAME_INDEX %stack.3.s
G_STORE %0(p0), %7(p0) :: (store 4 into %ir.fmt.addr)
G_VASTART %8(p0) :: (store 4 into %ir.ap1, align 1)
%19:gpr32 = LW %8(p0), 0 :: (load 4)
SW %19, %9(p0), 0 :: (store 4)
%11:gprb(p0) = G_LOAD %9(p0) :: (load 4 from %ir.aq)
%12:gprb(s32) = G_CONSTANT i32 4
%13:gprb(p0) = G_GEP %11, %12(s32)
G_STORE %13(p0), %9(p0) :: (store 4 into %ir.aq)
%14:gprb(p0) = G_LOAD %11(p0) :: (load 4 from %ir.2)
G_STORE %14(p0), %10(p0) :: (store 4 into %ir.s)
%15:gprb(p0) = G_LOAD %10(p0) :: (load 4 from %ir.s)
ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
$a0 = COPY %17(p0)
$a1 = COPY %15(p0)
JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
RetRA
...

View File

@ -0,0 +1,66 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
@.str = private unnamed_addr constant [11 x i8] c"string %s\0A\00", align 1
declare void @llvm.va_start(i8*)
declare void @llvm.va_copy(i8*, i8*)
declare i32 @printf(i8*, ...)
define void @testVaCopyArg(i8* %fmt, ...) {
; MIPS32-LABEL: name: testVaCopyArg
; MIPS32: bb.1.entry:
; MIPS32: liveins: $a0, $a1, $a2, $a3
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.2
; MIPS32: G_STORE [[COPY1]](s32), [[FRAME_INDEX]](p0) :: (store 4 into %fixed-stack.2)
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
; MIPS32: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
; MIPS32: G_STORE [[COPY2]](s32), [[FRAME_INDEX1]](p0) :: (store 4 into %fixed-stack.1)
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
; MIPS32: [[FRAME_INDEX2:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
; MIPS32: G_STORE [[COPY3]](s32), [[FRAME_INDEX2]](p0) :: (store 4 into %fixed-stack.0)
; MIPS32: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @.str
; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY [[GV]](p0)
; MIPS32: [[FRAME_INDEX3:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.fmt.addr
; MIPS32: [[FRAME_INDEX4:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1.ap
; MIPS32: [[FRAME_INDEX5:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.2.aq
; MIPS32: [[FRAME_INDEX6:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.3.s
; MIPS32: G_STORE [[COPY]](p0), [[FRAME_INDEX3]](p0) :: (store 4 into %ir.fmt.addr)
; MIPS32: G_VASTART [[FRAME_INDEX4]](p0) :: (store 4 into %ir.ap1, align 1)
; MIPS32: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.va_copy), [[FRAME_INDEX5]](p0), [[FRAME_INDEX4]](p0)
; MIPS32: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX5]](p0) :: (load 4 from %ir.aq)
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[LOAD]], [[C]](s32)
; MIPS32: G_STORE [[GEP]](p0), [[FRAME_INDEX5]](p0) :: (store 4 into %ir.aq)
; MIPS32: [[LOAD1:%[0-9]+]]:_(p0) = G_LOAD [[LOAD]](p0) :: (load 4 from %ir.2)
; MIPS32: G_STORE [[LOAD1]](p0), [[FRAME_INDEX6]](p0) :: (store 4 into %ir.s)
; MIPS32: [[LOAD2:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX6]](p0) :: (load 4 from %ir.s)
; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
; MIPS32: $a0 = COPY [[COPY4]](p0)
; MIPS32: $a1 = COPY [[LOAD2]](p0)
; MIPS32: JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0
; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
; MIPS32: RetRA
entry:
%fmt.addr = alloca i8*, align 4
%ap = alloca i8*, align 4
%aq = alloca i8*, align 4
%s = alloca i8*, align 4
store i8* %fmt, i8** %fmt.addr, align 4
%ap1 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap1)
%0 = bitcast i8** %aq to i8*
%1 = bitcast i8** %ap to i8*
call void @llvm.va_copy(i8* %0, i8* %1)
%argp.cur = load i8*, i8** %aq, align 4
%argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
store i8* %argp.next, i8** %aq, align 4
%2 = bitcast i8* %argp.cur to i8**
%3 = load i8*, i8** %2, align 4
store i8* %3, i8** %s, align 4
%4 = load i8*, i8** %s, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i8* %4)
ret void
}

View File

@ -0,0 +1,123 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
--- |
@.str = private unnamed_addr constant [11 x i8] c"string %s\0A\00", align 1
declare void @llvm.va_start(i8*) #0
declare void @llvm.va_copy(i8*, i8*) #0
declare i32 @printf(i8*, ...)
define void @testVaCopyArg(i8* %fmt, ...) {
entry:
%fmt.addr = alloca i8*, align 4
%ap = alloca i8*, align 4
%aq = alloca i8*, align 4
%s = alloca i8*, align 4
store i8* %fmt, i8** %fmt.addr, align 4
%ap1 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap1)
%0 = bitcast i8** %aq to i8*
%1 = bitcast i8** %ap to i8*
call void @llvm.va_copy(i8* %0, i8* %1)
%argp.cur = load i8*, i8** %aq, align 4
%argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
store i8* %argp.next, i8** %aq, align 4
%2 = bitcast i8* %argp.cur to i8**
%3 = load i8*, i8** %2, align 4
store i8* %3, i8** %s, align 4
%4 = load i8*, i8** %s, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i8* %4)
ret void
}
...
---
name: testVaCopyArg
alignment: 4
tracksRegLiveness: true
liveins:
- { reg: '$a0' }
fixedStack:
- { id: 0, offset: 12, size: 4, alignment: 4, isImmutable: true }
- { id: 1, offset: 8, size: 4, alignment: 8, isImmutable: true }
- { id: 2, offset: 4, size: 4, alignment: 4, isImmutable: true }
- { id: 3, offset: 4, size: 4, alignment: 4, isImmutable: true }
stack:
- { id: 0, name: fmt.addr, size: 4, alignment: 4 }
- { id: 1, name: ap, size: 4, alignment: 4 }
- { id: 2, name: aq, size: 4, alignment: 4 }
- { id: 3, name: s, size: 4, alignment: 4 }
machineFunctionInfo: {}
body: |
bb.1.entry:
liveins: $a0, $a1, $a2, $a3
; MIPS32-LABEL: name: testVaCopyArg
; MIPS32: liveins: $a0, $a1, $a2, $a3
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
; MIPS32: G_STORE [[COPY1]](s32), [[FRAME_INDEX]](p0) :: (store 4 into %fixed-stack.1)
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
; MIPS32: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.2
; MIPS32: G_STORE [[COPY2]](s32), [[FRAME_INDEX1]](p0) :: (store 4 into %fixed-stack.2)
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
; MIPS32: [[FRAME_INDEX2:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.3
; MIPS32: G_STORE [[COPY3]](s32), [[FRAME_INDEX2]](p0) :: (store 4 into %fixed-stack.3)
; MIPS32: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @.str
; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY [[GV]](p0)
; MIPS32: [[FRAME_INDEX3:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.fmt.addr
; MIPS32: [[FRAME_INDEX4:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1.ap
; MIPS32: [[FRAME_INDEX5:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.2.aq
; MIPS32: [[FRAME_INDEX6:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.3.s
; MIPS32: G_STORE [[COPY]](p0), [[FRAME_INDEX3]](p0) :: (store 4 into %ir.fmt.addr)
; MIPS32: G_VASTART [[FRAME_INDEX4]](p0) :: (store 4 into %ir.ap1, align 1)
; MIPS32: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX4]](p0) :: (load 4)
; MIPS32: G_STORE [[LOAD]](p0), [[FRAME_INDEX5]](p0) :: (store 4)
; MIPS32: [[LOAD1:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX5]](p0) :: (load 4 from %ir.aq)
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[LOAD1]], [[C]](s32)
; MIPS32: G_STORE [[GEP]](p0), [[FRAME_INDEX5]](p0) :: (store 4 into %ir.aq)
; MIPS32: [[LOAD2:%[0-9]+]]:_(p0) = G_LOAD [[LOAD1]](p0) :: (load 4 from %ir.2)
; MIPS32: G_STORE [[LOAD2]](p0), [[FRAME_INDEX6]](p0) :: (store 4 into %ir.s)
; MIPS32: [[LOAD3:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX6]](p0) :: (load 4 from %ir.s)
; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
; MIPS32: $a0 = COPY [[COPY4]](p0)
; MIPS32: $a1 = COPY [[LOAD3]](p0)
; MIPS32: JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
; MIPS32: RetRA
%0:_(p0) = COPY $a0
%1:_(s32) = COPY $a1
%2:_(p0) = G_FRAME_INDEX %fixed-stack.2
G_STORE %1(s32), %2(p0) :: (store 4 into %fixed-stack.2)
%3:_(s32) = COPY $a2
%4:_(p0) = G_FRAME_INDEX %fixed-stack.1
G_STORE %3(s32), %4(p0) :: (store 4 into %fixed-stack.1)
%5:_(s32) = COPY $a3
%6:_(p0) = G_FRAME_INDEX %fixed-stack.0
G_STORE %5(s32), %6(p0) :: (store 4 into %fixed-stack.0)
%18:_(p0) = G_GLOBAL_VALUE @.str
%17:_(p0) = COPY %18(p0)
%7:_(p0) = G_FRAME_INDEX %stack.0.fmt.addr
%8:_(p0) = G_FRAME_INDEX %stack.1.ap
%9:_(p0) = G_FRAME_INDEX %stack.2.aq
%10:_(p0) = G_FRAME_INDEX %stack.3.s
G_STORE %0(p0), %7(p0) :: (store 4 into %ir.fmt.addr)
G_VASTART %8(p0) :: (store 4 into %ir.ap1, align 1)
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.va_copy), %9(p0), %8(p0)
%11:_(p0) = G_LOAD %9(p0) :: (load 4 from %ir.aq)
%12:_(s32) = G_CONSTANT i32 4
%13:_(p0) = G_GEP %11, %12(s32)
G_STORE %13(p0), %9(p0) :: (store 4 into %ir.aq)
%14:_(p0) = G_LOAD %11(p0) :: (load 4 from %ir.2)
G_STORE %14(p0), %10(p0) :: (store 4 into %ir.s)
%15:_(p0) = G_LOAD %10(p0) :: (load 4 from %ir.s)
ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
$a0 = COPY %17(p0)
$a1 = COPY %15(p0)
JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
RetRA
...

View File

@ -0,0 +1,67 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
@.str = private unnamed_addr constant [11 x i8] c"string %s\0A\00", align 1
declare void @llvm.va_start(i8*)
declare void @llvm.va_copy(i8*, i8*)
declare i32 @printf(i8*, ...)
define void @testVaCopyArg(i8* %fmt, ...) {
; MIPS32-LABEL: testVaCopyArg:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: addiu $sp, $sp, -40
; MIPS32-NEXT: .cfi_def_cfa_offset 40
; MIPS32-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
; MIPS32-NEXT: .cfi_offset 31, -4
; MIPS32-NEXT: addiu $1, $sp, 44
; MIPS32-NEXT: sw $5, 0($1)
; MIPS32-NEXT: addiu $1, $sp, 48
; MIPS32-NEXT: sw $6, 0($1)
; MIPS32-NEXT: addiu $1, $sp, 52
; MIPS32-NEXT: sw $7, 0($1)
; MIPS32-NEXT: lui $1, %hi($.str)
; MIPS32-NEXT: addiu $1, $1, %lo($.str)
; MIPS32-NEXT: addiu $2, $sp, 32
; MIPS32-NEXT: addiu $3, $sp, 28
; MIPS32-NEXT: addiu $5, $sp, 24
; MIPS32-NEXT: addiu $6, $sp, 20
; MIPS32-NEXT: sw $4, 0($2)
; MIPS32-NEXT: addiu $2, $sp, 44
; MIPS32-NEXT: sw $2, 0($3)
; MIPS32-NEXT: lw $2, 0($3)
; MIPS32-NEXT: sw $2, 0($5)
; MIPS32-NEXT: lw $2, 0($5)
; MIPS32-NEXT: ori $3, $zero, 4
; MIPS32-NEXT: addu $3, $2, $3
; MIPS32-NEXT: sw $3, 0($5)
; MIPS32-NEXT: lw $2, 0($2)
; MIPS32-NEXT: sw $2, 0($6)
; MIPS32-NEXT: lw $5, 0($6)
; MIPS32-NEXT: move $4, $1
; MIPS32-NEXT: jal printf
; MIPS32-NEXT: nop
; MIPS32-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
; MIPS32-NEXT: addiu $sp, $sp, 40
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%fmt.addr = alloca i8*, align 4
%ap = alloca i8*, align 4
%aq = alloca i8*, align 4
%s = alloca i8*, align 4
store i8* %fmt, i8** %fmt.addr, align 4
%ap1 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap1)
%0 = bitcast i8** %aq to i8*
%1 = bitcast i8** %ap to i8*
call void @llvm.va_copy(i8* %0, i8* %1)
%argp.cur = load i8*, i8** %aq, align 4
%argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
store i8* %argp.next, i8** %aq, align 4
%2 = bitcast i8* %argp.cur to i8**
%3 = load i8*, i8** %2, align 4
store i8* %3, i8** %s, align 4
%4 = load i8*, i8** %s, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i8* %4)
ret void
}

View File

@ -0,0 +1,125 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
--- |
@.str = private unnamed_addr constant [11 x i8] c"string %s\0A\00", align 1
declare void @llvm.va_start(i8*) #0
declare void @llvm.va_copy(i8*, i8*) #0
declare i32 @printf(i8*, ...)
define void @testVaCopyArg(i8* %fmt, ...) {
entry:
%fmt.addr = alloca i8*, align 4
%ap = alloca i8*, align 4
%aq = alloca i8*, align 4
%s = alloca i8*, align 4
store i8* %fmt, i8** %fmt.addr, align 4
%ap1 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap1)
%0 = bitcast i8** %aq to i8*
%1 = bitcast i8** %ap to i8*
call void @llvm.va_copy(i8* %0, i8* %1)
%argp.cur = load i8*, i8** %aq, align 4
%argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
store i8* %argp.next, i8** %aq, align 4
%2 = bitcast i8* %argp.cur to i8**
%3 = load i8*, i8** %2, align 4
store i8* %3, i8** %s, align 4
%4 = load i8*, i8** %s, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i8* %4)
ret void
}
...
---
name: testVaCopyArg
alignment: 4
legalized: true
tracksRegLiveness: true
liveins:
- { reg: '$a0' }
fixedStack:
- { id: 0, offset: 12, size: 4, alignment: 4, isImmutable: true }
- { id: 1, offset: 8, size: 4, alignment: 8, isImmutable: true }
- { id: 2, offset: 4, size: 4, alignment: 4, isImmutable: true }
- { id: 3, offset: 4, size: 4, alignment: 4, isImmutable: true }
stack:
- { id: 0, name: fmt.addr, size: 4, alignment: 4 }
- { id: 1, name: ap, size: 4, alignment: 4 }
- { id: 2, name: aq, size: 4, alignment: 4 }
- { id: 3, name: s, size: 4, alignment: 4 }
machineFunctionInfo: {}
body: |
bb.1.entry:
liveins: $a0, $a1, $a2, $a3
; MIPS32-LABEL: name: testVaCopyArg
; MIPS32: liveins: $a0, $a1, $a2, $a3
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:gprb(p0) = G_FRAME_INDEX %fixed-stack.1
; MIPS32: G_STORE [[COPY1]](s32), [[FRAME_INDEX]](p0) :: (store 4 into %fixed-stack.1)
; MIPS32: [[COPY2:%[0-9]+]]:gprb(s32) = COPY $a2
; MIPS32: [[FRAME_INDEX1:%[0-9]+]]:gprb(p0) = G_FRAME_INDEX %fixed-stack.2
; MIPS32: G_STORE [[COPY2]](s32), [[FRAME_INDEX1]](p0) :: (store 4 into %fixed-stack.2)
; MIPS32: [[COPY3:%[0-9]+]]:gprb(s32) = COPY $a3
; MIPS32: [[FRAME_INDEX2:%[0-9]+]]:gprb(p0) = G_FRAME_INDEX %fixed-stack.3
; MIPS32: G_STORE [[COPY3]](s32), [[FRAME_INDEX2]](p0) :: (store 4 into %fixed-stack.3)
; MIPS32: [[GV:%[0-9]+]]:gprb(p0) = G_GLOBAL_VALUE @.str
; MIPS32: [[COPY4:%[0-9]+]]:gprb(p0) = COPY [[GV]](p0)
; MIPS32: [[FRAME_INDEX3:%[0-9]+]]:gprb(p0) = G_FRAME_INDEX %stack.0.fmt.addr
; MIPS32: [[FRAME_INDEX4:%[0-9]+]]:gpr32(p0) = G_FRAME_INDEX %stack.1.ap
; MIPS32: [[FRAME_INDEX5:%[0-9]+]]:gpr32(p0) = G_FRAME_INDEX %stack.2.aq
; MIPS32: [[FRAME_INDEX6:%[0-9]+]]:gprb(p0) = G_FRAME_INDEX %stack.3.s
; MIPS32: G_STORE [[COPY]](p0), [[FRAME_INDEX3]](p0) :: (store 4 into %ir.fmt.addr)
; MIPS32: G_VASTART [[FRAME_INDEX4]](p0) :: (store 4 into %ir.ap1, align 1)
; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[FRAME_INDEX4]](p0), 0 :: (load 4)
; MIPS32: SW [[LW]], [[FRAME_INDEX5]](p0), 0 :: (store 4)
; MIPS32: [[LOAD:%[0-9]+]]:gprb(p0) = G_LOAD [[FRAME_INDEX5]](p0) :: (load 4 from %ir.aq)
; MIPS32: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 4
; MIPS32: [[GEP:%[0-9]+]]:gprb(p0) = G_GEP [[LOAD]], [[C]](s32)
; MIPS32: G_STORE [[GEP]](p0), [[FRAME_INDEX5]](p0) :: (store 4 into %ir.aq)
; MIPS32: [[LOAD1:%[0-9]+]]:gprb(p0) = G_LOAD [[LOAD]](p0) :: (load 4 from %ir.2)
; MIPS32: G_STORE [[LOAD1]](p0), [[FRAME_INDEX6]](p0) :: (store 4 into %ir.s)
; MIPS32: [[LOAD2:%[0-9]+]]:gprb(p0) = G_LOAD [[FRAME_INDEX6]](p0) :: (load 4 from %ir.s)
; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
; MIPS32: $a0 = COPY [[COPY4]](p0)
; MIPS32: $a1 = COPY [[LOAD2]](p0)
; MIPS32: JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
; MIPS32: RetRA
%0:_(p0) = COPY $a0
%1:_(s32) = COPY $a1
%2:_(p0) = G_FRAME_INDEX %fixed-stack.2
G_STORE %1(s32), %2(p0) :: (store 4 into %fixed-stack.2)
%3:_(s32) = COPY $a2
%4:_(p0) = G_FRAME_INDEX %fixed-stack.1
G_STORE %3(s32), %4(p0) :: (store 4 into %fixed-stack.1)
%5:_(s32) = COPY $a3
%6:_(p0) = G_FRAME_INDEX %fixed-stack.0
G_STORE %5(s32), %6(p0) :: (store 4 into %fixed-stack.0)
%18:_(p0) = G_GLOBAL_VALUE @.str
%17:_(p0) = COPY %18(p0)
%7:_(p0) = G_FRAME_INDEX %stack.0.fmt.addr
%8:gpr32(p0) = G_FRAME_INDEX %stack.1.ap
%9:gpr32(p0) = G_FRAME_INDEX %stack.2.aq
%10:_(p0) = G_FRAME_INDEX %stack.3.s
G_STORE %0(p0), %7(p0) :: (store 4 into %ir.fmt.addr)
G_VASTART %8(p0) :: (store 4 into %ir.ap1, align 1)
%19:gpr32 = LW %8(p0), 0 :: (load 4)
SW %19, %9(p0), 0 :: (store 4)
%11:_(p0) = G_LOAD %9(p0) :: (load 4 from %ir.aq)
%12:_(s32) = G_CONSTANT i32 4
%13:_(p0) = G_GEP %11, %12(s32)
G_STORE %13(p0), %9(p0) :: (store 4 into %ir.aq)
%14:_(p0) = G_LOAD %11(p0) :: (load 4 from %ir.2)
G_STORE %14(p0), %10(p0) :: (store 4 into %ir.s)
%15:_(p0) = G_LOAD %10(p0) :: (load 4 from %ir.s)
ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
$a0 = COPY %17(p0)
$a1 = COPY %15(p0)
JAL @printf, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
RetRA
...