diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -223,8 +223,7 @@ FMF.setNoSignedZeros(FPFeatures.noSignedZeros()); FMF.setAllowReciprocal(FPFeatures.allowReciprocalMath()); FMF.setApproxFunc(FPFeatures.allowApproximateFunctions()); - FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement() || - FPFeatures.allowFPContractWithinStatement()); + FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement()); } /// Propagate fast-math flags from \p Op to the instruction in \p V. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2939,6 +2939,8 @@ Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align); Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant); Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math); + if (Opts.FastRelaxedMath) + Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat); Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -457,8 +457,12 @@ FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); break; case PFC_Push: - Action = Sema::PSK_Push_Set; - FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt()); + if (FpPragmaStack.Stack.empty()) { + FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), + CurFPFeatures.getAsOpaqueInt()); + } + FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), + NewFPFeatures.getAsOpaqueInt()); break; case PFC_Pop: if (FpPragmaStack.Stack.empty()) { diff --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c --- a/clang/test/CodeGen/constrained-math-builtins.c +++ b/clang/test/CodeGen/constrained-math-builtins.c @@ -154,9 +154,9 @@ (double)f * f - f; (long double)-f * f + f; - // CHECK: call contract float @llvm.experimental.constrained.fmuladd.f32 + // CHECK: call float @llvm.experimental.constrained.fmuladd.f32 // CHECK: fneg - // CHECK: call contract double @llvm.experimental.constrained.fmuladd.f64 + // CHECK: call double @llvm.experimental.constrained.fmuladd.f64 // CHECK: fneg - // CHECK: call contract x86_fp80 @llvm.experimental.constrained.fmuladd.f80 + // CHECK: call x86_fp80 @llvm.experimental.constrained.fmuladd.f80 }; diff --git a/clang/test/CodeGen/fp-contract-on-pragma.cpp b/clang/test/CodeGen/fp-contract-on-pragma.cpp --- a/clang/test/CodeGen/fp-contract-on-pragma.cpp +++ b/clang/test/CodeGen/fp-contract-on-pragma.cpp @@ -3,7 +3,7 @@ // Is FP_CONTRACT honored in a simple case? float fp_contract_1(float a, float b, float c) { // CHECK: _Z13fp_contract_1fff -// CHECK: tail call contract float @llvm.fmuladd +// CHECK: tail call float @llvm.fmuladd #pragma clang fp contract(on) return a * b + c; } @@ -31,7 +31,7 @@ float fp_contract_3(float a, float b, float c) { // CHECK: _Z13fp_contract_3fff - // CHECK: tail call contract float @llvm.fmuladd + // CHECK: tail call float @llvm.fmuladd return template_muladd(a, b, c); } @@ -45,13 +45,13 @@ template class fp_contract_4; // CHECK: _ZN13fp_contract_4IiE6methodEfff -// CHECK: tail call contract float @llvm.fmuladd +// CHECK: tail call float @llvm.fmuladd // Check file-scoped FP_CONTRACT #pragma clang fp contract(on) float fp_contract_5(float a, float b, float c) { // CHECK: _Z13fp_contract_5fff - // CHECK: tail call contract float @llvm.fmuladd + // CHECK: tail call float @llvm.fmuladd return a * b + c; } @@ -69,8 +69,8 @@ float fp_contract_7(float a, float b, float c) { // CHECK: _Z13fp_contract_7fff -// CHECK: %[[M:.+]] = fmul contract float %b, 2.000000e+00 -// CHECK-NEXT: fsub contract float %[[M]], %c +// CHECK: %[[M:.+]] = fmul float %b, 2.000000e+00 +// CHECK-NEXT: fsub float %[[M]], %c #pragma clang fp contract(on) return (a = 2 * b) - c; } diff --git a/clang/test/CodeGen/fp-contract-pragma.cpp b/clang/test/CodeGen/fp-contract-pragma.cpp --- a/clang/test/CodeGen/fp-contract-pragma.cpp +++ b/clang/test/CodeGen/fp-contract-pragma.cpp @@ -2,9 +2,9 @@ // Is FP_CONTRACT honored in a simple case? float fp_contract_1(float a, float b, float c) { - // CHECK: _Z13fp_contract_1fff - // CHECK: tail call contract float @llvm.fmuladd -#pragma STDC FP_CONTRACT ON +// CHECK: _Z13fp_contract_1fff +// CHECK: tail call float @llvm.fmuladd + #pragma STDC FP_CONTRACT ON return a * b + c; } @@ -30,8 +30,8 @@ } float fp_contract_3(float a, float b, float c) { - // CHECK: _Z13fp_contract_3fff - // CHECK: tail call contract float @llvm.fmuladd +// CHECK: _Z13fp_contract_3fff +// CHECK: tail call float @llvm.fmuladd return template_muladd(a, b, c); } @@ -44,13 +44,13 @@ template class fp_contract_4; // CHECK: _ZN13fp_contract_4IiE6methodEfff -// CHECK: tail call contract float @llvm.fmuladd +// CHECK: tail call float @llvm.fmuladd // Check file-scoped FP_CONTRACT #pragma STDC FP_CONTRACT ON float fp_contract_5(float a, float b, float c) { - // CHECK: _Z13fp_contract_5fff - // CHECK: tail call contract float @llvm.fmuladd +// CHECK: _Z13fp_contract_5fff +// CHECK: tail call float @llvm.fmuladd return a * b + c; } @@ -67,25 +67,25 @@ // https://llvm.org/bugs/show_bug.cgi?id=25719 float fp_contract_7(float a, float b, float c) { - // CHECK: _Z13fp_contract_7fff - // CHECK: %[[M:.+]] = fmul contract float %b, 2.000000e+00 - // CHECK-NEXT: fsub contract float %[[M]], %c -#pragma STDC FP_CONTRACT ON +// CHECK: _Z13fp_contract_7fff +// CHECK: %[[M:.+]] = fmul float %b, 2.000000e+00 +// CHECK-NEXT: fsub float %[[M]], %c + #pragma STDC FP_CONTRACT ON return (a = 2 * b) - c; } float fp_contract_8(float a, float b, float c) { - // CHECK: _Z13fp_contract_8fff - // CHECK: fneg contract float %c - // CHECK: tail call contract float @llvm.fmuladd -#pragma STDC FP_CONTRACT ON +// CHECK: _Z13fp_contract_8fff +// CHECK: fneg float %c +// CHECK: tail call float @llvm.fmuladd + #pragma STDC FP_CONTRACT ON return a * b - c; } float fp_contract_9(float a, float b, float c) { - // CHECK: _Z13fp_contract_9fff - // CHECK: fneg contract float %a - // CHECK: tail call contract float @llvm.fmuladd -#pragma STDC FP_CONTRACT ON +// CHECK: _Z13fp_contract_9fff +// CHECK: fneg float %a +// CHECK: tail call float @llvm.fmuladd + #pragma STDC FP_CONTRACT ON return c - a * b; } diff --git a/clang/test/CodeGen/fp-floatcontrol-class.cpp b/clang/test/CodeGen/fp-floatcontrol-class.cpp --- a/clang/test/CodeGen/fp-floatcontrol-class.cpp +++ b/clang/test/CodeGen/fp-floatcontrol-class.cpp @@ -8,13 +8,13 @@ class ON { float w = 2 + y() * z(); // CHECK-LABEL: define {{.*}} @_ZN2ONC2Ev{{.*}} - //CHECK: call contract float {{.*}}llvm.fmuladd + //CHECK: call float {{.*}}llvm.fmuladd }; ON on; #pragma float_control(except, off) class OFF { float w = 2 + y() * z(); // CHECK-LABEL: define {{.*}} @_ZN3OFFC2Ev{{.*}} - //CHECK: call contract float {{.*}}llvm.fmuladd + //CHECK: call float {{.*}}llvm.fmuladd }; OFF off; diff --git a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp --- a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp +++ b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp @@ -1,6 +1,68 @@ // 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 -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. +float fp_precise_1(float a, float b, float c) { +// CHECK-O3: _Z12fp_precise_1fff +// CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} +// CHECK-O3: fadd fast float %[[M]], %c +#pragma float_control(precise, off) + return a * b + c; +} + +// Is float_control state cleared on exiting compound statements? +float fp_precise_2(float a, float b, float c) { + // CHECK-O3: _Z12fp_precise_2fff + // CHECK-O3: %[[M:.+]] = fmul float{{.*}} + // CHECK-O3: fadd float %[[M]], %c + { +#pragma float_control(precise, off) + } + return a * b + c; +} + +// Does float_control survive template instantiation? +class Foo {}; +Foo operator+(Foo, Foo); + +template +T template_muladd(T a, T b, T c) { +#pragma float_control(precise, off) + return a * b + c; +} + +float fp_precise_3(float a, float b, float c) { + // CHECK-O3: _Z12fp_precise_3fff + // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} + // CHECK-O3: fadd fast float %[[M]], %c + return template_muladd(a, b, c); +} + +template +class fp_precise_4 { + float method(float a, float b, float c) { +#pragma float_control(precise, off) + return a * b + c; + } +}; + +template class fp_precise_4; +// CHECK-O3: _ZN12fp_precise_4IiE6methodEfff +// CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} +// CHECK-O3: fadd fast float %[[M]], %c + +// Check file-scoped float_control +#pragma float_control(push) +#pragma float_control(precise, off) +float fp_precise_5(float a, float b, float c) { + // CHECK-O3: _Z12fp_precise_5fff + // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}} + // CHECK-O3: fadd fast float %[[M]], %c + return a * b + c; +} +#pragma float_control(pop) float fff(float x, float y) { // CHECK-LABEL: define float @_Z3fffff{{.*}} @@ -41,6 +103,14 @@ return z; } +float fma_test2(float a, float b, float c) { +// CHECK-LABEL define float @_Z9fma_test2fff{{.*}} +#pragma float_control(precise, off) + float x = a * b + c; + //CHECK: fmuladd + return x; +} + float fma_test1(float a, float b, float c) { // CHECK-LABEL define float @_Z9fma_test1fff{{.*}} #pragma float_control(precise, on) @@ -90,7 +160,7 @@ // CHECK-NS: define {{.*}}exc_off{{.*}} {} try { x = 1.0 / zero; /* division by zero, the result unused */ -//CHECK-NS: fdiv contract double +//CHECK-NS: fdiv double } catch (...) {} return zero; } diff --git a/clang/test/CodeGen/fp-floatcontrol-stack.cpp b/clang/test/CodeGen/fp-floatcontrol-stack.cpp --- a/clang/test/CodeGen/fp-floatcontrol-stack.cpp +++ b/clang/test/CodeGen/fp-floatcontrol-stack.cpp @@ -9,7 +9,7 @@ float fun_default FUN(1) //CHECK-LABEL: define {{.*}} @_Z11fun_defaultf{{.*}} #if DEFAULT -//CHECK-DDEFAULT: call contract float @llvm.fmuladd{{.*}} +//CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} #endif #if EBSTRICT // Note that backend wants constrained intrinsics used @@ -37,7 +37,7 @@ //CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict #endif #if NOHONOR -//CHECK-NOHONOR: nnan ninf contract float {{.*}}llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict +//CHECK-NOHONOR: nnan ninf float {{.*}}llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict #endif #if FAST //Not possible to enable float_control(except) in FAST mode. @@ -49,13 +49,13 @@ float exc_pop FUN(5) //CHECK-LABEL: define {{.*}} @_Z7exc_popf{{.*}} #if DEFAULT -//CHECK-DDEFAULT: call contract float @llvm.fmuladd{{.*}} +//CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict #endif #if NOHONOR -//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}} +//CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float @@ -66,13 +66,13 @@ float exc_off FUN(5) //CHECK-LABEL: define {{.*}} @_Z7exc_offf{{.*}} #if DEFAULT -//CHECK-DDEFAULT: call contract float @llvm.fmuladd{{.*}} +//CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} #endif #if EBSTRICT -//CHECK-DEBSTRICT: call contract float @llvm.fmuladd{{.*}} +//CHECK-DEBSTRICT: call float @llvm.fmuladd{{.*}} #endif #if NOHONOR -//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}} +//CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float @@ -83,30 +83,30 @@ float precise_on FUN(3) //CHECK-LABEL: define {{.*}} @_Z10precise_onf{{.*}} #if DEFAULT -//CHECK-DDEFAULT: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} #endif #if EBSTRICT -//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR // If precise is pushed then all fast-math should be off! -//CHECK-NOHONOR: call contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-NOHONOR: call float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST -//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #pragma float_control(pop) float precise_pop FUN(3) //CHECK-LABEL: define {{.*}} @_Z11precise_popf{{.*}} #if DEFAULT -//CHECK-DDEFAULT: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} #endif #if EBSTRICT -//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR -//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}} +//CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float @@ -143,14 +143,14 @@ //CHECK-DDEFAULT: llvm.fmuladd{{.*}} #endif #if EBSTRICT -//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR // fast math should be off, and contract should be on -//CHECK-NOHONOR: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST -//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #pragma float_control(push) @@ -160,13 +160,13 @@ //CHECK-DDEFAULT: llvm.fmuladd{{.*}} #endif #if EBSTRICT -//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR -//CHECK-NOHONOR: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST -//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #pragma float_control(precise, off) @@ -197,13 +197,13 @@ //CHECK-DDEFAULT: llvm.fmuladd{{.*}} #endif #if EBSTRICT -//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR -//CHECK-NOHONOR: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST -//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}} +//CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #ifndef FAST @@ -217,14 +217,14 @@ float z = 2 + y() * 7; //CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}} #if DEFAULT -//CHECK-DDEFAULT: call contract float {{.*}}llvm.fmuladd +//CHECK-DDEFAULT: call float {{.*}}llvm.fmuladd #endif #if EBSTRICT //Currently, same as default [command line options not considered] -//CHECK-DEBSTRICT: call contract float {{.*}}llvm.fmuladd +//CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd #endif #if NOHONOR -//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}} +//CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float @@ -237,13 +237,13 @@ float w = 2 + y() * 7; //CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}} #if DEFAULT -//CHECK-DDEFAULT: call contract float {{.*}}llvm.fmuladd +//CHECK-DDEFAULT: call float {{.*}}llvm.fmuladd #endif #if EBSTRICT -//CHECK-DEBSTRICT: call contract float {{.*}}llvm.fmuladd +//CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd #endif #if NOHONOR -//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}} +//CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float diff --git a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl --- a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl +++ b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl @@ -8,12 +8,12 @@ float spscalardiv(float a, float b) { // CHECK: @spscalardiv( - // NORMAL: fdiv contract float + // NORMAL: fdiv float // FAST: fdiv fast float - // FINITE: fdiv nnan ninf contract float - // UNSAFE: fdiv nnan nsz contract float - // MAD: fdiv contract float - // NOSIGNED: fdiv nsz contract float + // FINITE: fdiv nnan ninf float + // UNSAFE: fdiv nnan nsz float + // MAD: fdiv float + // NOSIGNED: fdiv nsz float return a / b; } // CHECK: attributes diff --git a/clang/test/CodeGenOpenCL/single-precision-constant.cl b/clang/test/CodeGenOpenCL/single-precision-constant.cl --- a/clang/test/CodeGenOpenCL/single-precision-constant.cl +++ b/clang/test/CodeGenOpenCL/single-precision-constant.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -cl-single-precision-constant -emit-llvm -o - | FileCheck %s float fn(float f) { - // CHECK: tail call contract float @llvm.fmuladd.f32(float %f, float 2.000000e+00, float 1.000000e+00) + // CHECK: tail call float @llvm.fmuladd.f32(float %f, float 2.000000e+00, float 1.000000e+00) return f*2. + 1.; }