Moving from bugs to tech. cwen reported that base-clang crashed on macppc in graphics/babl and emulators/mednafen [1]. I observed that clang crashed on powerpc64 in mednafen. I now propose to backport a commit in llvm 11.x git [2] to prevent these crashes. This change affects other arches.
[1] https://marc.info/?l=openbsd-bugs&m=159775378014683&w=2 [2] https://github.com/llvm/llvm-project/commit/d4ce862 FreeBSD on powerpc64 found the problems earlier: https://bugs.llvm.org/show_bug.cgi?id=45237 (babl) https://bugs.llvm.org/show_bug.cgi?id=45274 (mednafen) The problem is with clang -fno-unsafe-math-optimizations, one of the new floating-point options in clang-10. The diff disables the new options on all targets except X86 (and SystemZ), so it also affects arches other than PowerPC. The disabled options cause a warning. With the diff in clang: - mednafen stops using -fno-unsafe-math-optimizations, because the new warning fails the configure test. I can build and package mednafen on macppc (where a single *m68k*.cpp takes over 2 hours), but when I try to play Super Mario World (snes), mednafen crashes with a SIGSEGV. The build on powerpc64 stops crashing clang, but fails at an altivec error. - babl uses -fno-unsafe-math-optimizations and ignores the new warning. I can build and package babl, and all 27 tests pass on both macppc and powerpc64. - I have built src and xenocara on powerpc64. The diff is in llvm 11.x. To backport the diff, I manually applied some parts (where the context had changed), and I renamed RoundingMode::NearestTiesToEven back to FPR_RoundToNearest. Apply the diff in /usr/src/gnu/llvm. If DiagnosticFrontendKinds.inc exists under /usr/obj/gnu/usr.bin/clang/, you must delete the .inc, because there is a missing dependency in our Makefiles. Is this OK? Should we do something else? --George Index: clang/docs/ClangCommandLineReference.rst =================================================================== RCS file: /cvs/src/gnu/llvm/clang/docs/ClangCommandLineReference.rst,v retrieving revision 1.1.1.2 diff -u -p -r1.1.1.2 ClangCommandLineReference.rst --- clang/docs/ClangCommandLineReference.rst 9 Aug 2020 15:51:07 -0000 1.1.1.2 +++ clang/docs/ClangCommandLineReference.rst 30 Aug 2020 19:37:51 -0000 @@ -818,6 +818,10 @@ Enables the experimental global instruct Enables an experimental new pass manager in LLVM. +.. option:: -fexperimental-strict-floating-point + +Enables the use of non-default rounding modes and non-default exception handling on targets that are not currently ready. + .. option:: -ffine-grained-bitfield-accesses, -fno-fine-grained-bitfield-accesses Use separate accesses for consecutive bitfield runs with legal widths and alignments. Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== RCS file: /cvs/src/gnu/llvm/clang/include/clang/Basic/CodeGenOptions.def,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 CodeGenOptions.def --- clang/include/clang/Basic/CodeGenOptions.def 3 Aug 2020 14:31:32 -0000 1.1.1.1 +++ clang/include/clang/Basic/CodeGenOptions.def 30 Aug 2020 19:37:51 -0000 @@ -58,6 +58,8 @@ CODEGENOPT(DisableLLVMPasses , 1, 0) /// ///< frontend. CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0 +CODEGENOPT(ExperimentalStrictFloatingPoint, 1, 0) ///< Enables the new, experimental + ///< strict floating point. CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental ///< pass manager. CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new Index: clang/include/clang/Basic/DiagnosticFrontendKinds.td =================================================================== RCS file: /cvs/src/gnu/llvm/clang/include/clang/Basic/DiagnosticFrontendKinds.td,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 DiagnosticFrontendKinds.td --- clang/include/clang/Basic/DiagnosticFrontendKinds.td 3 Aug 2020 14:31:32 -0000 1.1.1.1 +++ clang/include/clang/Basic/DiagnosticFrontendKinds.td 30 Aug 2020 19:37:51 -0000 @@ -37,6 +37,12 @@ def note_fe_backend_plugin: Note<"%0">, def warn_fe_override_module : Warning< "overriding the module target triple with %0">, InGroup<DiagGroup<"override-module">>; +def warn_fe_backend_unsupported_fp_rounding : Warning< + "overriding currently unsupported rounding mode on this target">, + InGroup<UnsupportedFPOpt>; +def warn_fe_backend_unsupported_fp_exceptions : Warning< + "overriding currently unsupported use of floating point exceptions " + "on this target">, InGroup<UnsupportedFPOpt>; def remark_fe_backend_optimization_remark : Remark<"%0">, BackendInfo, InGroup<BackendOptimizationRemark>; Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== RCS file: /cvs/src/gnu/llvm/clang/include/clang/Basic/DiagnosticGroups.td,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 DiagnosticGroups.td --- clang/include/clang/Basic/DiagnosticGroups.td 3 Aug 2020 14:31:32 -0000 1.1.1.1 +++ clang/include/clang/Basic/DiagnosticGroups.td 30 Aug 2020 19:37:51 -0000 @@ -103,6 +103,7 @@ def DoublePromotion : DiagGroup<"double- def EnumTooLarge : DiagGroup<"enum-too-large">; def UnsupportedNan : DiagGroup<"unsupported-nan">; def UnsupportedAbs : DiagGroup<"unsupported-abs">; +def UnsupportedFPOpt : DiagGroup<"unsupported-floating-point-opt">; def UnsupportedCB : DiagGroup<"unsupported-cb">; def UnsupportedGPOpt : DiagGroup<"unsupported-gpopt">; def UnsupportedTargetOpt : DiagGroup<"unsupported-target-opt">; Index: clang/include/clang/Basic/LangOptions.def =================================================================== RCS file: /cvs/src/gnu/llvm/clang/include/clang/Basic/LangOptions.def,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 LangOptions.def --- clang/include/clang/Basic/LangOptions.def 3 Aug 2020 14:31:32 -0000 1.1.1.1 +++ clang/include/clang/Basic/LangOptions.def 30 Aug 2020 19:37:51 -0000 @@ -257,6 +257,7 @@ LANGOPT(SinglePrecisionConstants , 1, 0, LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math") /// FP_CONTRACT mode (on/off/fast). ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP contraction type") +COMPATIBLE_LANGOPT(ExpStrictFP, 1, false, "Enable experimental strict floating point") ENUM_LANGOPT(FPRoundingMode, FPRoundingModeKind, 3, FPR_ToNearest, "FP Rounding Mode type") ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP Exception Behavior Mode type") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") Index: clang/include/clang/Basic/TargetInfo.h =================================================================== RCS file: /cvs/src/gnu/llvm/clang/include/clang/Basic/TargetInfo.h,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 TargetInfo.h --- clang/include/clang/Basic/TargetInfo.h 3 Aug 2020 14:31:32 -0000 1.1.1.1 +++ clang/include/clang/Basic/TargetInfo.h 30 Aug 2020 19:37:51 -0000 @@ -176,6 +176,7 @@ protected: // LLVM IR type. bool HasFloat128; bool HasFloat16; + bool HasStrictFP; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; unsigned short SimdDefaultAlign; @@ -532,6 +533,9 @@ public: /// Determine whether the _Float16 type is supported on this target. virtual bool hasFloat16Type() const { return HasFloat16; } + + /// Determine whether constrained floating point is supported on this target. + virtual bool hasStrictFP() const { return HasStrictFP; } /// Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. Index: clang/include/clang/Driver/Options.td =================================================================== RCS file: /cvs/src/gnu/llvm/clang/include/clang/Driver/Options.td,v retrieving revision 1.1.1.2 diff -u -p -r1.1.1.2 Options.td --- clang/include/clang/Driver/Options.td 9 Aug 2020 15:51:08 -0000 1.1.1.2 +++ clang/include/clang/Driver/Options.td 30 Aug 2020 19:37:51 -0000 @@ -1235,6 +1235,9 @@ def fexperimental_isel : Flag<["-"], "fe def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Enables an experimental new pass manager in LLVM.">; +def fexperimental_strict_floating_point : Flag<["-"], "fexperimental-strict-floating-point">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Enables experimental strict floating point in LLVM.">; def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>; def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>; def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>, Index: clang/lib/Basic/TargetInfo.cpp =================================================================== RCS file: /cvs/src/gnu/llvm/clang/lib/Basic/TargetInfo.cpp,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 TargetInfo.cpp --- clang/lib/Basic/TargetInfo.cpp 3 Aug 2020 14:31:33 -0000 1.1.1.1 +++ clang/lib/Basic/TargetInfo.cpp 30 Aug 2020 19:37:52 -0000 @@ -36,6 +36,7 @@ TargetInfo::TargetInfo(const llvm::Tripl HasLegalHalfType = false; HasFloat128 = false; HasFloat16 = false; + HasStrictFP = false; PointerWidth = PointerAlign = 32; BoolWidth = BoolAlign = 8; IntWidth = IntAlign = 32; Index: clang/lib/Basic/Targets/SystemZ.h =================================================================== RCS file: /cvs/src/gnu/llvm/clang/lib/Basic/Targets/SystemZ.h,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 SystemZ.h --- clang/lib/Basic/Targets/SystemZ.h 3 Aug 2020 14:31:33 -0000 1.1.1.1 +++ clang/lib/Basic/Targets/SystemZ.h 30 Aug 2020 19:37:52 -0000 @@ -47,6 +47,7 @@ public: MinGlobalAlign = 16; resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64"); MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + HasStrictFP = true; } void getTargetDefines(const LangOptions &Opts, Index: clang/lib/Basic/Targets/X86.h =================================================================== RCS file: /cvs/src/gnu/llvm/clang/lib/Basic/Targets/X86.h,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 X86.h --- clang/lib/Basic/Targets/X86.h 3 Aug 2020 14:31:33 -0000 1.1.1.1 +++ clang/lib/Basic/Targets/X86.h 30 Aug 2020 19:37:52 -0000 @@ -148,6 +148,7 @@ public: : TargetInfo(Triple) { LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); AddrSpaceMap = &X86AddrSpaceMap; + HasStrictFP = true; } const char *getLongDoubleMangling() const override { Index: clang/lib/Frontend/CompilerInstance.cpp =================================================================== RCS file: /cvs/src/gnu/llvm/clang/lib/Frontend/CompilerInstance.cpp,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 CompilerInstance.cpp --- clang/lib/Frontend/CompilerInstance.cpp 3 Aug 2020 14:31:33 -0000 1.1.1.1 +++ clang/lib/Frontend/CompilerInstance.cpp 30 Aug 2020 19:37:52 -0000 @@ -927,6 +927,19 @@ bool CompilerInstance::ExecuteAction(Fro setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO)); } + if (!getTarget().hasStrictFP() && !getLangOpts().ExpStrictFP) { + if (getLangOpts().getFPRoundingMode() != + LangOptions::FPR_ToNearest) { + getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_rounding); + getLangOpts().setFPRoundingMode(LangOptions::FPR_ToNearest); + } + if (getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore) { + getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_exceptions); + getLangOpts().setFPExceptionMode(LangOptions::FPE_Ignore); + } + // FIXME: can we disable FEnvAccess? + } + // Inform the target of the language options. // // FIXME: We shouldn't need to do this, the target should be immutable once Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== RCS file: /cvs/src/gnu/llvm/clang/lib/Frontend/CompilerInvocation.cpp,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 CompilerInvocation.cpp --- clang/lib/Frontend/CompilerInvocation.cpp 3 Aug 2020 14:31:33 -0000 1.1.1.1 +++ clang/lib/Frontend/CompilerInvocation.cpp 30 Aug 2020 19:37:52 -0000 @@ -3175,6 +3175,9 @@ static void ParseLangArgs(LangOptions &O Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } + if (Args.hasArg(OPT_fexperimental_strict_floating_point)) + Opts.ExpStrictFP = true; + LangOptions::FPRoundingModeKind FPRM = LangOptions::FPR_ToNearest; if (Args.hasArg(OPT_frounding_math)) { FPRM = LangOptions::FPR_Dynamic;