[DAG] computeKnownFPClass - add ISD::SELECT/VSELECT handling + test coverage (#194009)

Fixes #193500
This commit is contained in:
NagaChaitanya Vellanki
2026-04-30 10:44:15 -07:00
committed by GitHub
parent 0aef0f274b
commit faeae9f34c
2 changed files with 207 additions and 0 deletions

View File

@@ -6159,6 +6159,19 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
Known.KnownFPClasses &= ~AssertedClasses;
break;
}
case ISD::SELECT:
case ISD::VSELECT: {
// TODO: Add adjustKnownFPClassForSelectArm clamp recognition as in
// IR-level ValueTracking.
KnownFPClass KnownFalseClass = computeKnownFPClass(
Op.getOperand(2), DemandedElts, InterestedClasses, Depth + 1);
if (KnownFalseClass.isUnknown())
break;
KnownFPClass KnownTrueClass = computeKnownFPClass(
Op.getOperand(1), DemandedElts, InterestedClasses, Depth + 1);
Known = KnownTrueClass.intersectWith(KnownFalseClass);
break;
}
default:
if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID) {

View File

@@ -70,3 +70,197 @@ define <vscale x 4 x i1> @test_no_overlap_nan_vs_pinf(<vscale x 4 x float> nofpc
%class = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f32(<vscale x 4 x float> %a, i32 512)
ret <vscale x 4 x i1> %class
}
; Fixed vector vselect tests
define <4 x i1> @vselect_both_nevernan(<4 x i1> %cond, <4 x float> nofpclass(nan) %a, <4 x float> nofpclass(nan) %b) {
; CHECK-LABEL: vselect_both_nevernan:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma
; CHECK-NEXT: vmclr.m v0
; CHECK-NEXT: ret
%sel = select <4 x i1> %cond, <4 x float> %a, <4 x float> %b
%class = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %sel, i32 3) ; 0x3 = "nan"
ret <4 x i1> %class
}
define <4 x i1> @vselect_both_neverzero(<4 x i1> %cond, <4 x float> nofpclass(zero) %a, <4 x float> nofpclass(zero) %b) {
; CHECK-LABEL: vselect_both_neverzero:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma
; CHECK-NEXT: vmclr.m v0
; CHECK-NEXT: ret
%sel = select <4 x i1> %cond, <4 x float> %a, <4 x float> %b
%class = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %sel, i32 96) ; 0x60 = "zero"
ret <4 x i1> %class
}
; Scalable vector vselect tests
define <vscale x 4 x i1> @vselect_both_neverinf(<vscale x 4 x i1> %cond, <vscale x 4 x float> nofpclass(inf) %a, <vscale x 4 x float> nofpclass(inf) %b) {
; CHECK-LABEL: vselect_both_neverinf:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma
; CHECK-NEXT: vmclr.m v0
; CHECK-NEXT: ret
%sel = select <vscale x 4 x i1> %cond, <vscale x 4 x float> %a, <vscale x 4 x float> %b
%class = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f32(<vscale x 4 x float> %sel, i32 516) ; 0x204 = "inf"
ret <vscale x 4 x i1> %class
}
define <vscale x 4 x i1> @vselect_both_nevernan_query_naninf(<vscale x 4 x i1> %cond, <vscale x 4 x float> nofpclass(nan) %a, <vscale x 4 x float> nofpclass(nan) %b) {
; CHECK-LABEL: vselect_both_nevernan_query_naninf:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
; CHECK-NEXT: vmerge.vvm v8, v10, v8, v0
; CHECK-NEXT: vfclass.v v8, v8
; CHECK-NEXT: li a0, 129
; CHECK-NEXT: vand.vx v8, v8, a0
; CHECK-NEXT: vmsne.vi v0, v8, 0
; CHECK-NEXT: ret
%sel = select <vscale x 4 x i1> %cond, <vscale x 4 x float> %a, <vscale x 4 x float> %b
%class = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f32(<vscale x 4 x float> %sel, i32 519) ; 0x207 = "nan|inf"
ret <vscale x 4 x i1> %class
}
define <vscale x 4 x i1> @vselect_rhs_unknown(<vscale x 4 x i1> %cond, <vscale x 4 x float> nofpclass(nan) %a, <vscale x 4 x float> %b) {
; CHECK-LABEL: vselect_rhs_unknown:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
; CHECK-NEXT: vmerge.vvm v8, v10, v8, v0
; CHECK-NEXT: vfclass.v v8, v8
; CHECK-NEXT: li a0, 768
; CHECK-NEXT: vand.vx v8, v8, a0
; CHECK-NEXT: vmsne.vi v0, v8, 0
; CHECK-NEXT: ret
%sel = select <vscale x 4 x i1> %cond, <vscale x 4 x float> %a, <vscale x 4 x float> %b
%class = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f32(<vscale x 4 x float> %sel, i32 3) ; 0x3 = "nan"
ret <vscale x 4 x i1> %class
}
define <vscale x 4 x i1> @vselect_lhs_unknown(<vscale x 4 x i1> %cond, <vscale x 4 x float> %a, <vscale x 4 x float> nofpclass(nan) %b) {
; CHECK-LABEL: vselect_lhs_unknown:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
; CHECK-NEXT: vmerge.vvm v8, v10, v8, v0
; CHECK-NEXT: vfclass.v v8, v8
; CHECK-NEXT: li a0, 768
; CHECK-NEXT: vand.vx v8, v8, a0
; CHECK-NEXT: vmsne.vi v0, v8, 0
; CHECK-NEXT: ret
%sel = select <vscale x 4 x i1> %cond, <vscale x 4 x float> %a, <vscale x 4 x float> %b
%class = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f32(<vscale x 4 x float> %sel, i32 3) ; 0x3 = "nan"
ret <vscale x 4 x i1> %class
}
define i1 @select_rhs_unknown(i1 %cond, float nofpclass(nan) %a, float %b) {
; CHECK-LABEL: select_rhs_unknown:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a0, a0, 1
; CHECK-NEXT: bnez a0, .LBB12_2
; CHECK-NEXT: # %bb.1:
; CHECK-NEXT: fmv.s fa0, fa1
; CHECK-NEXT: .LBB12_2:
; CHECK-NEXT: fclass.s a0, fa0
; CHECK-NEXT: andi a0, a0, 768
; CHECK-NEXT: snez a0, a0
; CHECK-NEXT: ret
%sel = select i1 %cond, float %a, float %b
%class = call i1 @llvm.is.fpclass.f32(float %sel, i32 3) ; 0x3 = "nan"
ret i1 %class
}
define i1 @select_lhs_unknown(i1 %cond, float %a, float nofpclass(nan) %b) {
; CHECK-LABEL: select_lhs_unknown:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a0, a0, 1
; CHECK-NEXT: bnez a0, .LBB13_2
; CHECK-NEXT: # %bb.1:
; CHECK-NEXT: fmv.s fa0, fa1
; CHECK-NEXT: .LBB13_2:
; CHECK-NEXT: fclass.s a0, fa0
; CHECK-NEXT: andi a0, a0, 768
; CHECK-NEXT: snez a0, a0
; CHECK-NEXT: ret
%sel = select i1 %cond, float %a, float %b
%class = call i1 @llvm.is.fpclass.f32(float %sel, i32 3) ; 0x3 = "nan"
ret i1 %class
}
define <vscale x 4 x i1> @vselect_asymmetric_nevernan_neverinf_query_nan(<vscale x 4 x i1> %cond, <vscale x 4 x float> nofpclass(nan) %a, <vscale x 4 x float> nofpclass(inf) %b) {
; CHECK-LABEL: vselect_asymmetric_nevernan_neverinf_query_nan:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
; CHECK-NEXT: vmerge.vvm v8, v10, v8, v0
; CHECK-NEXT: vfclass.v v8, v8
; CHECK-NEXT: li a0, 768
; CHECK-NEXT: vand.vx v8, v8, a0
; CHECK-NEXT: vmsne.vi v0, v8, 0
; CHECK-NEXT: ret
%sel = select <vscale x 4 x i1> %cond, <vscale x 4 x float> %a, <vscale x 4 x float> %b
%class = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f32(<vscale x 4 x float> %sel, i32 3) ; 0x3 = "nan"
ret <vscale x 4 x i1> %class
}
; Scalar select tests
define i1 @select_both_nevernan(i1 %cond, float nofpclass(nan) %a, float nofpclass(nan) %b) {
; CHECK-LABEL: select_both_nevernan:
; CHECK: # %bb.0:
; CHECK-NEXT: li a0, 0
; CHECK-NEXT: ret
%sel = select i1 %cond, float %a, float %b
%class = call i1 @llvm.is.fpclass.f32(float %sel, i32 3) ; 0x3 = "nan"
ret i1 %class
}
define i1 @select_both_neverinf(i1 %cond, float nofpclass(inf) %a, float nofpclass(inf) %b) {
; CHECK-LABEL: select_both_neverinf:
; CHECK: # %bb.0:
; CHECK-NEXT: li a0, 0
; CHECK-NEXT: ret
%sel = select i1 %cond, float %a, float %b
%class = call i1 @llvm.is.fpclass.f32(float %sel, i32 516) ; 0x204 = "inf"
ret i1 %class
}
define i1 @select_both_neverzero(i1 %cond, float nofpclass(zero) %a, float nofpclass(zero) %b) {
; CHECK-LABEL: select_both_neverzero:
; CHECK: # %bb.0:
; CHECK-NEXT: li a0, 0
; CHECK-NEXT: ret
%sel = select i1 %cond, float %a, float %b
%class = call i1 @llvm.is.fpclass.f32(float %sel, i32 96) ; 0x60 = "zero"
ret i1 %class
}
define i1 @select_asymmetric_nevernan_neverinf_query_nan(i1 %cond, float nofpclass(nan) %a, float nofpclass(inf) %b) {
; CHECK-LABEL: select_asymmetric_nevernan_neverinf_query_nan:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a0, a0, 1
; CHECK-NEXT: bnez a0, .LBB18_2
; CHECK-NEXT: # %bb.1:
; CHECK-NEXT: fmv.s fa0, fa1
; CHECK-NEXT: .LBB18_2:
; CHECK-NEXT: fclass.s a0, fa0
; CHECK-NEXT: andi a0, a0, 768
; CHECK-NEXT: snez a0, a0
; CHECK-NEXT: ret
%sel = select i1 %cond, float %a, float %b
%class = call i1 @llvm.is.fpclass.f32(float %sel, i32 3) ; 0x3 = "nan"
ret i1 %class
}
define i1 @select_asymmetric_nevernan_neverinf_query_inf(i1 %cond, float nofpclass(nan) %a, float nofpclass(inf) %b) {
; CHECK-LABEL: select_asymmetric_nevernan_neverinf_query_inf:
; CHECK: # %bb.0:
; CHECK-NEXT: andi a0, a0, 1
; CHECK-NEXT: bnez a0, .LBB19_2
; CHECK-NEXT: # %bb.1:
; CHECK-NEXT: fmv.s fa0, fa1
; CHECK-NEXT: .LBB19_2:
; CHECK-NEXT: fclass.s a0, fa0
; CHECK-NEXT: andi a0, a0, 129
; CHECK-NEXT: snez a0, a0
; CHECK-NEXT: ret
%sel = select i1 %cond, float %a, float %b
%class = call i1 @llvm.is.fpclass.f32(float %sel, i32 516) ; 0x204 = "inf"
ret i1 %class
}