[llvm] d32e801 - [RISCV][GISel] Add FP calling convention support (#69138)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 25 12:30:07 PDT 2023


Author: Craig Topper
Date: 2023-10-25T12:30:03-07:00
New Revision: d32e801d74fae1cbe9cf256a81def6ee9c2b4153

URL: https://github.com/llvm/llvm-project/commit/d32e801d74fae1cbe9cf256a81def6ee9c2b4153
DIFF: https://github.com/llvm/llvm-project/commit/d32e801d74fae1cbe9cf256a81def6ee9c2b4153.diff

LOG: [RISCV][GISel] Add FP calling convention support (#69138)

This includes support for using GPRs, FPRs, and stack.

Added: 
    llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-common.ll
    llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32.ll
    llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32d.ll
    llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32f-ilp32d-common.ll
    llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-common.ll
    llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64.ll
    llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64d.ll

Modified: 
    llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
index be1771b19316f96..1806fcf4b5a1664 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
@@ -94,11 +94,60 @@ struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
 
   void assignValueToReg(Register ValVReg, Register PhysReg,
                         const CCValAssign &VA) override {
+    // If we're passing an f32 value into an i64, anyextend before copying.
+    if (VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32)
+      ValVReg = MIRBuilder.buildAnyExt(LLT::scalar(64), ValVReg).getReg(0);
+
     Register ExtReg = extendRegister(ValVReg, VA);
     MIRBuilder.buildCopy(PhysReg, ExtReg);
     MIB.addUse(PhysReg, RegState::Implicit);
   }
 
+  unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
+                             ArrayRef<CCValAssign> VAs,
+                             std::function<void()> *Thunk) override {
+    assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
+    const CCValAssign &VALo = VAs[0];
+    const CCValAssign &VAHi = VAs[1];
+
+    assert(VAHi.needsCustom() && "Value doesn't need custom handling");
+    assert(VALo.getValNo() == VAHi.getValNo() &&
+           "Values belong to 
diff erent arguments");
+
+    assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
+           VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
+           "unexpected custom value");
+
+    Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
+                          MRI.createGenericVirtualRegister(LLT::scalar(32))};
+    MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]);
+
+    if (VAHi.isMemLoc()) {
+      LLT MemTy(VAHi.getLocVT());
+
+      MachinePointerInfo MPO;
+      Register StackAddr = getStackAddress(
+          MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
+
+      assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
+                           const_cast<CCValAssign &>(VAHi));
+    }
+
+    auto assignFunc = [=]() {
+      assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);
+      if (VAHi.isRegLoc())
+        assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
+    };
+
+    if (Thunk) {
+      *Thunk = assignFunc;
+      return 1;
+    }
+
+    assignFunc();
+    return 1;
+  }
+
 private:
   MachineInstrBuilder MIB;
 
@@ -170,6 +219,44 @@ struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {
     IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
   }
 
+  unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
+                             ArrayRef<CCValAssign> VAs,
+                             std::function<void()> *Thunk) override {
+    assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
+    const CCValAssign &VALo = VAs[0];
+    const CCValAssign &VAHi = VAs[1];
+
+    assert(VAHi.needsCustom() && "Value doesn't need custom handling");
+    assert(VALo.getValNo() == VAHi.getValNo() &&
+           "Values belong to 
diff erent arguments");
+
+    assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
+           VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
+           "unexpected custom value");
+
+    Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
+                          MRI.createGenericVirtualRegister(LLT::scalar(32))};
+
+    if (VAHi.isMemLoc()) {
+      LLT MemTy(VAHi.getLocVT());
+
+      MachinePointerInfo MPO;
+      Register StackAddr = getStackAddress(
+          MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
+
+      assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
+                           const_cast<CCValAssign &>(VAHi));
+    }
+
+    assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);
+    if (VAHi.isRegLoc())
+      assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
+
+    MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs);
+
+    return 1;
+  }
+
   /// How the physical register gets marked varies between formal
   /// parameters (it's a basic-block live-in), and a call instruction
   /// (it's an implicit-def of the BL).
@@ -212,6 +299,8 @@ static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget) {
   // supported yet.
   if (T->isIntegerTy())
     return T->getIntegerBitWidth() <= Subtarget.getXLen() * 2;
+  if (T->isFloatTy() || T->isDoubleTy())
+    return true;
   if (T->isPointerTy())
     return true;
   return false;
@@ -223,6 +312,8 @@ static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget) {
   // supported yet.
   if (T->isIntegerTy())
     return T->getIntegerBitWidth() <= Subtarget.getXLen() * 2;
+  if (T->isFloatTy() || T->isDoubleTy())
+    return true;
   if (T->isPointerTy())
     return true;
 

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-common.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-common.ll
new file mode 100644
index 000000000000000..8fc77feae2d431d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-common.ll
@@ -0,0 +1,75 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv32 -global-isel -stop-after=irtranslator \
+; RUN:    -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32I %s
+; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f \
+; RUN:    -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32I %s
+
+; This file contains tests that should have identical output for the ilp32,
+; and ilp32f.
+
+; Check that on RV32 ilp32[f], double is passed in a pair of registers. Unlike
+; the convention for varargs, this need not be an aligned pair.
+
+define i32 @callee_double_in_regs(i32 %a, double %b) nounwind {
+  ; RV32I-LABEL: name: callee_double_in_regs
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   liveins: $x10, $x11, $x12
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32I-NEXT:   [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
+  ; RV32I-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32)
+  ; RV32I-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[MV]](s64)
+  ; RV32I-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[FPTOSI]]
+  ; RV32I-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  %b_fptosi = fptosi double %b to i32
+  %1 = add i32 %a, %b_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_double_in_regs() nounwind {
+  ; RV32I-LABEL: name: caller_double_in_regs
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+  ; RV32I-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV32I-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64)
+  ; RV32I-NEXT:   $x10 = COPY [[C]](s32)
+  ; RV32I-NEXT:   $x11 = COPY [[UV]](s32)
+  ; RV32I-NEXT:   $x12 = COPY [[UV1]](s32)
+  ; RV32I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_regs, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit-def $x10
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_double_in_regs(i32 1, double 2.0)
+  ret i32 %1
+}
+
+define double @callee_small_scalar_ret() nounwind {
+  ; RV32I-LABEL: name: callee_small_scalar_ret
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
+  ; RV32I-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
+  ; RV32I-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32I-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10, implicit $x11
+  ret double 1.0
+}
+
+define i64 @caller_small_scalar_ret() nounwind {
+  ; RV32I-LABEL: name: caller_small_scalar_ret
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_small_scalar_ret, implicit-def $x1, implicit-def $x10, implicit-def $x11
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32I-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+  ; RV32I-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MV]](s64)
+  ; RV32I-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32I-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10, implicit $x11
+  %1 = call double @callee_small_scalar_ret()
+  %2 = bitcast double %1 to i64
+  ret i64 %2
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32.ll
new file mode 100644
index 000000000000000..3b4aca1e6953dac
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32.ll
@@ -0,0 +1,121 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv32 -global-isel -stop-after=irtranslator \
+; RUN:   -verify-machineinstrs < %s | FileCheck -check-prefix=RV32I %s
+
+; Any tests that would have identical output for some combination of the ilp32*
+; ABIs belong in calling-conv-*-common.ll. This file contains tests that will
+; have 
diff erent output across those ABIs. i.e. where some arguments would be
+; passed according to the floating point ABI.
+
+define i32 @callee_float_in_regs(i32 %a, float %b) nounwind {
+  ; RV32I-LABEL: name: callee_float_in_regs
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   liveins: $x10, $x11
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32I-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY1]](s32)
+  ; RV32I-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[FPTOSI]]
+  ; RV32I-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  %b_fptosi = fptosi float %b to i32
+  %1 = add i32 %a, %b_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_float_in_regs() nounwind {
+  ; RV32I-LABEL: name: caller_float_in_regs
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+  ; RV32I-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
+  ; RV32I-NEXT:   $x10 = COPY [[C]](s32)
+  ; RV32I-NEXT:   $x11 = COPY [[C1]](s32)
+  ; RV32I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_in_regs, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_float_in_regs(i32 1, float 2.0)
+  ret i32 %1
+}
+
+define i32 @callee_float_on_stack(i64 %a, i64 %b, i64 %c, i64 %d, float %e) nounwind {
+  ; RV32I-LABEL: name: callee_float_on_stack
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32I-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+  ; RV32I-NEXT:   [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
+  ; RV32I-NEXT:   [[COPY3:%[0-9]+]]:_(s32) = COPY $x13
+  ; RV32I-NEXT:   [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY2]](s32), [[COPY3]](s32)
+  ; RV32I-NEXT:   [[COPY4:%[0-9]+]]:_(s32) = COPY $x14
+  ; RV32I-NEXT:   [[COPY5:%[0-9]+]]:_(s32) = COPY $x15
+  ; RV32I-NEXT:   [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32)
+  ; RV32I-NEXT:   [[COPY6:%[0-9]+]]:_(s32) = COPY $x16
+  ; RV32I-NEXT:   [[COPY7:%[0-9]+]]:_(s32) = COPY $x17
+  ; RV32I-NEXT:   [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32)
+  ; RV32I-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV32I-NEXT:   [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 16)
+  ; RV32I-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV3]](s64)
+  ; RV32I-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TRUNC]], [[LOAD]]
+  ; RV32I-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  %1 = trunc i64 %d to i32
+  %2 = bitcast float %e to i32
+  %3 = add i32 %1, %2
+  ret i32 %3
+}
+
+define i32 @caller_float_on_stack() nounwind {
+  ; RV32I-LABEL: name: caller_float_on_stack
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV32I-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
+  ; RV32I-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
+  ; RV32I-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
+  ; RV32I-NEXT:   [[C4:%[0-9]+]]:_(s32) = G_FCONSTANT float 5.000000e+00
+  ; RV32I-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
+  ; RV32I-NEXT:   [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64)
+  ; RV32I-NEXT:   [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64)
+  ; RV32I-NEXT:   [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64)
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV32I-NEXT:   [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; RV32I-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C5]](s32)
+  ; RV32I-NEXT:   G_STORE [[C4]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
+  ; RV32I-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32I-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32I-NEXT:   $x12 = COPY [[UV2]](s32)
+  ; RV32I-NEXT:   $x13 = COPY [[UV3]](s32)
+  ; RV32I-NEXT:   $x14 = COPY [[UV4]](s32)
+  ; RV32I-NEXT:   $x15 = COPY [[UV5]](s32)
+  ; RV32I-NEXT:   $x16 = COPY [[UV6]](s32)
+  ; RV32I-NEXT:   $x17 = COPY [[UV7]](s32)
+  ; RV32I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_on_stack, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10
+  ; RV32I-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   $x10 = COPY [[COPY1]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_float_on_stack(i64 1, i64 2, i64 3, i64 4, float 5.0)
+  ret i32 %1
+}
+
+define float @callee_tiny_scalar_ret() nounwind {
+  ; RV32I-LABEL: name: callee_tiny_scalar_ret
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00
+  ; RV32I-NEXT:   $x10 = COPY [[C]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  ret float 1.0
+}
+
+define i32 @caller_tiny_scalar_ret() nounwind {
+  ; RV32I-LABEL: name: caller_tiny_scalar_ret
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_tiny_scalar_ret, implicit-def $x1, implicit-def $x10
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32I-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  %1 = call float @callee_tiny_scalar_ret()
+  %2 = bitcast float %1 to i32
+  ret i32 %2
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32d.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32d.ll
new file mode 100644
index 000000000000000..e33e279f7f48978
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32d.ll
@@ -0,0 +1,364 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi ilp32d \
+; RUN:    -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32-ILP32D %s
+
+; This file contains tests that will have 
diff ering output for the ilp32/ilp32f
+; and ilp32d ABIs.
+
+define i32 @callee_double_in_fpr(i32 %a, double %b) nounwind {
+  ; RV32-ILP32D-LABEL: name: callee_double_in_fpr
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   liveins: $x10, $f10_d
+  ; RV32-ILP32D-NEXT: {{  $}}
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV32-ILP32D-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY1]](s64)
+  ; RV32-ILP32D-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[FPTOSI]]
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %b_fptosi = fptosi double %b to i32
+  %1 = add i32 %a, %b_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_double_in_fpr() nounwind {
+  ; RV32-ILP32D-LABEL: name: caller_double_in_fpr
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+  ; RV32-ILP32D-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[C]](s32)
+  ; RV32-ILP32D-NEXT:   $f10_d = COPY [[C1]](s64)
+  ; RV32-ILP32D-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_fpr, implicit-def $x1, implicit $x10, implicit $f10_d, implicit-def $x10
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_double_in_fpr(i32 1, double 2.0)
+  ret i32 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_double_in_fpr_exhausted_gprs(i64 %a, i64 %b, i64 %c, i64 %d, i32 %e, double %f) nounwind {
+  ; RV32-ILP32D-LABEL: name: callee_double_in_fpr_exhausted_gprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $f10_d
+  ; RV32-ILP32D-NEXT: {{  $}}
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32-ILP32D-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
+  ; RV32-ILP32D-NEXT:   [[COPY3:%[0-9]+]]:_(s32) = COPY $x13
+  ; RV32-ILP32D-NEXT:   [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY2]](s32), [[COPY3]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY4:%[0-9]+]]:_(s32) = COPY $x14
+  ; RV32-ILP32D-NEXT:   [[COPY5:%[0-9]+]]:_(s32) = COPY $x15
+  ; RV32-ILP32D-NEXT:   [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY6:%[0-9]+]]:_(s32) = COPY $x16
+  ; RV32-ILP32D-NEXT:   [[COPY7:%[0-9]+]]:_(s32) = COPY $x17
+  ; RV32-ILP32D-NEXT:   [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32)
+  ; RV32-ILP32D-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV32-ILP32D-NEXT:   [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 16)
+  ; RV32-ILP32D-NEXT:   [[COPY8:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV32-ILP32D-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY8]](s64)
+  ; RV32-ILP32D-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[FPTOSI]]
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %f_fptosi = fptosi double %f to i32
+  %1 = add i32 %e, %f_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_double_in_fpr_exhausted_gprs() nounwind {
+  ; RV32-ILP32D-LABEL: name: caller_double_in_fpr_exhausted_gprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV32-ILP32D-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
+  ; RV32-ILP32D-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
+  ; RV32-ILP32D-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
+  ; RV32-ILP32D-NEXT:   [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+  ; RV32-ILP32D-NEXT:   [[C5:%[0-9]+]]:_(s64) = G_FCONSTANT double 6.000000e+00
+  ; RV32-ILP32D-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64)
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV32-ILP32D-NEXT:   [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; RV32-ILP32D-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C6]](s32)
+  ; RV32-ILP32D-NEXT:   G_STORE [[C4]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32-ILP32D-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32-ILP32D-NEXT:   $x12 = COPY [[UV2]](s32)
+  ; RV32-ILP32D-NEXT:   $x13 = COPY [[UV3]](s32)
+  ; RV32-ILP32D-NEXT:   $x14 = COPY [[UV4]](s32)
+  ; RV32-ILP32D-NEXT:   $x15 = COPY [[UV5]](s32)
+  ; RV32-ILP32D-NEXT:   $x16 = COPY [[UV6]](s32)
+  ; RV32-ILP32D-NEXT:   $x17 = COPY [[UV7]](s32)
+  ; RV32-ILP32D-NEXT:   $f10_d = COPY [[C5]](s64)
+  ; RV32-ILP32D-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_fpr_exhausted_gprs, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit $f10_d, implicit-def $x10
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[COPY1]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_double_in_fpr_exhausted_gprs(
+      i64 1, i64 2, i64 3, i64 4, i32 5, double 6.0)
+  ret i32 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_double_in_gpr_exhausted_fprs(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i) nounwind {
+  ; RV32-ILP32D-LABEL: name: callee_double_in_gpr_exhausted_fprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   liveins: $x10, $x11, $f10_d, $f11_d, $f12_d, $f13_d, $f14_d, $f15_d, $f16_d, $f17_d
+  ; RV32-ILP32D-NEXT: {{  $}}
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $f11_d
+  ; RV32-ILP32D-NEXT:   [[COPY2:%[0-9]+]]:_(s64) = COPY $f12_d
+  ; RV32-ILP32D-NEXT:   [[COPY3:%[0-9]+]]:_(s64) = COPY $f13_d
+  ; RV32-ILP32D-NEXT:   [[COPY4:%[0-9]+]]:_(s64) = COPY $f14_d
+  ; RV32-ILP32D-NEXT:   [[COPY5:%[0-9]+]]:_(s64) = COPY $f15_d
+  ; RV32-ILP32D-NEXT:   [[COPY6:%[0-9]+]]:_(s64) = COPY $f16_d
+  ; RV32-ILP32D-NEXT:   [[COPY7:%[0-9]+]]:_(s64) = COPY $f17_d
+  ; RV32-ILP32D-NEXT:   [[COPY8:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   [[COPY9:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32-ILP32D-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY8]](s32), [[COPY9]](s32)
+  ; RV32-ILP32D-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY7]](s64)
+  ; RV32-ILP32D-NEXT:   [[FPTOSI1:%[0-9]+]]:_(s32) = G_FPTOSI [[MV]](s64)
+  ; RV32-ILP32D-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[FPTOSI]], [[FPTOSI1]]
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %h_fptosi = fptosi double %h to i32
+  %i_fptosi = fptosi double %i to i32
+  %1 = add i32 %h_fptosi, %i_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_double_in_gpr_exhausted_fprs() nounwind {
+  ; RV32-ILP32D-LABEL: name: caller_double_in_gpr_exhausted_fprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_FCONSTANT double 3.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C4:%[0-9]+]]:_(s64) = G_FCONSTANT double 5.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C5:%[0-9]+]]:_(s64) = G_FCONSTANT double 6.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C6:%[0-9]+]]:_(s64) = G_FCONSTANT double 7.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C7:%[0-9]+]]:_(s64) = G_FCONSTANT double 8.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C8:%[0-9]+]]:_(s64) = G_FCONSTANT double 9.000000e+00
+  ; RV32-ILP32D-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C8]](s64)
+  ; RV32-ILP32D-NEXT:   $f10_d = COPY [[C]](s64)
+  ; RV32-ILP32D-NEXT:   $f11_d = COPY [[C1]](s64)
+  ; RV32-ILP32D-NEXT:   $f12_d = COPY [[C2]](s64)
+  ; RV32-ILP32D-NEXT:   $f13_d = COPY [[C3]](s64)
+  ; RV32-ILP32D-NEXT:   $f14_d = COPY [[C4]](s64)
+  ; RV32-ILP32D-NEXT:   $f15_d = COPY [[C5]](s64)
+  ; RV32-ILP32D-NEXT:   $f16_d = COPY [[C6]](s64)
+  ; RV32-ILP32D-NEXT:   $f17_d = COPY [[C7]](s64)
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32-ILP32D-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_gpr_exhausted_fprs, implicit-def $x1, implicit $f10_d, implicit $f11_d, implicit $f12_d, implicit $f13_d, implicit $f14_d, implicit $f15_d, implicit $f16_d, implicit $f17_d, implicit $x10, implicit $x11, implicit-def $x10
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_double_in_gpr_exhausted_fprs(
+      double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0,
+      double 7.0, double 8.0, double 9.0)
+  ret i32 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_double_in_gpr_and_stack_almost_exhausted_gprs_fprs(i64 %a, double %b, i64 %c, double %d, i64 %e, double %f, i32 %g, double %h, double %i, double %j, double %k, double %l, double %m) nounwind {
+  ; RV32-ILP32D-LABEL: name: callee_double_in_gpr_and_stack_almost_exhausted_gprs_fprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $f10_d, $f11_d, $f12_d, $f13_d, $f14_d, $f15_d, $f16_d, $f17_d
+  ; RV32-ILP32D-NEXT: {{  $}}
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32-ILP32D-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY2:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV32-ILP32D-NEXT:   [[COPY3:%[0-9]+]]:_(s32) = COPY $x12
+  ; RV32-ILP32D-NEXT:   [[COPY4:%[0-9]+]]:_(s32) = COPY $x13
+  ; RV32-ILP32D-NEXT:   [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY3]](s32), [[COPY4]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY5:%[0-9]+]]:_(s64) = COPY $f11_d
+  ; RV32-ILP32D-NEXT:   [[COPY6:%[0-9]+]]:_(s32) = COPY $x14
+  ; RV32-ILP32D-NEXT:   [[COPY7:%[0-9]+]]:_(s32) = COPY $x15
+  ; RV32-ILP32D-NEXT:   [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY8:%[0-9]+]]:_(s64) = COPY $f12_d
+  ; RV32-ILP32D-NEXT:   [[COPY9:%[0-9]+]]:_(s32) = COPY $x16
+  ; RV32-ILP32D-NEXT:   [[COPY10:%[0-9]+]]:_(s64) = COPY $f13_d
+  ; RV32-ILP32D-NEXT:   [[COPY11:%[0-9]+]]:_(s64) = COPY $f14_d
+  ; RV32-ILP32D-NEXT:   [[COPY12:%[0-9]+]]:_(s64) = COPY $f15_d
+  ; RV32-ILP32D-NEXT:   [[COPY13:%[0-9]+]]:_(s64) = COPY $f16_d
+  ; RV32-ILP32D-NEXT:   [[COPY14:%[0-9]+]]:_(s64) = COPY $f17_d
+  ; RV32-ILP32D-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV32-ILP32D-NEXT:   [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 16)
+  ; RV32-ILP32D-NEXT:   [[COPY15:%[0-9]+]]:_(s32) = COPY $x17
+  ; RV32-ILP32D-NEXT:   [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY15]](s32), [[LOAD]](s32)
+  ; RV32-ILP32D-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[MV3]](s64)
+  ; RV32-ILP32D-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY9]], [[FPTOSI]]
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %m_fptosi = fptosi double %m to i32
+  %1 = add i32 %g, %m_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_double_in_gpr_and_stack_almost_exhausted_gprs_fprs() nounwind {
+  ; RV32-ILP32D-LABEL: name: caller_double_in_gpr_and_stack_almost_exhausted_gprs_fprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV32-ILP32D-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
+  ; RV32-ILP32D-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5
+  ; RV32-ILP32D-NEXT:   [[C5:%[0-9]+]]:_(s64) = G_FCONSTANT double 6.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+  ; RV32-ILP32D-NEXT:   [[C7:%[0-9]+]]:_(s64) = G_FCONSTANT double 8.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C8:%[0-9]+]]:_(s64) = G_FCONSTANT double 9.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C9:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+01
+  ; RV32-ILP32D-NEXT:   [[C10:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.100000e+01
+  ; RV32-ILP32D-NEXT:   [[C11:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.200000e+01
+  ; RV32-ILP32D-NEXT:   [[C12:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.300000e+01
+  ; RV32-ILP32D-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C4]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C12]](s64)
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV32-ILP32D-NEXT:   [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; RV32-ILP32D-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C13]](s32)
+  ; RV32-ILP32D-NEXT:   G_STORE [[UV7]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32-ILP32D-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32-ILP32D-NEXT:   $f10_d = COPY [[C1]](s64)
+  ; RV32-ILP32D-NEXT:   $x12 = COPY [[UV2]](s32)
+  ; RV32-ILP32D-NEXT:   $x13 = COPY [[UV3]](s32)
+  ; RV32-ILP32D-NEXT:   $f11_d = COPY [[C3]](s64)
+  ; RV32-ILP32D-NEXT:   $x14 = COPY [[UV4]](s32)
+  ; RV32-ILP32D-NEXT:   $x15 = COPY [[UV5]](s32)
+  ; RV32-ILP32D-NEXT:   $f12_d = COPY [[C5]](s64)
+  ; RV32-ILP32D-NEXT:   $x16 = COPY [[C6]](s32)
+  ; RV32-ILP32D-NEXT:   $f13_d = COPY [[C7]](s64)
+  ; RV32-ILP32D-NEXT:   $f14_d = COPY [[C8]](s64)
+  ; RV32-ILP32D-NEXT:   $f15_d = COPY [[C9]](s64)
+  ; RV32-ILP32D-NEXT:   $f16_d = COPY [[C10]](s64)
+  ; RV32-ILP32D-NEXT:   $f17_d = COPY [[C11]](s64)
+  ; RV32-ILP32D-NEXT:   $x17 = COPY [[UV6]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_gpr_and_stack_almost_exhausted_gprs_fprs, implicit-def $x1, implicit $x10, implicit $x11, implicit $f10_d, implicit $x12, implicit $x13, implicit $f11_d, implicit $x14, implicit $x15, implicit $f12_d, implicit $x16, implicit $f13_d, implicit $f14_d, implicit $f15_d, implicit $f16_d, implicit $f17_d, implicit $x17, implicit-def $x10
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[COPY1]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_double_in_gpr_and_stack_almost_exhausted_gprs_fprs(
+      i64 1, double 2.0, i64 3, double 4.0, i64 5, double 6.0, i32 7, double 8.0,
+      double 9.0, double 10.0, double 11.0, double 12.0, double 13.0)
+  ret i32 %1
+}
+
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_double_on_stack_exhausted_gprs_fprs(i64 %a, double %b, i64 %c, double %d, i64 %e, double %f, i64 %g, double %h, double %i, double %j, double %k, double %l, double %m) nounwind {
+  ; RV32-ILP32D-LABEL: name: callee_double_on_stack_exhausted_gprs_fprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $f10_d, $f11_d, $f12_d, $f13_d, $f14_d, $f15_d, $f16_d, $f17_d
+  ; RV32-ILP32D-NEXT: {{  $}}
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32-ILP32D-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY2:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV32-ILP32D-NEXT:   [[COPY3:%[0-9]+]]:_(s32) = COPY $x12
+  ; RV32-ILP32D-NEXT:   [[COPY4:%[0-9]+]]:_(s32) = COPY $x13
+  ; RV32-ILP32D-NEXT:   [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY3]](s32), [[COPY4]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY5:%[0-9]+]]:_(s64) = COPY $f11_d
+  ; RV32-ILP32D-NEXT:   [[COPY6:%[0-9]+]]:_(s32) = COPY $x14
+  ; RV32-ILP32D-NEXT:   [[COPY7:%[0-9]+]]:_(s32) = COPY $x15
+  ; RV32-ILP32D-NEXT:   [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY8:%[0-9]+]]:_(s64) = COPY $f12_d
+  ; RV32-ILP32D-NEXT:   [[COPY9:%[0-9]+]]:_(s32) = COPY $x16
+  ; RV32-ILP32D-NEXT:   [[COPY10:%[0-9]+]]:_(s32) = COPY $x17
+  ; RV32-ILP32D-NEXT:   [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY9]](s32), [[COPY10]](s32)
+  ; RV32-ILP32D-NEXT:   [[COPY11:%[0-9]+]]:_(s64) = COPY $f13_d
+  ; RV32-ILP32D-NEXT:   [[COPY12:%[0-9]+]]:_(s64) = COPY $f14_d
+  ; RV32-ILP32D-NEXT:   [[COPY13:%[0-9]+]]:_(s64) = COPY $f15_d
+  ; RV32-ILP32D-NEXT:   [[COPY14:%[0-9]+]]:_(s64) = COPY $f16_d
+  ; RV32-ILP32D-NEXT:   [[COPY15:%[0-9]+]]:_(s64) = COPY $f17_d
+  ; RV32-ILP32D-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV32-ILP32D-NEXT:   [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s64) from %fixed-stack.0, align 16)
+  ; RV32-ILP32D-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV3]](s64)
+  ; RV32-ILP32D-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[LOAD]](s64)
+  ; RV32-ILP32D-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TRUNC]], [[FPTOSI]]
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %g_trunc = trunc i64 %g to i32
+  %m_fptosi = fptosi double %m to i32
+  %1 = add i32 %g_trunc, %m_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_double_on_stack_exhausted_gprs_fprs() nounwind {
+  ; RV32-ILP32D-LABEL: name: caller_double_on_stack_exhausted_gprs_fprs
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV32-ILP32D-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
+  ; RV32-ILP32D-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5
+  ; RV32-ILP32D-NEXT:   [[C5:%[0-9]+]]:_(s64) = G_FCONSTANT double 6.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7
+  ; RV32-ILP32D-NEXT:   [[C7:%[0-9]+]]:_(s64) = G_FCONSTANT double 8.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C8:%[0-9]+]]:_(s64) = G_FCONSTANT double 9.000000e+00
+  ; RV32-ILP32D-NEXT:   [[C9:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+01
+  ; RV32-ILP32D-NEXT:   [[C10:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.100000e+01
+  ; RV32-ILP32D-NEXT:   [[C11:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.200000e+01
+  ; RV32-ILP32D-NEXT:   [[C12:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.300000e+01
+  ; RV32-ILP32D-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C4]](s64)
+  ; RV32-ILP32D-NEXT:   [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64)
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV32-ILP32D-NEXT:   [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; RV32-ILP32D-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C13]](s32)
+  ; RV32-ILP32D-NEXT:   G_STORE [[C12]](s64), [[PTR_ADD]](p0) :: (store (s64) into stack, align 16)
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32-ILP32D-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32-ILP32D-NEXT:   $f10_d = COPY [[C1]](s64)
+  ; RV32-ILP32D-NEXT:   $x12 = COPY [[UV2]](s32)
+  ; RV32-ILP32D-NEXT:   $x13 = COPY [[UV3]](s32)
+  ; RV32-ILP32D-NEXT:   $f11_d = COPY [[C3]](s64)
+  ; RV32-ILP32D-NEXT:   $x14 = COPY [[UV4]](s32)
+  ; RV32-ILP32D-NEXT:   $x15 = COPY [[UV5]](s32)
+  ; RV32-ILP32D-NEXT:   $f12_d = COPY [[C5]](s64)
+  ; RV32-ILP32D-NEXT:   $x16 = COPY [[UV6]](s32)
+  ; RV32-ILP32D-NEXT:   $x17 = COPY [[UV7]](s32)
+  ; RV32-ILP32D-NEXT:   $f13_d = COPY [[C7]](s64)
+  ; RV32-ILP32D-NEXT:   $f14_d = COPY [[C8]](s64)
+  ; RV32-ILP32D-NEXT:   $f15_d = COPY [[C9]](s64)
+  ; RV32-ILP32D-NEXT:   $f16_d = COPY [[C10]](s64)
+  ; RV32-ILP32D-NEXT:   $f17_d = COPY [[C11]](s64)
+  ; RV32-ILP32D-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_on_stack_exhausted_gprs_fprs, implicit-def $x1, implicit $x10, implicit $x11, implicit $f10_d, implicit $x12, implicit $x13, implicit $f11_d, implicit $x14, implicit $x15, implicit $f12_d, implicit $x16, implicit $x17, implicit $f13_d, implicit $f14_d, implicit $f15_d, implicit $f16_d, implicit $f17_d, implicit-def $x10
+  ; RV32-ILP32D-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[COPY1]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_double_on_stack_exhausted_gprs_fprs(
+      i64 1, double 2.0, i64 3, double 4.0, i64 5, double 6.0, i64 7, double 8.0,
+      double 9.0, double 10.0, double 11.0, double 12.0, double 13.0)
+  ret i32 %1
+}
+
+define double @callee_double_ret() nounwind {
+  ; RV32-ILP32D-LABEL: name: callee_double_ret
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
+  ; RV32-ILP32D-NEXT:   $f10_d = COPY [[C]](s64)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $f10_d
+  ret double 1.0
+}
+
+define i32 @caller_double_ret() nounwind {
+  ; RV32-ILP32D-LABEL: name: caller_double_ret
+  ; RV32-ILP32D: bb.1 (%ir-block.0):
+  ; RV32-ILP32D-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_ret, implicit-def $x1, implicit-def $f10_d
+  ; RV32-ILP32D-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV32-ILP32D-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
+  ; RV32-ILP32D-NEXT:   $x10 = COPY [[TRUNC]](s32)
+  ; RV32-ILP32D-NEXT:   PseudoRET implicit $x10
+  %1 = call double @callee_double_ret()
+  %2 = bitcast double %1 to i64
+  %3 = trunc i64 %2 to i32
+  ret i32 %3
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32f-ilp32d-common.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32f-ilp32d-common.ll
new file mode 100644
index 000000000000000..31c759adefc5344
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32f-ilp32d-common.ll
@@ -0,0 +1,273 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f \
+; RUN:    -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32-ILP32FD %s
+; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi ilp32d \
+; RUN:    -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32-ILP32FD %s
+
+; This file contains tests that should have identical output for the ilp32f
+; and ilp32d ABIs.
+
+define i32 @callee_float_in_fpr(i32 %a, float %b) nounwind {
+  ; RV32-ILP32FD-LABEL: name: callee_float_in_fpr
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   liveins: $x10, $f10_f
+  ; RV32-ILP32FD-NEXT: {{  $}}
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $f10_f
+  ; RV32-ILP32FD-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY1]](s32)
+  ; RV32-ILP32FD-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[FPTOSI]]
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %b_fptosi = fptosi float %b to i32
+  %1 = add i32 %a, %b_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_float_in_fpr() nounwind {
+  ; RV32-ILP32FD-LABEL: name: caller_float_in_fpr
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+  ; RV32-ILP32FD-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[C]](s32)
+  ; RV32-ILP32FD-NEXT:   $f10_f = COPY [[C1]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_in_fpr, implicit-def $x1, implicit $x10, implicit $f10_f, implicit-def $x10
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_float_in_fpr(i32 1, float 2.0)
+  ret i32 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_float_in_fpr_exhausted_gprs(i64 %a, i64 %b, i64 %c, i64 %d, i32 %e, float %f) nounwind {
+  ; RV32-ILP32FD-LABEL: name: callee_float_in_fpr_exhausted_gprs
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $f10_f
+  ; RV32-ILP32FD-NEXT: {{  $}}
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32-ILP32FD-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+  ; RV32-ILP32FD-NEXT:   [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
+  ; RV32-ILP32FD-NEXT:   [[COPY3:%[0-9]+]]:_(s32) = COPY $x13
+  ; RV32-ILP32FD-NEXT:   [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY2]](s32), [[COPY3]](s32)
+  ; RV32-ILP32FD-NEXT:   [[COPY4:%[0-9]+]]:_(s32) = COPY $x14
+  ; RV32-ILP32FD-NEXT:   [[COPY5:%[0-9]+]]:_(s32) = COPY $x15
+  ; RV32-ILP32FD-NEXT:   [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32)
+  ; RV32-ILP32FD-NEXT:   [[COPY6:%[0-9]+]]:_(s32) = COPY $x16
+  ; RV32-ILP32FD-NEXT:   [[COPY7:%[0-9]+]]:_(s32) = COPY $x17
+  ; RV32-ILP32FD-NEXT:   [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32)
+  ; RV32-ILP32FD-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV32-ILP32FD-NEXT:   [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 16)
+  ; RV32-ILP32FD-NEXT:   [[COPY8:%[0-9]+]]:_(s32) = COPY $f10_f
+  ; RV32-ILP32FD-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY8]](s32)
+  ; RV32-ILP32FD-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[FPTOSI]]
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %f_fptosi = fptosi float %f to i32
+  %1 = add i32 %e, %f_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_float_in_fpr_exhausted_gprs() nounwind {
+  ; RV32-ILP32FD-LABEL: name: caller_float_in_fpr_exhausted_gprs
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV32-ILP32FD-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
+  ; RV32-ILP32FD-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
+  ; RV32-ILP32FD-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
+  ; RV32-ILP32FD-NEXT:   [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+  ; RV32-ILP32FD-NEXT:   [[C5:%[0-9]+]]:_(s32) = G_FCONSTANT float 6.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
+  ; RV32-ILP32FD-NEXT:   [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64)
+  ; RV32-ILP32FD-NEXT:   [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64)
+  ; RV32-ILP32FD-NEXT:   [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64)
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV32-ILP32FD-NEXT:   [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; RV32-ILP32FD-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C6]](s32)
+  ; RV32-ILP32FD-NEXT:   G_STORE [[C4]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32-ILP32FD-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32-ILP32FD-NEXT:   $x12 = COPY [[UV2]](s32)
+  ; RV32-ILP32FD-NEXT:   $x13 = COPY [[UV3]](s32)
+  ; RV32-ILP32FD-NEXT:   $x14 = COPY [[UV4]](s32)
+  ; RV32-ILP32FD-NEXT:   $x15 = COPY [[UV5]](s32)
+  ; RV32-ILP32FD-NEXT:   $x16 = COPY [[UV6]](s32)
+  ; RV32-ILP32FD-NEXT:   $x17 = COPY [[UV7]](s32)
+  ; RV32-ILP32FD-NEXT:   $f10_f = COPY [[C5]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_in_fpr_exhausted_gprs, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit $f10_f, implicit-def $x10
+  ; RV32-ILP32FD-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[COPY1]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_float_in_fpr_exhausted_gprs(
+      i64 1, i64 2, i64 3, i64 4, i32 5, float 6.0)
+  ret i32 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_float_in_gpr_exhausted_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, float %i) nounwind {
+  ; RV32-ILP32FD-LABEL: name: callee_float_in_gpr_exhausted_fprs
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   liveins: $x10, $f10_f, $f11_f, $f12_f, $f13_f, $f14_f, $f15_f, $f16_f, $f17_f
+  ; RV32-ILP32FD-NEXT: {{  $}}
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+  ; RV32-ILP32FD-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $f11_f
+  ; RV32-ILP32FD-NEXT:   [[COPY2:%[0-9]+]]:_(s32) = COPY $f12_f
+  ; RV32-ILP32FD-NEXT:   [[COPY3:%[0-9]+]]:_(s32) = COPY $f13_f
+  ; RV32-ILP32FD-NEXT:   [[COPY4:%[0-9]+]]:_(s32) = COPY $f14_f
+  ; RV32-ILP32FD-NEXT:   [[COPY5:%[0-9]+]]:_(s32) = COPY $f15_f
+  ; RV32-ILP32FD-NEXT:   [[COPY6:%[0-9]+]]:_(s32) = COPY $f16_f
+  ; RV32-ILP32FD-NEXT:   [[COPY7:%[0-9]+]]:_(s32) = COPY $f17_f
+  ; RV32-ILP32FD-NEXT:   [[COPY8:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY7]](s32)
+  ; RV32-ILP32FD-NEXT:   [[FPTOSI1:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY8]](s32)
+  ; RV32-ILP32FD-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[FPTOSI]], [[FPTOSI1]]
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %h_fptosi = fptosi float %h to i32
+  %i_fptosi = fptosi float %i to i32
+  %1 = add i32 %h_fptosi, %i_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_float_in_gpr_exhausted_fprs() nounwind {
+  ; RV32-ILP32FD-LABEL: name: caller_float_in_gpr_exhausted_fprs
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C2:%[0-9]+]]:_(s32) = G_FCONSTANT float 3.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C3:%[0-9]+]]:_(s32) = G_FCONSTANT float 4.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C4:%[0-9]+]]:_(s32) = G_FCONSTANT float 5.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C5:%[0-9]+]]:_(s32) = G_FCONSTANT float 6.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C6:%[0-9]+]]:_(s32) = G_FCONSTANT float 7.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C7:%[0-9]+]]:_(s32) = G_FCONSTANT float 8.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C8:%[0-9]+]]:_(s32) = G_FCONSTANT float 9.000000e+00
+  ; RV32-ILP32FD-NEXT:   $f10_f = COPY [[C]](s32)
+  ; RV32-ILP32FD-NEXT:   $f11_f = COPY [[C1]](s32)
+  ; RV32-ILP32FD-NEXT:   $f12_f = COPY [[C2]](s32)
+  ; RV32-ILP32FD-NEXT:   $f13_f = COPY [[C3]](s32)
+  ; RV32-ILP32FD-NEXT:   $f14_f = COPY [[C4]](s32)
+  ; RV32-ILP32FD-NEXT:   $f15_f = COPY [[C5]](s32)
+  ; RV32-ILP32FD-NEXT:   $f16_f = COPY [[C6]](s32)
+  ; RV32-ILP32FD-NEXT:   $f17_f = COPY [[C7]](s32)
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[C8]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_in_gpr_exhausted_fprs, implicit-def $x1, implicit $f10_f, implicit $f11_f, implicit $f12_f, implicit $f13_f, implicit $f14_f, implicit $f15_f, implicit $f16_f, implicit $f17_f, implicit $x10, implicit-def $x10
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_float_in_gpr_exhausted_fprs(
+      float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0,
+      float 7.0, float 8.0, float 9.0)
+  ret i32 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_float_on_stack_exhausted_gprs_fprs(i64 %a, float %b, i64 %c, float %d, i64 %e, float %f, i64 %g, float %h, float %i, float %j, float %k, float %l, float %m) nounwind {
+  ; RV32-ILP32FD-LABEL: name: callee_float_on_stack_exhausted_gprs_fprs
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $f10_f, $f11_f, $f12_f, $f13_f, $f14_f, $f15_f, $f16_f, $f17_f
+  ; RV32-ILP32FD-NEXT: {{  $}}
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+  ; RV32-ILP32FD-NEXT:   [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+  ; RV32-ILP32FD-NEXT:   [[COPY2:%[0-9]+]]:_(s32) = COPY $f10_f
+  ; RV32-ILP32FD-NEXT:   [[COPY3:%[0-9]+]]:_(s32) = COPY $x12
+  ; RV32-ILP32FD-NEXT:   [[COPY4:%[0-9]+]]:_(s32) = COPY $x13
+  ; RV32-ILP32FD-NEXT:   [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY3]](s32), [[COPY4]](s32)
+  ; RV32-ILP32FD-NEXT:   [[COPY5:%[0-9]+]]:_(s32) = COPY $f11_f
+  ; RV32-ILP32FD-NEXT:   [[COPY6:%[0-9]+]]:_(s32) = COPY $x14
+  ; RV32-ILP32FD-NEXT:   [[COPY7:%[0-9]+]]:_(s32) = COPY $x15
+  ; RV32-ILP32FD-NEXT:   [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32)
+  ; RV32-ILP32FD-NEXT:   [[COPY8:%[0-9]+]]:_(s32) = COPY $f12_f
+  ; RV32-ILP32FD-NEXT:   [[COPY9:%[0-9]+]]:_(s32) = COPY $x16
+  ; RV32-ILP32FD-NEXT:   [[COPY10:%[0-9]+]]:_(s32) = COPY $x17
+  ; RV32-ILP32FD-NEXT:   [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY9]](s32), [[COPY10]](s32)
+  ; RV32-ILP32FD-NEXT:   [[COPY11:%[0-9]+]]:_(s32) = COPY $f13_f
+  ; RV32-ILP32FD-NEXT:   [[COPY12:%[0-9]+]]:_(s32) = COPY $f14_f
+  ; RV32-ILP32FD-NEXT:   [[COPY13:%[0-9]+]]:_(s32) = COPY $f15_f
+  ; RV32-ILP32FD-NEXT:   [[COPY14:%[0-9]+]]:_(s32) = COPY $f16_f
+  ; RV32-ILP32FD-NEXT:   [[COPY15:%[0-9]+]]:_(s32) = COPY $f17_f
+  ; RV32-ILP32FD-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV32-ILP32FD-NEXT:   [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 16)
+  ; RV32-ILP32FD-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV3]](s64)
+  ; RV32-ILP32FD-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[LOAD]](s32)
+  ; RV32-ILP32FD-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TRUNC]], [[FPTOSI]]
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[ADD]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %g_trunc = trunc i64 %g to i32
+  %m_fptosi = fptosi float %m to i32
+  %1 = add i32 %g_trunc, %m_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_float_on_stack_exhausted_gprs_fprs() nounwind {
+  ; RV32-ILP32FD-LABEL: name: caller_float_on_stack_exhausted_gprs_fprs
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV32-ILP32FD-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
+  ; RV32-ILP32FD-NEXT:   [[C3:%[0-9]+]]:_(s32) = G_FCONSTANT float 4.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5
+  ; RV32-ILP32FD-NEXT:   [[C5:%[0-9]+]]:_(s32) = G_FCONSTANT float 6.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7
+  ; RV32-ILP32FD-NEXT:   [[C7:%[0-9]+]]:_(s32) = G_FCONSTANT float 8.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C8:%[0-9]+]]:_(s32) = G_FCONSTANT float 9.000000e+00
+  ; RV32-ILP32FD-NEXT:   [[C9:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+01
+  ; RV32-ILP32FD-NEXT:   [[C10:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.100000e+01
+  ; RV32-ILP32FD-NEXT:   [[C11:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.200000e+01
+  ; RV32-ILP32FD-NEXT:   [[C12:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.300000e+01
+  ; RV32-ILP32FD-NEXT:   [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
+  ; RV32-ILP32FD-NEXT:   [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64)
+  ; RV32-ILP32FD-NEXT:   [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C4]](s64)
+  ; RV32-ILP32FD-NEXT:   [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64)
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV32-ILP32FD-NEXT:   [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; RV32-ILP32FD-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C13]](s32)
+  ; RV32-ILP32FD-NEXT:   G_STORE [[C12]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[UV]](s32)
+  ; RV32-ILP32FD-NEXT:   $x11 = COPY [[UV1]](s32)
+  ; RV32-ILP32FD-NEXT:   $f10_f = COPY [[C1]](s32)
+  ; RV32-ILP32FD-NEXT:   $x12 = COPY [[UV2]](s32)
+  ; RV32-ILP32FD-NEXT:   $x13 = COPY [[UV3]](s32)
+  ; RV32-ILP32FD-NEXT:   $f11_f = COPY [[C3]](s32)
+  ; RV32-ILP32FD-NEXT:   $x14 = COPY [[UV4]](s32)
+  ; RV32-ILP32FD-NEXT:   $x15 = COPY [[UV5]](s32)
+  ; RV32-ILP32FD-NEXT:   $f12_f = COPY [[C5]](s32)
+  ; RV32-ILP32FD-NEXT:   $x16 = COPY [[UV6]](s32)
+  ; RV32-ILP32FD-NEXT:   $x17 = COPY [[UV7]](s32)
+  ; RV32-ILP32FD-NEXT:   $f13_f = COPY [[C7]](s32)
+  ; RV32-ILP32FD-NEXT:   $f14_f = COPY [[C8]](s32)
+  ; RV32-ILP32FD-NEXT:   $f15_f = COPY [[C9]](s32)
+  ; RV32-ILP32FD-NEXT:   $f16_f = COPY [[C10]](s32)
+  ; RV32-ILP32FD-NEXT:   $f17_f = COPY [[C11]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_on_stack_exhausted_gprs_fprs, implicit-def $x1, implicit $x10, implicit $x11, implicit $f10_f, implicit $x12, implicit $x13, implicit $f11_f, implicit $x14, implicit $x15, implicit $f12_f, implicit $x16, implicit $x17, implicit $f13_f, implicit $f14_f, implicit $f15_f, implicit $f16_f, implicit $f17_f, implicit-def $x10
+  ; RV32-ILP32FD-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[COPY1]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_float_on_stack_exhausted_gprs_fprs(
+      i64 1, float 2.0, i64 3, float 4.0, i64 5, float 6.0, i64 7, float 8.0,
+      float 9.0, float 10.0, float 11.0, float 12.0, float 13.0)
+  ret i32 %1
+}
+
+define float @callee_float_ret() nounwind {
+  ; RV32-ILP32FD-LABEL: name: callee_float_ret
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00
+  ; RV32-ILP32FD-NEXT:   $f10_f = COPY [[C]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $f10_f
+  ret float 1.0
+}
+
+define i32 @caller_float_ret() nounwind {
+  ; RV32-ILP32FD-LABEL: name: caller_float_ret
+  ; RV32-ILP32FD: bb.1 (%ir-block.0):
+  ; RV32-ILP32FD-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_ret, implicit-def $x1, implicit-def $f10_f
+  ; RV32-ILP32FD-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+  ; RV32-ILP32FD-NEXT:   $x10 = COPY [[COPY]](s32)
+  ; RV32-ILP32FD-NEXT:   PseudoRET implicit $x10
+  %1 = call float @callee_float_ret()
+  %2 = bitcast float %1 to i32
+  ret i32 %2
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-common.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-common.ll
new file mode 100644
index 000000000000000..4d6275db77bc895
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-common.ll
@@ -0,0 +1,62 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv64 \
+; RUN:     -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV64I %s
+; RUN: llc -mtriple=riscv64 -mattr=+f -target-abi lp64f \
+; RUN:    -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV64I %s
+
+; This file contains tests that should have identical output for the lp64 and
+; lp64f ABIs.
+
+define i64 @callee_double_in_regs(i64 %a, double %b) nounwind {
+  ; RV64I-LABEL: name: callee_double_in_regs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   liveins: $x10, $x11
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+  ; RV64I-NEXT:   [[FPTOSI:%[0-9]+]]:_(s64) = G_FPTOSI [[COPY1]](s64)
+  ; RV64I-NEXT:   [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[FPTOSI]]
+  ; RV64I-NEXT:   $x10 = COPY [[ADD]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %b_fptosi = fptosi double %b to i64
+  %1 = add i64 %a, %b_fptosi
+  ret i64 %1
+}
+
+define i64 @caller_double_in_regs() nounwind {
+  ; RV64I-LABEL: name: caller_double_in_regs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV64I-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV64I-NEXT:   $x10 = COPY [[C]](s64)
+  ; RV64I-NEXT:   $x11 = COPY [[C1]](s64)
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_regs, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   $x10 = COPY [[COPY]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %1 = call i64 @callee_double_in_regs(i64 1, double 2.0)
+  ret i64 %1
+}
+
+define double @callee_double_ret() nounwind {
+  ; RV64I-LABEL: name: callee_double_ret
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
+  ; RV64I-NEXT:   $x10 = COPY [[C]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  ret double 1.0
+}
+
+define i64 @caller_double_ret() nounwind {
+  ; RV64I-LABEL: name: caller_double_ret
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_ret, implicit-def $x1, implicit-def $x10
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   $x10 = COPY [[COPY]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %1 = call double @callee_double_ret()
+  %2 = bitcast double %1 to i64
+  ret i64 %2
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64.ll
new file mode 100644
index 000000000000000..a45af04c09b21c6
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64.ll
@@ -0,0 +1,82 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv64 -global-isel -stop-after=irtranslator \
+; RUN:    -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64,RV64I %s
+; RUN: llc -mtriple=riscv64 -mattr=+f -target-abi=lp64 \
+; RUN:    -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64,RV64F %s
+
+; Any tests that would have identical output for some combination of the lp64*
+; ABIs belong in calling-conv-*-common.ll. This file contains tests that will
+; have 
diff erent output across those ABIs. i.e. where some arguments would be
+; passed according to the floating point ABI.
+
+define i64 @callee_float_in_regs(i64 %a, float %b) nounwind {
+  ; RV64-LABEL: name: callee_float_in_regs
+  ; RV64: bb.1 (%ir-block.0):
+  ; RV64-NEXT:   liveins: $x10, $x11
+  ; RV64-NEXT: {{  $}}
+  ; RV64-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+  ; RV64-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64)
+  ; RV64-NEXT:   [[FPTOSI:%[0-9]+]]:_(s64) = G_FPTOSI [[TRUNC]](s32)
+  ; RV64-NEXT:   [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[FPTOSI]]
+  ; RV64-NEXT:   $x10 = COPY [[ADD]](s64)
+  ; RV64-NEXT:   PseudoRET implicit $x10
+  %b_fptosi = fptosi float %b to i64
+  %1 = add i64 %a, %b_fptosi
+  ret i64 %1
+}
+
+define i64 @caller_float_in_regs() nounwind {
+  ; RV64I-LABEL: name: caller_float_in_regs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV64I-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
+  ; RV64I-NEXT:   [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C1]](s32)
+  ; RV64I-NEXT:   $x10 = COPY [[C]](s64)
+  ; RV64I-NEXT:   $x11 = COPY [[ANYEXT]](s64)
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_in_regs, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   $x10 = COPY [[COPY]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  ;
+  ; RV64F-LABEL: name: caller_float_in_regs
+  ; RV64F: bb.1 (%ir-block.0):
+  ; RV64F-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV64F-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
+  ; RV64F-NEXT:   $x10 = COPY [[C]](s64)
+  ; RV64F-NEXT:   [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C1]](s32)
+  ; RV64F-NEXT:   $x11 = COPY [[ANYEXT]](s64)
+  ; RV64F-NEXT:   PseudoCALL target-flags(riscv-call) @callee_float_in_regs, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+  ; RV64F-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64F-NEXT:   $x10 = COPY [[COPY]](s64)
+  ; RV64F-NEXT:   PseudoRET implicit $x10
+  %1 = call i64 @callee_float_in_regs(i64 1, float 2.0)
+  ret i64 %1
+}
+
+define float @callee_tiny_scalar_ret() nounwind {
+  ; RV64-LABEL: name: callee_tiny_scalar_ret
+  ; RV64: bb.1 (%ir-block.0):
+  ; RV64-NEXT:   [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00
+  ; RV64-NEXT:   [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C]](s32)
+  ; RV64-NEXT:   $x10 = COPY [[ANYEXT]](s64)
+  ; RV64-NEXT:   PseudoRET implicit $x10
+  ret float 1.0
+}
+
+define i64 @caller_tiny_scalar_ret() nounwind {
+  ; RV64-LABEL: name: caller_tiny_scalar_ret
+  ; RV64: bb.1 (%ir-block.0):
+  ; RV64-NEXT:   PseudoCALL target-flags(riscv-call) @callee_tiny_scalar_ret, implicit-def $x1, implicit-def $x10
+  ; RV64-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
+  ; RV64-NEXT:   [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[TRUNC]](s32)
+  ; RV64-NEXT:   $x10 = COPY [[SEXT]](s64)
+  ; RV64-NEXT:   PseudoRET implicit $x10
+  %1 = call float @callee_tiny_scalar_ret()
+  %2 = bitcast float %1 to i32
+  %3 = sext i32 %2 to i64
+  ret i64 %3
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64d.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64d.ll
new file mode 100644
index 000000000000000..90ab171dd55a95d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64d.ll
@@ -0,0 +1,273 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv64 -mattr=+d -target-abi lp64d \
+; RUN:    -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV64I %s
+
+; This file contains tests that should have identical output for the lp64 and
+; lp64f ABIs.
+
+define i64 @callee_double_in_regs(i64 %a, double %b) nounwind {
+  ; RV64I-LABEL: name: callee_double_in_regs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   liveins: $x10, $f10_d
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV64I-NEXT:   [[FPTOSI:%[0-9]+]]:_(s64) = G_FPTOSI [[COPY1]](s64)
+  ; RV64I-NEXT:   [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[FPTOSI]]
+  ; RV64I-NEXT:   $x10 = COPY [[ADD]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %b_fptosi = fptosi double %b to i64
+  %1 = add i64 %a, %b_fptosi
+  ret i64 %1
+}
+
+define i64 @caller_double_in_regs() nounwind {
+  ; RV64I-LABEL: name: caller_double_in_regs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+  ; RV64I-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV64I-NEXT:   $x10 = COPY [[C]](s64)
+  ; RV64I-NEXT:   $f10_d = COPY [[C1]](s64)
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_regs, implicit-def $x1, implicit $x10, implicit $f10_d, implicit-def $x10
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   $x10 = COPY [[COPY]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %1 = call i64 @callee_double_in_regs(i64 1, double 2.0)
+  ret i64 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i64 @callee_double_in_fpr_exhausted_gprs(i128 %a, i128 %b, i128 %c, i128 %d, i64 %e, double %f) nounwind {
+  ; RV64I-LABEL: name: callee_double_in_fpr_exhausted_gprs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $f10_d
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+  ; RV64I-NEXT:   [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY]](s64), [[COPY1]](s64)
+  ; RV64I-NEXT:   [[COPY2:%[0-9]+]]:_(s64) = COPY $x12
+  ; RV64I-NEXT:   [[COPY3:%[0-9]+]]:_(s64) = COPY $x13
+  ; RV64I-NEXT:   [[MV1:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY2]](s64), [[COPY3]](s64)
+  ; RV64I-NEXT:   [[COPY4:%[0-9]+]]:_(s64) = COPY $x14
+  ; RV64I-NEXT:   [[COPY5:%[0-9]+]]:_(s64) = COPY $x15
+  ; RV64I-NEXT:   [[MV2:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY4]](s64), [[COPY5]](s64)
+  ; RV64I-NEXT:   [[COPY6:%[0-9]+]]:_(s64) = COPY $x16
+  ; RV64I-NEXT:   [[COPY7:%[0-9]+]]:_(s64) = COPY $x17
+  ; RV64I-NEXT:   [[MV3:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY6]](s64), [[COPY7]](s64)
+  ; RV64I-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV64I-NEXT:   [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s64) from %fixed-stack.0, align 16)
+  ; RV64I-NEXT:   [[COPY8:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV64I-NEXT:   [[FPTOSI:%[0-9]+]]:_(s64) = G_FPTOSI [[COPY8]](s64)
+  ; RV64I-NEXT:   [[ADD:%[0-9]+]]:_(s64) = G_ADD [[LOAD]], [[FPTOSI]]
+  ; RV64I-NEXT:   $x10 = COPY [[ADD]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %f_fptosi = fptosi double %f to i64
+  %1 = add i64 %e, %f_fptosi
+  ret i64 %1
+}
+
+define i64 @caller_double_in_fpr_exhausted_gprs() nounwind {
+  ; RV64I-LABEL: name: caller_double_in_fpr_exhausted_gprs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 1
+  ; RV64I-NEXT:   [[C1:%[0-9]+]]:_(s128) = G_CONSTANT i128 2
+  ; RV64I-NEXT:   [[C2:%[0-9]+]]:_(s128) = G_CONSTANT i128 3
+  ; RV64I-NEXT:   [[C3:%[0-9]+]]:_(s128) = G_CONSTANT i128 4
+  ; RV64I-NEXT:   [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5
+  ; RV64I-NEXT:   [[C5:%[0-9]+]]:_(s64) = G_FCONSTANT double 6.000000e+00
+  ; RV64I-NEXT:   [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C]](s128)
+  ; RV64I-NEXT:   [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C1]](s128)
+  ; RV64I-NEXT:   [[UV4:%[0-9]+]]:_(s64), [[UV5:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C2]](s128)
+  ; RV64I-NEXT:   [[UV6:%[0-9]+]]:_(s64), [[UV7:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C3]](s128)
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV64I-NEXT:   [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+  ; RV64I-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C6]](s64)
+  ; RV64I-NEXT:   G_STORE [[C4]](s64), [[PTR_ADD]](p0) :: (store (s64) into stack, align 16)
+  ; RV64I-NEXT:   $x10 = COPY [[UV]](s64)
+  ; RV64I-NEXT:   $x11 = COPY [[UV1]](s64)
+  ; RV64I-NEXT:   $x12 = COPY [[UV2]](s64)
+  ; RV64I-NEXT:   $x13 = COPY [[UV3]](s64)
+  ; RV64I-NEXT:   $x14 = COPY [[UV4]](s64)
+  ; RV64I-NEXT:   $x15 = COPY [[UV5]](s64)
+  ; RV64I-NEXT:   $x16 = COPY [[UV6]](s64)
+  ; RV64I-NEXT:   $x17 = COPY [[UV7]](s64)
+  ; RV64I-NEXT:   $f10_d = COPY [[C5]](s64)
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_fpr_exhausted_gprs, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit $f10_d, implicit-def $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   $x10 = COPY [[COPY1]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %1 = call i64 @callee_double_in_fpr_exhausted_gprs(
+      i128 1, i128 2, i128 3, i128 4, i64 5, double 6.0)
+  ret i64 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i32 @callee_double_in_gpr_exhausted_fprs(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i) nounwind {
+  ; RV64I-LABEL: name: callee_double_in_gpr_exhausted_fprs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   liveins: $x10, $f10_d, $f11_d, $f12_d, $f13_d, $f14_d, $f15_d, $f16_d, $f17_d
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $f11_d
+  ; RV64I-NEXT:   [[COPY2:%[0-9]+]]:_(s64) = COPY $f12_d
+  ; RV64I-NEXT:   [[COPY3:%[0-9]+]]:_(s64) = COPY $f13_d
+  ; RV64I-NEXT:   [[COPY4:%[0-9]+]]:_(s64) = COPY $f14_d
+  ; RV64I-NEXT:   [[COPY5:%[0-9]+]]:_(s64) = COPY $f15_d
+  ; RV64I-NEXT:   [[COPY6:%[0-9]+]]:_(s64) = COPY $f16_d
+  ; RV64I-NEXT:   [[COPY7:%[0-9]+]]:_(s64) = COPY $f17_d
+  ; RV64I-NEXT:   [[COPY8:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   [[FPTOSI:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY7]](s64)
+  ; RV64I-NEXT:   [[FPTOSI1:%[0-9]+]]:_(s32) = G_FPTOSI [[COPY8]](s64)
+  ; RV64I-NEXT:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[FPTOSI]], [[FPTOSI1]]
+  ; RV64I-NEXT:   [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ADD]](s32)
+  ; RV64I-NEXT:   $x10 = COPY [[ANYEXT]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %h_fptosi = fptosi double %h to i32
+  %i_fptosi = fptosi double %i to i32
+  %1 = add i32 %h_fptosi, %i_fptosi
+  ret i32 %1
+}
+
+define i32 @caller_double_in_gpr_exhausted_fprs() nounwind {
+  ; RV64I-LABEL: name: caller_double_in_gpr_exhausted_fprs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
+  ; RV64I-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV64I-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_FCONSTANT double 3.000000e+00
+  ; RV64I-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.000000e+00
+  ; RV64I-NEXT:   [[C4:%[0-9]+]]:_(s64) = G_FCONSTANT double 5.000000e+00
+  ; RV64I-NEXT:   [[C5:%[0-9]+]]:_(s64) = G_FCONSTANT double 6.000000e+00
+  ; RV64I-NEXT:   [[C6:%[0-9]+]]:_(s64) = G_FCONSTANT double 7.000000e+00
+  ; RV64I-NEXT:   [[C7:%[0-9]+]]:_(s64) = G_FCONSTANT double 8.000000e+00
+  ; RV64I-NEXT:   [[C8:%[0-9]+]]:_(s64) = G_FCONSTANT double 9.000000e+00
+  ; RV64I-NEXT:   $f10_d = COPY [[C]](s64)
+  ; RV64I-NEXT:   $f11_d = COPY [[C1]](s64)
+  ; RV64I-NEXT:   $f12_d = COPY [[C2]](s64)
+  ; RV64I-NEXT:   $f13_d = COPY [[C3]](s64)
+  ; RV64I-NEXT:   $f14_d = COPY [[C4]](s64)
+  ; RV64I-NEXT:   $f15_d = COPY [[C5]](s64)
+  ; RV64I-NEXT:   $f16_d = COPY [[C6]](s64)
+  ; RV64I-NEXT:   $f17_d = COPY [[C7]](s64)
+  ; RV64I-NEXT:   $x10 = COPY [[C8]](s64)
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_in_gpr_exhausted_fprs, implicit-def $x1, implicit $f10_d, implicit $f11_d, implicit $f12_d, implicit $f13_d, implicit $f14_d, implicit $f15_d, implicit $f16_d, implicit $f17_d, implicit $x10, implicit-def $x10
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
+  ; RV64I-NEXT:   [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]](s32)
+  ; RV64I-NEXT:   $x10 = COPY [[ANYEXT]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %1 = call i32 @callee_double_in_gpr_exhausted_fprs(
+      double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0,
+      double 7.0, double 8.0, double 9.0)
+  ret i32 %1
+}
+
+; Must keep define on a single line due to an update_llc_test_checks.py limitation
+define i64 @callee_double_on_stack_exhausted_gprs_fprs(i128 %a, double %b, i128 %c, double %d, i128 %e, double %f, i128 %g, double %h, double %i, double %j, double %k, double %l, double %m) nounwind {
+  ; RV64I-LABEL: name: callee_double_on_stack_exhausted_gprs_fprs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $f10_d, $f11_d, $f12_d, $f13_d, $f14_d, $f15_d, $f16_d, $f17_d
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+  ; RV64I-NEXT:   [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY]](s64), [[COPY1]](s64)
+  ; RV64I-NEXT:   [[COPY2:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV64I-NEXT:   [[COPY3:%[0-9]+]]:_(s64) = COPY $x12
+  ; RV64I-NEXT:   [[COPY4:%[0-9]+]]:_(s64) = COPY $x13
+  ; RV64I-NEXT:   [[MV1:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY3]](s64), [[COPY4]](s64)
+  ; RV64I-NEXT:   [[COPY5:%[0-9]+]]:_(s64) = COPY $f11_d
+  ; RV64I-NEXT:   [[COPY6:%[0-9]+]]:_(s64) = COPY $x14
+  ; RV64I-NEXT:   [[COPY7:%[0-9]+]]:_(s64) = COPY $x15
+  ; RV64I-NEXT:   [[MV2:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY6]](s64), [[COPY7]](s64)
+  ; RV64I-NEXT:   [[COPY8:%[0-9]+]]:_(s64) = COPY $f12_d
+  ; RV64I-NEXT:   [[COPY9:%[0-9]+]]:_(s64) = COPY $x16
+  ; RV64I-NEXT:   [[COPY10:%[0-9]+]]:_(s64) = COPY $x17
+  ; RV64I-NEXT:   [[MV3:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY9]](s64), [[COPY10]](s64)
+  ; RV64I-NEXT:   [[COPY11:%[0-9]+]]:_(s64) = COPY $f13_d
+  ; RV64I-NEXT:   [[COPY12:%[0-9]+]]:_(s64) = COPY $f14_d
+  ; RV64I-NEXT:   [[COPY13:%[0-9]+]]:_(s64) = COPY $f15_d
+  ; RV64I-NEXT:   [[COPY14:%[0-9]+]]:_(s64) = COPY $f16_d
+  ; RV64I-NEXT:   [[COPY15:%[0-9]+]]:_(s64) = COPY $f17_d
+  ; RV64I-NEXT:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+  ; RV64I-NEXT:   [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s64) from %fixed-stack.0, align 16)
+  ; RV64I-NEXT:   [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[MV3]](s128)
+  ; RV64I-NEXT:   [[FPTOSI:%[0-9]+]]:_(s64) = G_FPTOSI [[LOAD]](s64)
+  ; RV64I-NEXT:   [[ADD:%[0-9]+]]:_(s64) = G_ADD [[TRUNC]], [[FPTOSI]]
+  ; RV64I-NEXT:   $x10 = COPY [[ADD]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %g_trunc = trunc i128 %g to i64
+  %m_fptosi = fptosi double %m to i64
+  %1 = add i64 %g_trunc, %m_fptosi
+  ret i64 %1
+}
+
+define i64 @caller_double_on_stack_exhausted_gprs_fprs() nounwind {
+  ; RV64I-LABEL: name: caller_double_on_stack_exhausted_gprs_fprs
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 1
+  ; RV64I-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
+  ; RV64I-NEXT:   [[C2:%[0-9]+]]:_(s128) = G_CONSTANT i128 3
+  ; RV64I-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.000000e+00
+  ; RV64I-NEXT:   [[C4:%[0-9]+]]:_(s128) = G_CONSTANT i128 5
+  ; RV64I-NEXT:   [[C5:%[0-9]+]]:_(s64) = G_FCONSTANT double 6.000000e+00
+  ; RV64I-NEXT:   [[C6:%[0-9]+]]:_(s128) = G_CONSTANT i128 7
+  ; RV64I-NEXT:   [[C7:%[0-9]+]]:_(s64) = G_FCONSTANT double 8.000000e+00
+  ; RV64I-NEXT:   [[C8:%[0-9]+]]:_(s64) = G_FCONSTANT double 9.000000e+00
+  ; RV64I-NEXT:   [[C9:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+01
+  ; RV64I-NEXT:   [[C10:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.100000e+01
+  ; RV64I-NEXT:   [[C11:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.200000e+01
+  ; RV64I-NEXT:   [[C12:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.300000e+01
+  ; RV64I-NEXT:   [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C]](s128)
+  ; RV64I-NEXT:   [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C2]](s128)
+  ; RV64I-NEXT:   [[UV4:%[0-9]+]]:_(s64), [[UV5:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C4]](s128)
+  ; RV64I-NEXT:   [[UV6:%[0-9]+]]:_(s64), [[UV7:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[C6]](s128)
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x2
+  ; RV64I-NEXT:   [[C13:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+  ; RV64I-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C13]](s64)
+  ; RV64I-NEXT:   G_STORE [[C12]](s64), [[PTR_ADD]](p0) :: (store (s64) into stack, align 16)
+  ; RV64I-NEXT:   $x10 = COPY [[UV]](s64)
+  ; RV64I-NEXT:   $x11 = COPY [[UV1]](s64)
+  ; RV64I-NEXT:   $f10_d = COPY [[C1]](s64)
+  ; RV64I-NEXT:   $x12 = COPY [[UV2]](s64)
+  ; RV64I-NEXT:   $x13 = COPY [[UV3]](s64)
+  ; RV64I-NEXT:   $f11_d = COPY [[C3]](s64)
+  ; RV64I-NEXT:   $x14 = COPY [[UV4]](s64)
+  ; RV64I-NEXT:   $x15 = COPY [[UV5]](s64)
+  ; RV64I-NEXT:   $f12_d = COPY [[C5]](s64)
+  ; RV64I-NEXT:   $x16 = COPY [[UV6]](s64)
+  ; RV64I-NEXT:   $x17 = COPY [[UV7]](s64)
+  ; RV64I-NEXT:   $f13_d = COPY [[C7]](s64)
+  ; RV64I-NEXT:   $f14_d = COPY [[C8]](s64)
+  ; RV64I-NEXT:   $f15_d = COPY [[C9]](s64)
+  ; RV64I-NEXT:   $f16_d = COPY [[C10]](s64)
+  ; RV64I-NEXT:   $f17_d = COPY [[C11]](s64)
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_on_stack_exhausted_gprs_fprs, implicit-def $x1, implicit $x10, implicit $x11, implicit $f10_d, implicit $x12, implicit $x13, implicit $f11_d, implicit $x14, implicit $x15, implicit $f12_d, implicit $x16, implicit $x17, implicit $f13_d, implicit $f14_d, implicit $f15_d, implicit $f16_d, implicit $f17_d, implicit-def $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY $x10
+  ; RV64I-NEXT:   $x10 = COPY [[COPY1]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %1 = call i64 @callee_double_on_stack_exhausted_gprs_fprs(
+      i128 1, double 2.0, i128 3, double 4.0, i128 5, double 6.0, i128 7, double 8.0,
+      double 9.0, double 10.0, double 11.0, double 12.0, double 13.0)
+  ret i64 %1
+}
+
+define double @callee_double_ret() nounwind {
+  ; RV64I-LABEL: name: callee_double_ret
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
+  ; RV64I-NEXT:   $f10_d = COPY [[C]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $f10_d
+  ret double 1.0
+}
+
+define i64 @caller_double_ret() nounwind {
+  ; RV64I-LABEL: name: caller_double_ret
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   PseudoCALL target-flags(riscv-call) @callee_double_ret, implicit-def $x1, implicit-def $f10_d
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
+  ; RV64I-NEXT:   $x10 = COPY [[COPY]](s64)
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  %1 = call double @callee_double_ret()
+  %2 = bitcast double %1 to i64
+  ret i64 %2
+}


        


More information about the llvm-commits mailing list