Skip to content

[ARM]: codegen llvm.roundeven.v* #141786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);

Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()) {
Expand All @@ -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);
}
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/ARM/ARMInstrVFP.td
Original file line number Diff line number Diff line change
Expand Up @@ -1135,8 +1135,13 @@ multiclass vrint_inst_anpm<string opc, bits<2> rm,
Requires<[HasFPARMv8,HasDPVFP]>;
}

// Match either froundeven or int_arm_neon_vrintn
def vrintn_or_froundeven : PatFrags<(ops node:$src),
[(int_arm_neon_vrintn node:$src),
(froundeven node:$src)]>;

defm VRINTA : vrint_inst_anpm<"a", 0b00, fround>;
defm VRINTN : vrint_inst_anpm<"n", 0b01, int_arm_neon_vrintn>;
defm VRINTN : vrint_inst_anpm<"n", 0b01, vrintn_or_froundeven>;
defm VRINTP : vrint_inst_anpm<"p", 0b10, fceil>;
defm VRINTM : vrint_inst_anpm<"m", 0b11, ffloor>;

Expand Down
18 changes: 18 additions & 0 deletions llvm/test/CodeGen/ARM/arm32-rounding.ll
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ entry:
ret double %call
}

; CHECK-LABEL: test13
; CHECK: vrintn.f32
define float @test13(float %a) {
entry:
%round = call float @llvm.roundeven.f32(float %a)
ret float %round
}

; CHECK-LABEL: test14
; CHECK: vrintn.f64
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
Expand All @@ -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)
13 changes: 13 additions & 0 deletions llvm/test/CodeGen/ARM/fp16-fullfp16.ll
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,18 @@ define void @test_round(ptr %p) {
ret void
}

define void @test_roundeven(ptr %p) {
; CHECK-LABEL: test_roundeven:
; CHECK: vldr.16 s0, [r0]
; CHECK-NEXT: vrintn.f16 s0, s0
; CHECK-NEXT: vstr.16 s0, [r0]
; CHECK-NEXT: bx lr
%a = load half, ptr %p, align 2
%r = call half @llvm.roundeven.f16(half %a)
store half %r, ptr %p
ret void
}

define void @test_fmuladd(ptr %p, ptr %q, ptr %r) {
; CHECK-LABEL: test_fmuladd:
; CHECK: vldr.16 s0, [r1]
Expand Down Expand Up @@ -623,4 +635,5 @@ declare half @llvm.trunc.f16(half %a)
declare half @llvm.rint.f16(half %a)
declare half @llvm.nearbyint.f16(half %a)
declare half @llvm.round.f16(half %a)
declare half @llvm.roundeven.f16(half %a)
declare half @llvm.fmuladd.f16(half %a, half %b, half %c)
16 changes: 16 additions & 0 deletions llvm/test/CodeGen/ARM/fp16-promote.ll
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ declare half @llvm.trunc.f16(half %a) #0
declare half @llvm.rint.f16(half %a) #0
declare half @llvm.nearbyint.f16(half %a) #0
declare half @llvm.round.f16(half %a) #0
declare half @llvm.roundeven.f16(half %a) #0
declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0

; CHECK-ALL-LABEL: test_sqrt:
Expand Down Expand Up @@ -811,6 +812,21 @@ define void @test_round(ptr %p) {
ret void
}

; CHECK-FP16-LABEL: test_roundeven:
; CHECK-FP16: vcvtb.f32.f16
; CHECK-FP16: bl roundevenf
; CHECK-FP16: vcvtb.f16.f32
; CHECK-LIBCALL-LABEL: test_roundeven:
; CHECK-LIBCALL: bl __aeabi_h2f
; CHECK-LIBCALL: bl roundevenf
; CHECK-LIBCALL: bl __aeabi_f2h
define void @test_roundeven(ptr %p) {
%a = load half, ptr %p, align 2
%r = call half @llvm.roundeven.f16(half %a)
store half %r, ptr %p
ret void
}

; CHECK-FP16-LABEL: test_fmuladd:
; CHECK-FP16: vcvtb.f32.f16
; CHECK-FP16: vcvtb.f32.f16
Expand Down
108 changes: 108 additions & 0 deletions llvm/test/CodeGen/ARM/vrint.ll
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
; RUN: llc -mtriple=armv8 -mattr=+neon %s -o - | FileCheck %s

declare float @llvm.arm.neon.vrintn.f32(float) nounwind readnone
declare <2 x float> @llvm.arm.neon.vrintn.v2f32(<2 x float>) nounwind readnone
declare <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float>) nounwind readnone

; CHECK-LABEL: vrintn_f32:
; CHECK: vrintn.f32
Expand All @@ -9,3 +11,109 @@ define float @vrintn_f32(ptr %A) nounwind {
%tmp2 = call float @llvm.arm.neon.vrintn.f32(float %tmp1)
ret float %tmp2
}

define <2 x float> @frintn_2s(<2 x float> %A) nounwind {
; CHECK-LABEL: frintn_2s:
; CHECK: @ %bb.0:
; CHECK-NEXT: vmov d16, r0, r1
; CHECK-NEXT: vrintn.f32 d16, d16
; CHECK-NEXT: vmov r0, r1, d16
; CHECK-NEXT: bx lr
%tmp3 = call <2 x float> @llvm.arm.neon.vrintn.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: @ %bb.0:
; CHECK-NEXT: vmov d17, r2, r3
; CHECK-NEXT: vmov d16, r0, r1
; CHECK-NEXT: vrintn.f32 q8, q8
; CHECK-NEXT: vmov r0, r1, d16
; CHECK-NEXT: vmov r2, r3, d17
; CHECK-NEXT: bx lr
%tmp3 = call <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float> %A)
ret <4 x float> %tmp3
}

