From: Strahinja Petrovic Date: Fri, 5 Aug 2016 08:47:26 +0000 (+0000) Subject: [PowerPC] fix passing long double arguments to function (soft-float) X-Git-Tag: llvmorg-4.0.0-rc1~13260 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=30e0ce8e9fc4598388fcd3c4d57894036cdd5903;p=platform%2Fupstream%2Fllvm.git [PowerPC] fix passing long double arguments to function (soft-float) This patch fixes passing long double type arguments to function in soft float mode. If there is less than 4 argument registers free (long double type is mapped in 4 gpr registers in soft float mode) long double type argument must be passed through stack. Differential Revision: https://reviews.llvm.org/D20114. llvm-svn: 277804 --- diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td b/llvm/lib/Target/PowerPC/PPCCallingConv.td index 53d2f77..db6d087 100644 --- a/llvm/lib/Target/PowerPC/PPCCallingConv.td +++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td @@ -26,6 +26,9 @@ class CCIfNotSubtarget 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 @@ def CC_PPC32_SVR4_Common : CallingConv<[ CCIfType<[i32], CCIfSplit>>>, + CCIfSplit>>>, // The 'nest' parameter, if any, is passed in R11. CCIfNest>, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 472db99..2ccbcd9 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2676,6 +2676,32 @@ bool llvm::CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, 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, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index e3be807..c12f9c6 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -953,6 +953,13 @@ namespace llvm { 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, diff --git a/llvm/test/CodeGen/PowerPC/ppc32-skip-regs.ll b/llvm/test/CodeGen/PowerPC/ppc32-skip-regs.ll new file mode 100644 index 0000000..4acfd3c --- /dev/null +++ b/llvm/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" }