This is a proposal to add 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

Note: Preliminary patch, not ready for code review, doesn't yet run end-to-end with the llvm patch, and the logic for the new option is not yet written.

### 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! |

`–ffp-model=precise`: FP expressions are already strictly ordered.

### 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`