[PATCH] D100118: [clang] Add support for new builtin __arithmetic_fence to control floating point optimization, and new clang option fprotect-parens
Aaron Ballman via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 4 06:55:54 PDT 2021
aaron.ballman added reviewers: rsmith, rjmccall.
aaron.ballman added inline comments.
================
Comment at: clang/docs/UsersManual.rst:1484
+ Where unsafe floating point optimizations are enabled, this option
+ determines whether the optimizer honors parentheses when floating-point
+ expressions are evaluated. If unsafe floating point optimizations are
----------------
We may need to expound on what "honor parentheses" means. The summary for the patch mentions `(a + b) + c`, but does this also mean `(x + y) * z` could be interpreted as `x + (y * z)`? What about for non-arithmetic expressions involving parentheses, like `(float1 == float2 && float1 == float3) || blah()`?
================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:8480-8481
+def err_typecheck_expect_flt_or_vector : Error<
+ "operand of type %0 where floating, complex or "
+ "a vector of such types is required (%0 invalid)">;
def err_cast_selector_expr : Error<
----------------
================
Comment at: clang/include/clang/Basic/TargetInfo.h:1427
+ /// Controls if __arithmetic_fence is supported in the targetted backend.
+ virtual bool checkArithmeticFenceSupported() const { return false; }
----------------
================
Comment at: clang/include/clang/Basic/TargetInfo.h:1162
/// the language based on the target options where applicable.
- virtual void adjust(LangOptions &Opts);
+ virtual void adjust(DiagnosticsEngine &Diags, LangOptions &Opts);
----------------
mibintc wrote:
> There's no good place to diagnose when LangOptions and TargetOptions conflict, I see "conflict" diagnostics being emitted in clang/CodeGen when creating the func or module, which seems wrong to me. On the other hand, the "adjust" function makes a good place to do the reconciliation I think. This is the change that could be pulled out in a refactoring and committed prior to this patch. What do you think?
I think this makes sense, but should be done as a separate patch.
================
Comment at: clang/include/clang/Driver/Options.td:1757
+ LangOpts<"ProtectParens">, DefaultFalse,
+ PosFlag<SetTrue, [CC1Option],
+ "Determines whether the optimizer honors parentheses when "
----------------
Should this option also be exposed to clang-cl (should it be a `CoreOption`)?
================
Comment at: clang/lib/CodeGen/CGBuiltin.cpp:2839
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+ auto FMF = Builder.getFastMathFlags();
+ bool isArithmeticFenceEnabled = FMF.allowReassoc();
----------------
Please spell out the type here.
================
Comment at: clang/lib/Driver/ToolChains/Clang.cpp:2712-2714
+ case options::OPT_fprotect_parens:
+ case options::OPT_fno_protect_parens:
+ break;
----------------
Is this code needed for some reason?
================
Comment at: clang/lib/Sema/SemaChecking.cpp:6422
+ Expr *Arg = TheCall->getArg(0);
+ if (Arg->isInstantiationDependent())
+ return false;
----------------
What if there is no argument given?
================
Comment at: clang/lib/Sema/SemaChecking.cpp:6425
+
+ const QualType ArgTy = TheCall->getArg(0)->getType();
+ bool IsFloating = [&]() {
----------------
================
Comment at: clang/lib/Sema/SemaChecking.cpp:6427-6430
+ if (const VectorType *VT = dyn_cast<VectorType>(ArgTy.getCanonicalType()))
+ return VT->getElementType().getTypePtr()->isFloatingType();
+ if (const ComplexType *CT = dyn_cast<ComplexType>(ArgTy.getCanonicalType()))
+ return CT->getElementType().getTypePtr()->isFloatingType();
----------------
================
Comment at: clang/lib/Sema/SemaChecking.cpp:6436-6437
+ << ArgTy;
+ if (checkArgCount(*this, TheCall, 1))
+ return true;
+ TheCall->setType(ArgTy);
----------------
This looks like it should move up a bit.
================
Comment at: clang/lib/Sema/SemaCoroutine.cpp:387
JustAddress = S.MaybeCreateExprWithCleanups(JustAddress);
- return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume,
- JustAddress);
+ return S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_resume,
+ JustAddress).get();
----------------
I am fine ignoring this clang-format issue; I think your formatting is far more readable.
================
Comment at: clang/lib/Sema/SemaExpr.cpp:4026
+ !E->isLValue() &&
+ (ExprTy->isFloatingType() || (ExprTy->isComplexType()))) {
+ return BuildBuiltinCallExpr(R, Builtin::BI__arithmetic_fence, E);
----------------
Do you have to worry about vector types here as well?
================
Comment at: clang/lib/Sema/SemaExpr.cpp:4027
+ (ExprTy->isFloatingType() || (ExprTy->isComplexType()))) {
+ return BuildBuiltinCallExpr(R, Builtin::BI__arithmetic_fence, E);
+ }
----------------
One worry I have about this is that the AST will be a bit mysterious for people writing AST matchers. The source code will have parens in it, but the AST will have a `ParenExpr` node or not only depending on the language options. This may also cause problems for other parts of the code that are checking for properly-parenthesized expressions (like && and || within the same expression), so we should probably have a test case like:
```
bool func(float f1, float f2, float f3) {
return (f1 == f2 && f1 == f3) || f2 == f3; // Should not warn here
}
```
================
Comment at: clang/lib/Sema/SemaExpr.cpp:6535
+// with the specified CallArgs
+ExprResult Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id,
+ MultiExprArg CallArgs) {
----------------
Because this cannot fail, is there a benefit to returning an `ExprResult` rather than an `Expr *` as before? Then you can remove a bunch of `get()` calls elsewhere that look suspicious because they're not checking for a failure.
================
Comment at: clang/test/Sema/arithmetic-fence-builtin.c:45
+#endif
+//PPC: error: option '-fprotect-parens' cannot be specified on this target
----------------
You should add a test that we diagnose things like:
```
__arithmetic_fence();
__arithmetic_fence(1, 2);
```
I think it would also be useful to add an AST test (to `clang\test\AST`) that shows the call expression AST nodes being inserted for paren expressions.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D100118/new/
https://reviews.llvm.org/D100118
More information about the cfe-commits
mailing list