define <4 x half> @roundeven_4h(<4 x half> %A) nounwind {
; CHECK-LABEL: roundeven_4h:
; CHECK: @ %bb.0:
; CHECK-NEXT: vmov s0, r3
; CHECK-NEXT: vcvtb.f32.f16 s0, s0
; CHECK-NEXT: vmov s2, r2
; CHECK-NEXT: vrintn.f32 s0, s0
; CHECK-NEXT: vcvtb.f32.f16 s2, s2
; CHECK-NEXT: vrintn.f32 s2, s2
; CHECK-NEXT: vcvtb.f16.f32 s0, s0
; CHECK-NEXT: vcvtb.f16.f32 s2, s2
; CHECK-NEXT: vmov r2, s0
; CHECK-NEXT: vmov s0, r1
; CHECK-NEXT: vmov r3, s2
; CHECK-NEXT: vcvtb.f32.f16 s0, s0
; CHECK-NEXT: vmov s2, r0
; CHECK-NEXT: vrintn.f32 s0, s0
; CHECK-NEXT: vcvtb.f32.f16 s2, s2
; CHECK-NEXT: vcvtb.f16.f32 s0, s0
; CHECK-NEXT: vrintn.f32 s2, s2
; CHECK-NEXT: vmov r0, s0
; CHECK-NEXT: vcvtb.f16.f32 s2, s2
; CHECK-NEXT: vmov r1, s2
; CHECK-NEXT: pkhbt r2, r3, r2, lsl #16
; CHECK-NEXT: pkhbt r0, r1, r0, lsl #16
; CHECK-NEXT: vmov d16, r0, r2
; CHECK-NEXT: vmov.u16 r0, d16[0]
; CHECK-NEXT: vmov.u16 r1, d16[1]
; CHECK-NEXT: vmov.u16 r2, d16[2]
; CHECK-NEXT: vmov.u16 r3, d16[3]
; CHECK-NEXT: bx lr
%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: @ %bb.0:
; CHECK-NEXT: vmov d0, r0, r1
; CHECK-NEXT: vrintn.f32 s3, s1
; CHECK-NEXT: vrintn.f32 s2, s0
; CHECK-NEXT: vmov r0, r1, d1
; CHECK-NEXT: bx lr
%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: @ %bb.0:
; CHECK-NEXT: vmov d1, r2, r3
; CHECK-NEXT: vmov d0, r0, r1
; CHECK-NEXT: vrintn.f32 s7, s3
; CHECK-NEXT: vrintn.f32 s6, s2
; CHECK-NEXT: vrintn.f32 s5, s1
; CHECK-NEXT: vrintn.f32 s4, s0
; CHECK-NEXT: vmov r2, r3, d3
; CHECK-NEXT: vmov r0, r1, d2
; CHECK-NEXT: bx lr
%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: @ %bb.0:
; CHECK-NEXT: vmov d16, r2, r3
; CHECK-NEXT: vmov d17, r0, r1
; CHECK-NEXT: vrintn.f64 d16, d16
; CHECK-NEXT: vrintn.f64 d17, d17
; CHECK-NEXT: vmov r2, r3, d16
; CHECK-NEXT: vmov r0, r1, d17
; CHECK-NEXT: bx lr
%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
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/Thumb2/bf16-instructions.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2373,7 +2373,7 @@ define bfloat @test_roundeven(bfloat %a) {
; CHECK-FP-NEXT: vmov r0, s0
; CHECK-FP-NEXT: lsls r0, r0, #16
; CHECK-FP-NEXT: vmov s0, r0
; CHECK-FP-NEXT: bl roundevenf
; CHECK-FP-NEXT: vrintn.f32 s0, s0
; CHECK-FP-NEXT: bl __truncsfbf2
; CHECK-FP-NEXT: vmov.f16 r0, s0
; CHECK-FP-NEXT: vmov s0, r0
Expand Down
10 changes: 10 additions & 0 deletions llvm/test/CodeGen/Thumb2/float-intrinsics-double.ll
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ define double @round_d(double %a) {
ret double %1
}

declare double @llvm.roundeven.f64(double %Val)
define double @roundeven_d(double %a) {
; CHECK-LABEL: roundeven_d:
; SOFT: {{(bl|b)}} roundeven
; VFP4: b roundeven
; FP-ARMv8: vrintn.f64
%1 = call double @llvm.roundeven.f64(double %a)
ret double %1
}

declare double @llvm.fmuladd.f64(double %a, double %b, double %c)
define double @fmuladd_d(double %a, double %b, double %c) {
; CHECK-LABEL: fmuladd_d:
Expand Down
10 changes: 10 additions & 0 deletions llvm/test/CodeGen/Thumb2/float-intrinsics-float.ll
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@ define float @round_f(float %a) {
ret float %1
}

declare float @llvm.roundeven.f32(float %Val)
define float @roundeven_f(float %a) {
; CHECK-LABEL: roundeven_f:
; SOFT: bl roundevenf
; VFP4: b roundevenf
; FP-ARMv8: vrintn.f32
%1 = call float @llvm.roundeven.f32(float %a)
ret float %1
}

declare float @llvm.fmuladd.f32(float %a, float %b, float %c)
define float @fmuladd_f(float %a, float %b, float %c) {
; CHECK-LABEL: fmuladd_f:
Expand Down