[llvm-dev] Floating point semantic modes

Blower, Melanie I via llvm-dev
Thu, 30 Jan 2020 22:31:27 -0000

BTW There's no clang option for allow_approximate_fns; there is this option:

def fcuda_approx_transcendentals : Flag<["-"],
"fcuda-approx-transcendentals">,
  Flags<[CC1Option]>, HelpText<"Use approximate transcendental
functions">;
def fno_cuda_approx_transcendentals : Flag<["-"],
"fno-cuda-approx-transcendentals">;

Should this option be added generally for clang?

> -----Original Message-----
> From: Kaylor, Andrew <andrew.kaylor at intel.com>
> Sent: Wednesday, January 29, 2020 6:55 PM
> To: Szabolcs Nagy <nsz at port70.net>; cfe-dev at lists.llvm.org;
LLVM Developers
> Mailing List <llvm-dev at lists.llvm.org>
> Cc: Ristow, Warren <warren.ristow at sony.com>; Ulrich Weigand
> (Ulrich.Weigand at de.ibm.com) <Ulrich.Weigand at de.ibm.com>;
Cameron
> McInally <cameron.mcinally at nyu.edu>; Kevin Neal <Kevin.Neal at
sas.com>;
> Blower, Melanie I <melanie.blower at intel.com>; sepavloff at
gmail.com;
> hfinkel at anl.gov; Sanjay Patel <spatel at rotateright.com>; Wang,
Pengfei
> <pengfei.wang at intel.com>
> Subject: RE: [llvm-dev] Floating point semantic modes
>
> > ... math errno ...
>
> I wouldn't recommend to anyone that they should rely on math errno
(because I
> don't trust libraries to correctly support it). My goal here was to
incorporate our
> existing support for it into the rest of what I'm trying to document.
>
> My understanding is that for clang this primarily controls whether or not
we feel
> free to substitute intrinsics for recognized math library calls. I
don't know if we
> have any code in the optimizer that introduces access to or modification of
> errno in the user's program. The library calls that test should always
act as
> barriers to one another.
>
>
> > ideally there would be a way to support snan too. (e.g. isnan(x)
> > cannot be turned into x!=x then)
>
> The except_behavior mode is supposed to handle this. The LLVM support for
> constrained intrinsics is considering all manner of FP exceptions that
could be
> raised, including the distinction between QNaN and SNaN. The default LLVM
IR
> definition does not support this distinction.
>
> We seem to have an issue with isnan() in clang though. If you call isnan()
you get
> a call to __isnan() which should be fine (assuming the library does the
right
> thing), but we're translating __builtin_isnan() to x!=x. That's not
what we should
> be doing if except_behavior isn't "ignore".
>
>
> > excess precision handling is missing from this list which matters for
x87 and
> m68k fpu support and may matter for _Float16 implementations that fall back
> to _Float32 arithmetic.
>
> Yeah, we don't currently have any support for controlling that, at
least in the
> x87 case. I think our current strategy is nothing more than setting
> FLT_EVAL_METHOD to reflect that we might not be using source precision for
> intermediate results. This is something we should consider adding.
>
>
> > the granularity of these knobs is also interesting (expression, code
block,
> function or translation unit), iso c pragmas work on code block level.
>
> I'd have to defer to someone more familiar with the front end to say
how that is
> handled.
>
>
> > -ftrapping-math vs -ffp-exception-behaviour=maytrap is unclear.
>
> The "maytrap" setting is supposed to prevent the optimizer from
introducing
> spurious exceptions (e.g. speculative execution) while still allowing it to
optimize
> away potential exceptions (e.g. dce operations whose results are never
used).
>
>
> > FLT_ROUNDS, FLT_EVAL_METHOD and math_errhandling are controlled by
> the
> > c runtime, so a compiler has no business changing them, the compiler
> > can define its own __FLT_ROUNDS, etc macros and the libc may or may
> > not use those, but e.g. in case of FLT_ROUNDS it makes no sense for
> > the compiler to try to do anything: the mode changes at runtime, the
> > libc macro will expand to a function call that determines the current
> > rounding mode. (same problem arises if you can change the other modes
> > on a per function or code block granularity.)
>
> I don't think I understand what you're saying here. FLT_ROUNDS, in
particular, I
> thought was supposed to be implemented without reference to the runtime
> library. In clang we're mapping this to an intrinsic that gets a
target-specific
> inline expansion. For example: https://godbolt.org/z/uQD-AF
>
> And FLT_EVAL_METHOD I take to be an indicator of how the compiler is
> handling intermediate results.
>
>
>
> -----Original Message-----
> From: Szabolcs Nagy <nsz at port70.net>
> Sent: Tuesday, January 28, 2020 5:09 AM
> To: Kaylor, Andrew <andrew.kaylor at intel.com>
> Cc: cfe-dev at lists.llvm.org; LLVM Developers Mailing List <llvm-
> dev at lists.llvm.org>; Ristow, Warren <warren.ristow at
sony.com>; Ulrich
> Weigand (Ulrich.Weigand at de.ibm.com) <Ulrich.Weigand at
de.ibm.com>;
> Cameron McInally <cameron.mcinally at nyu.edu>; Kevin Neal
> <Kevin.Neal at sas.com>; Blower, Melanie I <melanie.blower at
intel.com>;
> sepavloff at gmail.com; hfinkel at anl.gov; Sanjay Patel
> <spatel at rotateright.com>; Wang, Pengfei <pengfei.wang at
intel.com>
> Subject: Re: [llvm-dev] Floating point semantic modes
>
> * Kaylor, Andrew via llvm-dev <llvm-dev at lists.llvm.org>
[2020-01-27 23:24:10
> +0000]:
> > Hi all,
> >
> > I'm trying to put together a set of rules for how the various
floating point
> semantic modes should be handled in clang. A lot of this information will
be
> relevant to other front ends, but the details are necessarily bound to a
front end
> implementation so I'm framing the discussion here in terms of clang.
Other front
> ends can choose to follow clang or not. The existence of this set of
semantics is
> an LLVM property that applies to all front ends, but the front ends will
have to
> do something to initialize them.
> >
> > I will eventually do something to convert this into an RST document
and find a
> home for it in the clang documentation, but I'd like to start by
getting input on
> whether everyone agrees with my judgment on how these things should work
> and whether I've missed anything.
> >
> > Here's what I've got.
> >
>
> i'm not an llvm/clang dev, i hope this mail wont bounce.
>
> > =====================> > FP semantic modes
> > =====================> > except_behavior { ignore, strict,
may_trap } fenv_access { on, off }
> > rounding_mode { dynamic, tonearest, downward, upward, towardzero }
> > contract { on, off, fast } denormal_fp_math { IEEE, PreserveSign,
> > PositiveZero } denormal_fp32_math { IEEE, PreserveSign, PositiveZero }
> > support_math_errno { on, off }
>
> note that math errno handling can be
>
> 1) errno is set,
> 2) errno may be set and
> 3) errno is guaranteed to be untouched
>
> iso c math_errhandling can select between 1 and 2, (user can or cannot rely
on
> errno) but for optimizing math calls as side-effect-free pure functions, 3
is
> needed.
>
> -f(no-)math-errno selects between 1 and 3.
> with 3, moving math calls across errno checks or calls that set errno can
break
> semantics depending on how libm is implemented (e.g. glibc will set errno
> independently of how you compiled your code).
>
> > no_honor_nans { on, off }
>
> ideally there would be a way to support snan too.
> (e.g. isnan(x) cannot be turned into x!=x then)
>
> > no_honor_infinities { on, off }
> > no_signed_zeros { on, off }
> > allow_reciprocal { on, off }
> > allow_approximate_fns { on, off }
> > allow_reassociation { on, off }
>
> excess precision handling is missing from this list which matters for x87
and
> m68k fpu support and may matter for _Float16 implementations that fall back
> to _Float32 arithmetic.
>
> the granularity of these knobs is also interesting (expression, code block,
> function or translation unit), iso c pragmas work on code block level.
>
> > =====================> > FP models
> > =====================> > -----------------------
> > precise (default)
> > -----------------------
> > except_behavior { ignore }
> > fenv_access { off }
> > rounding_mode { tonearest }
> > contract { on }
> > denormal_fp_math { IEEE }
> > denormal_fp32_math { IEEE }
> > support_math_errno { on }
> > no_honor_nans { off }
> > no_honor_infinities { off }
> > no_signed_zeros { off }
> > allow_reciprocal { off }
> > allow_approximate_fns { off }
> > allow_reassociation { off }
> >
> > ------------------
> > strict
> > ------------------
> > except_behavior { strict }
> > fenv_access { on }
> > rounding_mode { dynamic }
> > contract { off }
> > denormal_fp_math { IEEE }
> > denormal_fp32_math { IEEE }
> > support_math_errno { on }
> > no_honor_nans { off }
> > no_honor_infinities { off }
> > no_signed_zeros { off }
> > allow_reciprocal { off }
> > allow_approximate_fns { off }
> > allow_reassociation { off }
> >
> > ------------------
> > fast
> > ------------------
> > except_behavior { ignore }
> > fenv_access { off }
> > rounding_mode { tonearest }
> > contract { fast }
> > denormal_fp_math { PreserveSign }
> > denormal_fp32_math { PreserveSign }
> > support_math_errno { off }
> > no_honor_nans { on }
> > no_honor_infinities { on }
> > no_signed_zeros { on }
> > allow_reciprocal { on }
> > allow_approximate_fns { on }
> > allow_reassociation { on }
> >
> > =====================> > Command-line options
> > =====================> > -ffp-model={precise|strict|fast}
> >   Sets all semantic modes as described above.
> >
> > -ffast-math
> >   Equivalent to -ffp-model=fast. (I'm not sure that's
currently true.)
> >
> > -f[no-]math-errno
> > -ffp-contract={on|off|fast}
> > -f[no-]honor-infinities
> > -f[no-]honor-nans
> > -f[no-]associative-math
> > -f[no-]reciprocal-math
> > -f[no-]signed-zeros
> > -f[no-]trapping-math
> > -f[no-]rounding-math
> > -fdenormal-fp-math={ieee, preservesign, positivezero}
> > -fdenormal-fp-math-fp32={ieee, preservesign, positivezero}
> > -ffp-exception-behavior={ignore,maytrap,strict}
> >   Each of these has a 1-to-1 correspondance to an FP semantic mode.
> >   (I think several of these should set "except_behavior" to
"ignore".)
>
> -ftrapping-math vs -ffp-exception-behaviour=maytrap is unclear.
>
> (-ftrapping-math is weird in gcc, it does not handle all fp exception
cases, not
> sure what clang plans to do with that)
>
> >
> > -f[no-]finite-math-only
> >   Controls no_honor_nans and no_honor_infinities.
> >
> > -f[no-]unsafe-math-optimizations
> >   Turns no_signed_zeros, allow_reciprocal, allow_approximate_fns, and
> allow_reassociation on or off.
> >   Also, sets except_behavior to "on" for
-funsafe-math-optimizations.
> >   (Currently, -fno-]unsafe-math-optimizations clears except_behavior,
> > but I regard this as a bug.)
> >
> > All command line options will override any previous values of all
settings they
> control with options taking effect in a left-to-right manner.
> >
> > =====================> > pragmas
> > =====================> > STDC FENV_ACCESS {ON|OFF}
> >   Patch in progress. I think ON should force the following:
> >
> >     except_behavior { strict }
> >     fenv_access { on }
> >     rounding_mode { dynamic }
> >     denormal_fp_math { IEEE }
> >     denormal_fp32_math { IEEE }
> >     no_signed_zeros { off }
> >     allow_reciprocal { off }
> >     allow_approximate_fns { off }
> >     allow_reassociation { off }
> >
> >   And OFF should set fenv_access to off, except_behavior to ignore,
and
> rounding_mode to tonearest. Other modes should be reset to their command
> line defined settings.
> >
> >   I don't think this pragma should have any effect on contract,
> support_math_errno, no_honor_nans, or no_honor_infinities.
> >
> > STDC FP_CONTRACT {ON|OFF|DEFAULT}
> >   This pragma controls the contract FP semantic mode. No other FP
semantic
> modes are effected.
> >
> > float_control ({precise|except}, {on|off}[, push]) float_control (pop)
> >   Patch in progress. These are tricky.
> >   I think they should have the following effects:
> >
> > float_control (precise, on[, push])
> >   contract { on }
> >   denormal_fp_math { IEEE }
> >   denormal_fp32_math { IEEE }
> >   no_signed_zeros { off }
> >   allow_reciprocal { off }
> >   allow_approximate_fns { off }
> >   allow_reassociation { off }
> >
> > float_control (precise, off[, push])
> >   contract { fast }
> >   denormal_fp_math { preservesign }
> >   denormal_fp32_math { preservesign }
> >   no_signed_zeros { on }
> >   allow_reciprocal { on }
> >   allow_approximate_fns { on }
> >   allow_reassociation { on }
> >
> > Note, this is less than what the -ffp-model=precise control does.
Should this
> override support_math_errno, no_honor_nans, or no_honor_infinities?
> >
> > float_control (except, on[, push])
> >   except_behavior { strict }
> >
> > float_control (except, off[, push])
> >   except_behavior { ignore }
> >
> > The MSVC documentation says you can only use the float_control pragma
to
> turn exception semantics on when precise semantics are enabled. For us,
this
> would mean:
> >   denormal_fp_math { IEEE }
> >   denormal_fp32_math { IEEE }
> >   no_signed_zeros { off }
> >   allow_reciprocal { off }
> >   allow_approximate_fns { off }
> >   allow_reassociation { off }
> >
> > The MSVC documentation also says you can't use the float_control
pragma to
> turn excpetion semantics off when precise semantics are enabled, and you
can't
> use the float_control pragma to turn precise off when fenv_access is on.
> >
> > I believe we should follow the MSVC restrictions.
> >
> > ========================> > Code-visible identifiers
> > ========================> > __FAST_MATH__
> >
> > This symbol will only be defined if and only if all of the following
are set
> (before pragmas are applied):
> >   except_behavior { ignore }
> >   fenv_access { off }
> >   rounding_mode { tonearest }
> >   contract { fast }
> >   denormal_fp_math { PreserveSign }
> >   denormal_fp32_math { PreserveSign }
> >   support_math_errno { off }
> >   no_honor_nans { on }
> >   no_honor_infinities { on }
> >   no_signed_zeros { on }
> >   allow_reciprocal { on }
> >   allow_approximate_fns { on }
> >   allow_reassociation { on }
> >
> > __FINITE_MATH_ONLY__
> >
> > This symbol will only be defined if and only if all of the following
are set
> (before pragmas are applied):
> >   no_honor_nans { on }
> >   no_honor_infinities { on }
> >
> > FLT_ROUNDS
> >
> > Should be set to -1 (indeterminable) if rounding_mode() is dynamic or
1
> (tonearest) if rounding_mode is tonearest. There are values for other
rounding
> modes, but clang offers no way to set those rounding modes.
> >
> > FLT_EVAL_METHOD
> >
> > Should be set to -1 if any of allow_reciprocal, allow_approximate_fns,
or
> allow_reassociation is set. Should any other flags also make this -1?
Otherwise,
> the setting is target-defined.
> >
> > math_errhandling
> >
> > The MATH_ERRNO bit will be set or cleared based on the setting of
> support_math_errno. Should MATH_ERREXCEPT be set or cleared based on
> except_behavior?
>
>
> FLT_ROUNDS, FLT_EVAL_METHOD and math_errhandling
>
> are controlled by the c runtime, so a compiler has no business changing
them,
> the compiler can define its own __FLT_ROUNDS, etc macros and the libc may
or
> may not use those, but e.g.
> in case of FLT_ROUNDS it makes no sense for the compiler to try to do
anything:
> the mode changes at runtime, the libc macro will expand to a function call
that
> determines the current rounding mode. (same problem arises if you can
change
> the other modes on a per function or code block granularity.)
>
> and i don't think it's a good idea to change FLT_EVAL_METHOD with
non-precise
> arithmetic modes, because it is used to decide if excess range and
precision is
> available, but arithmetic changes don't affect that. (e.g. float_t is
still same as
> float).
>
> >
> >
> > Thanks in advance for any opinions and suggestions.
> >
> > -Andy
>
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev