[X86] Use correct calling convention for MCU psABI libcalls
authorMichael Kuperstein <michael.m.kuperstein@intel.com>
Sun, 25 Oct 2015 08:14:05 +0000 (08:14 +0000)
committerMichael Kuperstein <michael.m.kuperstein@intel.com>
Sun, 25 Oct 2015 08:14:05 +0000 (08:14 +0000)
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
lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/X86/mcu-abi.ll [new file with mode: 0644]

index 3b35e20f8d97d3e0cd13e4d8d9e2af9a0cc74a10..4d1208ff51a21271ced177ca53a931cbb6567eaf 100644 (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
index 158e861c1ef3e4f66d517883af8ccadcda3c9504..21935cdd46993bf95c2ca243c2e09b614b570620 100644 (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),
index 83c733a523d622561f9729b6a54febe2274b6339..d1879570a0329799233a73760f9c059762443ef7 100644 (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;
+  }
+}
index 5ca5b5bcf784f2c8d4126e7dd050a83d250d0c3e..7b44f4314284e36de28898683bd380ea027e9c4e 100644 (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,
diff --git a/test/CodeGen/X86/mcu-abi.ll b/test/CodeGen/X86/mcu-abi.ll
new file mode 100644 (file)
index 0000000..4da9f3d
--- /dev/null
@@ -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"}