Skip to content

Commit

Permalink
[Driver, CodeGen] add options to enable/disable an FP cast optimization
Browse files Browse the repository at this point in the history
As discussed in the post-commit thread for:
rL330437 ( http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20180423/545906.html )

We need a way to opt-out of a float-to-int-to-float cast optimization because too much 
existing code relies on the platform-specific undefined result of those casts when the 
float-to-int overflows.

The LLVM changes associated with adding this function attribute are here:
rL330947
rL330950
rL330951

Also as suggested, I changed the LLVM doc to mention the specific sanitizer flag that 
catches this problem:
rL330958

Differential Revision: https://reviews.llvm.org/D46135

llvm-svn: 331041
  • Loading branch information
rotateright committed Apr 27, 2018
1 parent 9a48598 commit d175476
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 0 deletions.
10 changes: 10 additions & 0 deletions clang/docs/UsersManual.rst
Expand Up @@ -1255,6 +1255,16 @@ are listed below.
flushed-to-zero number is preserved in the sign of 0, denormals are
flushed to positive zero, respectively.

.. option:: -f[no-]fp-cast-overflow-workaround

Enable a workaround for code that casts floating-point values to
integers and back to floating-point. If the floating-point value
is not representable in the intermediate integer type, the code is
incorrect according to the language standard. This flag will attempt
to generate code as if the result of an overflowing conversion matches
the overflowing behavior of a target's native float-to-int conversion
instructions.

.. option:: -fwhole-program-vtables

Enable whole-program vtable optimizations, such as single-implementation
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -1029,6 +1029,11 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
" | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">;

def ffp_cast_overflow_workaround : Flag<["-"],
"ffp-cast-overflow-workaround">, Group<f_Group>, Flags<[CC1Option]>;
def fno_fp_cast_overflow_workaround : Flag<["-"],
"fno-fp-cast-overflow-workaround">, Group<f_Group>, Flags<[CC1Option]>;

def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;

Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Frontend/CodeGenOptions.def
Expand Up @@ -136,6 +136,12 @@ CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled
CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN.
CODEGENOPT(FlushDenorm , 1, 0) ///< Allow FP denorm numbers to be flushed to zero
CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt

/// Disable a float-to-int-to-float cast optimization. This attempts to generate
/// code as if the result of an overflowing conversion matches the overflowing
/// behavior of a target's native float-to-int conversion instructions.
CODEGENOPT(FPCastOverflowWorkaround, 1, 0)

CODEGENOPT(UniformWGSize , 1, 0) ///< -cl-uniform-work-group-size
CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
/// \brief Method of Objective-C dispatch to use.
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Expand Up @@ -1727,6 +1727,9 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
FuncAttrs.addAttribute("no-trapping-math",
llvm::toStringRef(CodeGenOpts.NoTrappingMath));

if (CodeGenOpts.FPCastOverflowWorkaround)
FuncAttrs.addAttribute("fp-cast-overflow-workaround", "true");

// TODO: Are these all needed?
// unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
FuncAttrs.addAttribute("no-infs-fp-math",
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -2241,6 +2241,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-mfpmath");
CmdArgs.push_back(A->getValue());
}

// Disable a codegen optimization for floating-point casts.
if (Args.hasFlag(options::OPT_ffp_cast_overflow_workaround,
options::OPT_fno_fp_cast_overflow_workaround, false))
CmdArgs.push_back("-ffp-cast-overflow-workaround");
}

static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -699,6 +699,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math);
Opts.FPCastOverflowWorkaround = Args.hasArg(OPT_ffp_cast_overflow_workaround);

Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CodeGen/no-junk-ftrunc.c
@@ -0,0 +1,14 @@
// RUN: %clang_cc1 -S -ffp-cast-overflow-workaround %s -emit-llvm -o - | FileCheck %s
// CHECK-LABEL: main
// CHECK: attributes #0 = {{.*}}"fp-cast-overflow-workaround"="true"{{.*}}

// The workaround attribute is not applied by default.

// RUN: %clang_cc1 -S %s -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT
// DEFAULT-LABEL: main
// DEFAULT-NOT: fp-cast-overflow-workaround

int main() {
return 0;
}

24 changes: 24 additions & 0 deletions clang/test/Driver/fast-math.c
Expand Up @@ -287,3 +287,27 @@
// 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"

// This isn't fast-math, but the option is handled in the same place as other FP params.
// Last option wins, and the flag is *not* passed by default.

// RUN: %clang -### -ffp-cast-overflow-workaround -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPOV-WORKAROUND %s
// CHECK-FPOV-WORKAROUND: "-cc1"
// CHECK-FPOV-WORKAROUND: "-ffp-cast-overflow-workaround"

// RUN: %clang -### -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPOV-WORKAROUND-DEFAULT %s
// CHECK-FPOV-WORKAROUND-DEFAULT: "-cc1"
// CHECK-FPOV-WORKAROUND-DEFAULT-NOT: "-ffp-cast-overflow-workaround"

// RUN: %clang -### -fno-fp-cast-overflow-workaround -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-FPOV-WORKAROUND %s
// CHECK-NO-FPOV-WORKAROUND: "-cc1"
// CHECK-NO-FPOV-WORKAROUND-NOT: "-ffp-cast-overflow-workaround"

// RUN: %clang -### -ffp-cast-overflow-workaround -fno-fp-cast-overflow-workaround -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-FPOV-WORKAROUND-OVERRIDE %s
// CHECK-NO-FPOV-WORKAROUND-OVERRIDE: "-cc1"
// CHECK-NO-FPOV-WORKAROUND-OVERRIDE-NOT: "-ffp-cast-overflow-workaround"

0 comments on commit d175476

Please sign in to comment.