summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Target/TargetLowering.h7
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp3
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp24
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.h3
-rw-r--r--llvm/test/CodeGen/X86/mcu-abi.ll11
5 files changed, 48 insertions, 0 deletions
diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h
index 3b35e20f8d9..4d1208ff51a 100644
--- a/llvm/include/llvm/Target/TargetLowering.h
+++ b/llvm/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/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 158e861c1ef..21935cdd469 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/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/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 83c733a523d..d1879570a03 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/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/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 5ca5b5bcf78..7b44f431428 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/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<const TargetRegisterClass *, uint8_t>
findRepresentativeClass(const TargetRegisterInfo *TRI,
diff --git a/llvm/test/CodeGen/X86/mcu-abi.ll b/llvm/test/CodeGen/X86/mcu-abi.ll
new file mode 100644
index 00000000000..4da9f3d91ba
--- /dev/null
+++ b/llvm/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"}
OpenPOWER on IntegriCloud