Skip to content

Commit 284d136

Browse files
authored
[RISCV] Teach copyPhysReg to allow copies between GPR<->FPR32/FPR64 (#70525)
This is needed because GISel emits copies instead of bitcasts like SelectionDAG.
1 parent f706837 commit 284d136

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,36 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
471471
return;
472472
}
473473

474+
if (RISCV::FPR32RegClass.contains(DstReg) &&
475+
RISCV::GPRRegClass.contains(SrcReg)) {
476+
BuildMI(MBB, MBBI, DL, get(RISCV::FMV_W_X), DstReg)
477+
.addReg(SrcReg, getKillRegState(KillSrc));
478+
return;
479+
}
480+
481+
if (RISCV::GPRRegClass.contains(DstReg) &&
482+
RISCV::FPR32RegClass.contains(SrcReg)) {
483+
BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_W), DstReg)
484+
.addReg(SrcReg, getKillRegState(KillSrc));
485+
return;
486+
}
487+
488+
if (RISCV::FPR64RegClass.contains(DstReg) &&
489+
RISCV::GPRRegClass.contains(SrcReg)) {
490+
assert(STI.getXLen() == 64 && "Unexpected GPR size");
491+
BuildMI(MBB, MBBI, DL, get(RISCV::FMV_D_X), DstReg)
492+
.addReg(SrcReg, getKillRegState(KillSrc));
493+
return;
494+
}
495+
496+
if (RISCV::GPRRegClass.contains(DstReg) &&
497+
RISCV::FPR64RegClass.contains(SrcReg)) {
498+
assert(STI.getXLen() == 64 && "Unexpected GPR size");
499+
BuildMI(MBB, MBBI, DL, get(RISCV::FMV_X_D), DstReg)
500+
.addReg(SrcReg, getKillRegState(KillSrc));
501+
return;
502+
}
503+
474504
// VR->VR copies.
475505
if (RISCV::VRRegClass.contains(DstReg, SrcReg)) {
476506
copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
2+
; RUN: llc -mtriple=riscv32 -global-isel -mattr=+f -target-abi=ilp32 \
3+
; RUN: -verify-machineinstrs < %s | FileCheck -check-prefix=RV32I %s
4+
5+
; Test copying between FPR32 and GPR on RV32.
6+
; FIXME: This test should be replaced with a more general calling convention
7+
; test once we have more FP implemented.
8+
9+
define float @fadd(float %x, float %y) {
10+
; RV32I-LABEL: fadd:
11+
; RV32I: # %bb.0:
12+
; RV32I-NEXT: fmv.w.x fa5, a0
13+
; RV32I-NEXT: fmv.w.x fa4, a1
14+
; RV32I-NEXT: fadd.s fa5, fa5, fa4
15+
; RV32I-NEXT: fmv.x.w a0, fa5
16+
; RV32I-NEXT: ret
17+
%a = fadd float %x, %y
18+
ret float %a
19+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
2+
; RUN: llc -mtriple=riscv64 -global-isel -mattr=+d -target-abi=lp64 \
3+
; RUN: -verify-machineinstrs < %s | FileCheck -check-prefix=RV64I %s
4+
5+
; Test copying between FPR64 and GPR on RV64.
6+
; FIXME: This test should be replaced with a more general calling convention
7+
; test once we have more FP implemented.
8+
9+
define double @fadd_f64(double %x, double %y) {
10+
; RV64I-LABEL: fadd_f64:
11+
; RV64I: # %bb.0:
12+
; RV64I-NEXT: fmv.d.x fa5, a0
13+
; RV64I-NEXT: fmv.d.x fa4, a1
14+
; RV64I-NEXT: fadd.d fa5, fa5, fa4
15+
; RV64I-NEXT: fmv.x.d a0, fa5
16+
; RV64I-NEXT: ret
17+
%a = fadd double %x, %y
18+
ret double %a
19+
20+
; Test copying between FPR32 and GPR on RV64.
21+
; FIXME: This test should be replaced with a more general calling convention
22+
; test once we have more FP implemented.
23+
24+
define float @fadd_f32(float %x, float %y) {
25+
; RV32I-LABEL: fadd:
26+
; RV32I: # %bb.0:
27+
; RV32I-NEXT: fmv.d.x fa5, a0
28+
; RV32I-NEXT: fmv.d.x fa4, a1
29+
; RV32I-NEXT: fadd.d fa5, fa5, fa4
30+
; RV32I-NEXT: fmv.x.d a0, fa5
31+
; RV32I-NEXT: ret
32+
%a = fadd float %x, %y
33+
ret float %a
34+
}

0 commit comments

Comments
 (0)