https://github.com/spavloff updated https://github.com/llvm/llvm-project/pull/85605
>From 5049e0209e240f0f8a3ccb6e248d55d1480b7bad Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Mon, 18 Mar 2024 13:20:15 +0700 Subject: [PATCH] [clang] Set correct FPOptions if attribute 'optnone' presents Attribute `optnone` must turn off all optimizations including fast-math ones. Actually AST nodes in the 'optnone' function still had fast-math flags. This change implements fixing FP options before function body is parsed. --- clang/include/clang/Basic/LangOptions.h | 11 +++++++++++ clang/include/clang/Sema/Sema.h | 1 + clang/lib/Parse/ParseStmt.cpp | 4 ++++ clang/lib/Sema/SemaDecl.cpp | 10 ++++++++++ clang/test/AST/ast-dump-fpfeatures.cpp | 11 +++++++++++ 5 files changed, 37 insertions(+) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 08fc706e3cbf74..19c60a8cb5e946 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -842,6 +842,8 @@ class FPOptions { /// Return difference with the given option set. FPOptionsOverride getChangesFrom(const FPOptions &Base) const; + void applyChanges(FPOptionsOverride FPO); + // We can define most of the accessors automatically: #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ TYPE get##NAME() const { \ @@ -923,6 +925,11 @@ class FPOptionsOverride { setAllowFPContractAcrossStatement(); } + void setDisallowOptimizations() { + setFPPreciseEnabled(true); + setDisallowFPContract(); + } + storage_type getAsOpaqueInt() const { return (static_cast<storage_type>(Options.getAsOpaqueInt()) << FPOptions::StorageBitSize) | @@ -979,6 +986,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const return getChangesSlow(Base); } +inline void FPOptions::applyChanges(FPOptionsOverride FPO) { + *this = FPO.applyOverrides(*this); +} + /// Describes the kind of translation unit being processed. enum TranslationUnitKind { /// The translation unit is a complete translation unit. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 95ea5ebc7f1ac1..ccc2ded67589ec 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3222,6 +3222,7 @@ class Sema final { Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D, SkipBodyInfo *SkipBody = nullptr, FnBodyKind BodyKind = FnBodyKind::Other); + void applyFunctionAttributesBeforeParsingBody(Decl *FD); /// Determine whether we can delay parsing the body of a function or /// function template until it is used, assuming we don't care about emitting diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 76a3fa8f2627de..489ae9f167b95d 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -2508,6 +2508,10 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { Sema::PragmaStackSentinelRAII PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod); + // Some function attributes (like OptimizeNoneAttr) affect FP options. + Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); + Actions.applyFunctionAttributesBeforeParsingBody(Decl); + // Do not enter a scope for the brace, as the arguments are in the same scope // (the function body) as the body itself. Instead, just read the statement // list and put it into a CompoundStmt for safe keeping. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5850cd0ab6b9aa..1f52f5e57e5376 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15919,6 +15919,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, return D; } +void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) { + if (FD && FD->hasAttr<OptimizeNoneAttr>()) { + FPOptionsOverride FPO; + FPO.setDisallowOptimizations(); + CurFPFeatures.applyChanges(FPO); + FpPragmaStack.CurrentValue = + CurFPFeatures.getChangesFrom(FPOptions(LangOpts)); + } +} + /// Given the set of return statements within a function body, /// compute the variables that are subject to the named return value /// optimization. diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp b/clang/test/AST/ast-dump-fpfeatures.cpp index da0011602a728e..5eda5528c07018 100644 --- a/clang/test/AST/ast-dump-fpfeatures.cpp +++ b/clang/test/AST/ast-dump-fpfeatures.cpp @@ -187,3 +187,14 @@ float func_18(float x, float y) { // CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward // CHECK: ReturnStmt // CHECK: BinaryOperator {{.*}} ConstRoundingMode=downward + +#pragma float_control(precise, off) +__attribute__((optnone)) +float func_19(float x, float y) { + return x + y; +} + +// CHECK-LABEL: FunctionDecl {{.*}} func_19 'float (float, float)' +// CHECK: CompoundStmt {{.*}} MathErrno=1 +// CHECK: ReturnStmt +// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits