Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -956,7 +956,7 @@ Group; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, Group; -def fassociative_math : Flag<["-"], "fassociative-math">, Group; +def fassociative_math : Flag<["-"], "fassociative-math">, Group, Flags<[CC1Option]>; def fno_associative_math : Flag<["-"], "fno-associative-math">, Group; def freciprocal_math : Flag<["-"], "freciprocal-math">, Group, Flags<[CC1Option]>, Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -110,6 +110,7 @@ CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero +CODEGENOPT(AssociativeMath , 1, 0) ///< Allow reassociation of FP math ops CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated. CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled. CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -101,6 +101,9 @@ if (CGM.getCodeGenOpts().ReciprocalMath) { FMF.setAllowReciprocal(); } + if (CGM.getCodeGenOpts().AssociativeMath) { + FMF.setAllowReassoc(); + } Builder.setFastMathFlags(FMF); } Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -2156,6 +2156,9 @@ if (!SignedZeros) CmdArgs.push_back("-fno-signed-zeros"); + if (AssociativeMath) + CmdArgs.push_back("-fassociative-math"); + if (ReciprocalMath) CmdArgs.push_back("-freciprocal-math"); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -637,6 +637,7 @@ Args.hasArg(OPT_cl_no_signed_zeros) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math)); + Opts.AssociativeMath = Args.hasArg(OPT_fassociative_math); Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero); Opts.CorrectlyRoundedDivSqrt = Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); Index: test/CodeGen/finite-math.c =================================================================== --- test/CodeGen/finite-math.c +++ test/CodeGen/finite-math.c @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -ffinite-math-only -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=FINITE // RUN: %clang_cc1 -fno-signed-zeros -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=NSZ // RUN: %clang_cc1 -freciprocal-math -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=RECIP +// RUN: %clang_cc1 -fassociative-math -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=ASSOC float f0, f1, f2; @@ -10,6 +11,7 @@ // FINITE: fadd nnan ninf // NSZ: fadd nsz // RECIP: fadd arcp + // ASSOC: fadd reassoc f0 = f1 + f2; // CHECK: ret Index: test/Driver/fast-math.c =================================================================== --- test/Driver/fast-math.c +++ test/Driver/fast-math.c @@ -121,18 +121,23 @@ // RUN: | FileCheck --check-prefix=CHECK-UNSAFE-MATH %s // CHECK-UNSAFE-MATH: "-cc1" // CHECK-UNSAFE-MATH: "-menable-unsafe-fp-math" +// CHECK-UNSAFE-MATH: "-fassociative-math" // // RUN: %clang -### -fno-fast-math -fno-math-errno -fassociative-math -freciprocal-math \ // RUN: -fno-signed-zeros -fno-trapping-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH-UNSAFE-MATH %s // CHECK-NO-FAST-MATH-UNSAFE-MATH: "-cc1" // CHECK-NO-FAST-MATH-UNSAFE-MATH: "-menable-unsafe-fp-math" -// +// CHECK-NO-FAST-MATH-UNSAFE-MATH: "-fassociative-math" + +// The 2nd -fno-fast-math overrides -fassociative-math. + // RUN: %clang -### -fno-fast-math -fno-math-errno -fassociative-math -freciprocal-math \ // RUN: -fno-fast-math -fno-signed-zeros -fno-trapping-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-UNSAFE-MATH-NO-FAST-MATH %s // CHECK-UNSAFE-MATH-NO-FAST-MATH: "-cc1" // CHECK-UNSAFE-MATH-NO-FAST-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-UNSAFE-MATH-NO-FAST-MATH-NOT: "-fassociative-math" // // Check that various umbrella flags also enable these frontend options. // RUN: %clang -### -ffast-math -c %s 2>&1 \ @@ -151,7 +156,7 @@ // One umbrella flag is *really* weird and also changes the semantics of the // program by adding a special preprocessor macro. Check that the frontend flag // modeling this semantic change is provided. Also check that the flag is not -// present if any of the optimization is disabled. +// present if any of the optimizations are disabled. // RUN: %clang -### -ffast-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-FAST-MATH %s // RUN: %clang -### -fno-fast-math -ffast-math -c %s 2>&1 \ @@ -175,8 +180,11 @@ // RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH %s // RUN: %clang -### -ffast-math -fmath-errno -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH %s +// RUN: %clang -### -ffast-math -fno-associative-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH --check-prefix=CHECK-ASSOC-MATH %s // CHECK-NO-FAST-MATH: "-cc1" // CHECK-NO-FAST-MATH-NOT: "-ffast-math" +// CHECK-ASSOC-MATH-NOT: "-fassociative-math" // // Check various means of disabling these flags, including disabling them after // they've been enabled via an umbrella flag. @@ -209,21 +217,16 @@ // CHECK-NO-NO-NANS-NOT: "-menable-no-nans" // CHECK-NO-NO-NANS-NOT: "-ffinite-math-only" // CHECK-NO-NO-NANS: "-o" -// + +// A later inverted option overrides an earlier option. + // RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ // RUN: -fno-trapping-math -fno-associative-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s -// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ -// RUN: -fno-trapping-math -fno-reciprocal-math -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s -// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ -// RUN: -fno-trapping-math -fsigned-zeros -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s -// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ -// RUN: -fno-trapping-math -ftrapping-math -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s + // RUN: %clang -### -funsafe-math-optimizations -fno-associative-math -c %s \ // RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s + // RUN: %clang -### -funsafe-math-optimizations -fno-reciprocal-math -c %s \ // RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s // RUN: %clang -### -funsafe-math-optimizations -fsigned-zeros -c %s 2>&1 \ @@ -235,6 +238,7 @@ // RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s // RUN: %clang -### -ffast-math -fno-associative-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s + // RUN: %clang -### -ffast-math -fno-reciprocal-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s // RUN: %clang -### -ffast-math -fsigned-zeros -c %s 2>&1 \ @@ -243,10 +247,32 @@ // RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s // RUN: %clang -### -ffast-math -fno-unsafe-math-optimizations -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s + // CHECK-NO-UNSAFE-MATH: "-cc1" // CHECK-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-NO_UNSAFE-MATH-NOT: "-fassociative-math" // CHECK-NO-UNSAFE-MATH: "-o" -// + +// In these runs, associative math is allowed even though the unsafe umbrella option is not deployed. + +// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -fno-reciprocal-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ASSOC-NO-UNSAFE-MATH %s + +// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -fsigned-zeros -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ASSOC-NO-UNSAFE-MATH %s + +// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -ftrapping-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ASSOC-NO-UNSAFE-MATH %s + +// CHECK-ASSOC-NO-UNSAFE-MATH: "-cc1" +// CHECK-ASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-ASSOC-NO_UNSAFE-MATH: "-fassociative-math" +// CHECK-ASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-ASSOC-NO-UNSAFE-MATH: "-o" + // RUN: %clang -### -ftrapping-math -fno-trapping-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-TRAPPING-MATH %s // CHECK-NO-TRAPPING-MATH: "-fno-trapping-math"