// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DDEFAULT=1 -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DDEFAULT %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DEBSTRICT=1 -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DEBSTRICT %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -DFAST=1 -ffast-math -ffp-contract=fast -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-FAST %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DNOHONOR=1 -menable-no-infs -menable-no-nans -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-NOHONOR %s #define FUN(n) \ (float z) { return n * z + n; } float fun_default FUN(1) //CHECK-LABEL: define {{.*}} @_Z11fun_defaultf{{.*}} #if DEFAULT //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} #endif #if EBSTRICT // Note that backend wants constrained intrinsics used // throughout the function if they are needed anywhere in the function. // In that case, operations are built with constrained intrinsics operator // but using default settings for exception behavior and rounding mode. //CHECK-DEBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif #pragma float_control(push) #ifndef FAST // Rule: precise must be enabled #pragma float_control(except, on) #endif float exc_on FUN(2) //CHECK-LABEL: define {{.*}} @_Z6exc_onf{{.*}} #if DEFAULT //CHECK-DDEFAULT: llvm.experimental.constrained.fmul{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict #endif #if NOHONOR //CHECK-NOHONOR: nnan ninf float {{.*}}llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict #endif #if FAST //Not possible to enable float_control(except) in FAST mode. //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif #pragma float_control(pop) float exc_pop FUN(5) //CHECK-LABEL: define {{.*}} @_Z7exc_popf{{.*}} #if DEFAULT //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 float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif #pragma float_control(except, off) float exc_off FUN(5) //CHECK-LABEL: define {{.*}} @_Z7exc_offf{{.*}} #if DEFAULT //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: call float @llvm.fmuladd{{.*}} #endif #if NOHONOR //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif #pragma float_control(precise, on, push) float precise_on FUN(3) //CHECK-LABEL: define {{.*}} @_Z10precise_onf{{.*}} #if DEFAULT //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR // If precise is pushed then all fast-math should be off! //CHECK-NOHONOR: call float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #pragma float_control(pop) float precise_pop FUN(3) //CHECK-LABEL: define {{.*}} @_Z11precise_popf{{.*}} #if DEFAULT //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif #pragma float_control(precise, off) float precise_off FUN(4) //CHECK-LABEL: define {{.*}} @_Z11precise_offf{{.*}} #if DEFAULT // Note: precise_off enables fp_contract=fast and the instructions // generated do not include the contract flag, although it was enabled // in IRBuilder. //CHECK-DDEFAULT: fmul fast float //CHECK-DDEFAULT: fadd fast float #endif #if EBSTRICT //CHECK-DEBSTRICT: fmul fast float //CHECK-DEBSTRICT: fadd fast float #endif #if NOHONOR // fast math should be enabled, and contract should be fast //CHECK-NOHONOR: fmul fast float //CHECK-NOHONOR: fadd fast float #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif #pragma float_control(precise, on) float precise_on2 FUN(3) //CHECK-LABEL: define {{.*}} @_Z11precise_on2f{{.*}} #if DEFAULT //CHECK-DDEFAULT: llvm.fmuladd{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR // fast math should be off, and contract should be on //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #pragma float_control(push) float precise_push FUN(3) //CHECK-LABEL: define {{.*}} @_Z12precise_pushf{{.*}} #if DEFAULT //CHECK-DDEFAULT: llvm.fmuladd{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #pragma float_control(precise, off) float precise_off2 FUN(4) //CHECK-LABEL: define {{.*}} @_Z12precise_off2f{{.*}} #if DEFAULT //CHECK-DDEFAULT: fmul fast float //CHECK-DDEFAULT: fadd fast float #endif #if EBSTRICT //CHECK-DEBSTRICT: fmul fast float //CHECK-DEBSTRICT: fadd fast float #endif #if NOHONOR // fast math settings since precise is off //CHECK-NOHONOR: fmul fast float //CHECK-NOHONOR: fadd fast float #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif #pragma float_control(pop) float precise_pop2 FUN(3) //CHECK-LABEL: define {{.*}} @_Z12precise_pop2f{{.*}} #if DEFAULT //CHECK-DDEFAULT: llvm.fmuladd{{.*}} #endif #if EBSTRICT //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}} #endif #if NOHONOR //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif #ifndef FAST // Rule: precise must be enabled #pragma float_control(except, on) #endif float y(); class ON { // Settings for top level class initializer revert to command line // source pragma's do not pertain. float z = 2 + y() * 7; //CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}} #if DEFAULT //CHECK-DDEFAULT: call float {{.*}}llvm.fmuladd #endif #if EBSTRICT //Currently, same as default [command line options not considered] //CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd #endif #if NOHONOR //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif }; ON on; #pragma float_control(except, off) class OFF { float w = 2 + y() * 7; //CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}} #if DEFAULT //CHECK-DDEFAULT: call float {{.*}}llvm.fmuladd #endif #if EBSTRICT //CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd #endif #if NOHONOR //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} #endif #if FAST //CHECK-FAST: fmul fast float //CHECK-FAST: fadd fast float #endif }; OFF off;