spatel created this revision. Herald added a subscriber: mcrosier. There are 2 parts to getting the -fassociative-math command-line flag translated to LLVM FMF:
1. In the driver/frontend, we accept the flag and its 'no' inverse and deal with the interactions with other flags like -ffast-math. This was mostly already done - we just needed to pass the flag on as a codegen option. The test file is complicated because there are many potential combinations of flags here. 2. In codegen, we map the option to FMF in the IR builder. This is simple code and corresponding test. For the motivating example from PR27372: float foo(float a, float x) { return ((a + x) - x); } $ ./clang -O2 27372.c -S -o - -ffast-math -fno-associative-math -emit-llvm | egrep 'fadd|fsub' %add = fadd nnan ninf nsz arcp contract float %0, %1 %sub = fsub nnan ninf nsz arcp contract float %add, %2 So 'reassoc' is off as expected (and so is the new 'afn' but that's a different patch). This case now works as expected end-to-end although the underlying logic is still wrong: $ ./clang -O2 27372.c -S -o - -ffast-math -fno-associative-math | grep xmm addss %xmm1, %xmm0 subss %xmm1, %xmm0 We're not done because the case where 'reassoc' is set is ignored by optimizer passes. Example: $ ./clang -O2 27372.c -S -o - -fassociative-math -emit-llvm | grep fadd %add = fadd reassoc float %0, %1 $ ./clang -O2 27372.c -S -o - -fassociative-math | grep xmm addss %xmm1, %xmm0 subss %xmm1, %xmm0 https://reviews.llvm.org/D39812 Files: include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def lib/CodeGen/CodeGenFunction.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGen/finite-math.c test/Driver/fast-math.c
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,18 +238,41 @@ // 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 \ // RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s // RUN: %clang -### -ffast-math -ftrapping-math -c %s 2>&1 \ // 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" 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: 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: 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/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: 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: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -956,7 +956,7 @@ Group<f_Group>; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, Group<f_Group>; -def fassociative_math : Flag<["-"], "fassociative-math">, Group<f_Group>; +def fassociative_math : Flag<["-"], "fassociative-math">, Group<f_Group>, Flags<[CC1Option]>; def fno_associative_math : Flag<["-"], "fno-associative-math">, Group<f_Group>; def freciprocal_math : Flag<["-"], "freciprocal-math">, Group<f_Group>, Flags<[CC1Option]>,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits