<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">