<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/114520>114520</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            SelectionDAGBuilder (wrongly in at least x86 half case) assumes that it's safe to replace cmp + select by maxnum if maxnum is promoted
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          uuuvn
      </td>
    </tr>
</table>

<pre>
    https://godbolt.org/z/z33cz5h8a

I think the cause is this line where it seems like llvm assumes that operation would become legal after promotion but in half to float maxnum on x86 it isn't the case and we end up with an introduced call to fmaxf in a freestanding environment.
https://github.com/llvm/llvm-project/blob/61a6439f35b6de28ff4aff4450d6fca970292fd5/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp#L3781


This patch fixes it but i'm not sure weather it's the right way to go about it as it will disable instruction combine even when it's perfectly legal after promotion:

```diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f41dbe81434c..58a11b2e9001 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3778,7 +3778,7 @@ void SelectionDAGBuilder::visitSelect(const User &I) {
     }
 
 if (!IsUnaryAbs && Opc != ISD::DELETED_NODE &&
- (TLI.isOperationLegalOrCustomOrPromote(Opc, VT) ||
+ (TLI.isOperationLegalOrCustom(Opc, VT) ||
          (UseScalarMinMax &&
           TLI.isOperationLegalOrCustom(Opc, VT.getScalarType()))) &&
         // If the underlying comparison instruction is used by any other
```


<details>
<summary>Bug</summary>

```C
void r_2_10001(__fp16* restrict data0, __fp16* restrict data1) {
  __fp16 acc0 = (__fp16)(-__builtin_inff());
  for (int ridx0 = 0; ridx0 < 2; ridx0++) {
    __fp16 val0 = *(data1+ridx0);
    acc0 = ((acc0<val0)?val0:acc0);
  }
  *(data0+0) = acc0;
}
```

`clang -march=x86-64-v4 --target=x86_64-none-unknown-elf -fno-math-errno -O2 -Wall -Werror -x c -fPIC -ffreestanding -nostdlib test.c -o test.ll -S -emit-llvm`

```llvm
; ModuleID = 'test.c'
source_filename = "test.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-none-unknown-elf"

; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
define void @r_2_10001(ptr noalias nocapture noundef writeonly %data0, ptr noalias nocapture noundef readonly %data1) local_unnamed_addr #0 {
entry:
  %0 = load half, ptr %data1, align 2, !tbaa !4
  %cmp2 = fcmp ogt half %0, 0xHFC00
  %cond.v = select i1 %cmp2, half %0, half 0xHFC00
  %add.ptr.1 = getelementptr inbounds i8, ptr %data1, i64 2
 %1 = load half, ptr %add.ptr.1, align 2, !tbaa !4
  %cmp2.1 = fcmp olt half %cond.v, %1
  %cond.v.1 = select i1 %cmp2.1, half %1, half %cond.v
  store half %cond.v.1, ptr %data0, align 2, !tbaa !4
  ret void
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) "frame-pointer"="all" "min-legal-vector-width"="0" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64-v4" "target-features"="+avx,+avx2,+avx512bw,+avx512cd,+avx512dq,+avx512f,+avx512vl,+bmi,+bmi2,+cmov,+crc32,+cx16,+cx8,+evex512,+f16c,+fma,+fxsr,+lzcnt,+mmx,+movbe,+popcnt,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" }

!llvm.module.flags = !{!0, !1, !2}
!llvm.ident = !{!3}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 2}
!3 = !{!"clang version 20.0.0git (https://github.com/llvm/llvm-project.git 61a6439f35b6de28ff4aff4450d6fca970292fd5)"}
!4 = !{!5, !5, i64 0}
!5 = !{!"__fp16", !6, i64 0}
!6 = !{!"omnipotent char", !7, i64 0}
!7 = !{!"Simple C/C++ TBAA"}
```

`llc -debug test.ll -o test.s -O2 2>llc_debug.txt`

