sepavloff updated this revision to Diff 433963.
sepavloff added a comment.
Update the patch
- Add a flag to reflect rounding mode change by FENV_ROUND,
- Keep dynamic mode in AST and change it later in CodeGen,
- Add new tests.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D126364/new/
https://reviews.llvm.org/D126364
Files:
clang/include/clang/Basic/LangOptions.h
clang/include/clang/Sema/Sema.h
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/Parse/ParsePragma.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaAttr.cpp
clang/test/AST/ast-dump-fpfeatures.cpp
clang/test/CodeGen/pragma-fenv_access.c
Index: clang/test/CodeGen/pragma-fenv_access.c
===================================================================
--- clang/test/CodeGen/pragma-fenv_access.c
+++ clang/test/CodeGen/pragma-fenv_access.c
@@ -20,7 +20,7 @@
return x + y;
}
// CHECK-LABEL: @func_02
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
float func_03(float x, float y) {
@@ -41,7 +41,15 @@
return x + y;
}
// CHECK-LABEL: @func_04
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK: fadd float
+
+
+float func_04a(float x, float y) {
+ #pragma float_control(except, on)
+ return x + y;
+}
+// CHECK-LABEL: @func_04a
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
float func_05(float x, float y) {
@@ -57,18 +65,117 @@
return x + y;
}
// CHECK-LABEL: @func_06
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK: fadd float
float func_07(float x, float y) {
x -= y;
if (x) {
#pragma STDC FENV_ACCESS ON
- y *= 2;
+ y *= 2.0F;
}
- return y + 4;
+ return y + 4.0F;
}
// 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.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
// 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.tonearest", metadata !"fpexcept.ignore")
+
+
+float func_08(float x, float y) {
+ #pragma STDC FENV_ROUND FE_UPWARD
+ #pragma STDC FENV_ACCESS ON
+ return x + y;
+}
+// CHECK-LABEL: @func_08
+// CHECK: call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.upward", metadata !"fpexcept.strict")
+
+
+float func_08a(float x, float y) {
+ #pragma STDC FENV_ROUND FE_TONEAREST
+ #pragma STDC FENV_ACCESS ON
+ return x + y;
+}
+// CHECK-LABEL: @func_08a
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+
+
+float func_09(float x, float y) {
+ #pragma clang fp exceptions(maytrap)
+ #pragma STDC FENV_ACCESS ON
+ return x + y;
+}
+// CHECK-LABEL: @func_09
+// CHECK: call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.maytrap")
+
+
+float func_10(float x, float y) {
+ #pragma clang fp exceptions(maytrap)
+ #pragma STDC FENV_ROUND FE_UPWARD
+ #pragma STDC FENV_ACCESS ON
+ return x + y;
+}
+// CHECK-LABEL: @func_10
+// CHECK: call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.upward", metadata !"fpexcept.maytrap")
+
+
+float func_11(float x, float y, float z) {
+ #pragma STDC FENV_ACCESS ON
+ float res = x * y;
+ {
+ #pragma STDC FENV_ACCESS OFF
+ return res + z;
+ }
+}
+// CHECK-LABEL: @func_11
+// CHECK: call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+
+
+float func_12(float x, float y, float z) {
+ #pragma STDC FENV_ROUND FE_TOWARDZERO
+ #pragma STDC FENV_ACCESS ON
+ float res = x * y;
+ {
+ #pragma STDC FENV_ACCESS OFF
+ return res + z;
+ }
+}
+// CHECK-LABEL: @func_12
+// CHECK: call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.ignore")
+
+
+float func_13(float x, float y) {
+ x -= y;
+ {
+ #pragma STDC FENV_ROUND FE_TONEAREST
+ #pragma STDC FENV_ACCESS ON
+ y *= 2.0F;
+ }
+ {
+ #pragma STDC FENV_ACCESS ON
+ return y + 4.0F;
+ }
+}
+// CHECK-LABEL: @func_13
+// CHECK: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+// CHECK: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_14(float x, float y) {
+ #pragma STDC FENV_ROUND FE_DYNAMIC
+ #pragma STDC FENV_ACCESS ON
+ return x + y;
+}
+// CHECK-LABEL: @func_14
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_15(float x, float y) {
+ #pragma STDC FENV_ROUND FE_DYNAMIC
+ return x + y;
+}
+// CHECK-LABEL: @func_15
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
Index: clang/test/AST/ast-dump-fpfeatures.cpp
===================================================================
--- clang/test/AST/ast-dump-fpfeatures.cpp
+++ clang/test/AST/ast-dump-fpfeatures.cpp
@@ -109,7 +109,7 @@
}
// CHECK-LABEL: FunctionDecl {{.*}} func_12 'float (float, float)'
-// CHECK: BinaryOperator {{.*}} 'float' '+' RoundingMode=tonearest
+// CHECK: BinaryOperator {{.*}} 'float' '+' RoundingMode=dynamic
#pragma STDC FENV_ROUND FE_TONEAREST
Index: clang/lib/Sema/SemaAttr.cpp
===================================================================
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1246,18 +1246,12 @@
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
}
-void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) {
- // C2x: 7.6.2p3 If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off",
- // the translator may assume that the default rounding mode is in effect.
- if (FPR == llvm::RoundingMode::Dynamic &&
- !CurFPFeatures.getAllowFEnvAccess() &&
- CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Ignore)
- FPR = llvm::RoundingMode::NearestTiesToEven;
-
+void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) {
FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
NewFPFeatures.setRoundingModeOverride(FPR);
FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
+ IsRoundingModeSet = true;
}
void Sema::setExceptionMode(SourceLocation Loc,
@@ -1278,12 +1272,24 @@
// pragma, or by using the /fp:precise or /fp:strict compiler options
if (!isPreciseFPEnabled())
Diag(Loc, diag::err_pragma_fenv_requires_precise);
+ // Enabling FENV access sets RoundingMode to Dynamic and ExceptionBehavior
+ // to Strict unless they are already overwritten.
+ if (!IsRoundingModeSet)
+ NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic);
+ if (!NewFPFeatures.hasFPExceptionModeOverride())
+ NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
+ else if (NewFPFeatures.getFPExceptionModeOverride() ==
+ LangOptions::FPE_Ignore) {
+ if (NewFPFeatures.hasAllowFEnvAccessOverride())
+ NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
+ }
NewFPFeatures.setAllowFEnvAccessOverride(true);
- // Enabling FENV access sets the RoundingMode to Dynamic.
- // and ExceptionBehavior to Strict
- NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic);
- NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
} else {
+ if (CurFPFeatures.getRoundingMode() == llvm::RoundingMode::Dynamic)
+ NewFPFeatures.setRoundingModeOverride(
+ llvm::RoundingMode::NearestTiesToEven);
+ if (CurFPFeatures.getFPExceptionMode() != LangOptions::FPE_Ignore)
+ NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore);
NewFPFeatures.setAllowFEnvAccessOverride(false);
}
FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2662,10 +2662,12 @@
: S(S), OldFPFeaturesState(S.CurFPFeatures),
OldOverrides(S.FpPragmaStack.CurrentValue),
OldEvalMethod(S.PP.getCurrentFPEvalMethod()),
- OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()) {}
+ OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()),
+ OldIsRoundingModeSet(S.IsRoundingModeSet) {}
Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() {
S.CurFPFeatures = OldFPFeaturesState;
S.FpPragmaStack.CurrentValue = OldOverrides;
S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod);
+ S.IsRoundingModeSet = OldIsRoundingModeSet;
}
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -804,7 +804,7 @@
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.setRoundingMode(PragmaLoc, RM);
+ Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
}
StmtResult Parser::HandlePragmaCaptured()
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -146,7 +146,7 @@
FMFGuard.emplace(CGF.Builder);
llvm::RoundingMode NewRoundingBehavior =
- static_cast<llvm::RoundingMode>(FPFeatures.getRoundingMode());
+ FPFeatures.getEffectiveRoundingMode();
CGF.Builder.setDefaultConstrainedRounding(NewRoundingBehavior);
auto NewExceptionBehavior =
ToConstrainedExceptMD(static_cast<LangOptions::FPExceptionModeKind>(
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -704,6 +704,9 @@
return result;
}
+ /// Was rounding mode overridden by pragma FENV_ROUND?
+ bool IsRoundingModeSet = false;
+
// RAII object to push / pop sentinel slots for all MS #pragma stacks.
// Actions should be performed only if we enter / exit a C++ method body.
class PragmaStackSentinelRAII {
@@ -1571,6 +1574,7 @@
FPOptionsOverride OldOverrides;
LangOptions::FPEvalMethodKind OldEvalMethod;
SourceLocation OldFPPragmaLocation;
+ bool OldIsRoundingModeSet;
};
void addImplicitTypedef(StringRef Name, QualType T);
@@ -10282,7 +10286,7 @@
LangOptions::FPExceptionModeKind);
/// Called to set constant rounding mode for floating point operations.
- void setRoundingMode(SourceLocation Loc, llvm::RoundingMode);
+ void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
/// Called to set exception behavior for floating point operations.
void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -669,6 +669,16 @@
getAllowFEnvAccess();
}
+ RoundingMode getEffectiveRoundingMode() const {
+ RoundingMode RM = getRoundingMode();
+ // C2x: 7.6.2p3 If the FE_DYNAMIC mode is specified and FENV_ACCESS is
+ // "off", the translator may assume that the default rounding mode is in
+ // effect.
+ if (RM == RoundingMode::Dynamic && !getAllowFEnvAccess())
+ RM = RoundingMode::NearestTiesToEven;
+ return RM;
+ }
+
bool operator==(FPOptions other) const { return Value == other.Value; }
/// Return the default value of FPOptions that's used when trailing
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits