From cb8c009801c927c4f6401d76bac45370c936d778 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sat, 16 Dec 2017 16:11:17 +0000 Subject: [PATCH] [Driver, CodeGen] pass through and apply -fassociative-math 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 -fno-signed-zeros -fno-trapping-math. This was mostly already done - we just need to translate the flag as a codegen option. The test file is complicated because there are many potential combinations of flags here. Note that we are matching gcc's behavior that requires 'nsz' and no-trapping-math. 2. In codegen, we map the codegen 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 -fno-signed-zeros -fno-trapping-math -emit-llvm | grep fadd %add = fadd reassoc float %0, %1 $ ./clang -O2 27372.c -S -o - -fassociative-math -fno-signed-zeros -fno-trapping-math | grep xmm addss %xmm1, %xmm0 subss %xmm1, %xmm0 Differential Revision: https://reviews.llvm.org/D39812 llvm-svn: 320920 --- clang/include/clang/Driver/CC1Options.td | 2 + clang/include/clang/Frontend/CodeGenOptions.def | 1 + clang/lib/CodeGen/CodeGenFunction.cpp | 3 ++ clang/lib/Driver/ToolChains/Clang.cpp | 3 ++ clang/lib/Frontend/CompilerInvocation.cpp | 1 + clang/test/CodeGen/finite-math.c | 2 + clang/test/Driver/fast-math.c | 63 ++++++++++++++++++++----- 7 files changed, 62 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 026f016..7dea88b 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -263,6 +263,8 @@ def menable_no_nans : Flag<["-"], "menable-no-nans">, def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, HelpText<"Allow unsafe floating-point math optimizations which may decrease " "precision">; +def mreassociate : Flag<["-"], "mreassociate">, + HelpText<"Allow reassociation transformations for floating-point instructions">; def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; def mtp : Separate<["-"], "mtp">, diff --git a/clang/include/clang/Frontend/CodeGenOptions.def b/clang/include/clang/Frontend/CodeGenOptions.def index 9dbdaea0..bb91cf5 100644 --- a/clang/include/clang/Frontend/CodeGenOptions.def +++ b/clang/include/clang/Frontend/CodeGenOptions.def @@ -117,6 +117,7 @@ CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled. 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(Reassociate , 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. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index f9155b2..9dbd7cc 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -103,6 +103,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) if (CGM.getCodeGenOpts().ReciprocalMath) { FMF.setAllowReciprocal(); } + if (CGM.getCodeGenOpts().Reassociate) { + FMF.setAllowReassoc(); + } Builder.setFastMathFlags(FMF); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 706ac5b..0a89ff9 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2170,6 +2170,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, if (!SignedZeros) CmdArgs.push_back("-fno-signed-zeros"); + if (AssociativeMath && !SignedZeros && !TrappingMath) + CmdArgs.push_back("-mreassociate"); + if (ReciprocalMath) CmdArgs.push_back("-freciprocal-math"); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 9fabcdf..2e8a737 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -639,6 +639,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_cl_no_signed_zeros) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math)); + Opts.Reassociate = Args.hasArg(OPT_mreassociate); Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero); Opts.CorrectlyRoundedDivSqrt = Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); diff --git a/clang/test/CodeGen/finite-math.c b/clang/test/CodeGen/finite-math.c index 90a83fa..d1a2956 100644 --- a/clang/test/CodeGen/finite-math.c +++ b/clang/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 -mreassociate -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=REASSOC float f0, f1, f2; @@ -10,6 +11,7 @@ void foo(void) { // FINITE: fadd nnan ninf // NSZ: fadd nsz // RECIP: fadd arcp + // REASSOC: fadd reassoc f0 = f1 + f2; // CHECK: ret diff --git a/clang/test/Driver/fast-math.c b/clang/test/Driver/fast-math.c index 5094a5b..7bb057f 100644 --- a/clang/test/Driver/fast-math.c +++ b/clang/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: "-mreassociate" // // 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: "-mreassociate" + +// 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: "-mreassociate" // // 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: "-mreassociate" // // 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,43 @@ // 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: "-mreassociate" // CHECK-NO-UNSAFE-MATH: "-o" -// + + +// Reassociate is allowed because it does not require reciprocal-math. + +// 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-REASSOC-NO-UNSAFE-MATH %s + +// CHECK-REASSOC-NO-UNSAFE-MATH: "-cc1" +// CHECK-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-REASSOC-NO_UNSAFE-MATH: "-mreassociate" +// CHECK-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-REASSOC-NO-UNSAFE-MATH: "-o" + + +// In these runs, reassociate is not allowed because both no-signed-zeros and no-trapping-math are required. + +// 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-REASSOC-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-REASSOC-NO-UNSAFE-MATH %s + +// CHECK-NO-REASSOC-NO-UNSAFE-MATH: "-cc1" +// CHECK-NO-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-NO-REASSOC-NO_UNSAFE-MATH-NOT: "-mreassociate" +// CHECK-NO-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-NO-REASSOC-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" -- 2.7.4