[llvm] [RISCV] Teach copyPhysReg to allow copies between GPR<->FPR32/FPR64 when the GPR is the same size. (PR #70525)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 28 14:24:03 PDT 2023


https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/70525

>From f289b8ec7045a0561cbab4c8e4865c823e8f8fd2 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 27 Oct 2023 15:13:11 -0700
Subject: [PATCH] [RISCV] Teach copyPhysReg to allow copies between
 GPR<->FPR32/FPR64.

This is needed because GISel emits copies instead of bitcasts like SelectionDAG.
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      | 30 ++++++++++++++++
 .../RISCV/GlobalISel/fpr-gpr-copy-rv32.ll     | 19 +++++++++++
 .../RISCV/GlobalISel/fpr-gpr-copy-rv64.ll     | 34 +++++++++++++++++++
 3 files changed, 83 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv32.ll
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index bfe43bae7cb12a5..3b82645d38a457c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -471,6 +471,36 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
     return;
   }
 
+  if (RISCV::FPR32RegClass.contains(DstReg) &&
+      RISCV::GPRRegClass.contains(SrcReg)) {
+    BuildMI(MBB, MBBI, DL, get(RISCV::FMV_W_X), DstReg)
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
+  if (RISCV::GPRRegClass.contains(DstReg) &&
+      RISCV::FPR32RegClass.contains(SrcReg)) {
+    BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_W), DstReg)
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
+  if (RISCV::FPR64RegClass.contains(DstReg) &&
+      RISCV::GPRRegClass.contains(SrcReg)) {
+    assert(STI.getXLen() == 64 && "Unexpected GPR size");
+    BuildMI(MBB, MBBI, DL, get(RISCV::FMV_D_X), DstReg)
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
+  if (RISCV::GPRRegClass.contains(DstReg) &&
+      RISCV::FPR64RegClass.contains(SrcReg)) {
+    assert(STI.getXLen() == 64 && "Unexpected GPR size");
+    BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_D), DstReg)
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
   // VR->VR copies.
   if (RISCV::VRRegClass.contains(DstReg, SrcReg)) {
     copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V);
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv32.ll b/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv32.ll
new file mode 100644
index 000000000000000..1757e5550f81aeb
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv32.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv32 -global-isel -mattr=+f -target-abi=ilp32 \
+; RUN:   -verify-machineinstrs < %s | FileCheck -check-prefix=RV32I %s
+
+; Test copying between FPR32 and GPR on RV32.
+; FIXME: This test should be replaced with a more general calling convention
+; test once we have more FP implemented.
+
+define float @fadd(float %x, float %y) {
+; RV32I-LABEL: fadd:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    fmv.w.x fa5, a0
+; RV32I-NEXT:    fmv.w.x fa4, a1
+; RV32I-NEXT:    fadd.s fa5, fa5, fa4
+; RV32I-NEXT:    fmv.x.w a0, fa5
+; RV32I-NEXT:    ret
+  %a = fadd float %x, %y
+  ret float %a
+}
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll b/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll
new file mode 100644
index 000000000000000..2eca0ad66f5c6b6
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv64 -global-isel -mattr=+d -target-abi=lp64 \
+; RUN:   -verify-machineinstrs < %s | FileCheck -check-prefix=RV64I %s
+
+; Test copying between FPR64 and GPR on RV64.
+; FIXME: This test should be replaced with a more general calling convention
+; test once we have more FP implemented.
+
+define double @fadd_f64(double %x, double %y) {
+; RV64I-LABEL: fadd_f64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    fmv.d.x fa5, a0
+; RV64I-NEXT:    fmv.d.x fa4, a1
+; RV64I-NEXT:    fadd.d fa5, fa5, fa4
+; RV64I-NEXT:    fmv.x.d a0, fa5
+; RV64I-NEXT:    ret
+  %a = fadd double %x, %y
+  ret double %a
+
+; Test copying between FPR32 and GPR on RV64.
+; FIXME: This test should be replaced with a more general calling convention
+; test once we have more FP implemented.
+
+define float @fadd_f32(float %x, float %y) {
+; RV32I-LABEL: fadd:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    fmv.d.x fa5, a0
+; RV32I-NEXT:    fmv.d.x fa4, a1
+; RV32I-NEXT:    fadd.d fa5, fa5, fa4
+; RV32I-NEXT:    fmv.x.d a0, fa5
+; RV32I-NEXT:    ret
+  %a = fadd float %x, %y
+  ret float %a
+}



More information about the llvm-commits mailing list