diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td @@ -213,6 +213,9 @@ // FP Conversion def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_W_S FPR32:$src)>; + +// FP reciprocal operation +def : Pat<(fdiv fpimm1, FPR32:$src), (FRECIP_S $src)>; } // Predicates = [HasBasicF] let Predicates = [HasBasicF, IsLA64] in { diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td @@ -215,6 +215,9 @@ def : Pat<(f32 (fpround FPR64:$src)), (FCVT_S_D FPR64:$src)>; // f32 -> f64 def : Pat<(f64 (fpextend FPR32:$src)), (FCVT_D_S FPR32:$src)>; + +// FP reciprocal operation +def : Pat<(fdiv fpimm1, FPR64:$src), (FRECIP_D $src)>; } // Predicates = [HasBasicD] /// Floating point constants diff --git a/llvm/test/CodeGen/LoongArch/fp-reciprocal.ll b/llvm/test/CodeGen/LoongArch/fp-reciprocal.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/fp-reciprocal.ll @@ -0,0 +1,68 @@ +; 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 @f32_reciprocal(float %a) nounwind { +; LA32F-LABEL: f32_reciprocal: +; LA32F: # %bb.0: +; LA32F-NEXT: frecip.s $fa0, $fa0 +; LA32F-NEXT: ret +; +; LA32D-LABEL: f32_reciprocal: +; LA32D: # %bb.0: +; LA32D-NEXT: frecip.s $fa0, $fa0 +; LA32D-NEXT: ret +; +; LA64F-LABEL: f32_reciprocal: +; LA64F: # %bb.0: +; LA64F-NEXT: frecip.s $fa0, $fa0 +; LA64F-NEXT: ret +; +; LA64D-LABEL: f32_reciprocal: +; LA64D: # %bb.0: +; LA64D-NEXT: frecip.s $fa0, $fa0 +; LA64D-NEXT: ret + %1 = fdiv float 1.0, %a + ret float %1 +} + +define double @f64_reciprocal(double %a) nounwind { +; LA32F-LABEL: f64_reciprocal: +; LA32F: # %bb.0: +; LA32F-NEXT: addi.w $sp, $sp, -16 +; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; LA32F-NEXT: move $a3, $a1 +; LA32F-NEXT: move $a2, $a0 +; LA32F-NEXT: lu12i.w $a1, 261888 +; LA32F-NEXT: move $a0, $zero +; LA32F-NEXT: bl %plt(__divdf3) +; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload +; LA32F-NEXT: addi.w $sp, $sp, 16 +; LA32F-NEXT: ret +; +; LA32D-LABEL: f64_reciprocal: +; LA32D: # %bb.0: +; LA32D-NEXT: frecip.d $fa0, $fa0 +; LA32D-NEXT: ret +; +; LA64F-LABEL: f64_reciprocal: +; LA64F: # %bb.0: +; LA64F-NEXT: addi.d $sp, $sp, -16 +; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64F-NEXT: move $a1, $a0 +; LA64F-NEXT: lu52i.d $a0, $zero, 1023 +; LA64F-NEXT: bl %plt(__divdf3) +; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64F-NEXT: addi.d $sp, $sp, 16 +; LA64F-NEXT: ret +; +; LA64D-LABEL: f64_reciprocal: +; LA64D: # %bb.0: +; LA64D-NEXT: frecip.d $fa0, $fa0 +; LA64D-NEXT: ret + %1 = fdiv double 1.0, %a + ret double %1 +}