Index: lib/Target/PowerPC/PPCCallingConv.td =================================================================== --- lib/Target/PowerPC/PPCCallingConv.td +++ lib/Target/PowerPC/PPCCallingConv.td @@ -26,6 +26,9 @@ class CCIfOrigArgWasNotPPCF128 : CCIf<"!static_cast(&State)->WasOriginalArgPPCF128(ValNo)", A>; +class CCIfOrigArgWasPPCF128 + : CCIf<"static_cast(&State)->WasOriginalArgPPCF128(ValNo)", + A>; //===----------------------------------------------------------------------===// // Return Value Calling Convention @@ -142,6 +145,9 @@ CCIfType<[i32], CCIfSplit>>>, + CCIfSplit>>>, // The 'nest' parameter, if any, is passed in R11. CCIfNest>, Index: lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- lib/Target/PowerPC/PPCISelLowering.h +++ lib/Target/PowerPC/PPCISelLowering.h @@ -926,6 +926,13 @@ ISD::ArgFlagsTy &ArgFlags, CCState &State); + bool + CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); + bool CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -2608,6 +2608,32 @@ return false; } +bool +llvm::CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg ArgRegs[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + const unsigned NumArgRegs = array_lengthof(ArgRegs); + + unsigned RegNum = State.getFirstUnallocated(ArgRegs); + int RegsLeft = NumArgRegs - RegNum; + + // Skip if there is not enough registers left for long double type (4 gpr regs + // in soft float mode) and put long double argument on the stack. + if (RegNum != NumArgRegs && RegsLeft < 4) { + for (int i = 0; i < RegsLeft; i++) { + State.AllocateReg(ArgRegs[RegNum + i]); + } + } + + return false; +} + bool llvm::CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, Index: test/CodeGen/PowerPC/ppc32-skip-regs.ll =================================================================== --- test/CodeGen/PowerPC/ppc32-skip-regs.ll +++ test/CodeGen/PowerPC/ppc32-skip-regs.ll @@ -0,0 +1,26 @@ +; RUN: llc -O2 -mtriple=powerpc-unknown-linux-gnu < %s | FileCheck %s + +target datalayout = "E-m:e-p:32:32-i64:64-n32" +target triple = "powerpc-buildroot-linux-gnu" + +@x = global ppc_fp128 0xM3FF00000000000000000000000000000, align 16 +@.str = private unnamed_addr constant [9 x i8] c"%Lf %Lf\0A\00", align 1 + +define void @foo() #0 { +entry: + %0 = load ppc_fp128, ppc_fp128* @x, align 16 + %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), ppc_fp128 %0, ppc_fp128 %0) + ret void +} +; Do not put second argument of function in r8 register, because there is no enough registers +; left for long double type (4 registers in soft float mode). Instead in r8 register this +; argument put on stack. +; CHECK-NOT: mr 8, 4 +; CHECK: stw 7, 20(1) +; CHECK: stw 6, 16(1) +; CHECK: stw 5, 12(1) +; CHECK: stw 4, 8(1) + +declare i32 @printf(i8* nocapture readonly, ...) + +attributes #0 = { "use-soft-float"="true" }