[llvm] bb648c9 - [WebAssembly] Add lowering for llvm.rint and llvm.roundeven

Derek Schuff via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 23 14:09:23 PDT 2023


Author: xortoast
Date: 2023-06-23T14:07:11-07:00
New Revision: bb648c9177cda700ae63cfced347f62d417a4824

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

LOG: [WebAssembly] Add lowering for llvm.rint and llvm.roundeven

WebAssembly doesn't expose inexact exceptions, so frint can be mapped to
fnearbyint. Likewise, WebAssembly always rounds ties-to-even, so
froundeven can be mapped to fnearbyint.

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

Added: 
    

Modified: 
    llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
    llvm/test/CodeGen/WebAssembly/f32.ll
    llvm/test/CodeGen/WebAssembly/f64.ll
    llvm/test/CodeGen/WebAssembly/libcalls.ll
    llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
    llvm/test/CodeGen/WebAssembly/simd-unsupported.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index d719ab1899ba1..095550e307a25 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -125,8 +125,8 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
       setOperationAction(Op, T, Expand);
     // Note supported floating-point library function operators that otherwise
     // default to expand.
-    for (auto Op :
-         {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT, ISD::FRINT})
+    for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT,
+                    ISD::FRINT, ISD::FROUNDEVEN})
       setOperationAction(Op, T, Legal);
     // Support minimum and maximum, which otherwise default to expand.
     setOperationAction(ISD::FMINIMUM, T, Legal);
@@ -247,7 +247,7 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
 
     // Expand float operations supported for scalars but not SIMD
     for (auto Op : {ISD::FCOPYSIGN, ISD::FLOG, ISD::FLOG2, ISD::FLOG10,
-                    ISD::FEXP, ISD::FEXP2, ISD::FRINT})
+                    ISD::FEXP, ISD::FEXP2})
       for (auto T : {MVT::v4f32, MVT::v2f64})
         setOperationAction(Op, T, Expand);
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
index 104f5f7d2e68c..cc9a9f86f6830 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
@@ -76,6 +76,10 @@ def : Pat<(fcopysign F32:$lhs, F64:$rhs),
 def : Pat<(frint f32:$src), (NEAREST_F32 f32:$src)>;
 def : Pat<(frint f64:$src), (NEAREST_F64 f64:$src)>;
 
+// WebAssembly always rounds ties-to-even, so map froundeven to fnearbyint.
+def : Pat<(froundeven f32:$src), (NEAREST_F32 f32:$src)>;
+def : Pat<(froundeven f64:$src), (NEAREST_F64 f64:$src)>;
+
 let isCommutable = 1 in {
 defm EQ : ComparisonFP<SETOEQ, "eq  ", 0x5b, 0x61>;
 defm NE : ComparisonFP<SETUNE, "ne  ", 0x5c, 0x62>;

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index c85c1001e9c15..8cd41d7017a02 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1158,6 +1158,14 @@ defm FLOOR : SIMDUnary<F64x2, ffloor, "floor", 0x75>;
 defm TRUNC: SIMDUnary<F64x2, ftrunc, "trunc", 0x7a>;
 defm NEAREST: SIMDUnary<F64x2, fnearbyint, "nearest", 0x94>;
 
+// WebAssembly doesn't expose inexact exceptions, so map frint to fnearbyint.
+def : Pat<(v4f32 (frint (v4f32 V128:$src))), (NEAREST_F32x4 V128:$src)>;
+def : Pat<(v2f64 (frint (v2f64 V128:$src))), (NEAREST_F64x2 V128:$src)>;
+
+// WebAssembly always rounds ties-to-even, so map froundeven to fnearbyint.
+def : Pat<(v4f32 (froundeven (v4f32 V128:$src))), (NEAREST_F32x4 V128:$src)>;
+def : Pat<(v2f64 (froundeven (v2f64 V128:$src))), (NEAREST_F64x2 V128:$src)>;
+
 //===----------------------------------------------------------------------===//
 // Floating-point binary arithmetic
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/test/CodeGen/WebAssembly/f32.ll b/llvm/test/CodeGen/WebAssembly/f32.ll
index 3d7d312e0af92..7410fa43e4081 100644
--- a/llvm/test/CodeGen/WebAssembly/f32.ll
+++ b/llvm/test/CodeGen/WebAssembly/f32.ll
@@ -13,6 +13,7 @@ declare float @llvm.floor.f32(float)
 declare float @llvm.trunc.f32(float)
 declare float @llvm.nearbyint.f32(float)
 declare float @llvm.rint.f32(float)
+declare float @llvm.roundeven.f32(float)
 declare float @llvm.fma.f32(float, float, float)
 
 define float @fadd32(float %x, float %y) {
@@ -163,6 +164,17 @@ define float @nearest32_via_rint(float %x) {
   ret float %a
 }
 
+define float @nearest32_via_roundeven(float %x) {
+; CHECK-LABEL: nearest32_via_roundeven:
+; CHECK:         .functype nearest32_via_roundeven (f32) -> (f32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get $push1=, 0
+; CHECK-NEXT:    f32.nearest $push0=, $pop1
+; CHECK-NEXT:    return $pop0
+  %a = call float @llvm.roundeven.f32(float %x)
+  ret float %a
+}
+
 ; This is not "minimum" because a -0.0 input returns +0.0.
 
 define float @fmin32(float %x) {

diff  --git a/llvm/test/CodeGen/WebAssembly/f64.ll b/llvm/test/CodeGen/WebAssembly/f64.ll
index 9c7d10de5509e..d79f34185eb87 100644
--- a/llvm/test/CodeGen/WebAssembly/f64.ll
+++ b/llvm/test/CodeGen/WebAssembly/f64.ll
@@ -13,6 +13,7 @@ declare double @llvm.floor.f64(double)
 declare double @llvm.trunc.f64(double)
 declare double @llvm.nearbyint.f64(double)
 declare double @llvm.rint.f64(double)
+declare double @llvm.roundeven.f64(double)
 declare double @llvm.fma.f64(double, double, double)
 
 define double @fadd64(double %x, double %y) {
@@ -163,6 +164,17 @@ define double @nearest64_via_rint(double %x) {
   ret double %a
 }
 
+define double @nearest64_via_roundeven(double %x) {
+; CHECK-LABEL: nearest64_via_roundeven:
+; CHECK:         .functype nearest64_via_roundeven (f64) -> (f64)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get $push1=, 0
+; CHECK-NEXT:    f64.nearest $push0=, $pop1
+; CHECK-NEXT:    return $pop0
+  %a = call double @llvm.roundeven.f64(double %x)
+  ret double %a
+}
+
 ; This is not "minimum" because a -0.0 input returns +0.0.
 
 define double @fmin64(double %x) {

diff  --git a/llvm/test/CodeGen/WebAssembly/libcalls.ll b/llvm/test/CodeGen/WebAssembly/libcalls.ll
index 2672cf1e1c9be..27bb960afd547 100644
--- a/llvm/test/CodeGen/WebAssembly/libcalls.ll
+++ b/llvm/test/CodeGen/WebAssembly/libcalls.ll
@@ -18,7 +18,6 @@ declare double @llvm.pow.f64(double, double)
 declare double @llvm.powi.f64.i32(double, i32)
 declare double @llvm.log.f64(double)
 declare double @llvm.exp.f64(double)
-declare double @llvm.roundeven.f64(double)
 declare double @llvm.ldexp.f64.i32(double, i32)
 declare i32 @llvm.lround(double)
 
@@ -236,21 +235,20 @@ define double @f64libcalls(double %x, double %y, i32 %z) {
 ; CHECK-LABEL: f64libcalls:
 ; CHECK:         .functype f64libcalls (f64, f64, i32) -> (f64)
 ; CHECK-NEXT:  # %bb.0:
-; CHECK-NEXT:    local.get $push13=, 0
-; CHECK-NEXT:    local.get $push10=, 0
-; CHECK-NEXT:    call $push0=, cos, $pop10
+; CHECK-NEXT:    local.get $push12=, 0
+; CHECK-NEXT:    local.get $push9=, 0
+; CHECK-NEXT:    call $push0=, cos, $pop9
 ; CHECK-NEXT:    call $push1=, log10, $pop0
-; CHECK-NEXT:    local.get $push11=, 1
-; CHECK-NEXT:    call $push2=, pow, $pop1, $pop11
-; CHECK-NEXT:    local.get $push12=, 2
-; CHECK-NEXT:    call $push3=, __powidf2, $pop2, $pop12
+; CHECK-NEXT:    local.get $push10=, 1
+; CHECK-NEXT:    call $push2=, pow, $pop1, $pop10
+; CHECK-NEXT:    local.get $push11=, 2
+; CHECK-NEXT:    call $push3=, __powidf2, $pop2, $pop11
 ; CHECK-NEXT:    call $push4=, log, $pop3
 ; CHECK-NEXT:    call $push5=, exp, $pop4
 ; CHECK-NEXT:    call $push6=, cbrt, $pop5
-; CHECK-NEXT:    call $push7=, roundeven, $pop6
-; CHECK-NEXT:    call $push8=, lround, $pop7
-; CHECK-NEXT:    call $push9=, ldexp, $pop13, $pop8
-; CHECK-NEXT:    return $pop9
+; CHECK-NEXT:    call $push7=, lround, $pop6
+; CHECK-NEXT:    call $push8=, ldexp, $pop12, $pop7
+; CHECK-NEXT:    return $pop8
  %a = call double @llvm.cos.f64(double %x)
  %b = call double @llvm.log10.f64(double %a)
  %c = call double @llvm.pow.f64(double %b, double %y)
@@ -258,10 +256,9 @@ define double @f64libcalls(double %x, double %y, i32 %z) {
  %e = call double @llvm.log.f64(double %d)
  %f = call double @llvm.exp.f64(double %e)
  %g = call fast double @llvm.pow.f64(double %f, double 0x3FD5555555555555)
- %h = call double @llvm.roundeven.f64(double %g)
- %i = call i32 @llvm.lround(double %h)
- %j = call double @llvm.ldexp.f64.i32(double %x, i32 %i);
- ret double %j
+ %h = call i32 @llvm.lround(double %g)
+ %i = call double @llvm.ldexp.f64.i32(double %x, i32 %h);
+ ret double %i
 }
 
 ; fcmp ord and unord (RTLIB::O_F32 / RTLIB::UO_F32 etc) are a special case (see

diff  --git a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
index 5c9196ca6700a..a033d2de79c87 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
@@ -725,6 +725,26 @@ define <4 x float> @nearest_v4f32(<4 x float> %a) {
   ret <4 x float> %v
 }
 
+; CHECK-LABEL: nearest_v4f32_via_rint:
+; CHECK-NEXT: .functype nearest_v4f32_via_rint (v128) -> (v128){{$}}
+; CHECK-NEXT: f32x4.nearest $push[[R:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[R]]{{$}}
+declare <4 x float> @llvm.rint.v4f32(<4 x float>)
+define <4 x float> @nearest_v4f32_via_rint(<4 x float> %a) {
+  %v = call <4 x float> @llvm.rint.v4f32(<4 x float> %a)
+  ret <4 x float> %v
+}
+
+; CHECK-LABEL: nearest_v4f32_via_roundeven:
+; CHECK-NEXT: .functype nearest_v4f32_via_roundeven (v128) -> (v128){{$}}
+; CHECK-NEXT: f32x4.nearest $push[[R:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[R]]{{$}}
+declare <4 x float> @llvm.roundeven.v4f32(<4 x float>)
+define <4 x float> @nearest_v4f32_via_roundeven(<4 x float> %a) {
+  %v = call <4 x float> @llvm.roundeven.v4f32(<4 x float> %a)
+  ret <4 x float> %v
+}
+
 ; CHECK-LABEL: madd_v4f32:
 ; CHECK-NEXT: .functype madd_v4f32 (v128, v128, v128) -> (v128){{$}}
 ; CHECK-NEXT: f32x4.relaxed_madd $push[[R:[0-9]+]]=, $0, $1, $2{{$}}
@@ -862,6 +882,26 @@ define <2 x double> @nearest_v2f64(<2 x double> %a) {
   ret <2 x double> %v
 }
 
+; CHECK-LABEL: nearest_v2f64_via_rint:
+; CHECK-NEXT: .functype nearest_v2f64_via_rint (v128) -> (v128){{$}}
+; CHECK-NEXT: f64x2.nearest $push[[R:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[R]]{{$}}
+declare <2 x double> @llvm.rint.v2f64(<2 x double>)
+define <2 x double> @nearest_v2f64_via_rint(<2 x double> %a) {
+  %v = call <2 x double> @llvm.rint.v2f64(<2 x double> %a)
+  ret <2 x double> %v
+}
+
+; CHECK-LABEL: nearest_v2f64_via_roundeven:
+; CHECK-NEXT: .functype nearest_v2f64_via_roundeven (v128) -> (v128){{$}}
+; CHECK-NEXT: f64x2.nearest $push[[R:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[R]]{{$}}
+declare <2 x double> @llvm.roundeven.v2f64(<2 x double>)
+define <2 x double> @nearest_v2f64_via_roundeven(<2 x double> %a) {
+  %v = call <2 x double> @llvm.roundeven.v2f64(<2 x double> %a)
+  ret <2 x double> %v
+}
+
 ; CHECK-LABEL: madd_v2f64:
 ; CHECK-NEXT: .functype madd_v2f64 (v128, v128, v128) -> (v128){{$}}
 ; CHECK-NEXT: f64x2.relaxed_madd $push[[R:[0-9]+]]=, $0, $1, $2{{$}}

diff  --git a/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll b/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll
index 4999db6d8e99b..d214a3af5a151 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll
@@ -433,14 +433,6 @@ define <4 x float> @exp2_v4f32(<4 x float> %x) {
   ret <4 x float> %v
 }
 
-; CHECK-LABEL: rint_v4f32:
-; CHECK: f32.nearest
-declare <4 x float> @llvm.rint.v4f32(<4 x float>)
-define <4 x float> @rint_v4f32(<4 x float> %x) {
-  %v = call <4 x float> @llvm.rint.v4f32(<4 x float> %x)
-  ret <4 x float> %v
-}
-
 ; CHECK-LABEL: round_v4f32:
 ; CHECK: call $push[[L:[0-9]+]]=, roundf
 declare <4 x float> @llvm.round.v4f32(<4 x float>)
@@ -533,14 +525,6 @@ define <2 x double> @exp2_v2f64(<2 x double> %x) {
   ret <2 x double> %v
 }
 
-; CHECK-LABEL: rint_v2f64:
-; CHECK: f64.nearest
-declare <2 x double> @llvm.rint.v2f64(<2 x double>)
-define <2 x double> @rint_v2f64(<2 x double> %x) {
-  %v = call <2 x double> @llvm.rint.v2f64(<2 x double> %x)
-  ret <2 x double> %v
-}
-
 ; CHECK-LABEL: round_v2f64:
 ; CHECK: call $push[[L:[0-9]+]]=, round
 declare <2 x double> @llvm.round.v2f64(<2 x double>)


        


More information about the llvm-commits mailing list