what does -ffp-contract=fast allow?

This is just paraphrasing from D26602, so credit to Nicolai for first raising the issue there.

float foo(float x, float y) {
return x * (y + 1);
}

$ ./clang -O2 xy1.c -S -o - -target aarch64 -ffp-contract=fast | grep fm
fmadd s0, s1, s0, s0

Is this a bug? We transformed the original expression into:
x * y + x

When x=INF and y=0, the code returns INF if we don’t reassociate. With reassociation to FMA, it returns NAN because 0 * INF = NAN.

  1. I used aarch64 as the example target, but this is not target-dependent (as long as the target has FMA).

  2. This is not -ffast-math…or is it? The C standard only shows on/off settings for the associated FP_CONTRACT pragma.

  3. AFAIK, clang has no documentation for -ffp-contract:
    http://clang.llvm.org/docs/UsersManual.html

  4. GCC says:
    https://gcc.gnu.org/onlinedocs/gcc-6.2.0/gcc/Optimize-Options.html#Optimize-Options
    “-ffp-contract=fast enables floating-point expression contraction such as forming of fused multiply-add operations if the target has native support for them.”

  5. The LLVM backend (where this reassociation currently happens) shows:
    FPOpFusion::Fast - Enable fusion of FP ops wherever it’s profitable.

Is this a bug? We transformed the original expression into:
x * y + x

I’d say yes, it’s a bug.

Unless ‑ffast‑math is used (or some appropriate subset that gives us leeway, like ‑fno‑honor‑infinities or ‑fno‑honor‑nans, or somesuch), the re-association isn’t allowed, and that blocks the madd contraction.

-Warren

Is this a bug? We transformed the original expression into:
x * y + x

I’d say yes, it’s a bug.

Unless ‑ffast‑math is used (or some appropriate subset that gives us leeway, like ‑fno‑honor‑infinities or ‑fno‑honor‑nans, or somesuch), the re-association isn’t allowed, and that blocks the madd contraction.

I agree too, but the more difficult question is "which flags are needed here?”
Would FPContract + no-inf be enough? If not why and how to document it?