[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
Fri Oct 27 17:14:10 PDT 2023


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

This is needed because GISel emits copies instead of bitcasts like SelectionDAG.
    
I've restricted to the case where size matches in this patch. GISel
can also emit copies from FPR32->GPR on RV64, but maybe that should be handled
in GISel itself.

>From 79a6d18386666d4e2e91e9d2d9bb905d318d4dda 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 1/3] [RISCV] Teach copyPhysReg to allow copies between
 GPR<->FPR32/FPR64 when the GPR is the same size.

This is needed because GISel emits copies instead of bitcasts like SelectionDAG.

I've restricted to the case where size matches in this patch. GISel
can also emit copies from FPR32->GPR on RV64, but maybe that should be handled
in GISel itself.
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      | 28 +++++++++++++++++++
 .../RISCV/GlobalISel/fpr-gpr-copy-rv32.ll     | 19 +++++++++++++
 .../RISCV/GlobalISel/fpr-gpr-copy-rv64.ll     | 19 +++++++++++++
 3 files changed, 66 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..7b76504b7e8fc2e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -471,6 +471,34 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
     return;
   }
 
+  if (STI.getXLen() == 32 && RISCV::FPR32RegClass.contains(DstReg) &&
+      RISCV::GPRRegClass.contains(SrcReg)) {
+    BuildMI(MBB, MBBI, DL, get(RISCV::FMV_W_X), DstReg)
+      .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
+  if (STI.getXLen() == 32 && RISCV::GPRRegClass.contains(DstReg) &&
+      RISCV::FPR32RegClass.contains(SrcReg)) {
+    BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_W), DstReg)
+      .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
+  if (STI.getXLen() == 64 && RISCV::FPR64RegClass.contains(DstReg) &&
+      RISCV::GPRRegClass.contains(SrcReg)) {
+    BuildMI(MBB, MBBI, DL, get(RISCV::FMV_D_X), DstReg)
+      .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
+  if (STI.getXLen() == 64 && RISCV::GPRRegClass.contains(DstReg) &&
+      RISCV::FPR64RegClass.contains(SrcReg)) {
+    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..6155e73a855a479
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll
@@ -0,0 +1,19 @@
+; 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=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 double @fadd(double %x, double %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 double %x, %y
+  ret double %a
+}

>From 4b52934b4497c5f4ae6342c050416255991d8f7c Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 27 Oct 2023 15:15:49 -0700
Subject: [PATCH 2/3] !fixup clang-format

---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 7b76504b7e8fc2e..91575bd0dd174b0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -474,28 +474,28 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   if (STI.getXLen() == 32 && RISCV::FPR32RegClass.contains(DstReg) &&
       RISCV::GPRRegClass.contains(SrcReg)) {
     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_W_X), DstReg)
-      .addReg(SrcReg, getKillRegState(KillSrc));
+        .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   }
 
   if (STI.getXLen() == 32 && RISCV::GPRRegClass.contains(DstReg) &&
       RISCV::FPR32RegClass.contains(SrcReg)) {
     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_W), DstReg)
-      .addReg(SrcReg, getKillRegState(KillSrc));
+        .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   }
 
   if (STI.getXLen() == 64 && RISCV::FPR64RegClass.contains(DstReg) &&
       RISCV::GPRRegClass.contains(SrcReg)) {
     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_D_X), DstReg)
-      .addReg(SrcReg, getKillRegState(KillSrc));
+        .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   }
 
   if (STI.getXLen() == 64 && RISCV::GPRRegClass.contains(DstReg) &&
       RISCV::FPR64RegClass.contains(SrcReg)) {
     BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_D), DstReg)
-      .addReg(SrcReg, getKillRegState(KillSrc));
+        .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   }
 

>From 2057f1281d6377bbc42b105b967cf8ebaa406d89 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 27 Oct 2023 15:17:30 -0700
Subject: [PATCH 3/3] !fixup correct comment in test

---
 llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll b/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll
index 6155e73a855a479..88dc15087206519 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/fpr-gpr-copy-rv64.ll
@@ -2,7 +2,7 @@
 ; RUN: llc -mtriple=riscv64 -global-isel -mattr=+d -target-abi=lp64 \
 ; RUN:   -verify-machineinstrs < %s | FileCheck -check-prefix=RV32I %s
 
-; Test copying between FPR32 and GPR on RV32.
+; 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.
 



More information about the llvm-commits mailing list