mibintc created this revision.
mibintc added reviewers: sepavloff, rjmccall.
Herald added a project: clang.
mibintc requested review of this revision.
I rebased https://reviews.llvm.org/D69272 to work on the blocking comment from
@rsmith
@sepavloff Is it OK if I continue work on this item? Not sure about the
protocol when continuing someone else's patch.
@rsmith asked "I don't see changes to the constant evaluator". The semantic
rules for enabling this pragma require that strict or precise semantics be in
effect., see SemaAttr.cpp And the floating point constant evaluation doesn't
occur when strict or precise
One of the test cases in this patch shows 1+2 isn't folded in strict mode.
However, I don't see where is the decision about floating point constant
folding, can someone tell me where that occurs? . I thought the constant
folding was in AST/ExprConstant.cpp and indeed constant folding does occur
there. But sometimes, if the floating point semantics are set to 'strict', even
tho' folding has occurred successfully in ExprConstant.cpp, when i look at
emit-llvm, there is arithmetic emitted for the floating point expression; For
example if you use the command line option -ffp-exception-behavior=strict and
you compile this function, it will emit the add instruction; but without the
option you will see the folded expression 3.0. Either way (i.e. regardless of
option) if you put a breakpoint inside ExprConstant.cpp the calculation of the
floating sum does occur. The function is float myAdd(void) { return 1.0 + 2.0;
}
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D87528
Files:
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
clang/lib/Parse/ParsePragma.cpp
clang/lib/Parse/ParseStmt.cpp
clang/lib/Sema/SemaStmt.cpp
clang/test/CodeGen/fp-floatcontrol-pragma.cpp
clang/test/CodeGen/pragma-fenv_access.c
clang/test/Parser/fp-floatcontrol-syntax.cpp
clang/test/Parser/pragma-fenv_access.c
clang/test/Preprocessor/pragma_unknown.c
Index: clang/test/Preprocessor/pragma_unknown.c
===================================================================
--- clang/test/Preprocessor/pragma_unknown.c
+++ clang/test/Preprocessor/pragma_unknown.c
@@ -16,15 +16,6 @@
// CHECK: {{^}}#pragma STDC FP_CONTRACT DEFAULT{{$}}
// CHECK: {{^}}#pragma STDC FP_CONTRACT IN_BETWEEN{{$}}
-#pragma STDC FENV_ACCESS ON // expected-warning {{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
-#pragma STDC FENV_ACCESS OFF
-#pragma STDC FENV_ACCESS DEFAULT
-#pragma STDC FENV_ACCESS IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS ON{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS OFF{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS DEFAULT{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS IN_BETWEEN{{$}}
-
#pragma STDC CX_LIMITED_RANGE ON
#pragma STDC CX_LIMITED_RANGE OFF
#pragma STDC CX_LIMITED_RANGE DEFAULT
Index: clang/test/Parser/pragma-fenv_access.c
===================================================================
--- /dev/null
+++ clang/test/Parser/pragma-fenv_access.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#pragma STDC FENV_ACCESS IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
+
+#pragma STDC FENV_ACCESS OFF
+
+float func_04(int x, float y) {
+ if (x)
+ return y + 2;
+ #pragma STDC FENV_ACCESS ON // expected-error{{'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of a compound statement}}
+ return x + y;
+}
Index: clang/test/Parser/fp-floatcontrol-syntax.cpp
===================================================================
--- clang/test/Parser/fp-floatcontrol-syntax.cpp
+++ clang/test/Parser/fp-floatcontrol-syntax.cpp
@@ -26,19 +26,14 @@
double a = 0.0;
double b = 1.0;
-//FIXME At some point this warning will be removed, until then
-// document the warning
-#ifdef FAST
-// expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
-#pragma STDC FENV_ACCESS ON
-#else
-#pragma STDC FENV_ACCESS ON // expected-warning{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
-#endif
#ifdef STRICT
#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when except is enabled}}
#else
+#ifndef FAST
// Currently FENV_ACCESS cannot be enabled by pragma, skip error check
-#pragma float_control(precise, off) // not-expected-error {{'#pragma float_control(precise, off)' is illegal when fenv_access is enabled}}
+#pragma STDC FENV_ACCESS ON
+#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when fenv_access is enabled}}
+#endif
#endif
#pragma float_control(precise, on)
Index: clang/test/CodeGen/pragma-fenv_access.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/pragma-fenv_access.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -ffp-exception-behavior=strict -frounding-math -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
+
+#pragma STDC FENV_ACCESS ON
+
+float func_01(float x, float y) {
+ return x + y;
+}
+// CHECK-LABEL: @func_01
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_02(float x, float y) {
+ #pragma STDC FENV_ACCESS OFF
+ return x + y;
+}
+// CHECK-LABEL: @func_02
+// CHECK: fadd float {{.*}}
+
+
+float func_03(float x, float y) {
+ return x + y;
+}
+// CHECK-LABEL: @func_03
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+#pragma STDC FENV_ACCESS OFF
+
+float func_04(float x, float y) {
+ return x + y;
+}
+// CHECK-LABEL: @func_04
+// CHECK: fadd float {{.*}}
+
+
+float func_05(float x, float y) {
+ #pragma STDC FENV_ACCESS ON
+ return x + y;
+}
+// CHECK-LABEL: @func_05
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_06(float x, float y) {
+ return x + y;
+}
+// CHECK-LABEL: @func_06
+// CHECK: fadd float {{.*}}
+
+
+float func_07(float x, float y) {
+ x -= y;
+ if (x) {
+ #pragma STDC FENV_ACCESS ON
+ y *= 2;
+ }
+ return y + 4;
+}
+// CHECK-LABEL: @func_07
+// CHECK: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
Index: clang/test/CodeGen/fp-floatcontrol-pragma.cpp
===================================================================
--- clang/test/CodeGen/fp-floatcontrol-pragma.cpp
+++ clang/test/CodeGen/fp-floatcontrol-pragma.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -verify -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FENV %s
// RUN: %clang_cc1 -triple %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 %s
// Verify float_control(precise, off) enables fast math flags on fp operations.
@@ -138,7 +138,6 @@
// CHECK-LABEL define float {{.*}}test_OperatorCall{{.*}}
#if FENV_ON
-// expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
#pragma STDC FENV_ACCESS ON
#endif
// CHECK-LABEL: define {{.*}}callt{{.*}}
@@ -146,7 +145,16 @@
void callt() {
volatile float z;
z = z * z;
-//CHECK: = fmul float
+ //CHECK-FENV: llvm.experimental.constrained.fmul{{.*}}
+}
+
+// CHECK-LABEL: define {{.*}}myAdd{{.*}}
+float myAdd() {
+ return 1.0 + 2.0;
+ // Check that floating point constant folding doesn't occur if
+ // #pragma STC FENV_ACCESS is enabled.
+ //CHECK-FENV: llvm.experimental.constrained.fadd{{.*}}double 1.0{{.*}}double 2.0{{.*}}
+ //CHECK: ret float 3.0{{.*}}
}
#if EXCEPT
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -389,6 +389,13 @@
PopCompoundScope();
}
+void Sema::ActOnAfterCompoundStatementLeadingPragmas() {
+ if (getCurFPFeatures().getAllowFEnvAccess()) {
+ FunctionDecl *F = getCurFunctionDecl();
+ F->setUsesFPIntrin(true);
+ }
+}
+
sema::CompoundScopeInfo &Sema::getCurCompoundScope() const {
return getCurFunction()->CompoundScopes.back();
}
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -366,7 +366,8 @@
case tok::annot_pragma_fenv_access:
ProhibitAttributes(Attrs);
- HandlePragmaFEnvAccess();
+ Diag(Tok, diag::err_pragma_stdc_fenv_access_scope);
+ ConsumeAnnotationToken();
return StmtEmpty();
case tok::annot_pragma_fenv_round:
@@ -1033,9 +1034,9 @@
Tok.getLocation(),
"in compound statement ('{}')");
- // Record the state of the FPFeatures, restore on leaving the
+ // Record the current FPFeatures, restore on leaving the
// compound statement.
- Sema::FPFeaturesStateRAII SaveFPContractState(Actions);
+ Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
InMessageExpressionRAIIObject InMessage(*this, false);
BalancedDelimiterTracker T(*this, tok::l_brace);
@@ -1046,6 +1047,7 @@
// Parse any pragmas at the beginning of the compound statement.
ParseCompoundStatementLeadingPragmas();
+ Actions.ActOnAfterCompoundStatementLeadingPragmas();
StmtVector Stmts;
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -106,10 +106,6 @@
tok::OnOffSwitch OOS;
if (PP.LexOnOffSwitch(OOS))
return;
- if (OOS == tok::OOS_ON) {
- PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
- return;
- }
MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1);
Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -1137,6 +1137,10 @@
/// definition.
void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F);
+ /// Set the LLVM function attributes that represent floating point
+ /// environment.
+ void setLLVMFunctionFEnvAttributes(const FunctionDecl *D, llvm::Function *F);
+
/// Return true iff the given type uses 'sret' when used as a return type.
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI);
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1725,6 +1725,15 @@
}
}
+void CodeGenModule::setLLVMFunctionFEnvAttributes(const FunctionDecl *D,
+ llvm::Function *F) {
+ if (D->usesFPIntrin()) {
+ llvm::AttrBuilder FuncAttrs;
+ FuncAttrs.addAttribute("strictfp");
+ F->addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs);
+ }
+}
+
void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
const Decl *D = GD.getDecl();
if (dyn_cast_or_null<NamedDecl>(D))
@@ -4554,9 +4563,11 @@
MaybeHandleStaticInExternC(D, Fn);
-
maybeSetTrivialComdat(*D, *Fn);
+ // Set CodeGen attributes that represent floating point environment.
+ setLLVMFunctionFEnvAttributes(D, Fn);
+
CodeGenFunction(*this).GenerateCode(GD, Fn, FI);
setNonAliasAttributes(GD, Fn);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -900,8 +900,10 @@
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
Builder.setIsFPConstrained(FD->usesFPIntrin());
- if (FD->usesFPIntrin())
+ if (FD->usesFPIntrin()) {
Fn->addFnAttr(llvm::Attribute::StrictFP);
+ Builder.setIsFPConstrained(true);
+ }
}
// If a custom alignment is used, force realigning to this alignment on
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -4329,6 +4329,7 @@
void ActOnFinishOfCompoundStmt();
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr);
+ void ActOnAfterCompoundStatementLeadingPragmas();
/// A RAII object to enter scope of a compound statement.
class CompoundScopeRAII {
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1133,9 +1133,9 @@
// - #pragma stdc unknown
def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
InGroup<UnknownPragmas>;
-def warn_stdc_fenv_access_not_supported :
- Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
- InGroup<UnknownPragmas>;
+def err_pragma_stdc_fenv_access_scope : Error<
+ "'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of a "
+ "compound statement">;
def warn_stdc_fenv_round_not_supported :
Warning<"pragma STDC FENV_ROUND is not supported">,
InGroup<UnknownPragmas>;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits