[llvm] [ARM]: codegen `llvm.roundeven.v*` (PR #141786)

via llvm-commits llvm-commits at lists.llvm.org
Wed May 28 08:06:49 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: Folkert de Vries (folkertdev)

<details>
<summary>Changes</summary>

fixes https://github.com/llvm/llvm-project/issues/73588

The aarch64 version of `frintn.ll` notes the intention to auto-upgrade `frintn` to `roundeven`. I haven't been able to figure out how to make that happen though (either for arm or aarch64).

---
Full diff: https://github.com/llvm/llvm-project/pull/141786.diff


4 Files Affected:

- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+6) 
- (modified) llvm/lib/Target/ARM/ARMInstrVFP.td (+1-1) 
- (modified) llvm/test/CodeGen/ARM/arm32-rounding.ll (+18) 
- (added) llvm/test/CodeGen/ARM/frintn.ll (+78) 


``````````diff
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index afbf1b4c55e70..8b65d3eeafa06 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -905,6 +905,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FCEIL, MVT::v2f64, Expand);
     setOperationAction(ISD::FTRUNC, MVT::v2f64, Expand);
     setOperationAction(ISD::FRINT, MVT::v2f64, Expand);
+    setOperationAction(ISD::FROUNDEVEN, MVT::v2f64, Expand);
     setOperationAction(ISD::FNEARBYINT, MVT::v2f64, Expand);
     setOperationAction(ISD::FFLOOR, MVT::v2f64, Expand);
     setOperationAction(ISD::FMA, MVT::v2f64, Expand);
@@ -927,6 +928,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FCEIL, MVT::v4f32, Expand);
     setOperationAction(ISD::FTRUNC, MVT::v4f32, Expand);
     setOperationAction(ISD::FRINT, MVT::v4f32, Expand);
+    setOperationAction(ISD::FROUNDEVEN, MVT::v4f32, Expand);
     setOperationAction(ISD::FNEARBYINT, MVT::v4f32, Expand);
     setOperationAction(ISD::FFLOOR, MVT::v4f32, Expand);
 
@@ -945,6 +947,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FCEIL, MVT::v2f32, Expand);
     setOperationAction(ISD::FTRUNC, MVT::v2f32, Expand);
     setOperationAction(ISD::FRINT, MVT::v2f32, Expand);
+    setOperationAction(ISD::FROUNDEVEN, MVT::v2f32, Expand);
     setOperationAction(ISD::FNEARBYINT, MVT::v2f32, Expand);
     setOperationAction(ISD::FFLOOR, MVT::v2f32, Expand);
 
@@ -1087,6 +1090,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FCEIL,      MVT::f64, Expand);
     setOperationAction(ISD::FTRUNC,     MVT::f64, Expand);
     setOperationAction(ISD::FRINT,      MVT::f64, Expand);
+    setOperationAction(ISD::FROUNDEVEN, MVT::f64, Expand);
     setOperationAction(ISD::FNEARBYINT, MVT::f64, Expand);
     setOperationAction(ISD::FFLOOR,     MVT::f64, Expand);
     setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
@@ -1534,6 +1538,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FTRUNC, MVT::f32, Legal);
     setOperationAction(ISD::FNEARBYINT, MVT::f32, Legal);
     setOperationAction(ISD::FRINT, MVT::f32, Legal);
+    setOperationAction(ISD::FROUNDEVEN, MVT::f32, Legal);
     setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
     setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);
     if (Subtarget->hasNEON()) {
@@ -1550,6 +1555,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
       setOperationAction(ISD::FTRUNC, MVT::f64, Legal);
       setOperationAction(ISD::FNEARBYINT, MVT::f64, Legal);
       setOperationAction(ISD::FRINT, MVT::f64, Legal);
+      setOperationAction(ISD::FROUNDEVEN, MVT::f64, Legal);
       setOperationAction(ISD::FMINNUM, MVT::f64, Legal);
       setOperationAction(ISD::FMAXNUM, MVT::f64, Legal);
     }
diff --git a/llvm/lib/Target/ARM/ARMInstrVFP.td b/llvm/lib/Target/ARM/ARMInstrVFP.td
index 2ee2cb2fda4a0..483786a88d28c 100644
--- a/llvm/lib/Target/ARM/ARMInstrVFP.td
+++ b/llvm/lib/Target/ARM/ARMInstrVFP.td
@@ -1095,7 +1095,7 @@ multiclass vrint_inst_zrx<string opc, bit op, bit op2, SDPatternOperator node> {
 
 defm VRINTZ : vrint_inst_zrx<"z", 0, 1, ftrunc>;
 defm VRINTR : vrint_inst_zrx<"r", 0, 0, fnearbyint>;
-defm VRINTX : vrint_inst_zrx<"x", 1, 0, frint>;
+defm VRINTX : vrint_inst_zrx<"x", 1, 0, any_froundeven>;
 
 multiclass vrint_inst_anpm<string opc, bits<2> rm,
                            SDPatternOperator node = null_frag> {
diff --git a/llvm/test/CodeGen/ARM/arm32-rounding.ll b/llvm/test/CodeGen/ARM/arm32-rounding.ll
index b0a9f54e42404..3b9aced91143e 100644
--- a/llvm/test/CodeGen/ARM/arm32-rounding.ll
+++ b/llvm/test/CodeGen/ARM/arm32-rounding.ll
@@ -104,6 +104,22 @@ entry:
   ret double %call
 }
 
+; CHECK-LABEL: test13
+; CHECK: b roundevenf
+define float @test13(float %a) {
+entry:
+  %round = call float @llvm.roundeven.f32(float %a)
+  ret float %round
+}
+
+; CHECK-LABEL: test14
+; CHECK: b roundeven
+define double @test14(double %a) {
+entry:
+  %round = call double @llvm.roundeven.f64(double %a)
+  ret double %round
+}
+
 declare float @floorf(float) nounwind readnone
 declare double @floor(double) nounwind readnone
 declare float @ceilf(float) nounwind readnone
@@ -116,3 +132,5 @@ declare float @nearbyintf(float) nounwind readnone
 declare double @nearbyint(double) nounwind readnone
 declare float @rintf(float) nounwind readnone
 declare double @rint(double) nounwind readnone
+declare float @llvm.roundeven.f32(float)
+declare double @llvm.roundeven.f64(double)
diff --git a/llvm/test/CodeGen/ARM/frintn.ll b/llvm/test/CodeGen/ARM/frintn.ll
new file mode 100644
index 0000000000000..e801b8ea0a707
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/frintn.ll
@@ -0,0 +1,78 @@
+; RUN: llc -mtriple=armv8 -mattr=+neon %s -o - | FileCheck %s
+
+; The llvm.arm.neon.frintn intrinsic should be auto-upgraded to the
+; target-independent roundeven intrinsic.
+
+define <4 x half> @frintn_4h(<4 x half> %A) nounwind {
+;CHECK-LABEL: frintn_4h:
+;CHECK: bl llvm.arm.neon.frintn.v4f16
+	%tmp3 = call <4 x half> @llvm.arm.neon.frintn.v4f16(<4 x half> %A)
+	ret <4 x half> %tmp3
+}
+
+define <2 x float> @frintn_2s(<2 x float> %A) nounwind {
+;CHECK-LABEL: frintn_2s:
+;CHECK: bl llvm.arm.neon.frintn.v2f32
+	%tmp3 = call <2 x float> @llvm.arm.neon.frintn.v2f32(<2 x float> %A)
+	ret <2 x float> %tmp3
+}
+
+define <4 x float> @frintn_4s(<4 x float> %A) nounwind {
+;CHECK-LABEL: frintn_4s:
+;CHECK: bl llvm.arm.neon.frintn.v4f32
+	%tmp3 = call <4 x float> @llvm.arm.neon.frintn.v4f32(<4 x float> %A)
+	ret <4 x float> %tmp3
+}
+
+define <2 x double> @frintn_2d(<2 x double> %A) nounwind {
+;CHECK-LABEL: frintn_2d:
+;CHECK: bl llvm.arm.neon.frintn.v2f64
+	%tmp3 = call <2 x double> @llvm.arm.neon.frintn.v2f64(<2 x double> %A)
+	ret <2 x double> %tmp3
+}
+
+declare <4 x half> @llvm.arm.neon.frintn.v4f16(<4 x half>) nounwind readnone
+declare <2 x float> @llvm.arm.neon.frintn.v2f32(<2 x float>) nounwind readnone
+declare <4 x float> @llvm.arm.neon.frintn.v4f32(<4 x float>) nounwind readnone
+declare <2 x double> @llvm.arm.neon.frintn.v2f64(<2 x double>) nounwind readnone
+
+define <4 x half> @roundeven_4h(<4 x half> %A) nounwind {
+;CHECK-LABEL: roundeven_4h:
+;CHECK: vcvtb.f16.f32 s0, s0
+;CHECK: vrintx.f32 s2, s2
+;CHECK: vmov r0, s0
+;CHECK: vcvtb.f16.f32 s2, s2
+	%tmp3 = call <4 x half> @llvm.roundeven.v4f16(<4 x half> %A)
+	ret <4 x half> %tmp3
+}
+
+define <2 x float> @roundeven_2s(<2 x float> %A) nounwind {
+;CHECK-LABEL: roundeven_2s:
+;CHECK: vrintx.f32 s3, s1
+;CHECK: vrintx.f32 s2, s0
+	%tmp3 = call <2 x float> @llvm.roundeven.v2f32(<2 x float> %A)
+	ret <2 x float> %tmp3
+}
+
+define <4 x float> @roundeven_4s(<4 x float> %A) nounwind {
+;CHECK-LABEL: roundeven_4s:
+;CHECK: vrintx.f32 s7, s3
+;CHECK: vrintx.f32 s6, s2
+;CHECK: vrintx.f32 s5, s1
+;CHECK: vrintx.f32 s4, s0
+	%tmp3 = call <4 x float> @llvm.roundeven.v4f32(<4 x float> %A)
+	ret <4 x float> %tmp3
+}
+
+define <2 x double> @roundeven_2d(<2 x double> %A) nounwind {
+;CHECK-LABEL: roundeven_2d:
+;CHECK: vrintx.f64 d16, d16
+;CHECK: vrintx.f64 d17, d17
+	%tmp3 = call <2 x double> @llvm.roundeven.v2f64(<2 x double> %A)
+	ret <2 x double> %tmp3
+}
+
+declare <4 x half> @llvm.roundeven.v4f16(<4 x half>) nounwind readnone
+declare <2 x float> @llvm.roundeven.v2f32(<2 x float>) nounwind readnone
+declare <4 x float> @llvm.roundeven.v4f32(<4 x float>) nounwind readnone
+declare <2 x double> @llvm.roundeven.v2f64(<2 x double>) nounwind readnone

``````````

</details>


https://github.com/llvm/llvm-project/pull/141786


More information about the llvm-commits mailing list