[clang] [llvm] [LangRef] Clarify specification for float min/max operations (PR #172012)
Phoebe Wang via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 8 05:00:17 PST 2026
phoebewang wrote:
> > It is not just implementation work. It bloats the code for `Oz` and soft-float platform, which might be unacceptable by such users;
>
> Only if the frontends actually emit the operation. If Clang and Rust are updated to add the `nsz` flag, nothing changes.
What's the difference between `unordered-sign-zero minnum` and `minnum + nsz` then? Do you mean we don't need support the `ordered-sign-zero minnum`, because it's never got used?
> We _already_ have an implementation for this! It's used to lower `fminimumnum` and `fmaximumnum`. My patch (#170069) even improves the codegen for it.
>
> At least on x86, the only thing we need is to hook `minnum`/`maxnum` up to `LowerFMINIMUM_FMAXIMUM`.
>
> As another point, x86 _does_ natively support the IEEE754-2008 semantics with AVX-512, via `VRANGEPS`. IIRC, we currently don't emit that instruction at all unless it's used as an intrinsic, but we could under these rules.
1. Improved ≠ zero cost;
2. X86 has `VRANGEPS` ≠ all X86 targets have ≠...≠ Users enable related feature to use it, [here](https://discourse.llvm.org/t/rfc-a-consistent-set-of-semantics-for-the-floating-point-minimum-and-maximum-operations/89006/78?u=phoebe) is a good summary for this;
> I would like to see LLVM do the exact opposite of this, and have fewer "holes" in its intrinsic support. @RalfJung is probably more familiar with this than I am, but IIRC, some Rust changes have been reverted because LLVM just doesn't support some intrinsics in some backends. It's not documented anywhere which intrinsics are supported on which backends.
So you should also object to this patch, because it nearly clones `minnum/maxnum` from `minimumnum/maximumnum` with the only sNaN difference.
> By your logic, maybe we just shouldn't support `minnum` and `maxnum` on x86 at all. After all, they mandate that you return the non-qNaN argument, and x86's `minps`/`maxps` don't do that. As a result, we need to fix up the output with an extra `cmpunordps`, which reduces performance and increases code size. Sure, you can add a `nnan` flag to avoid this penalty, but why not make it the default, and add `minnum_c` and `maxnum_c` for people who really want the libm `fmin`/`fmax` behavior?
I don't understand the logic. I introduced the background is unordered signed 0 complies C at the first paragraph. If you want to remove NaN suppot from C standard, then I'm glad to propose like that :)
> As @RalfJung mentioned, the entire point of having an IR is exposing a uniform and consistent set of semantics, that can be optimized (potentially using target-specific knowledge). By exposing a version of `minnum`/`maxnum` that supports signed-zero ordering, we make the IR more uniform. By supporting it on all targets, we make it consistent. By making it an IR-level intrinsic instead of requiring frontends to emit signed-zero fixup logic themselves, we can perform optimizations, including "known bits" optimizations and elision of the fixup step if one operand is a constant.
Did you forget `minimumnum` and `maximumnum` when saying uniform? I asked more than once, but nobody explained why the optimizaiton must use `minnum`/`maxnum`. Yes, `minimumnum`/`maximumnum` has cost to quiet sNaN. But then, why the sNaN just be ignored by the optimizaiton using `minnum`/`maxnum`?
https://github.com/llvm/llvm-project/pull/172012
More information about the cfe-commits
mailing list