[llvm] 8223635 - [AMDGPU] Fix miscompile in performSelectCombine for fcmp one with NaN (#213029)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 30 09:51:11 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-07-30T18:51:03+02:00
New Revision: 8223635500c61d10820c011371498b96cd4ffbc7
URL: https://github.com/llvm/llvm-project/commit/8223635500c61d10820c011371498b96cd4ffbc7
DIFF: https://github.com/llvm/llvm-project/commit/8223635500c61d10820c011371498b96cd4ffbc7.diff
LOG: [AMDGPU] Fix miscompile in performSelectCombine for fcmp one with NaN (#213029)
The fold `select (fcmp one x, K), y, K -> ..., x` returned x instead of
K when x was NaN, changing the result
Added:
Modified:
llvm/lib/Target/AMDGPU/SIISelLowering.cpp
llvm/test/CodeGen/AMDGPU/select-cmp-shared-constant-fp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index b3e8982d52fee..5091340e2c894 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -18701,8 +18701,10 @@ SDValue SITargetLowering::performSelectCombine(SDNode *N,
if (!isFloatingPoint && !isInteger)
return SDValue();
- bool isEquality = CC == (isFloatingPoint ? ISD::SETOEQ : ISD::SETEQ);
- bool isNonEquality = CC == (isFloatingPoint ? ISD::SETONE : ISD::SETNE);
+ // Bare SETEQ/SETNE is the builder's NaN-impossible downgrade.
+ bool isEquality = CC == ISD::SETEQ || (isFloatingPoint && CC == ISD::SETOEQ);
+ bool isNonEquality =
+ CC == ISD::SETNE || (isFloatingPoint && CC == ISD::SETONE);
if (!isEquality && !isNonEquality)
return SDValue();
@@ -18738,6 +18740,11 @@ SDValue SITargetLowering::performSelectCombine(SDNode *N,
!(isNonEquality && FalseVal == ConstVal))
return SDValue();
+ // SETONE's false arm is also taken for NaN ArgVal, so require NaN excluded.
+ if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
+ !Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
+ return SDValue();
+
SDValue SelectLHS = (isEquality && TrueVal == ConstVal) ? ArgVal : TrueVal;
SDValue SelectRHS =
(isNonEquality && FalseVal == ConstVal) ? ArgVal : FalseVal;
diff --git a/llvm/test/CodeGen/AMDGPU/select-cmp-shared-constant-fp.ll b/llvm/test/CodeGen/AMDGPU/select-cmp-shared-constant-fp.ll
index 41ad7cb34552c..d26c8aec789f1 100644
--- a/llvm/test/CodeGen/AMDGPU/select-cmp-shared-constant-fp.ll
+++ b/llvm/test/CodeGen/AMDGPU/select-cmp-shared-constant-fp.ll
@@ -70,7 +70,7 @@ define float @fcmp_select_fold_one_f32_imm(float %arg, float %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
- %cmp = fcmp one float %arg, 0x4005BF0A00000000
+ %cmp = fcmp nnan one float %arg, 0x4005BF0A00000000
%sel = select i1 %cmp, float %other, float 0x4005BF0A00000000
ret float %sel
}
@@ -92,7 +92,30 @@ define float @fcmp_select_fold_one_imm_f32(float %arg, float %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
- %cmp = fcmp one float 0x4005BF0A00000000, %arg
+ %cmp = fcmp nnan one float 0x4005BF0A00000000, %arg
+ %sel = select i1 %cmp, float %other, float 0x4005BF0A00000000
+ ret float %sel
+}
+
+; Should NOT be folded: fcmp one without nnan, %arg may be NaN
+define float @fcmp_select_no_fold_one_f32_arg_maybe_nan(float %arg, float %other) {
+; GFX900-LABEL: fcmp_select_no_fold_one_f32_arg_maybe_nan:
+; GFX900: ; %bb.0: ; %entry
+; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX900-NEXT: s_mov_b32 s4, 0x402df850
+; GFX900-NEXT: v_mov_b32_e32 v2, 0x402df850
+; GFX900-NEXT: v_cmp_lg_f32_e32 vcc, s4, v0
+; GFX900-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
+; GFX900-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1010-LABEL: fcmp_select_no_fold_one_f32_arg_maybe_nan:
+; GFX1010: ; %bb.0: ; %entry
+; GFX1010-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1010-NEXT: v_cmp_lg_f32_e32 vcc_lo, 0x402df850, v0
+; GFX1010-NEXT: v_cndmask_b32_e32 v0, 0x402df850, v1, vcc_lo
+; GFX1010-NEXT: s_setpc_b64 s[30:31]
+entry:
+ %cmp = fcmp one float %arg, 0x4005BF0A00000000
%sel = select i1 %cmp, float %other, float 0x4005BF0A00000000
ret float %sel
}
@@ -419,7 +442,7 @@ define double @fcmp_select_fold_one_f64_imm(double %arg, double %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
- %cmp = fcmp one double %arg, 2.718281828459045
+ %cmp = fcmp nnan one double %arg, 2.718281828459045
%sel = select i1 %cmp, double %other, double 2.718281828459045
ret double %sel
}
@@ -444,6 +467,35 @@ define double @fcmp_select_fold_one_imm_f64(double %arg, double %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc_lo
; GFX1010-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
+entry:
+ %cmp = fcmp nnan one double 2.718281828459045, %arg
+ %sel = select i1 %cmp, double %other, double 2.718281828459045
+ ret double %sel
+}
+
+; Should NOT be folded: fcmp one without nnan, %arg may be NaN
+define double @fcmp_select_no_fold_one_f64_arg_maybe_nan(double %arg, double %other) {
+; GFX900-LABEL: fcmp_select_no_fold_one_f64_arg_maybe_nan:
+; GFX900: ; %bb.0: ; %entry
+; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX900-NEXT: s_mov_b32 s4, 0x8b145769
+; GFX900-NEXT: s_mov_b32 s5, 0x4005bf0a
+; GFX900-NEXT: v_cmp_lg_f64_e32 vcc, s[4:5], v[0:1]
+; GFX900-NEXT: v_mov_b32_e32 v4, 0x8b145769
+; GFX900-NEXT: v_mov_b32_e32 v1, 0x4005bf0a
+; GFX900-NEXT: v_cndmask_b32_e32 v0, v4, v2, vcc
+; GFX900-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc
+; GFX900-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1010-LABEL: fcmp_select_no_fold_one_f64_arg_maybe_nan:
+; GFX1010: ; %bb.0: ; %entry
+; GFX1010-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1010-NEXT: s_mov_b32 s4, 0x8b145769
+; GFX1010-NEXT: s_mov_b32 s5, 0x4005bf0a
+; GFX1010-NEXT: v_cmp_lg_f64_e32 vcc_lo, s[4:5], v[0:1]
+; GFX1010-NEXT: v_cndmask_b32_e32 v0, 0x8b145769, v2, vcc_lo
+; GFX1010-NEXT: v_cndmask_b32_e32 v1, 0x4005bf0a, v3, vcc_lo
+; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
%cmp = fcmp one double 2.718281828459045, %arg
%sel = select i1 %cmp, double %other, double 2.718281828459045
@@ -895,7 +947,7 @@ define half @fcmp_select_fold_one_f16_imm(half %arg, half %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
- %cmp = fcmp one half %arg, 0xH4020
+ %cmp = fcmp nnan one half %arg, 0xH4020
%sel = select i1 %cmp, half %other, half 0xH4020
ret half %sel
}
@@ -917,7 +969,30 @@ define half @fcmp_select_fold_one_imm_f16(half %arg, half %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
- %cmp = fcmp one half 0xH4020, %arg
+ %cmp = fcmp nnan one half 0xH4020, %arg
+ %sel = select i1 %cmp, half %other, half 0xH4020
+ ret half %sel
+}
+
+; Should NOT be folded: fcmp one without nnan, %arg may be NaN
+define half @fcmp_select_no_fold_one_f16_arg_maybe_nan(half %arg, half %other) {
+; GFX900-LABEL: fcmp_select_no_fold_one_f16_arg_maybe_nan:
+; GFX900: ; %bb.0: ; %entry
+; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX900-NEXT: s_movk_i32 s4, 0x4020
+; GFX900-NEXT: v_mov_b32_e32 v2, 0x4020
+; GFX900-NEXT: v_cmp_lg_f16_e32 vcc, s4, v0
+; GFX900-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
+; GFX900-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1010-LABEL: fcmp_select_no_fold_one_f16_arg_maybe_nan:
+; GFX1010: ; %bb.0: ; %entry
+; GFX1010-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1010-NEXT: v_cmp_lg_f16_e32 vcc_lo, 0x4020, v0
+; GFX1010-NEXT: v_cndmask_b32_e32 v0, 0x4020, v1, vcc_lo
+; GFX1010-NEXT: s_setpc_b64 s[30:31]
+entry:
+ %cmp = fcmp one half %arg, 0xH4020
%sel = select i1 %cmp, half %other, half 0xH4020
ret half %sel
}
@@ -1188,7 +1263,7 @@ define bfloat @fcmp_select_fold_one_bf16_imm(bfloat %arg, bfloat %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
- %cmp = fcmp one bfloat %arg, 0xR4020
+ %cmp = fcmp nnan one bfloat %arg, 0xR4020
%sel = select i1 %cmp, bfloat %other, bfloat 0xR4020
ret bfloat %sel
}
@@ -1212,7 +1287,32 @@ define bfloat @fcmp_select_fold_one_imm_bf16(bfloat %arg, bfloat %other) {
; GFX1010-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc_lo
; GFX1010-NEXT: s_setpc_b64 s[30:31]
entry:
- %cmp = fcmp one bfloat 0xR4020, %arg
+ %cmp = fcmp nnan one bfloat 0xR4020, %arg
+ %sel = select i1 %cmp, bfloat %other, bfloat 0xR4020
+ ret bfloat %sel
+}
+
+; Should NOT be folded: fcmp one without nnan, %arg may be NaN
+define bfloat @fcmp_select_no_fold_one_bf16_arg_maybe_nan(bfloat %arg, bfloat %other) {
+; GFX900-LABEL: fcmp_select_no_fold_one_bf16_arg_maybe_nan:
+; GFX900: ; %bb.0: ; %entry
+; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX900-NEXT: v_lshlrev_b32_e32 v0, 16, v0
+; GFX900-NEXT: s_mov_b32 s4, 0x40200000
+; GFX900-NEXT: v_mov_b32_e32 v2, 0x4020
+; GFX900-NEXT: v_cmp_lg_f32_e32 vcc, s4, v0
+; GFX900-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
+; GFX900-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX1010-LABEL: fcmp_select_no_fold_one_bf16_arg_maybe_nan:
+; GFX1010: ; %bb.0: ; %entry
+; GFX1010-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX1010-NEXT: v_lshlrev_b32_e32 v0, 16, v0
+; GFX1010-NEXT: v_cmp_lg_f32_e32 vcc_lo, 0x40200000, v0
+; GFX1010-NEXT: v_cndmask_b32_e32 v0, 0x4020, v1, vcc_lo
+; GFX1010-NEXT: s_setpc_b64 s[30:31]
+entry:
+ %cmp = fcmp one bfloat %arg, 0xR4020
%sel = select i1 %cmp, bfloat %other, bfloat 0xR4020
ret bfloat %sel
}
More information about the llvm-commits
mailing list