```asm
        .text
        .file   "test.c"
        .section        .rodata.cst4,"aM",@progbits,4
        .p2align        2, 0x0                          # -- Begin function r_2_10001
.LCPI0_0:
        .long   0xff800000                      # float -Inf
        .text
        .globl  r_2_10001
        .p2align        4
        .type   r_2_10001,@function
r_2_10001: # @r_2_10001
# %bb.0: # %entry
        pushq   %rbp
        movq    %rsp, %rbp
        pushq   %r14
        pushq   %rbx
        movq    %rsi, %rbx
        movq    %rdi, %r14
        movzwl  (%rsi), %eax
        vmovd   %eax, %xmm0
        vcvtph2ps       %xmm0, %xmm0
        vmovss  .LCPI0_0(%rip), %xmm1           # xmm1 = [-Inf,0.0E+0,0.0E+0,0.0E+0]
        callq   fmaxf@PLT
        vcvtps2ph       $4, %xmm0, %xmm0
        vmovd   %xmm0, %eax
        vcvtph2ps       %xmm0, %xmm0
        movzwl  2(%rbx), %ecx
        vmovd   %ecx, %xmm1
        vcvtph2ps       %xmm1, %xmm1
        vucomiss        %xmm0, %xmm1
        cmoval  %ecx, %eax
        movw    %ax, (%r14)
        popq    %rbx
        popq    %r14
        popq    %rbp
        retq
.Lfunc_end0:
        .size   r_2_10001, .Lfunc_end0-r_2_10001
                                        # -- End function
        .ident  "clang version 20.0.0git (https://github.com/llvm/llvm-project.git 61a6439f35b6de28ff4aff4450d6fca970292fd5)"
        .section        ".note.GNU-stack","",@progbits
```

