Skip to content

Commit

Permalink
[LoongArch] Use LSX for scalar FP rounding with explicit rounding mode (
Browse files Browse the repository at this point in the history
#114766)

LoongArch FP base ISA only have frint.{s/d} instruction which reads the
global rounding mode. Utilize LSX for explicit rounding mode for scalar
ceil/floor/trunc/roundeven calls when -mlsx opend. It is faster than
calling the libm library functions.

Same as what gcc did:
https://gcc.gnu.org/pipermail/gcc-cvs/2023-November/394218.html
  • Loading branch information
zhaoqi5 authored Nov 6, 2024
1 parent 435e584 commit 92be2cb
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 8 deletions.
4 changes: 4 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
VT, Expand);
}
setOperationAction(ISD::CTPOP, GRLenVT, Legal);
setOperationAction(ISD::FCEIL, {MVT::f32, MVT::f64}, Legal);
setOperationAction(ISD::FFLOOR, {MVT::f32, MVT::f64}, Legal);
setOperationAction(ISD::FTRUNC, {MVT::f32, MVT::f64}, Legal);
setOperationAction(ISD::FROUNDEVEN, {MVT::f32, MVT::f64}, Legal);
}

// Set operations for 'LASX' feature.
Expand Down
26 changes: 26 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -2259,6 +2259,32 @@ def : Pat<(loongarch_vfrsqrte v2f64:$src),
(VFRSQRTE_D v2f64:$src)>;
}

// Vector floating-point conversion
def : Pat<(f32 (fceil FPR32:$fj)),
(f32 (EXTRACT_SUBREG (VFRINTRP_S (VREPLVEI_W
(SUBREG_TO_REG (i64 0), FPR32:$fj, sub_32), 0)), sub_32))>;
def : Pat<(f64 (fceil FPR64:$fj)),
(f64 (EXTRACT_SUBREG (VFRINTRP_D (VREPLVEI_D
(SUBREG_TO_REG (i64 0), FPR64:$fj, sub_64), 0)), sub_64))>;
def : Pat<(f32 (ffloor FPR32:$fj)),
(f32 (EXTRACT_SUBREG (VFRINTRM_S (VREPLVEI_W
(SUBREG_TO_REG (i64 0), FPR32:$fj, sub_32), 0)), sub_32))>;
def : Pat<(f64 (ffloor FPR64:$fj)),
(f64 (EXTRACT_SUBREG (VFRINTRM_D (VREPLVEI_D
(SUBREG_TO_REG (i64 0), FPR64:$fj, sub_64), 0)), sub_64))>;
def : Pat<(f32 (ftrunc FPR32:$fj)),
(f32 (EXTRACT_SUBREG (VFRINTRZ_S (VREPLVEI_W
(SUBREG_TO_REG (i64 0), FPR32:$fj, sub_32), 0)), sub_32))>;
def : Pat<(f64 (ftrunc FPR64:$fj)),
(f64 (EXTRACT_SUBREG (VFRINTRZ_D (VREPLVEI_D
(SUBREG_TO_REG (i64 0), FPR64:$fj, sub_64), 0)), sub_64))>;
def : Pat<(f32 (froundeven FPR32:$fj)),
(f32 (EXTRACT_SUBREG (VFRINTRNE_S (VREPLVEI_W
(SUBREG_TO_REG (i64 0), FPR32:$fj, sub_32), 0)), sub_32))>;
def : Pat<(f64 (froundeven FPR64:$fj)),
(f64 (EXTRACT_SUBREG (VFRINTRNE_D (VREPLVEI_D
(SUBREG_TO_REG (i64 0), FPR64:$fj, sub_64), 0)), sub_64))>;

