Index: lib/Target/Mips/MipsCallLowering.cpp =================================================================== --- lib/Target/Mips/MipsCallLowering.cpp +++ lib/Target/Mips/MipsCallLowering.cpp @@ -454,10 +454,6 @@ 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 @@ if (!Handler.handle(ArgLocs, ArgInfos)) return false; + if (F.isVarArg()) { + ArrayRef 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()->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 @@ subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs); SmallVector ArgLocs; - MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + bool IsCalleeVarArg = false; + if (Info.Callee.isGlobal()) { + const Function *CF = static_cast(Info.Callee.getGlobal()); + IsCalleeVarArg = CF->isVarArg(); + } + MipsCCState CCInfo(F.getCallingConv(), IsCalleeVarArg, MF, ArgLocs, F.getContext()); CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv), 1); Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -2872,7 +2872,7 @@ #include "MipsGenCallingConv.inc" CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{ - return CC_Mips; + return CC_Mips_FixedArg; } CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{ Index: lib/Target/Mips/MipsInstructionSelector.cpp =================================================================== --- lib/Target/Mips/MipsInstructionSelector.cpp +++ lib/Target/Mips/MipsInstructionSelector.cpp @@ -773,6 +773,30 @@ MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0); break; } + case G_VASTART: { + MipsFunctionInfo *FuncInfo = MF.getInfo(); + 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; + break; + } default: return false; } Index: lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- lib/Target/Mips/MipsLegalizerInfo.cpp +++ lib/Target/Mips/MipsLegalizerInfo.cpp @@ -122,6 +122,9 @@ getActionDefinitionsBuilder(G_DYN_STACKALLOC) .lowerFor({{p0, s32}}); + getActionDefinitionsBuilder(G_VASTART) + .legalFor({p0}); + // FP instructions getActionDefinitionsBuilder(G_FCONSTANT) .legalFor({s32, s64}); @@ -252,6 +255,19 @@ 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; + break; + } default: break; } Index: lib/Target/Mips/MipsRegisterBankInfo.cpp =================================================================== --- lib/Target/Mips/MipsRegisterBankInfo.cpp +++ lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -403,6 +403,7 @@ case G_SREM: case G_UREM: case G_BRINDIRECT: + case G_VASTART: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; break; case G_LOAD: { Index: test/CodeGen/Mips/GlobalISel/instruction-select/var_arg.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/instruction-select/var_arg.mir @@ -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 + +... Index: test/CodeGen/Mips/GlobalISel/irtranslator/var_arg.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/irtranslator/var_arg.ll @@ -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 +} Index: test/CodeGen/Mips/GlobalISel/legalizer/var_arg.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/legalizer/var_arg.mir @@ -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 + +... Index: test/CodeGen/Mips/GlobalISel/llvm-ir/var_arg.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/llvm-ir/var_arg.ll @@ -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 +} Index: test/CodeGen/Mips/GlobalISel/regbankselect/var_arg.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/regbankselect/var_arg.mir @@ -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 + +...