[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

llvm-svn: 251223
This commit is contained in:
Michael Kuperstein 2015-10-25 08:14:05 +00:00
parent fe897623f3
commit eaa16005af
5 changed files with 48 additions and 0 deletions

View File

@ -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

View File

@ -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),

View File

@ -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;
}
}

View File

@ -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<const TargetRegisterClass *, uint8_t>
findRepresentativeClass(const TargetRegisterInfo *TRI,

View File

@ -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"}