[llvm] [RISCV] Add register bank and instruction selection support for FP G_SELECT. (PR #72726)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 18 11:40:29 PST 2023
https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/72726
>From f13f52918200b2a1e9a72673f1fcfdb2111c0739 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 17 Nov 2023 15:59:13 -0800
Subject: [PATCH 1/3] [RISCV] Add register bank and instruction selection
support for G_SELECT.
Try to pick the FP register bank based on surrounding use/defs. Code
is basically copied from AArch64.
Need legalizer changes to make this more useful. Right now we're stuck
with only being able to FP typs the same size as XLen.
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 12 ++++-
.../RISCV/GISel/RISCVRegisterBankInfo.cpp | 51 +++++++++++++++++--
.../instruction-select/fp-select-rv32.mir | 33 ++++++++++++
.../instruction-select/fp-select-rv64.mir | 34 +++++++++++++
.../regbankselect/fp-select-rv32.mir | 34 +++++++++++++
.../regbankselect/fp-select-rv64.mir | 34 +++++++++++++
6 files changed, 192 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv32.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv32.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv64.mir
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 25f4a217c070349..2586390e8562d1c 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -816,8 +816,16 @@ bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
RISCVCC::CondCode CC;
getOperandsForBranch(SelectMI.getCondReg(), MRI, CC, LHS, RHS);
- MachineInstr *Result = MIB.buildInstr(RISCV::Select_GPR_Using_CC_GPR)
- .addDef(SelectMI.getReg(0))
+ Register DstReg = SelectMI.getReg(0);
+
+ unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
+ if (RBI.getRegBank(DstReg, MRI, TRI)->getID() == RISCV::FPRBRegBankID) {
+ unsigned Size = MRI.getType(DstReg).getSizeInBits();
+ Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR : RISCV::Select_FPR64_Using_CC_GPR;
+ }
+
+ MachineInstr *Result = MIB.buildInstr(Opc)
+ .addDef(DstReg)
.addReg(LHS)
.addReg(RHS)
.addImm(CC)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
index 6d77e2b7edd9010..5721bd9609040e6 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
@@ -323,12 +323,55 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
break;
}
- case TargetOpcode::G_SELECT:
- OpdsMapping[0] = GPRValueMapping;
+ case TargetOpcode::G_SELECT: {
+ LLT Ty = MRI.getType(MI.getOperand(0).getReg());
+
+ // Try to minimize the number of copies. If we have more floating point
+ // constrained values than not, then we'll put everything on FPR. Otherwise,
+ // everything has to be on GPR.
+ unsigned NumFP = 0;
+
+ // Check if the uses of the result always produce floating point values.
+ //
+ // For example:
+ //
+ // %z = G_SELECT %cond %x %y
+ // fpr = G_FOO %z ...
+ if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
+ [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); }))
+ ++NumFP;
+
+ // Check if the defs of the source values always produce floating point
+ // values.
+ //
+ // For example:
+ //
+ // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
+ // %z = G_SELECT %cond %x %y
+ //
+ // Also check whether or not the sources have already been decided to be
+ // FPR. Keep track of this.
+ //
+ // This doesn't check the condition, since it's just whatever is in NZCV.
+ // This isn't passed explicitly in a register to fcsel/csel.
+ for (unsigned Idx = 2; Idx < 4; ++Idx) {
+ Register VReg = MI.getOperand(Idx).getReg();
+ MachineInstr *DefMI = MRI.getVRegDef(VReg);
+ if (getRegBank(VReg, MRI, TRI) == &RISCV::FPRBRegBank ||
+ onlyDefinesFP(*DefMI, MRI, TRI))
+ ++NumFP;
+ }
+
+ // Condition operand is always GPR.
OpdsMapping[1] = GPRValueMapping;
- OpdsMapping[2] = GPRValueMapping;
- OpdsMapping[3] = GPRValueMapping;
+
+ const ValueMapping *Mapping = GPRValueMapping;
+ if (NumFP >= 2)
+ Mapping = getFPValueMapping(Ty.getSizeInBits());
+
+ OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = Mapping;
break;
+ }
case TargetOpcode::G_FPTOSI:
case TargetOpcode::G_FPTOUI: {
LLT Ty = MRI.getType(MI.getOperand(1).getReg());
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv32.mir
new file mode 100644
index 000000000000000..4fffbc42b2cff34
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv32.mir
@@ -0,0 +1,33 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=instruction-select \
+# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: fp_select_s32
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $x10, $f10_f, $f11_f
+
+ ; CHECK-LABEL: name: fp_select_s32
+ ; CHECK: liveins: $x10, $f10_f, $f11_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr32 = COPY $f10_f
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr32 = COPY $f11_f
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+ ; CHECK-NEXT: [[Select_FPR32_Using_CC_GPR:%[0-9]+]]:fpr32 = Select_FPR32_Using_CC_GPR [[ANDI]], $x0, 1, [[COPY1]], [[COPY2]]
+ ; CHECK-NEXT: $f10_f = COPY [[Select_FPR32_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $f10_f
+ %0:gprb(s32) = COPY $x10
+ %1:fprb(s32) = COPY $f10_f
+ %2:fprb(s32) = COPY $f11_f
+ %3:gprb(s32) = G_CONSTANT i32 1
+ %4:gprb(s32) = G_AND %0, %3
+ %5:fprb(s32) = G_SELECT %4(s32), %1, %2
+ $f10_f = COPY %5(s32)
+ PseudoRET implicit $f10_f
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir
new file mode 100644
index 000000000000000..8efb8b10d8a931d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir
@@ -0,0 +1,34 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=instruction-select \
+# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: fp_select_s64
+alignment: 1
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $x10, $f10_d, $f11_d
+
+ ; CHECK-LABEL: name: fp_select_s64
+ ; CHECK: liveins: $x10, $f10_d, $f11_d
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $f10_d
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr64 = COPY $f11_d
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+ ; CHECK-NEXT: [[Select_FPR64_Using_CC_GPR:%[0-9]+]]:fpr64 = Select_FPR64_Using_CC_GPR [[ANDI]], $x0, 1, [[COPY1]], [[COPY2]]
+ ; CHECK-NEXT: $f10_d = COPY [[Select_FPR64_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $f10_d
+ %0:gprb(s64) = COPY $x10
+ %1:fprb(s64) = COPY $f10_d
+ %2:fprb(s64) = COPY $f11_d
+ %3:gprb(s64) = G_CONSTANT i64 1
+ %4:gprb(s64) = G_AND %0, %3
+ %5:fprb(s64) = G_SELECT %4(s64), %1, %2
+ $f10_d = COPY %5(s64)
+ PseudoRET implicit $f10_d
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv32.mir
new file mode 100644
index 000000000000000..312fadca866206c
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv32.mir
@@ -0,0 +1,34 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=regbankselect \
+# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \
+# RUN: -o - | FileCheck -check-prefix=RV32I %s
+
+---
+name: fp_select_s32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $x10, $f10_f, $f11_f
+
+ ; RV32I-LABEL: name: fp_select_s32
+ ; RV32I: liveins: $x10, $f10_f, $f11_f
+ ; RV32I-NEXT: {{ $}}
+ ; RV32I-NEXT: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10
+ ; RV32I-NEXT: [[COPY1:%[0-9]+]]:fprb(s32) = COPY $f10_f
+ ; RV32I-NEXT: [[COPY2:%[0-9]+]]:fprb(s32) = COPY $f11_f
+ ; RV32I-NEXT: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 1
+ ; RV32I-NEXT: [[AND:%[0-9]+]]:gprb(s32) = G_AND [[COPY]], [[C]]
+ ; RV32I-NEXT: [[SELECT:%[0-9]+]]:fprb(s32) = G_SELECT [[AND]](s32), [[COPY1]], [[COPY2]]
+ ; RV32I-NEXT: $f10_f = COPY [[SELECT]](s32)
+ ; RV32I-NEXT: PseudoRET implicit $f10_f
+ %3:_(s32) = COPY $x10
+ %4:_(s32) = COPY $f10_f
+ %5:_(s32) = COPY $f11_f
+ %12:_(s32) = G_CONSTANT i32 1
+ %11:_(s32) = G_AND %3, %12
+ %10:_(s32) = G_SELECT %11(s32), %4, %5
+ $f10_f = COPY %10(s32)
+ PseudoRET implicit $f10_f
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv64.mir
new file mode 100644
index 000000000000000..22ebd5e93b01407
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/fp-select-rv64.mir
@@ -0,0 +1,34 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=regbankselect \
+# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \
+# RUN: -o - | FileCheck -check-prefix=RV32I %s
+
+---
+name: fp_select_s64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $x10, $f10_d, $f11_d
+
+ ; RV32I-LABEL: name: fp_select_s64
+ ; RV32I: liveins: $x10, $f10_d, $f11_d
+ ; RV32I-NEXT: {{ $}}
+ ; RV32I-NEXT: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10
+ ; RV32I-NEXT: [[COPY1:%[0-9]+]]:fprb(s64) = COPY $f10_d
+ ; RV32I-NEXT: [[COPY2:%[0-9]+]]:fprb(s64) = COPY $f11_d
+ ; RV32I-NEXT: [[C:%[0-9]+]]:gprb(s64) = G_CONSTANT i64 1
+ ; RV32I-NEXT: [[AND:%[0-9]+]]:gprb(s64) = G_AND [[COPY]], [[C]]
+ ; RV32I-NEXT: [[SELECT:%[0-9]+]]:fprb(s64) = G_SELECT [[AND]](s64), [[COPY1]], [[COPY2]]
+ ; RV32I-NEXT: $f10_d = COPY [[SELECT]](s64)
+ ; RV32I-NEXT: PseudoRET implicit $f10_d
+ %3:_(s64) = COPY $x10
+ %4:_(s64) = COPY $f10_d
+ %5:_(s64) = COPY $f11_d
+ %12:_(s64) = G_CONSTANT i64 1
+ %11:_(s64) = G_AND %3, %12
+ %10:_(s64) = G_SELECT %11(s64), %4, %5
+ $f10_d = COPY %10(s64)
+ PseudoRET implicit $f10_d
+
+...
>From 4ee36243aac06cdf88b2ec5beae875a25101a066 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 17 Nov 2023 16:41:14 -0800
Subject: [PATCH 2/3] fixup! clang-format
---
llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 3 ++-
llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp | 4 +++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 2586390e8562d1c..8a524b4c89c7789 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -821,7 +821,8 @@ bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
if (RBI.getRegBank(DstReg, MRI, TRI)->getID() == RISCV::FPRBRegBankID) {
unsigned Size = MRI.getType(DstReg).getSizeInBits();
- Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR : RISCV::Select_FPR64_Using_CC_GPR;
+ Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
+ : RISCV::Select_FPR64_Using_CC_GPR;
}
MachineInstr *Result = MIB.buildInstr(Opc)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
index 5721bd9609040e6..b516bd41beb52c4 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
@@ -338,7 +338,9 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
// %z = G_SELECT %cond %x %y
// fpr = G_FOO %z ...
if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
- [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); }))
+ [&](const MachineInstr &UseMI) {
+ return onlyUsesFP(UseMI, MRI, TRI);
+ }))
++NumFP;
// Check if the defs of the source values always produce floating point
>From d514e19bc51a3b30354ab1b1025ec4a6889a577d Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Sat, 18 Nov 2023 11:39:32 -0800
Subject: [PATCH 3/3] Add f32 test for rv64.
---
.../instruction-select/fp-select-rv64.mir | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir
index 8efb8b10d8a931d..e291c352e5a8573 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-select-rv64.mir
@@ -2,6 +2,36 @@
# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=instruction-select \
# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s
+---
+name: fp_select_s32
+alignment: 1
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $x10, $f10_d, $f11_d
+
+ ; CHECK-LABEL: name: fp_select_s32
+ ; CHECK: liveins: $x10, $f10_d, $f11_d
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr32 = COPY $f10_f
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr32 = COPY $f11_f
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+ ; CHECK-NEXT: [[Select_FPR32_Using_CC_GPR:%[0-9]+]]:fpr32 = Select_FPR32_Using_CC_GPR [[ANDI]], $x0, 1, [[COPY1]], [[COPY2]]
+ ; CHECK-NEXT: $f10_f = COPY [[Select_FPR32_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $f10_f
+ %0:gprb(s64) = COPY $x10
+ %1:fprb(s32) = COPY $f10_f
+ %2:fprb(s32) = COPY $f11_f
+ %3:gprb(s64) = G_CONSTANT i64 1
+ %4:gprb(s64) = G_AND %0, %3
+ %5:fprb(s32) = G_SELECT %4(s64), %1, %2
+ $f10_f = COPY %5(s32)
+ PseudoRET implicit $f10_f
+
+...
---
name: fp_select_s64
alignment: 1
More information about the llvm-commits
mailing list