This patch adds a new clang builtin, __arithmetic_fence. The purpose of the builtin is to provide the user fine control, at the expression level, over floating point optimization when -ffast-math (-ffp-model=fast) is enabled. We are also proposing a new clang builtin that provides access to this intrinsic, as well as a new clang command line option -fprotect-parens that will be implemented using this intrinsic.
This is the clang patch corresponding to https://reviews.llvm.org/D99675 which proposes a new llvm intrinsic llvm.arith.fence
Rationale
Some expression transformations that are mathematically correct, such as reassociation and distribution, may be incorrect when dealing with finite precision floating point. For example, these two expressions,
(a + b) + c a + (b + c)
are equivalent mathematically in integer arithmetic, but not in floating point. In some floating point (FP) models, the compiler is allowed to make these value-unsafe transformations for performance reasons, even when the programmer uses parentheses explicitly. But the compiler must always honor the parentheses implied by __arithmetic_fence, regardless of the FP model settings.
Under –ffp-model=fast, __arithmetic_fence provides a way to partially enforce ordering in an FP expression.
Original expression | Transformed expression | Permitted? |
---|---|---|
(a + b) + c | a + (b + c) | Yes! |
__arithmetic_fence(a + b) + c | a + (b + c) | No! |
Motivation:
- The new clang builtin provides clang compatibility with the Intel C++ compiler builtin __fence which has similar semantics, and likewise enables implementation of the option -fprotect-parens.
- The new builtin provides the clang programmer control over floating point optimizations at the expression level.
- The gnu fortran compiler, gfortran, likewise supports -fprotect-parens
Requirements for __arithmetic_fence:
- There is one operand. The operand type must be scalar floating point, complex floating point or vector thereof.
- The return type is the same as the operand type.
- The return value is equivalent to the operand.
- The invocation of __arithmetic_fence is not a C/C++ constant expression, even if the operands are constant.
New option -fprotect-parens
- Determines whether the optimizer honors parentheses when floating-point expressions are evaluated
- Option defaults to fno-protect-parens