[llc_debug.txt](https://github.com/user-attachments/files/17597256/llc_debug.txt)

</details>

<details>
<summary>No bug</summary>

```C
void r_2_10001(__fp16* restrict data0, __fp16* restrict data1) {
  __fp16 acc0 = (__fp16)(-__builtin_inff());
  for (int ridx0 = 0; ridx0 < 2; ridx0++) {
    __fp16 val0 = *(data1+ridx0);
    acc0 = ((acc0<val0)?val0:acc0);
  }
  *(data0+0) = acc0;
}
```

`clang -march=x86-64-v4 --target=x86_64-none-unknown-elf -fno-math-errno -O2 -Wall -Werror -x c -fPIC -ffreestanding -nostdlib test.c -o test.ll -S -emit-llvm`

```llvm
; ModuleID = 'test.c'
source_filename = "test.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-none-unknown-elf"

; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
define void @r_2_10001(ptr noalias nocapture noundef writeonly %data0, ptr noalias nocapture noundef readonly %data1) local_unnamed_addr #0 {
entry:
  %0 = load half, ptr %data1, align 2, !tbaa !4
  %cmp2 = fcmp ogt half %0, 0xHFC00
  %cond.v = select i1 %cmp2, half %0, half 0xHFC00
  %add.ptr.1 = getelementptr inbounds i8, ptr %data1, i64 2
 %1 = load half, ptr %add.ptr.1, align 2, !tbaa !4
  %cmp2.1 = fcmp olt half %cond.v, %1
  %cond.v.1 = select i1 %cmp2.1, half %1, half %cond.v
  store half %cond.v.1, ptr %data0, align 2, !tbaa !4
  ret void
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) "frame-pointer"="all" "min-legal-vector-width"="0" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64-v4" "target-features"="+avx,+avx2,+avx512bw,+avx512cd,+avx512dq,+avx512f,+avx512vl,+bmi,+bmi2,+cmov,+crc32,+cx16,+cx8,+evex512,+f16c,+fma,+fxsr,+lzcnt,+mmx,+movbe,+popcnt,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" }

!llvm.module.flags = !{!0, !1, !2}
!llvm.ident = !{!3}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 2}
!3 = !{!"clang version 20.0.0git (https://github.com/llvm/llvm-project.git 61a6439f35b6de28ff4aff4450d6fca970292fd5)"}
!4 = !{!5, !5, i64 0}
!5 = !{!"__fp16", !6, i64 0}
!6 = !{!"omnipotent char", !7, i64 0}
!7 = !{!"Simple C/C++ TBAA"}
```

`llc -debug test.ll -o test.s -O2 2>llc_debug.txt`

```asm
        .text
        .file   "test.c"
        .section        .rodata.cst4,"aM",@progbits,4
        .p2align        2, 0x0                          # -- Begin function r_2_10001
.LCPI0_0:
        .long   0xff800000                      # float -Inf
        .text
        .globl  r_2_10001
        .p2align        4
        .type   r_2_10001,@function
r_2_10001: # @r_2_10001
# %bb.0: # %entry
        pushq   %rbp
        movq    %rsp, %rbp
        movzwl  (%rsi), %eax
        vmovd   %eax, %xmm0
        vcvtph2ps       %xmm0, %xmm0
        vucomiss        .LCPI0_0(%rip), %xmm0
        movl    $64512, %ecx # imm = 0xFC00
        cmoval  %eax, %ecx
        vmovd   %ecx, %xmm0
        vcvtph2ps       %xmm0, %xmm0
        movzwl  2(%rsi), %eax
        vmovd   %eax, %xmm1
        vcvtph2ps       %xmm1, %xmm1
        vucomiss        %xmm0, %xmm1
        cmoval  %eax, %ecx
        movw    %cx, (%rdi)
        popq    %rbp
        retq
.Lfunc_end0:
        .size   r_2_10001, .Lfunc_end0-r_2_10001
                                        # -- End function
        .ident  "clang version 20.0.0git (https://github.com/llvm/llvm-project.git 61a6439f35b6de28ff4aff4450d6fca970292fd5)"
        .section        ".note.GNU-stack","",@progbits
```

[llc_debug.txt](https://github.com/user-attachments/files/17597378/llc_debug.txt)

</details>
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsOl2P27qOv0bzQjiwZSdxHuYhycycHaA9LdB272Mgy3KirSz5SHI--usXkhzbyWR6W5zde4GLDDI2JZEURZEURZgYw7eSsUc0XaHp0wNp7U7px7Zt9_KhUOXpcWdtY1C6RPgF4ZetKgsl7ETpLcIvP9x_mtIf011OUPyE4mV4voLdcfkd7I4BJa1hwI3rMiC4ZHDYMc2AWzCM1a7vOwMh9jUQY9qaOVRiQTVME8uVhINqRQkFo6pmINiWCCCVZRoarWrlUYrWApewI6ICq6ASilioyVG2NSgJx3zm5uNGIjy3nVyGAZElHBgwWULbwIHbHRAJXFqtypayEigRwjOsybFyMxCoNGPGEllyuQUm91wrWTNpJ2HtVwrjdtcWE6pqhF_cGrtX1Gj1P4xahF8KoQqEX2YJmWXpokqnxaxkOK-qjFRVlk3jclZRspjHeIGrcjriwx3dWpXsDyYRfvnCBKNOG0_LP66aq5aLkukJbRqE0w_pPE_G-xWeX90GNcTSHVT8yIzTmNcrwvMapLJgWs3gwIjdMQ3cIjw3Xpeab3cWDuTkVLVVQArl6CwQz-TAhYCSG1IIBlwaq1svGFBVF84g2J5JZxXyzLRhumLUitPt7XbqHYs_i8Ov5FUVuhwEUbR1MvxdjUHxt3XuZeKyZEeosqQsWJ5kaUYnk2lOkqTAbBHHCSRxPMuygBxF0d-XvFMPXoXf_9VCUBajLIYonc9zhNdzQHg1wGFwr3gJN7i4rUuXe264DaMI51RJY-GbYRoQnr0ivAA0X4W5wP2h-VPX6l68AoRzhJNX800SfVoWxpEiPINPDQWEE5Q-weuXpzDd0_OH56_PT5s_Pz09d3idlh2brx9eJ9x8OoebD87iPul1a6yqP-nP3ugYwvmnhiK8hv_-GgRcu99Zwf-Mz8_Iof9DOP9m2BdKBNEfufxIjhfSDojwq3NNtswGfl9PDfM6W_S_28xD4ILXyrt2K0umxcnFOqrqhmhulLxwYm6gNayE4gREnkC54HDll29jDUrXJbOEC4PS577LtHVN9Amlz6t2i9I1wi9D102P71TorU1v8CaJ4zhBON9sqiaZIbwEzYzVnFooiSWx08o7Y8mV3QU0IJTG4KxpxHWBcB5tNkXLheVyw2VVDapNew6Vcgadc2lB8_IY2MQoXfXNNeC-eXbTK-PvxNgTcRZjiXDeCbzqKMezwoXICOeuidK14-AxXzyULn3_BengZ6NpnGCxFyt9gsCrI-jRb2_0LKaCyC1ENdF0h9KnYz6LZlm0zyCKLNFbZkPnZpZFUkkWtfK7VAcZMVFBVEkV1cTuIqa1VBB9whD9wx3H0T-Y1kpDdAQKUfX5dQ1RdXEqR1IZWwpegGXGTihEKkCO-gtErOY28oHwjcjh58c6q1zBR1W2gr0-dTqdB6YIzwOKUa2mbFNxwSSpWYeFz1g4YIUFe0sT5OTOxw6PRTVKlyxq8NztSor9wzWTy6aDZpl_RLwHEpyjdJngPKryuIOk75qdyWdZ9MWhXYliNW9EL-47-9ATDep4aWXw_KW12qU6ULfGNlptNTMGpHJ7AVJpRlttHGROkoJUrTxwl3BxITSzrZZQs1rpk7NRva2Z0wNoRsqD5i7iLrqznFUuSfA-jrJ47OaN1SAVEZy4eSlprMtQ3Ewlq8CzUVKcAOFp7_4_p3HTj0l8VBCKErFppdveckPK0vl1Gg-OyqR1MWo5eM80eKBQpPRZ6Xnmge0aiOBbCdiBCCe2IMS9sxETWjfY86lo3YDa2pDhOvaOKj7-18s6jscESpaTvScx_ngFnpwZOYoLct94y4OU5aSxepJ4NltmmWAuwXXic1k4RRng-a0V8VkG-HxU42nyrg76OX5dD508QRNi0ERYciCeJm900ZG90UaY-szkotFx7DgZqzS7GgvEo9XHv7AOzaw34uvg6Z_EWs2L1jLTmZbzyvnq_821nMtXmtQsahSXlmnn6OkTwpgIgTB24zWXkc-_oz2jVunowEu76xHjDk2qqDsJzdBjNWkaLrc-hPckVreswzGW0O_uGmQD76KtKqYjw3-wHj3vcEPAimjT9kP9WXKJUjHi3Nn0eAivyP6I8DoAuIemCS4O4xYtx63yr3GrGjf2IrSKmvdAx5fWat9BmqbnzqPLGQKUB4DtmeMUGlUyox1Ukw44Gh0g8YNKG8C67tZRq33BAtioph83ZNfJaQzrAdxDaQ9l3n7PcI_RoxzzeQcYsg8bdmmtCCfuiJzU_mScVIJsTXeQJC4o4iTuvCDp3njg0NHykkl7SZS-nSYeYfAUw5kfwvhAd0Rvzgbjok-KIRvPk1wR5wOxyxo-sD0TI9oLGfEV7XygfeM3t-jTy6UhjEM2tGfauMMTx5N4ErsLKsL57xUNJo7q1-sFCyfiSLLsUrJpt7DpOYDHY-Tpm2Wck-BznJvdpJu9oVO15I2ybtPdxg0M5jcZzN8w-MJrl6-4W8G6u9B-XS2XF6t7JxEVgkJUsqLdDnlglxIan1lilD4LQTceZ2KP9r3MkJhzYhgvJpYd7dByCSCKF29TPzdowkXYgVq5E2NCjc28l2HyMSgDZbEL9QW3BuF1NhA32B8tKF7gcOzH8O4fwilEEazYlkuozqnakDR5ppMP68-v8SYeFVIWE6HkFsWL-FhVeez-3p8g1NeiV1m9p4ytUIVA8eJq4svVjJZo3fV0jO7VcZY_4A2D6dKLcZENdoaTuiO5KCZxj4SnIT07z9W0ZveX36ipLpq-u1b7c69punRiPD4mS7Lb3I43ufGe283xsh8fsa3V_sdBeIz8zGTR4TEy8NnXal8GRq47IBzrOh4w6N42O9yYgOXHbqHVam8cTm8bYWLeDBMf6zq5sgTf5T11uvL2gNfxJH4Od8ab4LQP8QtKhHBa8NVVlMWfP3y9FNvgZufFzrKxzO-IX75Z4YWmfk0PveJxp4DiONI8va15OtJ88pMZk5toLVU1NzflGrBcakHE9XzjBdZqfwjjZ0PIO6M636ScuarmhrWOesemPcId_EAz-9c5ijj_3DBZXgYSfyRf-jKMcKMrn30_lt2MbM-yhMu44Ob02USIvv_Wc_ZGwEcYT6SybPLHn98in_Z24d49r-P-T46x6eryhJo-_XxFrWE6ItYSunPXN4Pwizui3DuZTxdzPJ35BY95DpbSleQQfnlTqPulCt6fCop7Ee9exLsX8e5FvHsR717Euxfx7kW8exHvXsS7F_HuRbx7Ee9exPv3FPH-9WW1objz88LaRQUqSJjNsnC-dKUnrwle1-EKehwyvuvyUC_xr9SrfntJbypkv6vEf0WF7KYKhgoZHVfISv5ehexe9fqPq3ql8_w3q14P5WNaLtIFeWCPyTyNsyyfp9nD7jGnxYzN0mSO4xRX0_kcT3NasCLHZFqWi-qBP-IYZ0kSJ3Ge4CSb0CJZFGRGy6zK02Q2RVnMasLFxCdTSm8fuDEte0ySbIrjB0EKJsz542z96LepaLcGZbHgxpqBznIr2OONDy6dARy0kltx8t8vWxCMGOs_ifb3IUqMv0tcfHzdfYdrSMXAKtCsEYQycNc2d2R3F7HidP7Gmlc9ZLrvdFn50Gpx_QH5P_8e2mvAb1dQwv4R_28AAAD__yTyDow">