Default FPENV state

Hi,
We are interesting in expanding some vector operations directly in the
IR form as constants ⚙ D33406 PR28129 expand vector oparation to an IR constant.,
for example: _mm256_cmp_ps("any input", "any input", _CMP_TRUE_UQ)
should produce -1, -1, -1, ... vector, but for some values for example
"1.00 -nan" if FPU exceptions were enabled this operation triggers the
exception. Here is the question: Should we assume that FPENV was
initialized with FE_ALL_EXCEPT by default or we could rely for example
on "-fno-trapping-math" flag or we could completely ignore the FPU
exception issue(see https://bugs.llvm.org/show_bug.cgi?id=6050)?

                Thanks, Dinar.

Hi, Dinar,

You should assume that FPU exceptions are not enabled. LLVM does not (currently) support them. That having been said, in this particular case, the output is also different if a NaN is produced (i.e. it produces a NaN and not a -1), and so I'd think you can only do this transformations when the call has the nnan flag (e.g. because the code was compiled with -ffinite-math-only).

  -Hal

Let’s make sure we’re looking at the same example. The x86 instruction that I think we’re discussing is cmpps/cmppd with constant predicate TRUE_UQ (0xF), FALSE_OQ (0xB), etc.

The expected output for cases including NaN inputs is shown by the program in PR28110:
https://bugs.llvm.org/show_bug.cgi?id=28110

Based on the Intel documentation and the experimental data, the output value (ignoring exceptions) is never affected by the input value. It doesn’t matter if we have NaN input, we should still produce a constant with -1 elements, so I don’t think we need any relaxed-mode FP flags for this transform.

Here’s a simpler test program:

#include <immintrin.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

__m128 get_all_ones(__m128 a, __m128 b) {
return _mm_cmp_ps(a, b, 15);
}

int main() {
int elts[4];

__m128 nan = (__m128) _mm_set1_ps(nanf(“”));
memcpy(elts, &nan, 16);
printf(“4 nans as hex: %x %x %x %x\n”, elts[0], elts[1], elts[2], elts[3]);

// The params to cmpps with pred #15 should not matter - it always returns all ones.
// In this case one param is a nan.
__m128 ones = get_all_ones(nan, _mm_set1_ps(42.0));
memcpy(elts, &ones, 16);
printf(“expecting 4 all ones: %x %x %x %x\n”, elts[0], elts[1], elts[2], elts[3]);

// The params to cmpps with pred #15 should not matter - it always returns all ones.
// In this case both params are nan.
__m128 more_ones = get_all_ones(nan, nan);
memcpy(elts, &more_ones, 16);
printf(“expecting 4 all ones: %x %x %x %x\n”, elts[0], elts[1], elts[2], elts[3]);
return 0;
}

$ clang cmptrue.c -mavx -O1
$ ./a.out
4 nans as hex: 7fc00000 7fc00000 7fc00000 7fc00000
expecting 4 all ones: ffffffff ffffffff ffffffff ffffffff
expecting 4 all ones: ffffffff ffffffff ffffffff ffffffff

Sounds good. In that case, I agree. -Hal