[llvm] 422ffc5 - [RISCV][GISel] Add instruction selection for G_FCONSTANT using integer materialization.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 4 11:45:31 PDT 2023


Author: Craig Topper
Date: 2023-11-04T11:40:52-07:00
New Revision: 422ffc525a064c2397a57bbfa90c5446bd0f0aee

URL: https://github.com/llvm/llvm-project/commit/422ffc525a064c2397a57bbfa90c5446bd0f0aee
DIFF: https://github.com/llvm/llvm-project/commit/422ffc525a064c2397a57bbfa90c5446bd0f0aee.diff

LOG: [RISCV][GISel] Add instruction selection for G_FCONSTANT using integer materialization.

This supports any G_FCONSTANT for F and D extensions.

This builds the constant in the integer domain and moves it to FP
using either FMV or the stack.

Eventually we should use the constant pool for some constants that
require many instructions, but this is a good starting point to
get something working.

Added: 
    llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir

Modified: 
    llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
    llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
    llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 69364fe00eaf810..b7dcc3379a130ec 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -357,6 +357,42 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
     MI.eraseFromParent();
     return true;
   }
+  case TargetOpcode::G_FCONSTANT: {
+    // TODO: Use constant pool for complext constants.
+    // TODO: Optimize +0.0 to use fcvt.d.w for s64 on rv32.
+    Register DstReg = MI.getOperand(0).getReg();
+    const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
+    APInt Imm = FPimm.bitcastToAPInt();
+    unsigned Size = MRI.getType(DstReg).getSizeInBits();
+    if (Size == 32 || (Size == 64 && Subtarget->is64Bit())) {
+      Register GPRReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+      if (!materializeImm(GPRReg, Imm.getSExtValue(), MIB))
+        return false;
+
+      unsigned Opcode = Size == 64 ? RISCV::FMV_D_X : RISCV::FMV_W_X;
+      auto FMV = MIB.buildInstr(Opcode, {DstReg}, {GPRReg});
+      if (!FMV.constrainAllUses(TII, TRI, RBI))
+        return false;
+    } else {
+      assert(Size == 64 && !Subtarget->is64Bit() &&
+             "Unexpected size or subtarget");
+      // Split into two pieces and build through the stack.
+      Register GPRRegHigh = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+      Register GPRRegLow = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+      if (!materializeImm(GPRRegHigh, Imm.extractBits(32, 32).getSExtValue(),
+                          MIB))
+        return false;
+      if (!materializeImm(GPRRegLow, Imm.trunc(32).getSExtValue(), MIB))
+        return false;
+      MachineInstrBuilder PairF64 = MIB.buildInstr(
+          RISCV::BuildPairF64Pseudo, {DstReg}, {GPRRegLow, GPRRegHigh});
+      if (!PairF64.constrainAllUses(TII, TRI, RBI))
+        return false;
+    }
+
+    MI.eraseFromParent();
+    return true;
+  }
   case TargetOpcode::G_GLOBAL_VALUE:
     return selectGlobalValue(MI, MIB, MRI);
   case TargetOpcode::G_BRCOND: {

diff  --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 662e5e553121c8e..9b2c725907a0e34 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -209,6 +209,12 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
                 typeIs(1, s32)(Query));
       });
 
+  getActionDefinitionsBuilder(G_FCONSTANT)
+      .legalIf([=, &ST](const LegalityQuery &Query) -> bool {
+        return (ST.hasStdExtF() && typeIs(0, s32)(Query)) ||
+               (ST.hasStdExtD() && typeIs(0, s64)(Query));
+      });
+
   getLegacyLegalizerInfo().computeTables();
 }
 

diff  --git a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
index 99d3000568a9f17..3fc00cb760358bb 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
@@ -213,6 +213,12 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
                             getFPValueMapping(FromTy.getSizeInBits())});
     break;
   }
+  case TargetOpcode::G_FCONSTANT: {
+    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
+    OperandsMapping =
+        getOperandsMapping({getFPValueMapping(Ty.getSizeInBits()), nullptr});
+    break;
+  }
   default:
     return getInvalidInstructionMapping();
   }

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir
new file mode 100644
index 000000000000000..43f5ec1f5790771
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir
@@ -0,0 +1,221 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=instruction-select \
+# RUN:   -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,RV32
+# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=instruction-select \
+# RUN:   -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,RV64
+
+---
+name:            float_imm
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    ; RV32-LABEL: name: float_imm
+    ; RV32: [[LUI:%[0-9]+]]:gpr = LUI 263313
+    ; RV32-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], -37
+    ; RV32-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[ADDI]]
+    ; RV32-NEXT: $f10_f = COPY [[FMV_W_X]]
+    ; RV32-NEXT: PseudoRET implicit $f10_f
+    ;
+    ; RV64-LABEL: name: float_imm
+    ; RV64: [[LUI:%[0-9]+]]:gpr = LUI 263313
+    ; RV64-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], -37
+    ; RV64-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[ADDIW]]
+    ; RV64-NEXT: $f10_f = COPY [[FMV_W_X]]
+    ; RV64-NEXT: PseudoRET implicit $f10_f
+    %0:fprb(s32) = G_FCONSTANT float 0x400921FB60000000
+    $f10_f = COPY %0(s32)
+    PseudoRET implicit $f10_f
+
+...
+---
+name:            float_imm_op
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    liveins: $f10_f
+
+    ; CHECK-LABEL: name: float_imm_op
+    ; CHECK: liveins: $f10_f
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
+    ; CHECK-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 260096
+    ; CHECK-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[LUI]]
+    ; CHECK-NEXT: [[FADD_S:%[0-9]+]]:fpr32 = nofpexcept FADD_S [[COPY]], [[FMV_W_X]], 7
+    ; CHECK-NEXT: $f10_f = COPY [[FADD_S]]
+    ; CHECK-NEXT: PseudoRET implicit $f10_f
+    %0:fprb(s32) = COPY $f10_f
+    %1:fprb(s32) = G_FCONSTANT float 1.000000e+00
+    %2:fprb(s32) = G_FADD %0, %1
+    $f10_f = COPY %2(s32)
+    PseudoRET implicit $f10_f
+
+...
+---
+name:            float_positive_zero
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    liveins: $x10
+
+    ; CHECK-LABEL: name: float_positive_zero
+    ; CHECK: liveins: $x10
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
+    ; CHECK-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[COPY]]
+    ; CHECK-NEXT: $f10_f = COPY [[FMV_W_X]]
+    ; CHECK-NEXT: PseudoRET implicit $f10_f
+    %1:fprb(s32) = G_FCONSTANT float 0.000000e+00
+    $f10_f = COPY %1(s32)
+    PseudoRET implicit $f10_f
+
+...
+---
+name:            float_negative_zero
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    liveins: $x10
+
+    ; CHECK-LABEL: name: float_negative_zero
+    ; CHECK: liveins: $x10
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 524288
+    ; CHECK-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[LUI]]
+    ; CHECK-NEXT: $f10_f = COPY [[FMV_W_X]]
+    ; CHECK-NEXT: PseudoRET implicit $f10_f
+    %1:fprb(s32) = G_FCONSTANT float -0.000000e+00
+    $f10_f = COPY %1(s32)
+    PseudoRET implicit $f10_f
+
+...
+---
+name:            double_imm
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    ; RV32-LABEL: name: double_imm
+    ; RV32: [[LUI:%[0-9]+]]:gpr = LUI 262290
+    ; RV32-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], 507
+    ; RV32-NEXT: [[LUI1:%[0-9]+]]:gpr = LUI 345155
+    ; RV32-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI [[LUI1]], -744
+    ; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[ADDI1]], [[ADDI]]
+    ; RV32-NEXT: $f10_d = COPY [[BuildPairF64Pseudo]]
+    ; RV32-NEXT: PseudoRET implicit $f10_d
+    ;
+    ; RV64-LABEL: name: double_imm
+    ; RV64: [[LUI:%[0-9]+]]:gpr = LUI 512
+    ; RV64-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], 1169
+    ; RV64-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDIW]], 15
+    ; RV64-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[SLLI]], -299
+    ; RV64-NEXT: [[SLLI1:%[0-9]+]]:gpr = SLLI [[ADDI]], 14
+    ; RV64-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI [[SLLI1]], 1091
+    ; RV64-NEXT: [[SLLI2:%[0-9]+]]:gpr = SLLI [[ADDI1]], 12
+    ; RV64-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI [[SLLI2]], -744
+    ; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[ADDI2]]
+    ; RV64-NEXT: $f10_d = COPY [[FMV_D_X]]
+    ; RV64-NEXT: PseudoRET implicit $f10_d
+    %0:fprb(s64) = G_FCONSTANT double 0x400921FB54442D18
+    $f10_d = COPY %0(s64)
+    PseudoRET implicit $f10_d
+
+...
+---
+name:            double_imm_op
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    liveins: $f10_d
+
+    ; RV32-LABEL: name: double_imm_op
+    ; RV32: liveins: $f10_d
+    ; RV32-NEXT: {{  $}}
+    ; RV32-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
+    ; RV32-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 261888
+    ; RV32-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
+    ; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[COPY1]], [[LUI]]
+    ; RV32-NEXT: [[FADD_D:%[0-9]+]]:fpr64 = nofpexcept FADD_D [[COPY]], [[BuildPairF64Pseudo]], 7
+    ; RV32-NEXT: $f10_d = COPY [[FADD_D]]
+    ; RV32-NEXT: PseudoRET implicit $f10_d
+    ;
+    ; RV64-LABEL: name: double_imm_op
+    ; RV64: liveins: $f10_d
+    ; RV64-NEXT: {{  $}}
+    ; RV64-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
+    ; RV64-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 1023
+    ; RV64-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI]], 52
+    ; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[SLLI]]
+    ; RV64-NEXT: [[FADD_D:%[0-9]+]]:fpr64 = nofpexcept FADD_D [[COPY]], [[FMV_D_X]], 7
+    ; RV64-NEXT: $f10_d = COPY [[FADD_D]]
+    ; RV64-NEXT: PseudoRET implicit $f10_d
+    %0:fprb(s64) = COPY $f10_d
+    %1:fprb(s64) = G_FCONSTANT double 1.000000e+00
+    %2:fprb(s64) = G_FADD %0, %1
+    $f10_d = COPY %2(s64)
+    PseudoRET implicit $f10_d
+
+...
+---
+name:            double_positive_zero
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    liveins: $x10
+
+    ; RV32-LABEL: name: double_positive_zero
+    ; RV32: liveins: $x10
+    ; RV32-NEXT: {{  $}}
+    ; RV32-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
+    ; RV32-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
+    ; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[COPY1]], [[COPY]]
+    ; RV32-NEXT: $f10_d = COPY [[BuildPairF64Pseudo]]
+    ; RV32-NEXT: PseudoRET implicit $f10_d
+    ;
+    ; RV64-LABEL: name: double_positive_zero
+    ; RV64: liveins: $x10
+    ; RV64-NEXT: {{  $}}
+    ; RV64-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
+    ; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[COPY]]
+    ; RV64-NEXT: $f10_d = COPY [[FMV_D_X]]
+    ; RV64-NEXT: PseudoRET implicit $f10_d
+    %1:fprb(s64) = G_FCONSTANT double 0.000000e+00
+    $f10_d = COPY %1(s64)
+    PseudoRET implicit $f10_d
+
+...
+---
+name:            double_negative_zero
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.1:
+    liveins: $x10
+
+    ; RV32-LABEL: name: double_negative_zero
+    ; RV32: liveins: $x10
+    ; RV32-NEXT: {{  $}}
+    ; RV32-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 524288
+    ; RV32-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
+    ; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[COPY]], [[LUI]]
+    ; RV32-NEXT: $f10_d = COPY [[BuildPairF64Pseudo]]
+    ; RV32-NEXT: PseudoRET implicit $f10_d
+    ;
+    ; RV64-LABEL: name: double_negative_zero
+    ; RV64: liveins: $x10
+    ; RV64-NEXT: {{  $}}
+    ; RV64-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, -1
+    ; RV64-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI]], 63
+    ; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[SLLI]]
+    ; RV64-NEXT: $f10_d = COPY [[FMV_D_X]]
+    ; RV64-NEXT: PseudoRET implicit $f10_d
+    %1:fprb(s64) = G_FCONSTANT double -0.000000e+00
+    $f10_d = COPY %1(s64)
+    PseudoRET implicit $f10_d
+
+...


        


More information about the llvm-commits mailing list