Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Clang mishandles fast-math flags when pragmas are used #51530

Open Quuxplusone opened 3 years ago

Quuxplusone commented 3 years ago
Bugzilla Link PR52563
Status NEW
Importance P normal
Reported by Andy Kaylor (andrew.kaylor@intel.com)
Reported on 2021-11-19 12:57:53 -0800
Last modified on 2021-11-19 15:40:44 -0800
Version unspecified
Hardware All All
CC htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, llvm-dev@redking.me.uk, neeilans@live.com, richard-llvm@metafoo.co.uk, zahira.ammarguellat@intel.com
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also

When pragmas are used that modify the fast-math flags, clang doesn't correctly apply the changes to all instructions. I've seen this with phi and fneg instructions. There may be others.

Here are some examples (compiled with -funsafe-math-optimizations, which applies 'reassoc nsz arcp' outside pragma scopes):

#pragma clang fp reassociate(off)
double foo(bool flag, double x, double y) {
  return flag ? x : y;
}

clang generates a phi instruction with the 'reassoc' flag set.

#pragma clang fp reassociate(off)
double bar(double x) {
  return foo(x < 0, -x, x);
}

Here clang correctly omits the 'reassoc' flag from the fcmp but incorrectly sets it for the fneg.

#pragma clang fp reassociate(off)
void fubar(double x, double *pneg, double *psub) {
  *pneg = -x;
  *psub = 0.0-x;
}

Here clang correctly omits the 'reassoc' flag from the fsub but incorrectly sets it for the fneg.

The same problem occurs with "pragma float_control"

Quuxplusone commented 3 years ago

Call instructions are also not handled correctly:

#include <math.h>

#pragma float_control(precise, on)
float f(float x) {
  return logf(x + 3.2f);
}

compiled with 'clang -O2 -ffast-math'

define dso_local float @f(float %0) local_unnamed_addr #0 {
  %2 = fadd float %0, 0x40099999A0000000
  %3 = tail call fast float @llvm.log.f32(float %2)
  ret float %3
}

Notice the fadd instruction has no fast-math flags, but the call instruction does.