[llvm] [InstCombine] Add select to worklist when demanded FP class adds nsz (PR #222847)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 22:57:23 PDT 2026


https://github.com/itsvineet99 created https://github.com/llvm/llvm-project/pull/222847

When InstCombine simplifies a demanded FP class and applies the nsz fast-math flag to an instruction, it previously failed to push the instruction's operands back onto the worklist.

If one of those operands was a select representing a hand-rolled min/max, this bookkeeping failure caused the select to be optimized during the fixpoint verification pass, resulting in a fatal compiler crash.

This patch ensures that when nsz is inferred and added, any select operands are explicitly pushed to the worklist for re-evaluation.

Fixes #222343

>From ebae652039d78bc0e8783818b0cd9d08e6a80a15 Mon Sep 17 00:00:00 2001
From: Vineet Dorikar <vineetdorikar06 at gmail.com>
Date: Fri, 11 Sep 2026 11:19:56 +0530
Subject: [PATCH] [InstCombine] Add select to worklist when demanded FP class
 adds nsz

When InstCombine simplifies a demanded FP class and applies the nsz fast-math flag to an instruction, it previously failed to push the instruction's operands back onto the worklist.

If one of those operands was a select representing a hand-rolled min/max, this bookkeeping failure caused the select to be optimized during the fixpoint verification pass, resulting in a fatal compiler crash.

This patch ensures that when nsz is inferred and added, any select operands are explicitly pushed to the worklist for re-evaluation.

Fixes #222343
---
 .../InstCombineSimplifyDemanded.cpp           | 12 +++++++++++
 .../simplify-demanded-fpclass-maximum.ll      | 21 +++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 1002f34de0b8e..c3d8d101c7890 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -3056,7 +3056,19 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
       }
 
       if (InferredFMF != FMF) {
+        bool AddedNSZ = !FMF.noSignedZeros() && InferredFMF.noSignedZeros();
         CI->setFastMathFlags(InferredFMF);
+        
+        // BUG FIX: If we just added the nsz (No Signed Zero) flag, the demanded 
+        // FP class for our operands has changed. If an operand is a select, 
+        // it may now be foldable into a maxnum/minnum. Push it to the worklist!
+        if (AddedNSZ) {
+          for (Use &Op : CI->operands()) {
+            if (auto *Sel = dyn_cast<SelectInst>(Op.get()))
+              Worklist.push(Sel);
+          }
+        }
+        
         return FPOp;
       }
 
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
index 8b8284e8a50ae..fff8a9b7aa9ad 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
@@ -2192,3 +2192,24 @@ define nofpclass(snan) float @qnan_result_demands_snan_rhs(i1 %cond, float %unkn
 
 attributes #0 = { denormal_fpenv(preservesign) }
 attributes #1 = { denormal_fpenv(dynamic) }
+
+
+; nsf flag or something
+
+; Adapted from ret_always_positive_nonzero__maximum__not_zero_select_positive_or_unknown
+; in file Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll
+
+define nofpclass(pinf pnorm psub) float @test_nofpclass_worklist_bug(float %unknown, float nofpclass(zero) %not.zero) {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @test_nofpclass_worklist_bug(
+; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
+; CHECK-NEXT:    [[ALWAYS_POSITIVE:%.*]] = call float @returns_positive()
+; CHECK-NEXT:    [[SELECT_RHS:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[ALWAYS_POSITIVE]], float [[UNKNOWN]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nsz float @llvm.maximum.f32(float [[NOT_ZERO]], float [[SELECT_RHS]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %always.positive = call float @returns_positive()
+  %cond = fcmp nnan ogt float %always.positive, %unknown
+  %select.rhs = select i1 %cond, float %always.positive, float %unknown
+  %result = call float @llvm.maximum.f32(float %not.zero, float %select.rhs)
+  ret float %result
+}



More information about the llvm-commits mailing list