[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