[llvm] ada2641 - [RISCV][CodeGen] Add codegen pattern for FLI instruction in experimental zfa extension

Jun Sha via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 6 22:27:47 PST 2023


Author: Jun Sha (Joshua)
Date: 2023-03-07T14:27:48+08:00
New Revision: ada2641460672ed888df9e2791d3d4635f06e2ae

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

LOG: [RISCV][CodeGen] Add codegen pattern for FLI instruction in experimental zfa extension

This patch implements experimental support for the RISCV Zfa extension as specified here: https://github.com/riscv/riscv-isa-manual/releases/download/draft-20221119-5234c63/riscv-spec.pdf, Ch. 25. This extension has not been ratified. Once ratified, it'll move out of experimental status.

This change adds codegen support for load-immediate instructions (fli.s/fli.d/fli.h).

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D141560

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td
    llvm/test/CodeGen/RISCV/double-zfa.ll
    llvm/test/CodeGen/RISCV/float-zfa.ll
    llvm/test/CodeGen/RISCV/half-zfa.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index ca63794db7b6e..91ef4f58d274e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -842,6 +842,14 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
   }
   case ISD::ConstantFP: {
     const APFloat &APF = cast<ConstantFPSDNode>(Node)->getValueAPF();
+    if (Subtarget->hasStdExtZfa()) {
+      if ((VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(APF) != -1) || 
+          (VT == MVT::f16 && RISCVLoadFPImm::getLoadFP16Imm(APF) != -1) ||
+          (VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(APF) != -1 && 
+           !APF.isPosZero()))
+        break;
+    }
+
     bool NegZeroF64 = APF.isNegZero() && VT == MVT::f64;
     SDValue Imm;
     // For +0.0 or f64 -0.0 we need to start from X0. For all others, we will

diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 6b93d53d7dbf3..c8047cd09cadd 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1518,6 +1518,14 @@ bool RISCVTargetLowering::isOffsetFoldingLegal(
 
 bool RISCVTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
                                        bool ForCodeSize) const {
+  if (Subtarget.hasStdExtZfa()) {
+    if ((VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(Imm) != -1) || 
+        (VT == MVT::f16 && RISCVLoadFPImm::getLoadFP16Imm(Imm) != -1) ||
+        (VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(Imm) != -1 && 
+         !Imm.isPosZero()))
+      return true;
+  }
+  
   if (VT == MVT::f16 && !Subtarget.hasStdExtZfhOrZfhmin())
     return false;
   if (VT == MVT::f32 && !Subtarget.hasStdExtF())

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td
index c39b7f543f472..2b37a8df4d54c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td
@@ -178,7 +178,21 @@ def : InstAlias<"fgeq.h $rd, $rs, $rt",
 // Codegen patterns
 //===----------------------------------------------------------------------===//
 
+def fp32imm_to_loadfpimm : SDNodeXForm<fpimm, [{
+  return CurDAG->getTargetConstant(RISCVLoadFPImm::getLoadFP32Imm(N->getValueAPF()), 
+                                   SDLoc(N), Subtarget->getXLenVT());}]>;
+
+def fp64imm_to_loadfpimm : SDNodeXForm<fpimm, [{
+  return CurDAG->getTargetConstant(RISCVLoadFPImm::getLoadFP64Imm(N->getValueAPF()), 
+                                   SDLoc(N), Subtarget->getXLenVT());}]>;
+
+def fp16imm_to_loadfpimm : SDNodeXForm<fpimm, [{
+  return CurDAG->getTargetConstant(RISCVLoadFPImm::getLoadFP16Imm(N->getValueAPF()), 
+                                   SDLoc(N), Subtarget->getXLenVT());}]>;
+
 let Predicates = [HasStdExtZfa] in {
+def : Pat<(f32 fpimm:$imm), (FLI_S (fp32imm_to_loadfpimm fpimm:$imm))>;
+
 def: PatFprFpr<fminimum, FMINM_S, FPR32>;
 def: PatFprFpr<fmaximum, FMAXM_S, FPR32>;
 
@@ -201,6 +215,8 @@ def: PatSetCC<FPR32, strict_fsetcc, SETOLE, FLEQ_S>;
 } // Predicates = [HasStdExtZfa]
 
 let Predicates = [HasStdExtZfa, HasStdExtD] in {
+def : Pat<(f64 fpimm:$imm), (FLI_D (fp64imm_to_loadfpimm fpimm:$imm))>;
+
 def: PatFprFpr<fminimum, FMINM_D, FPR64>;
 def: PatFprFpr<fmaximum, FMAXM_D, FPR64>;
 
@@ -229,6 +245,8 @@ def : Pat<(RISCVBuildPairF64 GPR:$rs1, GPR:$rs2),
 }
 
 let Predicates = [HasStdExtZfa, HasStdExtZfh] in {
+def : Pat<(f16 fpimm:$imm), (FLI_H (fp16imm_to_loadfpimm fpimm:$imm))>;
+
 def: PatFprFpr<fminimum, FMINM_H, FPR16>;
 def: PatFprFpr<fmaximum, FMAXM_H, FPR16>;
 

diff  --git a/llvm/test/CodeGen/RISCV/double-zfa.ll b/llvm/test/CodeGen/RISCV/double-zfa.ll
index a4550cde2d67c..8bbe5e59ccbbc 100644
--- a/llvm/test/CodeGen/RISCV/double-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/double-zfa.ll
@@ -4,6 +4,79 @@
 ; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+experimental-zfa,+d < %s \
 ; RUN:     | FileCheck --check-prefixes=CHECK,RV64DZFA %s
 
+define double @loadfpimm1() {
+; CHECK-LABEL: loadfpimm1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, 6.250000e-02
+; CHECK-NEXT:    ret
+  ret double 0.0625
+}
+
+define double @loadfpimm2() {
+; CHECK-LABEL: loadfpimm2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, 7.500000e-01
+; CHECK-NEXT:    ret
+  ret double 0.75
+}
+
+define double @loadfpimm3() {
+; CHECK-LABEL: loadfpimm3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, 1.250000e+00
+; CHECK-NEXT:    ret
+  ret double 1.25
+}
+
+define double @loadfpimm4() {
+; CHECK-LABEL: loadfpimm4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, 3.000000e+00
+; CHECK-NEXT:    ret
+  ret double 3.0
+}
+
+define double @loadfpimm5() {
+; CHECK-LABEL: loadfpimm5:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, 2.560000e+02
+; CHECK-NEXT:    ret
+  ret double 256.0
+}
+
+define double @loadfpimm6() {
+; CHECK-LABEL: loadfpimm6:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, inf
+; CHECK-NEXT:    ret
+  ret double 0x7FF0000000000000
+}
+
+define double @loadfpimm7() {
+; CHECK-LABEL: loadfpimm7:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, nan
+; CHECK-NEXT:    ret
+  ret double 0x7FF8000000000000
+}
+
+define double @loadfpimm8() {
+; CHECK-LABEL: loadfpimm8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.d fa0, min
+; CHECK-NEXT:    ret
+  ret double 0x0010000000000000
+}
+
+define double @loadfpimm9() {
+; CHECK-LABEL: loadfpimm9:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lui a0, %hi(.LCPI8_0)
+; CHECK-NEXT:    fld fa0, %lo(.LCPI8_0)(a0)
+; CHECK-NEXT:    ret
+  ret double 255.0
+}
+
 declare double @llvm.minimum.f64(double, double)
 
 define double @fminm_d(double %a, double %b) nounwind {

diff  --git a/llvm/test/CodeGen/RISCV/float-zfa.ll b/llvm/test/CodeGen/RISCV/float-zfa.ll
index 2b47399e75278..fe8359d61a747 100644
--- a/llvm/test/CodeGen/RISCV/float-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/float-zfa.ll
@@ -4,6 +4,79 @@
 ; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+experimental-zfa < %s \
 ; RUN:     | FileCheck %s
 
+define float @loadfpimm1() {
+; CHECK-LABEL: loadfpimm1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, 6.250000e-02
+; CHECK-NEXT:    ret
+  ret float 0.0625
+}
+
+define float @loadfpimm2() {
+; CHECK-LABEL: loadfpimm2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, 7.500000e-01
+; CHECK-NEXT:    ret
+  ret float 0.75
+}
+
+define float @loadfpimm3() {
+; CHECK-LABEL: loadfpimm3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, 1.250000e+00
+; CHECK-NEXT:    ret
+  ret float 1.25
+}
+
+define float @loadfpimm4() {
+; CHECK-LABEL: loadfpimm4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, 3.000000e+00
+; CHECK-NEXT:    ret
+  ret float 3.0
+}
+
+define float @loadfpimm5() {
+; CHECK-LABEL: loadfpimm5:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, 2.560000e+02
+; CHECK-NEXT:    ret
+  ret float 256.0
+}
+
+define float @loadfpimm6() {
+; CHECK-LABEL: loadfpimm6:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, inf
+; CHECK-NEXT:    ret
+  ret float 0x7FF0000000000000
+}
+
+define float @loadfpimm7() {
+; CHECK-LABEL: loadfpimm7:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, nan
+; CHECK-NEXT:    ret
+  ret float 0x7FF8000000000000
+}
+
+define float @loadfpimm8() {
+; CHECK-LABEL: loadfpimm8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa0, min
+; CHECK-NEXT:    ret
+  ret float 0x3810000000000000
+}
+
+define float @loadfpimm9() {
+; CHECK-LABEL: loadfpimm9:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lui a0, 276464
+; CHECK-NEXT:    fmv.w.x fa0, a0
+; CHECK-NEXT:    ret
+  ret float 255.0
+}
+
 declare float @llvm.minimum.f32(float, float)
 
 define float @fminm_s(float %a, float %b) nounwind {

diff  --git a/llvm/test/CodeGen/RISCV/half-zfa.ll b/llvm/test/CodeGen/RISCV/half-zfa.ll
index 798977e540047..b6ff3fbae415c 100644
--- a/llvm/test/CodeGen/RISCV/half-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/half-zfa.ll
@@ -4,6 +4,79 @@
 ; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+experimental-zfa,+zfh < %s \
 ; RUN:     | FileCheck %s
 
+define half @loadfpimm1() {
+; CHECK-LABEL: loadfpimm1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, 6.250000e-02
+; CHECK-NEXT:    ret
+  ret half 0.0625
+}
+
+define half @loadfpimm2() {
+; CHECK-LABEL: loadfpimm2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, 7.500000e-01
+; CHECK-NEXT:    ret
+  ret half 0.75
+}
+
+define half @loadfpimm3() {
+; CHECK-LABEL: loadfpimm3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, 1.250000e+00
+; CHECK-NEXT:    ret
+  ret half 1.25
+}
+
+define half @loadfpimm4() {
+; CHECK-LABEL: loadfpimm4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, 3.000000e+00
+; CHECK-NEXT:    ret
+  ret half 3.0
+}
+
+define half @loadfpimm5() {
+; CHECK-LABEL: loadfpimm5:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, 2.560000e+02
+; CHECK-NEXT:    ret
+  ret half 256.0
+}
+
+define half @loadfpimm6() {
+; CHECK-LABEL: loadfpimm6:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, inf
+; CHECK-NEXT:    ret
+  ret half 0xH7C00
+}
+
+define half @loadfpimm7() {
+; CHECK-LABEL: loadfpimm7:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, nan
+; CHECK-NEXT:    ret
+  ret half 0xH7E00
+}
+
+define half @loadfpimm8() {
+; CHECK-LABEL: loadfpimm8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.h fa0, min
+; CHECK-NEXT:    ret
+  ret half 0xH0400
+}
+
+define half @loadfpimm9() {
+; CHECK-LABEL: loadfpimm9:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lui a0, %hi(.LCPI8_0)
+; CHECK-NEXT:    flh fa0, %lo(.LCPI8_0)(a0)
+; CHECK-NEXT:    ret
+  ret half 255.0
+}
+
 declare half @llvm.minimum.f16(half, half)
 
 define half @fminm_h(half %a, half %b) nounwind {


        


More information about the llvm-commits mailing list