sepavloff created this revision. sepavloff added reviewers: aaron.ballman, andrew.w.kaylor, rjmccall, efriedma, kpn. Herald added a project: All. sepavloff requested review of this revision. Herald added a project: clang.
Previously `#pragma STDC FENV_ACCESS ON` always set dynamic rounding mode and strict exception handling. It is however too pessimistic in many cases. In practice the pragma can be used to change rounding mode only or to check exception flags without changing rounding mode. It could be made by using other pragmas, `FENV_ROUND` or `clang fp exception`, but their effect was overwritten by `FENV_ACCESS`. This change modifies treatment of this pragma so that it sets rounding and exception handling only if they are not set by other pragmas. Also `#pragma STDC FENV_ACCESS OFF` turned off only FEnvAccess flag leaving rounding mode and exception handling unchanged, which does not make sense in many cases. The change fixes this behavior also. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D126364 Files: clang/lib/Sema/SemaAttr.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,7 @@ 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_05(float x, float y) { @@ -57,7 +57,7 @@ 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) { @@ -69,6 +69,58 @@ 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.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.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_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") Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -1278,12 +1278,29 @@ // 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 the RoundingMode to Dynamic + // and ExceptionBehavior to Strict unless they are already overwritten. + if (!NewFPFeatures.hasRoundingModeOverride()) + NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic); + else if (NewFPFeatures.getRoundingModeOverride() == + llvm::RoundingMode::NearestTiesToEven) { + if (NewFPFeatures.hasAllowFEnvAccessOverride()) + 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);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits