forked from OSchip/llvm-project
[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:
parent
fe897623f3
commit
eaa16005af
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"}
|
Loading…
Reference in New Issue