From 8052f4541d9069c7115e1e64057325ef5cc7972c Mon Sep 17 00:00:00 2001 From: Michael Kuperstein Date: Sun, 25 Oct 2015 08:14:05 +0000 Subject: [PATCH] [X86] Use correct calling convention for MCU psABI libcalls When using the MCU psABI, compiler-generated library calls should pass some parameters in-register. However, since inreg marking for x86 is currently done by the front end, it will not be applied to backend-generated calls. This is a workaround for PR3997, which describes a similar issue for -mregparm. Differential Revision: http://reviews.llvm.org/D13977 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251223 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 7 ++++++ lib/CodeGen/SelectionDAG/TargetLowering.cpp | 3 +++ lib/Target/X86/X86ISelLowering.cpp | 24 +++++++++++++++++++++ lib/Target/X86/X86ISelLowering.h | 3 +++ test/CodeGen/X86/mcu-abi.ll | 11 ++++++++++ 5 files changed, 48 insertions(+) create mode 100644 test/CodeGen/X86/mcu-abi.ll diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 3b35e20f8d9..4d1208ff51a 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -2437,6 +2437,13 @@ public: }; + // Mark inreg arguments for lib-calls. For normal calls this is done by + // the frontend ABI code. + virtual void markInRegArguments(SelectionDAG &DAG, + TargetLowering::ArgListTy &Args) const { + return; + } + /// This function lowers an abstract call to a function into an actual call. /// This returns a pair of operands. The first element is the return value /// for the function (if RetTy is not VoidTy). The second element is the diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 158e861c1ef..21935cdd469 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -100,6 +100,9 @@ TargetLowering::makeLibCall(SelectionDAG &DAG, Entry.isZExt = !shouldSignExtendTypeInLibCall(Op.getValueType(), isSigned); Args.push_back(Entry); } + + markInRegArguments(DAG, Args); + if (LC == RTLIB::UNKNOWN_LIBCALL) report_fatal_error("Unsupported library call operation!"); SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC), diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 83c733a523d..d1879570a03 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -27492,3 +27492,27 @@ bool X86TargetLowering::isIntDivCheap(EVT VT, AttributeSet Attr) const { Attribute::MinSize); return OptSize && !VT.isVector(); } + +void X86TargetLowering::markInRegArguments(SelectionDAG &DAG, + TargetLowering::ArgListTy& Args) const { + // The MCU psABI requires some arguments to be passed in-register. + // For regular calls, the inreg arguments are marked by the front-end. + // However, for compiler generated library calls, we have to patch this + // up here. + if (!Subtarget->isTargetMCU() || !Args.size()) + return; + + unsigned FreeRegs = 3; + for (auto &Arg : Args) { + // For library functions, we do not expect any fancy types. + unsigned Size = DAG.getDataLayout().getTypeSizeInBits(Arg.Ty); + unsigned SizeInRegs = (Size + 31) / 32; + if (SizeInRegs > 2 || SizeInRegs > FreeRegs) + continue; + + Arg.isInReg = true; + FreeRegs -= SizeInRegs; + if (!FreeRegs) + break; + } +} diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 5ca5b5bcf78..7b44f431428 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -917,6 +917,9 @@ namespace llvm { bool isIntDivCheap(EVT VT, AttributeSet Attr) const override; + void markInRegArguments(SelectionDAG &DAG, TargetLowering::ArgListTy& Args) + const override; + protected: std::pair findRepresentativeClass(const TargetRegisterInfo *TRI, diff --git a/test/CodeGen/X86/mcu-abi.ll b/test/CodeGen/X86/mcu-abi.ll new file mode 100644 index 00000000000..4da9f3d91ba --- /dev/null +++ b/test/CodeGen/X86/mcu-abi.ll @@ -0,0 +1,11 @@ +; RUN: llc < %s -mtriple=i686-pc-linux-elfiamcu | FileCheck %s + +; CHECK-LABEL: test_lib_args: +; CHECK: movl %edx, %eax +; CHECK: calll __fixsfsi +define i32 @test_lib_args(float inreg %a, float inreg %b) #0 { + %ret = fptosi float %b to i32 + ret i32 %ret +} + +attributes #0 = { nounwind "use-soft-float"="true"} -- 2.34.1