; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-neon-syntax=apple -mattr=+fullfp16 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD ; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-neon-syntax=apple -mattr=+fullfp16 -global-isel -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI ;; ---- sitofp + fdiv (power-of-2 divisors) ---- define <2 x float> @sitofp_v2f32_fdiv_2(<2 x i32> %in) { ; CHECK-SD-LABEL: sitofp_v2f32_fdiv_2: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.2s v0, v0, #1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v2f32_fdiv_2: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.2s v1, #64, lsl #24 ; CHECK-GI-NEXT: scvtf.2s v0, v0 ; CHECK-GI-NEXT: fdiv.2s v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = sitofp <2 x i32> %in to <2 x float> %div = fdiv <2 x float> %conv, ret <2 x float> %div } define <4 x float> @sitofp_v4f32_fdiv_4(<4 x i32> %in) { ; CHECK-SD-LABEL: sitofp_v4f32_fdiv_4: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.4s v0, v0, #2 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v4f32_fdiv_4: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: fmov.4s v1, #4.00000000 ; CHECK-GI-NEXT: scvtf.4s v0, v0 ; CHECK-GI-NEXT: fdiv.4s v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = sitofp <4 x i32> %in to <4 x float> %div = fdiv <4 x float> %conv, ret <4 x float> %div } define <2 x double> @sitofp_v2f64_fdiv_16(<2 x i64> %in) { ; CHECK-SD-LABEL: sitofp_v2f64_fdiv_16: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.2d v0, v0, #4 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v2f64_fdiv_16: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: fmov.2d v1, #16.00000000 ; CHECK-GI-NEXT: scvtf.2d v0, v0 ; CHECK-GI-NEXT: fdiv.2d v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = sitofp <2 x i64> %in to <2 x double> %div = fdiv <2 x double> %conv, ret <2 x double> %div } define <4 x half> @sitofp_v4f16_fdiv_8(<4 x i16> %in) { ; CHECK-SD-LABEL: sitofp_v4f16_fdiv_8: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.4h v0, v0, #3 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v4f16_fdiv_8: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.4h v1, #72, lsl #8 ; CHECK-GI-NEXT: scvtf.4h v0, v0 ; CHECK-GI-NEXT: fdiv.4h v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = sitofp <4 x i16> %in to <4 x half> %div = fdiv <4 x half> %conv, ret <4 x half> %div } define <8 x half> @sitofp_v8f16_fdiv_4(<8 x i16> %in) { ; CHECK-SD-LABEL: sitofp_v8f16_fdiv_4: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.8h v0, v0, #2 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v8f16_fdiv_4: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.8h v1, #68, lsl #8 ; CHECK-GI-NEXT: scvtf.8h v0, v0 ; CHECK-GI-NEXT: fdiv.8h v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = sitofp <8 x i16> %in to <8 x half> %div = fdiv <8 x half> %conv, ret <8 x half> %div } ;; ---- sitofp + fmul (reciprocal power-of-2 multipliers) ---- define <2 x float> @sitofp_v2f32_fmul_half(<2 x i32> %in) { ; CHECK-LABEL: sitofp_v2f32_fmul_half: ; CHECK: // %bb.0: ; CHECK-NEXT: scvtf.2s v0, v0, #1 ; CHECK-NEXT: ret %conv = sitofp <2 x i32> %in to <2 x float> %mul = fmul <2 x float> %conv, ret <2 x float> %mul } define <4 x float> @sitofp_v4f32_fmul_quarter(<4 x i32> %in) { ; CHECK-LABEL: sitofp_v4f32_fmul_quarter: ; CHECK: // %bb.0: ; CHECK-NEXT: scvtf.4s v0, v0, #2 ; CHECK-NEXT: ret %conv = sitofp <4 x i32> %in to <4 x float> %mul = fmul <4 x float> %conv, ret <4 x float> %mul } define <2 x double> @sitofp_v2f64_fmul_eighth(<2 x i64> %in) { ; CHECK-LABEL: sitofp_v2f64_fmul_eighth: ; CHECK: // %bb.0: ; CHECK-NEXT: scvtf.2d v0, v0, #3 ; CHECK-NEXT: ret %conv = sitofp <2 x i64> %in to <2 x double> %mul = fmul <2 x double> %conv, ret <2 x double> %mul } define <4 x half> @sitofp_v4f16_fmul_half(<4 x i16> %in) { ; CHECK-LABEL: sitofp_v4f16_fmul_half: ; CHECK: // %bb.0: ; CHECK-NEXT: scvtf.4h v0, v0, #1 ; CHECK-NEXT: ret %conv = sitofp <4 x i16> %in to <4 x half> %mul = fmul <4 x half> %conv, ret <4 x half> %mul } define <8 x half> @sitofp_v8f16_fmul_quarter(<8 x i16> %in) { ; CHECK-LABEL: sitofp_v8f16_fmul_quarter: ; CHECK: // %bb.0: ; CHECK-NEXT: scvtf.8h v0, v0, #2 ; CHECK-NEXT: ret %conv = sitofp <8 x i16> %in to <8 x half> %mul = fmul <8 x half> %conv, ret <8 x half> %mul } ;; ---- uitofp + fdiv (unsigned) ---- define <2 x float> @uitofp_v2f32_fdiv_2(<2 x i32> %in) { ; CHECK-SD-LABEL: uitofp_v2f32_fdiv_2: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ucvtf.2s v0, v0, #1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: uitofp_v2f32_fdiv_2: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.2s v1, #64, lsl #24 ; CHECK-GI-NEXT: ucvtf.2s v0, v0 ; CHECK-GI-NEXT: fdiv.2s v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = uitofp <2 x i32> %in to <2 x float> %div = fdiv <2 x float> %conv, ret <2 x float> %div } define <4 x float> @uitofp_v4f32_fdiv_4(<4 x i32> %in) { ; CHECK-SD-LABEL: uitofp_v4f32_fdiv_4: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ucvtf.4s v0, v0, #2 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: uitofp_v4f32_fdiv_4: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: fmov.4s v1, #4.00000000 ; CHECK-GI-NEXT: ucvtf.4s v0, v0 ; CHECK-GI-NEXT: fdiv.4s v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = uitofp <4 x i32> %in to <4 x float> %div = fdiv <4 x float> %conv, ret <4 x float> %div } define <2 x double> @uitofp_v2f64_fdiv_16(<2 x i64> %in) { ; CHECK-SD-LABEL: uitofp_v2f64_fdiv_16: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ucvtf.2d v0, v0, #4 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: uitofp_v2f64_fdiv_16: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: fmov.2d v1, #16.00000000 ; CHECK-GI-NEXT: ucvtf.2d v0, v0 ; CHECK-GI-NEXT: fdiv.2d v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = uitofp <2 x i64> %in to <2 x double> %div = fdiv <2 x double> %conv, ret <2 x double> %div } define <4 x half> @uitofp_v4f16_fdiv_8(<4 x i16> %in) { ; CHECK-SD-LABEL: uitofp_v4f16_fdiv_8: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ucvtf.4h v0, v0, #3 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: uitofp_v4f16_fdiv_8: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.4h v1, #72, lsl #8 ; CHECK-GI-NEXT: ucvtf.4h v0, v0 ; CHECK-GI-NEXT: fdiv.4h v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = uitofp <4 x i16> %in to <4 x half> %div = fdiv <4 x half> %conv, ret <4 x half> %div } define <8 x half> @uitofp_v8f16_fdiv_4(<8 x i16> %in) { ; CHECK-SD-LABEL: uitofp_v8f16_fdiv_4: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ucvtf.8h v0, v0, #2 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: uitofp_v8f16_fdiv_4: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.8h v1, #68, lsl #8 ; CHECK-GI-NEXT: ucvtf.8h v0, v0 ; CHECK-GI-NEXT: fdiv.8h v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = uitofp <8 x i16> %in to <8 x half> %div = fdiv <8 x half> %conv, ret <8 x half> %div } ;; ---- uitofp + fmul (unsigned, reciprocal) ---- define <2 x float> @uitofp_v2f32_fmul_half(<2 x i32> %in) { ; CHECK-LABEL: uitofp_v2f32_fmul_half: ; CHECK: // %bb.0: ; CHECK-NEXT: ucvtf.2s v0, v0, #1 ; CHECK-NEXT: ret %conv = uitofp <2 x i32> %in to <2 x float> %mul = fmul <2 x float> %conv, ret <2 x float> %mul } define <4 x float> @uitofp_v4f32_fmul_quarter(<4 x i32> %in) { ; CHECK-LABEL: uitofp_v4f32_fmul_quarter: ; CHECK: // %bb.0: ; CHECK-NEXT: ucvtf.4s v0, v0, #2 ; CHECK-NEXT: ret %conv = uitofp <4 x i32> %in to <4 x float> %mul = fmul <4 x float> %conv, ret <4 x float> %mul } define <2 x double> @uitofp_v2f64_fmul_eighth(<2 x i64> %in) { ; CHECK-LABEL: uitofp_v2f64_fmul_eighth: ; CHECK: // %bb.0: ; CHECK-NEXT: ucvtf.2d v0, v0, #3 ; CHECK-NEXT: ret %conv = uitofp <2 x i64> %in to <2 x double> %mul = fmul <2 x double> %conv, ret <2 x double> %mul } define <4 x half> @uitofp_v4f16_fmul_half(<4 x i16> %in) { ; CHECK-LABEL: uitofp_v4f16_fmul_half: ; CHECK: // %bb.0: ; CHECK-NEXT: ucvtf.4h v0, v0, #1 ; CHECK-NEXT: ret %conv = uitofp <4 x i16> %in to <4 x half> %mul = fmul <4 x half> %conv, ret <4 x half> %mul } define <8 x half> @uitofp_v8f16_fmul_quarter(<8 x i16> %in) { ; CHECK-LABEL: uitofp_v8f16_fmul_quarter: ; CHECK: // %bb.0: ; CHECK-NEXT: ucvtf.8h v0, v0, #2 ; CHECK-NEXT: ret %conv = uitofp <8 x i16> %in to <8 x half> %mul = fmul <8 x half> %conv, ret <8 x half> %mul } ;; ---- boundary: max valid shift per element type ---- define <2 x float> @sitofp_v2f32_fdiv_max(<2 x i32> %in) { ; CHECK-SD-LABEL: sitofp_v2f32_fdiv_max: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.2s v0, v0, #32 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v2f32_fdiv_max: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: scvtf.2s v0, v0 ; CHECK-GI-NEXT: adrp x8, .LCPI20_0 ; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI20_0] ; CHECK-GI-NEXT: fdiv.2s v0, v0, v1 ; CHECK-GI-NEXT: ret ; 2^32 = 4294967296.0 — max valid shift for i32 %conv = sitofp <2 x i32> %in to <2 x float> %div = fdiv <2 x float> %conv, ret <2 x float> %div } define <2 x double> @sitofp_v2f64_fdiv_max(<2 x i64> %in) { ; CHECK-SD-LABEL: sitofp_v2f64_fdiv_max: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.2d v0, v0, #64 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v2f64_fdiv_max: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: scvtf.2d v0, v0 ; CHECK-GI-NEXT: adrp x8, .LCPI21_0 ; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI21_0] ; CHECK-GI-NEXT: fdiv.2d v0, v0, v1 ; CHECK-GI-NEXT: ret ; 2^64 — max valid shift for i64 %conv = sitofp <2 x i64> %in to <2 x double> %div = fdiv <2 x double> %conv, ret <2 x double> %div } define <4 x half> @sitofp_v4f16_fdiv_max(<4 x i16> %in) { ; CHECK-SD-LABEL: sitofp_v4f16_fdiv_max: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: movi d1, #0000000000000000 ; CHECK-SD-NEXT: scvtf.4h v0, v0 ; CHECK-SD-NEXT: fmul.4h v0, v0, v1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v4f16_fdiv_max: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.4h v1, #124, lsl #8 ; CHECK-GI-NEXT: scvtf.4h v0, v0 ; CHECK-GI-NEXT: fdiv.4h v0, v0, v1 ; CHECK-GI-NEXT: ret ; 2^16 = 65536.0 — max valid shift for i16 (but not representable in f16) ; f16 max is 65504, so 65536.0 overflows to inf. This should NOT match. %conv = sitofp <4 x i16> %in to <4 x half> %div = fdiv <4 x half> %conv, ret <4 x half> %div } define <4 x half> @sitofp_v4f16_fdiv_1024(<4 x i16> %in) { ; CHECK-SD-LABEL: sitofp_v4f16_fdiv_1024: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: scvtf.4h v0, v0, #10 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: sitofp_v4f16_fdiv_1024: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.4h v1, #100, lsl #8 ; CHECK-GI-NEXT: scvtf.4h v0, v0 ; CHECK-GI-NEXT: fdiv.4h v0, v0, v1 ; CHECK-GI-NEXT: ret ; 2^10 = 1024.0 — shift=10, near upper end of f16 range %conv = sitofp <4 x i16> %in to <4 x half> %div = fdiv <4 x half> %conv, ret <4 x half> %div } ;; ---- negative: out-of-range shift ---- define <2 x float> @neg_sitofp_v2f32_fdiv_too_large(<2 x i32> %in) { ; CHECK-SD-LABEL: neg_sitofp_v2f32_fdiv_too_large: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: movi.2s v1, #47, lsl #24 ; CHECK-SD-NEXT: scvtf.2s v0, v0 ; CHECK-SD-NEXT: fmul.2s v0, v0, v1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: neg_sitofp_v2f32_fdiv_too_large: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: movi.2s v1, #80, lsl #24 ; CHECK-GI-NEXT: scvtf.2s v0, v0 ; CHECK-GI-NEXT: fdiv.2s v0, v0, v1 ; CHECK-GI-NEXT: ret ; 2^33 — exceeds i32 range, should NOT match %conv = sitofp <2 x i32> %in to <2 x float> %div = fdiv <2 x float> %conv, ret <2 x float> %div } define <2 x double> @neg_sitofp_v2f64_fdiv_too_large(<2 x i64> %in) { ; CHECK-SD-LABEL: neg_sitofp_v2f64_fdiv_too_large: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: mov x8, #4314448443020935168 // =0x3be0000000000000 ; CHECK-SD-NEXT: scvtf.2d v0, v0 ; CHECK-SD-NEXT: dup.2d v1, x8 ; CHECK-SD-NEXT: fmul.2d v0, v0, v1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: neg_sitofp_v2f64_fdiv_too_large: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: scvtf.2d v0, v0 ; CHECK-GI-NEXT: adrp x8, .LCPI25_0 ; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI25_0] ; CHECK-GI-NEXT: fdiv.2d v0, v0, v1 ; CHECK-GI-NEXT: ret ; 2^65 — exceeds i64 range, should NOT match %conv = sitofp <2 x i64> %in to <2 x double> %div = fdiv <2 x double> %conv, ret <2 x double> %div } ;; ---- negative: non-power-of-2 ---- define <2 x float> @neg_v2f32_fmul_non_pow2(<2 x i32> %in) { ; CHECK-SD-LABEL: neg_v2f32_fmul_non_pow2: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: mov w8, #36704 // =0x8f60 ; CHECK-SD-NEXT: scvtf.2s v0, v0 ; CHECK-SD-NEXT: movk w8, #9666, lsl #16 ; CHECK-SD-NEXT: dup.2s v1, w8 ; CHECK-SD-NEXT: fmul.2s v0, v0, v1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: neg_v2f32_fmul_non_pow2: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: scvtf.2s v0, v0 ; CHECK-GI-NEXT: adrp x8, .LCPI26_0 ; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI26_0] ; CHECK-GI-NEXT: fmul.2s v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = sitofp <2 x i32> %in to <2 x float> %mul = fmul <2 x float> %conv, ret <2 x float> %mul } define <4 x float> @neg_v4f32_fmul_non_pow2(<4 x i32> %in) { ; CHECK-SD-LABEL: neg_v4f32_fmul_non_pow2: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: mov w8, #36704 // =0x8f60 ; CHECK-SD-NEXT: scvtf.4s v0, v0 ; CHECK-SD-NEXT: movk w8, #9666, lsl #16 ; CHECK-SD-NEXT: dup.4s v1, w8 ; CHECK-SD-NEXT: fmul.4s v0, v0, v1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: neg_v4f32_fmul_non_pow2: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: scvtf.4s v0, v0 ; CHECK-GI-NEXT: adrp x8, .LCPI27_0 ; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI27_0] ; CHECK-GI-NEXT: fmul.4s v0, v0, v1 ; CHECK-GI-NEXT: ret %conv = sitofp <4 x i32> %in to <4 x float> %mul = fmul <4 x float> %conv, ret <4 x float> %mul } define <2 x double> @neg_v2f64_fmul_non_pow2(<2 x i64> %in) { ; CHECK-SD-LABEL: neg_v2f64_fmul_non_pow2: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: mov x8, #5243 // =0x147b ; CHECK-SD-NEXT: scvtf.2d v0, v0 ; CHECK-SD-NEXT: movk x8, #18350, lsl #16 ; CHECK-SD-NEXT: movk x8, #31457, lsl #32 ; CHECK-SD-NEXT: movk x8, #16276, lsl #48 ; CHECK-SD-NEXT: dup.2d v1, x8 ; CHECK-SD-NEXT: fmul.2d v0, v0, v1 ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: neg_v2f64_fmul_non_pow2: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: scvtf.2d v0, v0 ; CHECK-GI-NEXT: adrp x8, .LCPI28_0 ; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI28_0] ; CHECK-GI-NEXT: fmul.2d v0, v0, v1[0] ; CHECK-GI-NEXT: ret %conv = sitofp <2 x i64> %in to <2 x double> %mul = fmul <2 x double> %conv, ret <2 x double> %mul }