Targets without a `modf` libcall lower the intrinsic directly, matching the existing `llvm.frexp` expansion. Targets with an existing libcall are unchanged. Fixes #173021
348 lines
13 KiB
LLVM
348 lines
13 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: llc -mtriple=amdgcn -mcpu=gfx900 < %s | FileCheck %s
|
|
|
|
declare { float, float } @llvm.modf.f32(float)
|
|
declare { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float>)
|
|
declare { <4 x float>, <4 x float> } @llvm.modf.v4f32(<4 x float>)
|
|
|
|
define { float, float } @modf_3_25() {
|
|
; CHECK-LABEL: modf_3_25:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x3e800000
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0x40400000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float 0x400A000000000000)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_neg_3_25() {
|
|
; CHECK-LABEL: modf_neg_3_25:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0xbe800000
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0xc0400000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float 0xC00A000000000000)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_integer() {
|
|
; CHECK-LABEL: modf_integer:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v0, 1
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0xc2280000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float -42.0)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_fraction() {
|
|
; CHECK-LABEL: modf_fraction:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0.5
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float 0.5)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_negfraction() {
|
|
; CHECK-LABEL: modf_negfraction:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, -0.5
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v1, 1
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float -0.5)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_zero() {
|
|
; CHECK-LABEL: modf_zero:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float 0.0)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_negzero() {
|
|
; CHECK-LABEL: modf_negzero:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v0, 1
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v1, 1
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float -0.0)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_inf() {
|
|
; CHECK-LABEL: modf_inf:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0x7f800000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float 0x7FF0000000000000)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_neginf() {
|
|
; CHECK-LABEL: modf_neginf:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v0, 1
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0xff800000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float 0xFFF0000000000000)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_qnan() {
|
|
; CHECK-LABEL: modf_qnan:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x7fc00000
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0x7fc00000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float 0x7FF8000000000000)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_snan() {
|
|
; CHECK-LABEL: modf_snan:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_trunc_f32_e32 v1, 0x7f800001
|
|
; CHECK-NEXT: v_sub_f32_e32 v0, 0x7f800001, v1
|
|
; CHECK-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float bitcast (i32 2139095041 to float))
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_pos_denorm() {
|
|
; CHECK-LABEL: modf_pos_denorm:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x7fffff
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float bitcast (i32 8388607 to float))
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_neg_denorm() {
|
|
; CHECK-LABEL: modf_neg_denorm:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x807fffff
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v1, 1
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float bitcast (i32 -2139095041 to float))
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { float, float } @modf_posion() {
|
|
; CHECK-LABEL: modf_posion:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { float, float } @llvm.modf.f32(float poison)
|
|
ret { float, float } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_posion_vector() {
|
|
; CHECK-LABEL: modf_posion_vector:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> poison)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_zero_vector() {
|
|
; CHECK-LABEL: modf_zero_vector:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v2, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v3, 0
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> zeroinitializer)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_zero_negzero_vector() {
|
|
; CHECK-LABEL: modf_zero_negzero_vector:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v1, 1
|
|
; CHECK-NEXT: v_mov_b32_e32 v2, 0
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v3, 1
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> <float 0.0, float -0.0>)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|
|
|
|
define { float, float } @modf_modf(float %x) {
|
|
; CHECK-LABEL: modf_modf:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: s_mov_b32 s4, 0x7f800000
|
|
; CHECK-NEXT: v_trunc_f32_e32 v1, v0
|
|
; CHECK-NEXT: v_sub_f32_e32 v1, v0, v1
|
|
; CHECK-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
|
|
; CHECK-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc
|
|
; CHECK-NEXT: s_brev_b32 s5, -2
|
|
; CHECK-NEXT: v_bfi_b32 v0, s5, v1, v0
|
|
; CHECK-NEXT: v_trunc_f32_e32 v1, v0
|
|
; CHECK-NEXT: v_sub_f32_e32 v2, v0, v1
|
|
; CHECK-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
|
|
; CHECK-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
|
|
; CHECK-NEXT: v_bfi_b32 v0, s5, v2, v0
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%modf0 = call { float, float } @llvm.modf.f32(float %x)
|
|
%modf0.0 = extractvalue { float, float } %modf0, 0
|
|
%modf1 = call { float, float } @llvm.modf.f32(float %modf0.0)
|
|
ret { float, float } %modf1
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_modf_vector(<2 x float> %x) {
|
|
; CHECK-LABEL: modf_modf_vector:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: s_mov_b32 s4, 0x7f800000
|
|
; CHECK-NEXT: v_trunc_f32_e32 v2, v1
|
|
; CHECK-NEXT: v_sub_f32_e32 v2, v1, v2
|
|
; CHECK-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s4
|
|
; CHECK-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
|
|
; CHECK-NEXT: s_brev_b32 s5, -2
|
|
; CHECK-NEXT: v_bfi_b32 v1, s5, v2, v1
|
|
; CHECK-NEXT: v_trunc_f32_e32 v2, v0
|
|
; CHECK-NEXT: v_sub_f32_e32 v2, v0, v2
|
|
; CHECK-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
|
|
; CHECK-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
|
|
; CHECK-NEXT: v_bfi_b32 v0, s5, v2, v0
|
|
; CHECK-NEXT: v_trunc_f32_e32 v2, v0
|
|
; CHECK-NEXT: v_sub_f32_e32 v3, v0, v2
|
|
; CHECK-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
|
|
; CHECK-NEXT: v_cndmask_b32_e32 v3, 0, v3, vcc
|
|
; CHECK-NEXT: v_bfi_b32 v0, s5, v3, v0
|
|
; CHECK-NEXT: v_trunc_f32_e32 v3, v1
|
|
; CHECK-NEXT: v_sub_f32_e32 v4, v1, v3
|
|
; CHECK-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s4
|
|
; CHECK-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
|
|
; CHECK-NEXT: v_bfi_b32 v1, s5, v4, v1
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%modf0 = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> %x)
|
|
%modf0.0 = extractvalue { <2 x float>, <2 x float> } %modf0, 0
|
|
%modf1 = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> %modf0.0)
|
|
ret { <2 x float>, <2 x float> } %modf1
|
|
}
|
|
|
|
define { float, float } @modf_modf_const(float %x) {
|
|
; CHECK-LABEL: modf_modf_const:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x3e800000
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%modf0 = call { float, float } @llvm.modf.f32(float 0x400A000000000000)
|
|
%modf0.0 = extractvalue { float, float } %modf0, 0
|
|
%modf1 = call { float, float } @llvm.modf.f32(float %modf0.0)
|
|
ret { float, float } %modf1
|
|
}
|
|
|
|
define { <4 x float>, <4 x float> } @modf_nonsplat_vector() {
|
|
; CHECK-LABEL: modf_nonsplat_vector:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: s_and_b32 s4, 0x80000000, s4
|
|
; CHECK-NEXT: v_trunc_f32_e32 v6, s4
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x3e800000
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v1, 1
|
|
; CHECK-NEXT: v_mov_b32_e32 v2, s4
|
|
; CHECK-NEXT: v_mov_b32_e32 v3, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v4, 0x40400000
|
|
; CHECK-NEXT: v_mov_b32_e32 v5, 0xc2000000
|
|
; CHECK-NEXT: v_mov_b32_e32 v7, 0x4479c000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <4 x float>, <4 x float> } @llvm.modf.v4f32(<4 x float> <float 0x400A000000000000, float -32.0, float poison, float 999.0>)
|
|
ret { <4 x float>, <4 x float> } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_splat_3_25() {
|
|
; CHECK-LABEL: modf_splat_3_25:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x3e800000
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0x3e800000
|
|
; CHECK-NEXT: v_mov_b32_e32 v2, 0x40400000
|
|
; CHECK-NEXT: v_mov_b32_e32 v3, 0x40400000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> <float 0x400A000000000000, float 0x400A000000000000>)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_splat_qnan() {
|
|
; CHECK-LABEL: modf_splat_qnan:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0x7fc00000
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0x7fc00000
|
|
; CHECK-NEXT: v_mov_b32_e32 v2, 0x7fc00000
|
|
; CHECK-NEXT: v_mov_b32_e32 v3, 0x7fc00000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_splat_inf() {
|
|
; CHECK-LABEL: modf_splat_inf:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v2, 0x7f800000
|
|
; CHECK-NEXT: v_mov_b32_e32 v3, 0x7f800000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_splat_neginf() {
|
|
; CHECK-LABEL: modf_splat_neginf:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v0, 1
|
|
; CHECK-NEXT: v_bfrev_b32_e32 v1, 1
|
|
; CHECK-NEXT: v_mov_b32_e32 v2, 0xff800000
|
|
; CHECK-NEXT: v_mov_b32_e32 v3, 0xff800000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> <float 0xFFF0000000000000, float 0xFFF0000000000000>)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|
|
|
|
define { <2 x float>, <2 x float> } @modf_splat_poison_inf() {
|
|
; CHECK-LABEL: modf_splat_poison_inf:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
|
|
; CHECK-NEXT: s_and_b32 s4, 0x80000000, s4
|
|
; CHECK-NEXT: v_trunc_f32_e32 v2, s4
|
|
; CHECK-NEXT: v_mov_b32_e32 v0, s4
|
|
; CHECK-NEXT: v_mov_b32_e32 v1, 0
|
|
; CHECK-NEXT: v_mov_b32_e32 v3, 0x7f800000
|
|
; CHECK-NEXT: s_setpc_b64 s[30:31]
|
|
%ret = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> <float poison, float 0x7FF0000000000000>)
|
|
ret { <2 x float>, <2 x float> } %ret
|
|
}
|