I’m not sure I agree on the impossible part, I feel like a sufficiently smart interprocedural analysis that also implements range analysis interprocedurally could prove a lot to where it becomes useful.
I guess what I would like to see is SIMD libraries being able to confidently say nobody needs to use intrinsics (or differentiate between relaxed/normal SIMD on the user API level) because the language + high level SIMD APIs are smart enough to choose the right implementation.
IIRC IEEE min/max with proper NaN handling needs 8 instructions on x86 vs 1 on arm64 I find it very sad that we apparently haven’t really solved that yet without forcing the user to use different APIs.
You can do it with just 3 instructions for IEEE 754-2019 minimumNumber (ignores NaN):
vminpd ymm2, ymm1, ymm0
vcmpunordpd ymm0, ymm0, ymm0
vblendvpd ymm0, ymm2, ymm1, ymm0
If you want proper IEEE 754-2019 minimum (propagate NaN, -0.0 < +0.0, NaN bitpattern picked in the usual way) you can do it in 6: vminpd ymm1, ymm0, ymm1
vbroadcastsd ymm2, qword ptr [rip + .LCPI0_0]
vandpd ymm2, ymm0, ymm2
vorpd ymm1, ymm2, ymm1
vcmpunordpd ymm2, ymm0, ymm0
vblendvpd ymm0, ymm1, ymm0, ymm2
I personally find this a load of nonsense I don't care about.If you want propagating NaNs but don't care about signed zero or NaN payload/sign, you can use
vminpd ymm2, ymm0, ymm1
vminpd ymm1, ymm1, ymm0
vorpd ymm0, ymm1, ymm2
What I do in Polars is a bit different, there for propagating NaNs I do if (self < other) | self.is_nan() { self } else { other}
this isn't fully optimal on x86-64 but it's fairly simple and autovectorizes decently on various platforms, here's AVX2: vcmpltpd ymm2, ymm0, ymm1
vcmpunordpd ymm3, ymm0, ymm0
vorpd ymm2, ymm3, ymm2
vblendvpd ymm0, ymm1, ymm0, ymm2
Anything without range analysis is not worth it.
Note that:
NonZerof32 * NonZerof32 -> NonNanf32
NonZerof32::from_bits(1) multiplied with itself is zero.
Doing range analysis needs the language to support it at compile time, and the dev to specify what range it is.
The only 'stable' thing i can think of is a type for 'greater-eq-one' using only addition and multiplication. Practically every other operation breaks most of the type knowledge up to that point.