; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc -mtriple=riscv64 -mattr=+v,+f,+d < %s | FileCheck %s define i1 @isneginf_constant_f32() nounwind { ; CHECK-LABEL: isneginf_constant_f32: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %f = tail call i1 @llvm.is.fpclass.f32(float 1.0, i32 4) ; 0x4 = "neginf" ret i1 %f } define i8 @iszero_constant_v4f32() nounwind { ; CHECK-LABEL: iszero_constant_v4f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma ; CHECK-NEXT: vmclr.m v8 ; CHECK-NEXT: vmv.x.s a0, v8 ; CHECK-NEXT: ret %f = tail call <8 x i1> @llvm.is.fpclass.v4f32(<8 x float> , i32 96) ; 0x60 = "zero" %r = bitcast <8 x i1> %f to i8 ret i8 %r } ; elts 0,2 sign set, idx=0, ispos -> false define i1 @extract_bitcast_sign_set_not_pos(<4 x i32> %bits, ptr %p) nounwind { ; CHECK-LABEL: extract_bitcast_sign_set_not_pos: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vid.v v9 ; CHECK-NEXT: vsll.vi v9, v9, 31 ; CHECK-NEXT: lui a1, 524288 ; CHECK-NEXT: vrsub.vx v9, v9, a1 ; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %masked = or <4 x i32> %bits, %fvec = bitcast <4 x i32> %masked to <4 x float> store <4 x float> %fvec, ptr %p %elt = extractelement <4 x float> %fvec, i32 0 %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 960) ; 0x3C0 = any positive ret i1 %res } ; elts 0,2 sign set, idx=1 unknown sign, ispos -> cannot fold define i1 @extract_bitcast_unknown_sign_ispos(<4 x i32> %bits, ptr %p) nounwind { ; CHECK-LABEL: extract_bitcast_unknown_sign_ispos: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vid.v v9 ; CHECK-NEXT: vsll.vi v9, v9, 31 ; CHECK-NEXT: lui a1, 524288 ; CHECK-NEXT: vrsub.vx v9, v9, a1 ; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: vslidedown.vi v9, v8, 1 ; CHECK-NEXT: vfmv.f.s fa5, v9 ; CHECK-NEXT: fclass.s a1, fa5 ; CHECK-NEXT: andi a1, a1, 240 ; CHECK-NEXT: snez a1, a1 ; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: mv a0, a1 ; CHECK-NEXT: ret %masked = or <4 x i32> %bits, %fvec = bitcast <4 x i32> %masked to <4 x float> store <4 x float> %fvec, ptr %p %elt = extractelement <4 x float> %fvec, i32 1 %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 960) ; 0x3C0 = any positive ret i1 %res } ; elts 0,2 exp bit cleared (not NaN), idx=0, isnan -> false define i1 @extract_bitcast_not_nan(<4 x i32> %bits, ptr %p) nounwind { ; CHECK-LABEL: extract_bitcast_not_nan: ; CHECK: # %bb.0: ; CHECK-NEXT: lui a1, 786432 ; CHECK-NEXT: addi a1, a1, -1 ; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a1 ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vand.vv v8, v8, v9 ; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %masked = and <4 x i32> %bits, %fvec = bitcast <4 x i32> %masked to <4 x float> store <4 x float> %fvec, ptr %p %elt = extractelement <4 x float> %fvec, i32 0 %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 3) ; 0x3 = nan ret i1 %res } ; elts 0,2 exp bit cleared, idx=1 unchanged, isnan -> cannot fold define i1 @extract_bitcast_maybe_nan(<4 x i32> %bits, ptr %p) nounwind { ; CHECK-LABEL: extract_bitcast_maybe_nan: ; CHECK: # %bb.0: ; CHECK-NEXT: lui a1, 786432 ; CHECK-NEXT: addi a1, a1, -1 ; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a1 ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vand.vv v8, v8, v9 ; CHECK-NEXT: vslidedown.vi v9, v8, 1 ; CHECK-NEXT: vfmv.f.s fa5, v9 ; CHECK-NEXT: fclass.s a1, fa5 ; CHECK-NEXT: andi a1, a1, 768 ; CHECK-NEXT: snez a1, a1 ; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: mv a0, a1 ; CHECK-NEXT: ret %masked = and <4 x i32> %bits, %fvec = bitcast <4 x i32> %masked to <4 x float> store <4 x float> %fvec, ptr %p %elt = extractelement <4 x float> %fvec, i32 1 %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 3) ; 0x3 = nan ret i1 %res } ; mixed sign, unknown idx, ispos -> cannot fold define i1 @extract_bitcast_unknown_idx_not_pos(<4 x i32> %bits, ptr %p, i32 %idx) nounwind { ; CHECK-LABEL: extract_bitcast_unknown_idx_not_pos: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vid.v v9 ; CHECK-NEXT: lui a2, 524288 ; CHECK-NEXT: slli a1, a1, 32 ; CHECK-NEXT: vsll.vi v9, v9, 31 ; CHECK-NEXT: vrsub.vx v9, v9, a2 ; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: srli a1, a1, 32 ; CHECK-NEXT: vslidedown.vx v9, v8, a1 ; CHECK-NEXT: vfmv.f.s fa5, v9 ; CHECK-NEXT: fclass.s a1, fa5 ; CHECK-NEXT: andi a1, a1, 240 ; CHECK-NEXT: snez a1, a1 ; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: mv a0, a1 ; CHECK-NEXT: ret %masked = or <4 x i32> %bits, %fvec = bitcast <4 x i32> %masked to <4 x float> store <4 x float> %fvec, ptr %p %elt = extractelement <4 x float> %fvec, i32 %idx %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 960) ; 0x3C0 = any positive ret i1 %res } ; idx=6 (OOB) -> poison, isnan -> false define i1 @extract_bitcast_oob_idx(<4 x i32> %bits, ptr %p) nounwind { ; CHECK-LABEL: extract_bitcast_oob_idx: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vid.v v9 ; CHECK-NEXT: vsll.vi v9, v9, 31 ; CHECK-NEXT: lui a1, 524288 ; CHECK-NEXT: vrsub.vx v9, v9, a1 ; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: ret %masked = or <4 x i32> %bits, %fvec = bitcast <4 x i32> %masked to <4 x float> store <4 x float> %fvec, ptr %p %elt = extractelement <4 x float> %fvec, i32 6 %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 3) ; 0x3 = nan ret i1 %res } define i1 @extract_fabs_unknown_idx_isneg(<4 x float> %a0, i32 %idx) nounwind { ; CHECK-LABEL: extract_fabs_unknown_idx_isneg: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %abs = call <4 x float> @llvm.fabs.v4f32(<4 x float> %a0) %elt = extractelement <4 x float> %abs, i32 %idx %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 60) ; 0x3C = negative ret i1 %res } define i1 @extract_scalable_fabs_isneg( %a0) nounwind { ; CHECK-LABEL: extract_scalable_fabs_isneg: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %abs = call @llvm.fabs.nxv4f32( %a0) %elt = extractelement %abs, i32 0 %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 60) ; 0x3C = negative ret i1 %res } define i1 @fabs_is_nonneg_or_nan(float %x) nounwind { ; CHECK-LABEL: fabs_is_nonneg_or_nan: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 1 ; CHECK-NEXT: ret %a = call float @llvm.fabs.f32(float %x) %res = call i1 @llvm.is.fpclass.f32(float %a, i32 963) ; 0x3C3 = any positive | nan ret i1 %res } define @splat_constant_is_pos_normal() { ; CHECK-LABEL: splat_constant_is_pos_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %res = call @llvm.is.fpclass.nxv4f32( splat (float 1.0), i32 128) ; 128 = pos_normal ret %res } define @splat_constant_isnan_false() { ; CHECK-LABEL: splat_constant_isnan_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %res = call @llvm.is.fpclass.nxv4f32( splat (float 1.0), i32 3) ; 3 = nan ret %res } define @splat_constant_f64_isinf_false() { ; CHECK-LABEL: splat_constant_f64_isinf_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %res = call @llvm.is.fpclass.nxv2f64( splat (double 1.0), i32 516) ; 516 = inf ret %res } define <4 x i1> @fneg_vec_not_negative(<4 x i32> %vecbits) nounwind { ; CHECK-LABEL: fneg_vec_not_negative: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %masked = or <4 x i32> %vecbits, splat(i32 u0x80000000) ; set sign bits %fvec = bitcast <4 x i32> %masked to <4 x float> %neg = fneg <4 x float> %fvec %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %neg, i32 60) ; any negative ret <4 x i1> %res } define <4 x i1> @fneg_vec_not_positive(<4 x i32> %vecbits) nounwind { ; CHECK-LABEL: fneg_vec_not_positive: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %masked = and <4 x i32> %vecbits, splat(i32 u0x7fffffff) ; clear sign bit %fvec = bitcast <4 x i32> %masked to <4 x float> %neg = fneg <4 x float> %fvec %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %neg, i32 960) ; any positive ret <4 x i1> %res } define <4 x i1> @fneg_vec_unknown_sign(<4 x i32> %vecbits) nounwind { ; CHECK-LABEL: fneg_vec_unknown_sign: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vfneg.v v8, v8 ; CHECK-NEXT: vfclass.v v8, v8 ; CHECK-NEXT: vand.vi v8, v8, 15 ; CHECK-NEXT: vmsne.vi v0, v8, 0 ; CHECK-NEXT: ret %fvec = bitcast <4 x i32> %vecbits to <4 x float> ; no modification %neg = fneg <4 x float> %fvec %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %neg, i32 60) ; any negative ret <4 x i1> %res } define i1 @copysign_nan_mag_is_finite_or_inf(float %y) nounwind { ; CHECK-LABEL: copysign_nan_mag_is_finite_or_inf: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %r = call float @llvm.copysign.f32(float 0x7FF8000000000000, float %y) %res = call i1 @llvm.is.fpclass.f32(float %r, i32 1020) ; 0x3FC = finite | inf ret i1 %res } define i1 @copysign_zero_mag_isnan(float %y) nounwind { ; CHECK-LABEL: copysign_zero_mag_isnan: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %r = call float @llvm.copysign.f32(float 0.0, float %y) %res = call i1 @llvm.is.fpclass.f32(float %r, i32 3) ; 0x3 = nan ret i1 %res } define i1 @copysign_inf_mag_isfinite_or_nan(float %y) nounwind { ; CHECK-LABEL: copysign_inf_mag_isfinite_or_nan: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %r = call float @llvm.copysign.f32(float 0x7FF0000000000000, float %y) %res = call i1 @llvm.is.fpclass.f32(float %r, i32 507) ; 0x1FB = finite (0x1F8) | nan (0x3) ret i1 %res } define i1 @copysign_normal_mag_not_normal(float %y) nounwind { ; CHECK-LABEL: copysign_normal_mag_not_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: ret %r = call float @llvm.copysign.f32(float 1.0, float %y) %res = call i1 @llvm.is.fpclass.f32(float %r, i32 759) ; 0x2F7 = all classes except +/-normal (0x108) ret i1 %res } define i1 @copysign_normal_mag_is_normal(float %y) nounwind { ; CHECK-LABEL: copysign_normal_mag_is_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: li a0, 1 ; CHECK-NEXT: ret %r = call float @llvm.copysign.f32(float 1.0, float %y) %res = call i1 @llvm.is.fpclass.f32(float %r, i32 264) ; 0x108 = +/-normal ret i1 %res } define i1 @copysign_unknown_sign_no_fold(float %x, float %y) nounwind { ; CHECK-LABEL: copysign_unknown_sign_no_fold: ; CHECK: # %bb.0: ; CHECK-NEXT: fsgnj.s fa5, fa0, fa1 ; CHECK-NEXT: fclass.s a0, fa5 ; CHECK-NEXT: andi a0, a0, 15 ; CHECK-NEXT: snez a0, a0 ; CHECK-NEXT: ret %r = call float @llvm.copysign.f32(float %x, float %y) %res = call i1 @llvm.is.fpclass.f32(float %r, i32 60) ; 0x3C = any negative ret i1 %res } define @extract_subvec_scalable_isneg_false( %a0) { ; CHECK-LABEL: extract_subvec_scalable_isneg_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %abs = call @llvm.fabs.nxv8f32( %a0) %sub = call @llvm.vector.extract.nxv4f32.nxv8f32( %abs, i64 0) %res = call @llvm.is.fpclass.nxv4f32( %sub, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret %res } define <2 x i1> @extract_subvec_fixed_isneg_false(<4 x float> %a0) { ; CHECK-LABEL: extract_subvec_fixed_isneg_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %abs = call <4 x float> @llvm.fabs.v4f32(<4 x float> %a0) %sub = call <2 x float> @llvm.vector.extract.v2f32.v4f32(<4 x float> %abs, i64 0) %res = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %sub, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret <2 x i1> %res } define @insert_subvec_scalable_both_isneg_false( %base, %sub) { ; CHECK-LABEL: insert_subvec_scalable_both_isneg_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %absbase = call @llvm.fabs.nxv4f32( %base) %abssub = call @llvm.fabs.nxv2f32( %sub) %ins = call @llvm.vector.insert.nxv4f32.nxv2f32( %absbase, %abssub, i64 0) %res = call @llvm.is.fpclass.nxv4f32( %ins, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret %res } define <4 x i1> @insert_subvec_fixed_both_isneg_false(<4 x float> %base, <2 x float> %sub) { ; CHECK-LABEL: insert_subvec_fixed_both_isneg_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %absbase = call <4 x float> @llvm.fabs.v4f32(<4 x float> %base) %abssub = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sub) %ins = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> %absbase, <2 x float> %abssub, i64 0) %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %ins, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret <4 x i1> %res } define <2 x i1> @extract_subvec_fixed_mixed_to_pos_isneg_false(<4 x float> %a) { ; CHECK-LABEL: extract_subvec_fixed_mixed_to_pos_isneg_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %abs = call <4 x float> @llvm.fabs.v4f32(<4 x float> %a) %neg = fneg <4 x float> %abs %mixed = shufflevector <4 x float> %abs, <4 x float> %neg, <4 x i32> %sub = call <2 x float> @llvm.vector.extract.v2f32.v4f32(<4 x float> %mixed, i64 0) %res = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %sub, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret <2 x i1> %res } define <2 x i1> @extract_subvec_fixed_straddle_isneg_unknown(<4 x float> %a) { ; CHECK-LABEL: extract_subvec_fixed_straddle_isneg_unknown: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vfabs.v v8, v8 ; CHECK-NEXT: vfneg.v v9, v8 ; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; CHECK-NEXT: vslideup.vi v8, v9, 1 ; CHECK-NEXT: vfclass.v v8, v8 ; CHECK-NEXT: vand.vi v8, v8, 15 ; CHECK-NEXT: vmsne.vi v0, v8, 0 ; CHECK-NEXT: ret %abs = call <4 x float> @llvm.fabs.v4f32(<4 x float> %a) %neg = fneg <4 x float> %abs %mixed = shufflevector <4 x float> %abs, <4 x float> %neg, <4 x i32> %sub = call <2 x float> @llvm.vector.extract.v2f32.v4f32(<4 x float> %mixed, i64 0) %res = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %sub, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret <2 x i1> %res } define <4 x i1> @insert_subvec_fixed_pos_base_neg_sub_isneg_unknown(<4 x float> %base, <2 x float> %sub) { ; CHECK-LABEL: insert_subvec_fixed_pos_base_neg_sub_isneg_unknown: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vfabs.v v8, v8 ; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma ; CHECK-NEXT: vfneg.v v9, v9 ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma ; CHECK-NEXT: vslideup.vi v8, v9, 2 ; CHECK-NEXT: vfclass.v v8, v8 ; CHECK-NEXT: vand.vi v8, v8, 15 ; CHECK-NEXT: vmsne.vi v0, v8, 0 ; CHECK-NEXT: ret %abs_base = call <4 x float> @llvm.fabs.v4f32(<4 x float> %base) %neg_sub = fneg <2 x float> %sub %ins = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> %abs_base, <2 x float> %neg_sub, i64 2) %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %ins, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret <4 x i1> %res } define <4 x i1> @insert_subvec_fixed_pos_base_pos_sub_isneg_false(<4 x float> %base, <2 x float> %sub) { ; CHECK-LABEL: insert_subvec_fixed_pos_base_pos_sub_isneg_false: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: ret %abs_base = call <4 x float> @llvm.fabs.v4f32(<4 x float> %base) %abs_sub = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sub) %ins = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> %abs_base, <2 x float> %abs_sub, i64 2) %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %ins, i32 60) ; 60 = neginf,negnorm,negsub,negzero ret <4 x i1> %res }