Bug type: miscompilation
Component: ValueTracking
Bug location: llvm/lib/Analysis/ValueTracking.cpp: isGuaranteedNotToBeUndefOrPoison
Issue title: [InstCombine] Freeze is incorrectly dropped
Labels: miscompilation
llvm:analysis
generated by fuzzer
Reported by: dtcxzyw

Reproducer: https://alive2.llvm.org/ce/z/xyfr4N
```
; bin/opt -passes=instcombine test.ll -S
define float @test(float %arg) {
entry:
  %cond = tail call i1 @llvm.is.fpclass.f32(float %arg, i32 144)
  %0 = freeze i1 %cond
  br i1 %0, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  %fadd = fadd float %arg, 1.0
  br label %if.exit

if.exit:                                          ; preds = %if.then, %entry
  %ret = phi ninf float [ %fadd, %if.then ], [ %arg, %entry ]
  %1 = freeze float %ret
  ret float %1
}
```
```
=>
define float @test(float %arg) {
entry:
  %arg.fr = freeze float %arg
  %cond = is.fpclass float %arg.fr, i32 144
  br i1 %cond, label %if.then, label %if.exit

if.then:
  %fadd = fadd float %arg.fr, 1.000000
  br label %if.exit

if.exit:
  %ret = phi ninf float [ %fadd, %if.then ], [ %arg.fr, %entry ]
  ret float %ret
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
float %arg = #xff800000 (-oo)

Source:
i1 %cond = #x0 (0)
i1 %#0 = #x0 (0)
  >> Jump to %if.exit
float %ret = poison
float %#1 = #x00000003 (0.000000000000?)

Target:
float %arg.fr = #xff800000 (-oo)
i1 %cond = #x0 (0)
  >> Jump to %if.exit
float %ret = poison
Source value: #x00000003 (0.000000000000?)
Target value: poison
```


Fix patch:
commit 57a9f79336abebbdfffd52270bb615f7189758d2
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Thu Oct 2 01:11:51 2025 +0800

    [ValueTracking] Take PHI's poison-generating flags into account (#161530)
    
    ninf/nnan in the phi node may produce poison values. They should be
    considered in `isGuaranteedNotToBeUndefOrPoison`.
    Closes https://github.com/llvm/llvm-project/issues/161524.

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 6f11b250cf21..09a8fbea065a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7651,25 +7651,26 @@ static bool isGuaranteedNotToBeUndefOrPoison(
         return true;
     }
 
-    if (const auto *PN = dyn_cast<PHINode>(V)) {
-      unsigned Num = PN->getNumIncomingValues();
-      bool IsWellDefined = true;
-      for (unsigned i = 0; i < Num; ++i) {
-        if (PN == PN->getIncomingValue(i))
-          continue;
-        auto *TI = PN->getIncomingBlock(i)->getTerminator();
-        if (!isGuaranteedNotToBeUndefOrPoison(PN->getIncomingValue(i), AC, TI,
-                                              DT, Depth + 1, Kind)) {
-          IsWellDefined = false;
-          break;
+    if (!::canCreateUndefOrPoison(Opr, Kind,
+                                  /*ConsiderFlagsAndMetadata=*/true)) {
+      if (const auto *PN = dyn_cast<PHINode>(V)) {
+        unsigned Num = PN->getNumIncomingValues();
+        bool IsWellDefined = true;
+        for (unsigned i = 0; i < Num; ++i) {
+          if (PN == PN->getIncomingValue(i))
+            continue;
+          auto *TI = PN->getIncomingBlock(i)->getTerminator();
+          if (!isGuaranteedNotToBeUndefOrPoison(PN->getIncomingValue(i), AC, TI,
+                                                DT, Depth + 1, Kind)) {
+            IsWellDefined = false;
+            break;
+          }
         }
-      }
-      if (IsWellDefined)
+        if (IsWellDefined)
+          return true;
+      } else if (all_of(Opr->operands(), OpCheck))
         return true;
-    } else if (!::canCreateUndefOrPoison(Opr, Kind,
-                                         /*ConsiderFlagsAndMetadata*/ true) &&
-               all_of(Opr->operands(), OpCheck))
-      return true;
+    }
   }
 
   if (auto *I = dyn_cast<LoadInst>(V))


Regression tests:
file: llvm/test/Transforms/InstCombine/freeze-phi.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: pr161524
test_body: define float @pr161524(float noundef %arg) {
entry:
  %cond = tail call i1 @llvm.is.fpclass.f32(float %arg, i32 144)
  br i1 %cond, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  %fadd = fadd float %arg, 1.000000e+00
  br label %if.exit

if.exit:                                          ; preds = %if.then, %entry
  %ret = phi ninf float [ %fadd, %if.then ], [ %arg, %entry ]
  %ret.fr = freeze float %ret
  ret float %ret.fr
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i1 @llvm.is.fpclass.f32(float, i32 immarg) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }