Index: llvm/trunk/include/llvm/Target/TargetMachine.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetMachine.h +++ llvm/trunk/include/llvm/Target/TargetMachine.h @@ -103,6 +103,7 @@ unsigned O0WantsFastISel : 1; public: + const TargetOptions DefaultOptions; mutable TargetOptions Options; virtual ~TargetMachine(); Index: llvm/trunk/lib/Target/TargetMachine.cpp =================================================================== --- llvm/trunk/lib/Target/TargetMachine.cpp +++ llvm/trunk/lib/Target/TargetMachine.cpp @@ -44,7 +44,7 @@ const TargetOptions &Options) : TheTarget(T), DL(DataLayoutString), TargetTriple(TT), TargetCPU(CPU), TargetFS(FS), AsmInfo(nullptr), MRI(nullptr), MII(nullptr), STI(nullptr), - RequireStructuredCFG(false), Options(Options) { + RequireStructuredCFG(false), DefaultOptions(Options), Options(Options) { if (EnableIPRA.getNumOccurrences()) this->Options.EnableIPRA = EnableIPRA; } @@ -63,14 +63,15 @@ /// \brief Reset the target options based on the function's attributes. // FIXME: This function needs to go away for a number of reasons: // a) global state on the TargetMachine is terrible in general, -// b) there's no default state here to keep, -// c) these target options should be passed only on the function +// b) these target options should be passed only on the function // and not on the TargetMachine (via TargetOptions) at all. void TargetMachine::resetTargetOptions(const Function &F) const { #define RESET_OPTION(X, Y) \ do { \ if (F.hasFnAttribute(Y)) \ Options.X = (F.getFnAttribute(Y).getValueAsString() == "true"); \ + else \ + Options.X = DefaultOptions.X; \ } while (0) RESET_OPTION(LessPreciseFPMADOption, "less-precise-fpmad"); @@ -87,6 +88,8 @@ Options.FPDenormalMode = FPDenormal::PreserveSign; else if (Denormal == "positive-zero") Options.FPDenormalMode = FPDenormal::PositiveZero; + else + Options.FPDenormalMode = DefaultOptions.FPDenormalMode; } /// Returns the code generation relocation model. The choices are static, PIC, Index: llvm/trunk/test/CodeGen/NVPTX/fast-math.ll =================================================================== --- llvm/trunk/test/CodeGen/NVPTX/fast-math.ll +++ llvm/trunk/test/CodeGen/NVPTX/fast-math.ll @@ -21,14 +21,14 @@ } ; CHECK-LABEL: fadd -; CHECK: add.f32 +; CHECK: add.rn.f32 define float @fadd(float %a, float %b) { %t1 = fadd float %a, %b ret float %t1 } ; CHECK-LABEL: fadd_ftz -; CHECK: add.ftz.f32 +; CHECK: add.rn.ftz.f32 define float @fadd_ftz(float %a, float %b) #1 { %t1 = fadd float %a, %b ret float %t1 Index: llvm/trunk/test/CodeGen/PowerPC/change-no-infs.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/change-no-infs.ll +++ llvm/trunk/test/CodeGen/PowerPC/change-no-infs.ll @@ -0,0 +1,67 @@ +; Check that we can enable/disable NoInfsFPMath and NoNaNsInFPMath via function +; attributes. An attribute on one function should not magically apply to the +; next one. + +; RUN: llc < %s -mtriple=powerpc64-unknown-unknown -mcpu=pwr7 -mattr=-vsx \ +; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=SAFE + +; RUN: llc < %s -mtriple=powerpc64-unknown-unknown -mcpu=pwr7 -mattr=-vsx \ +; RUN: -enable-no-infs-fp-math -enable-no-nans-fp-math \ +; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=UNSAFE + +; The fcmp+select in these functions should be converted to a fsel instruction +; when both NoInfsFPMath and NoNaNsInFPMath are enabled. + +; CHECK-LABEL: default0: +define double @default0(double %a, double %y, double %z) { +entry: +; SAFE-NOT: fsel +; UNSAFE: fsel + %cmp = fcmp ult double %a, 0.000000e+00 + %z.y = select i1 %cmp, double %z, double %y + ret double %z.y +} + +; CHECK-LABEL: unsafe_math_off: +define double @unsafe_math_off(double %a, double %y, double %z) #0 #2 { +entry: +; SAFE-NOT: fsel +; UNSAFE-NOT: fsel + %cmp = fcmp ult double %a, 0.000000e+00 + %z.y = select i1 %cmp, double %z, double %y + ret double %z.y +} + +; CHECK-LABEL: default1: +define double @default1(double %a, double %y, double %z) { +; SAFE-NOT: fsel +; UNSAFE: fsel + %cmp = fcmp ult double %a, 0.000000e+00 + %z.y = select i1 %cmp, double %z, double %y + ret double %z.y +} + +; CHECK-LABEL: unsafe_math_on: +define double @unsafe_math_on(double %a, double %y, double %z) #1 #3 { +entry: +; SAFE-NOT: fsel +; UNSAFE-NOT: fsel + %cmp = fcmp ult double %a, 0.000000e+00 + %z.y = select i1 %cmp, double %z, double %y + ret double %z.y +} + +; CHECK-LABEL: default2: +define double @default2(double %a, double %y, double %z) { +; SAFE-NOT: fsel +; UNSAFE: fsel + %cmp = fcmp ult double %a, 0.000000e+00 + %z.y = select i1 %cmp, double %z, double %y + ret double %z.y +} + +attributes #0 = { "no-infs-fp-math"="false" } +attributes #1 = { "no-nans-fp-math"="false" } + +attributes #2 = { "no-infs-fp-math"="false" } +attributes #3 = { "no-infs-fp-math"="true" } Index: llvm/trunk/test/CodeGen/X86/change-unsafe-fp-math.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/change-unsafe-fp-math.ll +++ llvm/trunk/test/CodeGen/X86/change-unsafe-fp-math.ll @@ -0,0 +1,56 @@ +; Check that we can enable/disable UnsafeFPMath via function attributes. An +; attribute on one function should not magically apply to the next one. + +; RUN: llc < %s -mtriple=x86_64-unknown-unknown \ +; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=SAFE + +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -enable-unsafe-fp-math \ +; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=UNSAFE + +; The div in these functions should be converted to a mul when unsafe-fp-math +; is enabled. + +; CHECK-LABEL: unsafe_fp_math_default0: +define double @unsafe_fp_math_default0(double %x) { +; SAFE: divsd +; UNSAFE: mulsd + %div = fdiv double %x, 2.0 + ret double %div +} + +; CHECK-LABEL: unsafe_fp_math_off: +define double @unsafe_fp_math_off(double %x) #0 { +; SAFE: divsd +; UNSAFE: divsd + %div = fdiv double %x, 2.0 + ret double %div +} + +; CHECK-LABEL: unsafe_fp_math_default1: +define double @unsafe_fp_math_default1(double %x) { +; With unsafe math enabled, can change this div to a mul. +; SAFE: divsd +; UNSAFE: mulsd + %div = fdiv double %x, 2.0 + ret double %div +} + +; CHECK-LABEL: unsafe_fp_math_on: +define double @unsafe_fp_math_on(double %x) #1 { +; SAFE: mulsd +; UNSAFE: mulsd + %div = fdiv double %x, 2.0 + ret double %div +} + +; CHECK-LABEL: unsafe_fp_math_default2: +define double @unsafe_fp_math_default2(double %x) { +; With unsafe math enabled, can change this div to a mul. +; SAFE: divsd +; UNSAFE: mulsd + %div = fdiv double %x, 2.0 + ret double %div +} + +attributes #0 = { "unsafe-fp-math"="false" } +attributes #1 = { "unsafe-fp-math"="true" }