Bug type: miscompilation
Component: ValueTracking
Bug location: llvm/lib/Analysis/ValueTracking.cpp: matchSelectPattern
Issue title: [InstCombine] fcmp is incorrectly inverted
Labels: miscompilation
floating-point
llvm:analysis
generated by fuzzer
Reported by: dtcxzyw

Reproducer: https://alive2.llvm.org/ce/z/yVw9wM
```
define float @src(float %x) {
  %cmp = fcmp olt float %x, 0.000000e+00
  %sel = select nnan nsz i1 %cmp, float %x, float -0.000000e+00
  ret float %sel
}

define float @tgt(float %x) {
  %.inv = fcmp oge float %x, 0.000000e+00
  %sel1 = select i1 %.inv, float -0.000000e+00, float %x
  ret float %sel1
}
```
```
----------------------------------------
define float @src(float %x) {
#0:
  %cmp = fcmp olt float %x, 0.000000
  %sel = select nnan nsz i1 %cmp, float %x, float -0.000000
  ret float %sel
}
=>
define float @tgt(float %x) {
#0:
  %.inv = fcmp oge float %x, 0.000000
  %sel1 = select i1 %.inv, float -0.000000, float %x
  ret float %sel1
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:
float %x = #x7f800002 (SNaN)

Source:
i1 %cmp = #x0 (0)
float %sel = #x80000000 (-0.0)

Target:
i1 %.inv = #x0 (0)
float %sel1 = #x7f800002 (SNaN)
Source value: #x80000000 (-0.0)
Target value: #x7f800002 (SNaN)
```



Fix patch:
commit 2f15637e04f51e3ef435c0c0d39aab0e8b933023
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Mon Jun 9 15:46:09 2025 +0800

    [ValueTracking] Update `Ordered` when both operands are non-NaN. (#143349)
    
    When the original predicate is ordered and both operands are non-NaN,
    `Ordered` should be set to true. This variable still matters even if
    both operands are non-NaN because FMF only applies to select, not fcmp.
    
    Closes https://github.com/llvm/llvm-project/issues/143123.

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index d6bb852e208f..d8c1096049dc 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8660,6 +8660,7 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
     if (LHSSafe && RHSSafe) {
       // Both operands are known non-NaN.
       NaNBehavior = SPNB_RETURNS_ANY;
+      Ordered = CmpInst::isOrdered(Pred);
     } else if (CmpInst::isOrdered(Pred)) {
       // An ordered comparison will return false when given a NaN, so it
       // returns the RHS.


Regression tests:
file: llvm/test/Transforms/InstCombine/fcmp-select.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: test_fcmp_ord_select_fcmp_oeq_var_const
test_body: define i1 @test_fcmp_ord_select_fcmp_oeq_var_const(double %x) {
  %cmp1 = fcmp ord double %x, 0.000000e+00
  %sel = select i1 %cmp1, double %x, double 0.000000e+00
  %cmp2 = fcmp oeq double %sel, 1.000000e+00
  ret i1 %cmp2
}

test_name: test_select_nnan_nsz_fcmp_olt
test_body: define float @test_select_nnan_nsz_fcmp_olt(float %x) {
  %cmp = fcmp olt float %x, 0.000000e+00
  %sel = select nnan nsz i1 %cmp, float %x, float -0.000000e+00
  ret float %sel
}

test_name: test_select_nnan_nsz_fcmp_ult
test_body: define float @test_select_nnan_nsz_fcmp_ult(float %x) {
  %cmp = fcmp ult float %x, 0.000000e+00
  %sel = select nnan nsz i1 %cmp, float %x, float -0.000000e+00
  ret float %sel
}

test_name: test_fcmp_select_var_const_unordered
test_body: define i1 @test_fcmp_select_var_const_unordered(double %x, double %y) {
  %cmp1 = fcmp ult double %x, 0x3E80000000000000
  %sel = select i1 %cmp1, double %y, double 0.000000e+00
  %cmp2 = fcmp ugt double %sel, 0x3E80000000000000
  ret i1 %cmp2
}