Index: clang/include/clang/Basic/FPOptions.def =================================================================== --- clang/include/clang/Basic/FPOptions.def +++ clang/include/clang/Basic/FPOptions.def @@ -27,4 +27,5 @@ OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) +OPTION(MathErrno, bool, 1, BFloat16ExcessPrecision) #undef OPTION Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -850,6 +850,7 @@ setNoSignedZeroOverride(!Value); setAllowReciprocalOverride(!Value); setAllowApproxFuncOverride(!Value); + setMathErrnoOverride(Value); if (Value) /* Precise mode implies fp_contract=on and disables ffast-math */ setAllowFPContractWithinStatement(); Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -2245,6 +2245,13 @@ // likely to get lowered to the renamed library functions. const unsigned BuiltinIDIfNoAsmLabel = FD->hasAttr() ? 0 : BuiltinID; + bool MathErrnoOverrride = false; + if (E->hasStoredFPFeatures()) { + FPOptionsOverride OP = E->getFPFeatures(); + if (OP.hasMathErrnoOverride()) + MathErrnoOverrride = OP.getMathErrnoOverride(); + } + bool EmitIntrinsic = !MathErrnoOverrride && CGM.OptNone; // There are LLVM math intrinsics/instructions corresponding to math library // functions except the LLVM op will never set errno while the math library @@ -2257,9 +2264,12 @@ getContext().BuiltinInfo.isConstWithoutErrnoAndExceptions(BuiltinID); bool ConstWithoutExceptions = getContext().BuiltinInfo.isConstWithoutExceptions(BuiltinID); - if (FD->hasAttr() || - ((ConstWithoutErrnoAndExceptions || ConstWithoutExceptions) && - (!ConstWithoutErrnoAndExceptions || (!getLangOpts().MathErrno)))) { + + if ((FD->hasAttr() && EmitIntrinsic) || + (EmitIntrinsic || + ((ConstWithoutErrnoAndExceptions || ConstWithoutExceptions) && + (!ConstWithoutErrnoAndExceptions || + (!getLangOpts().MathErrno && EmitIntrinsic))))) { switch (BuiltinIDIfNoAsmLabel) { case Builtin::BIceil: case Builtin::BIceilf: Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -2381,6 +2381,9 @@ // Collect function IR attributes based on global settiings. getDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, FuncAttrs); + if (HasOptnone && !getLangOpts().MathErrno) + OptNone = false; + // Override some default IR attributes based on declaration-specific // information. if (TargetDecl) { Index: clang/lib/CodeGen/CodeGenModule.h =================================================================== --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -608,6 +608,7 @@ ~CodeGenModule(); void clear(); + bool OptNone = true; /// Finalize LLVM code generation. void Release(); Index: clang/test/CodeGen/math-errno.c =================================================================== --- /dev/null +++ clang/test/CodeGen/math-errno.c @@ -0,0 +1,52 @@ +// Tests that at -O2 math-errno is taken into account. Same than MSVC. +// RUN: %clang_cc1 -Wno-implicit-function-declaration -fmath-errno \ +// RUN: -O2 -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// Tests that with -ffast-math math-errno is taken into account with +// float_control(precise,on) and optnone. +// RUN: %clang_cc1 -Wno-implicit-function-declaration \ +// RUN: -ffast-math -emit-llvm -o - %s \ +// RUN: | FileCheck %s -check-prefix=FAST + +float f1(float x) { +#pragma float_control(precise,on) +return sqrtf(x); +} + +float f2(float x) { +#pragma float_control(precise,on) + { + float y = sqrtf(x); + return y; + } +} + +float f3(float x) { +#pragma float_control(precise,off) + { + float y = sqrtf(x); + return y; + } +} + +__attribute__((optnone)) +float f4(float x) { + x = sqrtf(x); + return x; +} + +// CHECK-LABEL: define dso_local float @f2(float noundef {{.*}}) +// CHECK: tail call float @sqrtf(float noundef {{.*}}) + +// CHECK-LABEL: define dso_local float @f3(float noundef {{.*}}) +// CHECK: call float @llvm.sqrt.f32(float {{.*}}) + +// FAST-LABEL: define dso_local nofpclass(nan inf) float @f1(float noundef nofpclass(nan inf) {{.*}}) +// FAST: call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) float @sqrtf(float noundef nofpclass(nan inf) {{.*}}) #[[ATTR0:[0-9]+]] + +// FAST-LABEL: define dso_local nofpclass(nan inf) float @f4(float noundef nofpclass(nan inf) {{.*}}) +// FAST: call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) float @sqrtf(float noundef nofpclass(nan inf) %0) #[[ATTR0:[0-9]+]] + +// FAST: attributes #[[ATTR0]] = { {{.*}} memory(none) } +