[LoongArch] Add codegen support for frint
authorgonglingqin <gonglingqin@loongson.cn>
Fri, 9 Sep 2022 06:12:07 +0000 (14:12 +0800)
committergonglingqin <gonglingqin@loongson.cn>
Fri, 9 Sep 2022 06:25:34 +0000 (14:25 +0800)
According to the revised description in `LoongArch Reference Manual v1.02`,
frint.[s/d] does not judge whether floating-point inexact exceptions are
allowed indicated by FCSR, i.e. always executes roundToIntegralExact(x).
What's more, the manual also specifically defines that frint.s/d is only
necessary to be defined in LA64. So ISD::FRINT is legal for LA64.

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

llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/test/CodeGen/LoongArch/frint.ll [new file with mode: 0644]

index 1a5034b..0bd1a21 100644 (file)
@@ -249,6 +249,11 @@ def : Pat<(loongarch_movfr2gr_s_la64 FPR32:$src),
 def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
 } // Predicates = [HasBasicF, IsLA64]
 
+// FP Rounding
+let Predicates = [HasBasicF, IsLA64] in {
+def : PatFpr<frint, FRINT_S, FPR32>;
+} // Predicates = [HasBasicF, IsLA64]
+
 let Predicates = [HasBasicF, IsLA32] in {
 // GPR -> FPR
 def : Pat<(bitconvert (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>;
index 4d2846e..d3ca503 100644 (file)
@@ -259,6 +259,11 @@ def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>;
 def : Pat<(bitconvert FPR64:$src), (MOVFR2GR_D FPR64:$src)>;
 } // Predicates = [HasBasicD, IsLA64]
 
+// FP Rounding
+let Predicates = [HasBasicD, IsLA64] in {
+def : PatFpr<frint, FRINT_D, FPR64>;
+} // Predicates = [HasBasicD, IsLA64]
+
 let Predicates = [HasBasicD, IsLA32] in {
 def : Pat<(f64 fpimm0), (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0)>;
 def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0))>;
index 85c7e52..e0b0b41 100644 (file)
@@ -80,6 +80,10 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::CTLZ, MVT::i32, Custom);
     if (Subtarget.hasBasicF() && !Subtarget.hasBasicD())
       setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
+    if (Subtarget.hasBasicF())
+      setOperationAction(ISD::FRINT, MVT::f32, Legal);
+    if (Subtarget.hasBasicD())
+      setOperationAction(ISD::FRINT, MVT::f64, Legal);
   }
 
   // LA32 does not have REVB.2W and REVB.D due to the 64-bit operands, and
diff --git a/llvm/test/CodeGen/LoongArch/frint.ll b/llvm/test/CodeGen/LoongArch/frint.ll
new file mode 100644 (file)
index 0000000..e7fa8d9
--- /dev/null
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch32 --mattr=+f,-d < %s | FileCheck %s --check-prefix=LA32F
+; RUN: llc --mtriple=loongarch32 --mattr=+d < %s | FileCheck %s --check-prefix=LA32D
+; RUN: llc --mtriple=loongarch64 --mattr=+f,-d < %s | FileCheck %s --check-prefix=LA64F
+; RUN: llc --mtriple=loongarch64 --mattr=+d < %s | FileCheck %s --check-prefix=LA64D
+
+define float @rint_f32(float %f) nounwind {
+; LA32F-LABEL: rint_f32:
+; LA32F:       # %bb.0: # %entry
+; LA32F-NEXT:    addi.w $sp, $sp, -16
+; LA32F-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT:    bl %plt(rintf)
+; LA32F-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT:    addi.w $sp, $sp, 16
+; LA32F-NEXT:    ret
+;
+; LA32D-LABEL: rint_f32:
+; LA32D:       # %bb.0: # %entry
+; LA32D-NEXT:    addi.w $sp, $sp, -16
+; LA32D-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32D-NEXT:    bl %plt(rintf)
+; LA32D-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32D-NEXT:    addi.w $sp, $sp, 16
+; LA32D-NEXT:    ret
+;
+; LA64F-LABEL: rint_f32:
+; LA64F:       # %bb.0: # %entry
+; LA64F-NEXT:    frint.s $fa0, $fa0
+; LA64F-NEXT:    ret
+;
+; LA64D-LABEL: rint_f32:
+; LA64D:       # %bb.0: # %entry
+; LA64D-NEXT:    frint.s $fa0, $fa0
+; LA64D-NEXT:    ret
+entry:
+  %0 = tail call float @llvm.rint.f32(float %f)
+  ret float %0
+}
+
+declare float @llvm.rint.f32(float)
+
+define double @rint_f64(double %d) nounwind {
+; LA32F-LABEL: rint_f64:
+; LA32F:       # %bb.0: # %entry
+; LA32F-NEXT:    addi.w $sp, $sp, -16
+; LA32F-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT:    bl %plt(rint)
+; LA32F-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT:    addi.w $sp, $sp, 16
+; LA32F-NEXT:    ret
+;
+; LA32D-LABEL: rint_f64:
+; LA32D:       # %bb.0: # %entry
+; LA32D-NEXT:    addi.w $sp, $sp, -16
+; LA32D-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32D-NEXT:    bl %plt(rint)
+; LA32D-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32D-NEXT:    addi.w $sp, $sp, 16
+; LA32D-NEXT:    ret
+;
+; LA64F-LABEL: rint_f64:
+; LA64F:       # %bb.0: # %entry
+; LA64F-NEXT:    addi.d $sp, $sp, -16
+; LA64F-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT:    bl %plt(rint)
+; LA64F-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT:    addi.d $sp, $sp, 16
+; LA64F-NEXT:    ret
+;
+; LA64D-LABEL: rint_f64:
+; LA64D:       # %bb.0: # %entry
+; LA64D-NEXT:    frint.d $fa0, $fa0
+; LA64D-NEXT:    ret
+entry:
+  %0 = tail call double @llvm.rint.f64(double %d)
+  ret double %0
+}
+
+declare double @llvm.rint.f64(double)