// load
def : Pat<(int_loongarch_lsx_vld GPR:$rj, timm:$imm),
(VLD GPR:$rj, (to_valid_timm timm:$imm))>;
Expand Down
48 changes: 40 additions & 8 deletions llvm/test/CodeGen/LoongArch/fp-rounding.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ define float @ceil_f32(float %i) nounwind {
;
; LSX-LABEL: ceil_f32:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(ceilf)
; LSX-NEXT: # kill: def $f0 killed $f0 def $vr0
; LSX-NEXT: vreplvei.w $vr0, $vr0, 0
; LSX-NEXT: vfrintrp.s $vr0, $vr0
; LSX-NEXT: # kill: def $f0 killed $f0 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call float @llvm.ceil.f32(float %i)
ret float %0
Expand All @@ -24,7 +28,11 @@ define double @ceil_f64(double %i) nounwind {
;
; LSX-LABEL: ceil_f64:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(ceil)
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 def $vr0
; LSX-NEXT: vreplvei.d $vr0, $vr0, 0
; LSX-NEXT: vfrintrp.d $vr0, $vr0
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call double @llvm.ceil.f64(double %i)
ret double %0
Expand All @@ -38,7 +46,11 @@ define float @floor_f32(float %i) nounwind {
;
; LSX-LABEL: floor_f32:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(floorf)
; LSX-NEXT: # kill: def $f0 killed $f0 def $vr0
; LSX-NEXT: vreplvei.w $vr0, $vr0, 0
; LSX-NEXT: vfrintrm.s $vr0, $vr0
; LSX-NEXT: # kill: def $f0 killed $f0 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call float @llvm.floor.f32(float %i)
ret float %0
Expand All @@ -52,7 +64,11 @@ define double @floor_f64(double %i) nounwind {
;
; LSX-LABEL: floor_f64:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(floor)
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 def $vr0
; LSX-NEXT: vreplvei.d $vr0, $vr0, 0
; LSX-NEXT: vfrintrm.d $vr0, $vr0
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call double @llvm.floor.f64(double %i)
ret double %0
Expand All @@ -66,7 +82,11 @@ define float @trunc_f32(float %i) nounwind {
;
; LSX-LABEL: trunc_f32:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(truncf)
; LSX-NEXT: # kill: def $f0 killed $f0 def $vr0
; LSX-NEXT: vreplvei.w $vr0, $vr0, 0
; LSX-NEXT: vfrintrz.s $vr0, $vr0
; LSX-NEXT: # kill: def $f0 killed $f0 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call float @llvm.trunc.f32(float %i)
ret float %0
Expand All @@ -80,7 +100,11 @@ define double @trunc_f64(double %i) nounwind {
;
; LSX-LABEL: trunc_f64:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(trunc)
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 def $vr0
; LSX-NEXT: vreplvei.d $vr0, $vr0, 0
; LSX-NEXT: vfrintrz.d $vr0, $vr0
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call double @llvm.trunc.f64(double %i)
ret double %0
Expand All @@ -94,7 +118,11 @@ define float @roundeven_f32(float %i) nounwind {
;
; LSX-LABEL: roundeven_f32:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(roundevenf)
; LSX-NEXT: # kill: def $f0 killed $f0 def $vr0
; LSX-NEXT: vreplvei.w $vr0, $vr0, 0
; LSX-NEXT: vfrintrne.s $vr0, $vr0
; LSX-NEXT: # kill: def $f0 killed $f0 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call float @llvm.roundeven.f32(float %i)
ret float %0
Expand All @@ -108,7 +136,11 @@ define double @roundeven_f64(double %i) nounwind {
;
; LSX-LABEL: roundeven_f64:
; LSX: # %bb.0: # %entry
; LSX-NEXT: b %plt(roundeven)
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 def $vr0
; LSX-NEXT: vreplvei.d $vr0, $vr0, 0
; LSX-NEXT: vfrintrne.d $vr0, $vr0
; LSX-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0
; LSX-NEXT: ret
entry:
%0 = call double @llvm.roundeven.f64(double %i)
ret double %0
Expand Down

0 comments on commit 92be2cb

Please sign in to comment.