Skip to content

Commit d175476

Browse files
committed
[Driver, CodeGen] add options to enable/disable an FP cast optimization
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
1 parent 9a48598 commit d175476

File tree

8 files changed

+69
-0
lines changed

8 files changed

+69
-0
lines changed

clang/docs/UsersManual.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,16 @@ are listed below.
12551255
flushed-to-zero number is preserved in the sign of 0, denormals are
12561256
flushed to positive zero, respectively.
12571257

1258+
.. option:: -f[no-]fp-cast-overflow-workaround
1259+
1260+
Enable a workaround for code that casts floating-point values to
1261+
integers and back to floating-point. If the floating-point value
1262+
is not representable in the intermediate integer type, the code is
1263+
incorrect according to the language standard. This flag will attempt
1264+
to generate code as if the result of an overflowing conversion matches
1265+
the overflowing behavior of a target's native float-to-int conversion
1266+
instructions.
1267+
12581268
.. option:: -fwhole-program-vtables
12591269

12601270
Enable whole-program vtable optimizations, such as single-implementation

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,11 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
10291029
Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
10301030
" | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">;
10311031

1032+
def ffp_cast_overflow_workaround : Flag<["-"],
1033+
"ffp-cast-overflow-workaround">, Group<f_Group>, Flags<[CC1Option]>;
1034+
def fno_fp_cast_overflow_workaround : Flag<["-"],
1035+
"fno-fp-cast-overflow-workaround">, Group<f_Group>, Flags<[CC1Option]>;
1036+
10321037
def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
10331038
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
10341039

clang/include/clang/Frontend/CodeGenOptions.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled
136136
CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN.
137137
CODEGENOPT(FlushDenorm , 1, 0) ///< Allow FP denorm numbers to be flushed to zero
138138
CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
139+
140+
/// Disable a float-to-int-to-float cast optimization. This attempts to generate
141+
/// code as if the result of an overflowing conversion matches the overflowing
142+
/// behavior of a target's native float-to-int conversion instructions.
143+
CODEGENOPT(FPCastOverflowWorkaround, 1, 0)
144+
139145
CODEGENOPT(UniformWGSize , 1, 0) ///< -cl-uniform-work-group-size
140146
CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
141147
/// \brief Method of Objective-C dispatch to use.

clang/lib/CodeGen/CGCall.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,9 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
17271727
FuncAttrs.addAttribute("no-trapping-math",
17281728
llvm::toStringRef(CodeGenOpts.NoTrappingMath));
17291729

1730+
if (CodeGenOpts.FPCastOverflowWorkaround)
1731+
FuncAttrs.addAttribute("fp-cast-overflow-workaround", "true");
1732+
17301733
// TODO: Are these all needed?
17311734
// unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
17321735
FuncAttrs.addAttribute("no-infs-fp-math",

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,6 +2241,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
22412241
CmdArgs.push_back("-mfpmath");
22422242
CmdArgs.push_back(A->getValue());
22432243
}
2244+
2245+
// Disable a codegen optimization for floating-point casts.
2246+
if (Args.hasFlag(options::OPT_ffp_cast_overflow_workaround,
2247+
options::OPT_fno_fp_cast_overflow_workaround, false))
2248+
CmdArgs.push_back("-ffp-cast-overflow-workaround");
22442249
}
22452250

22462251
static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
699699
Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
700700
Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
701701
Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math);
702+
Opts.FPCastOverflowWorkaround = Args.hasArg(OPT_ffp_cast_overflow_workaround);
703+
702704
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
703705
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
704706
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);

clang/test/CodeGen/no-junk-ftrunc.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -S -ffp-cast-overflow-workaround %s -emit-llvm -o - | FileCheck %s
2+
// CHECK-LABEL: main
3+
// CHECK: attributes #0 = {{.*}}"fp-cast-overflow-workaround"="true"{{.*}}
4+
5+
// The workaround attribute is not applied by default.
6+
7+
// RUN: %clang_cc1 -S %s -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT
8+
// DEFAULT-LABEL: main
9+
// DEFAULT-NOT: fp-cast-overflow-workaround
10+
11+
int main() {
12+
return 0;
13+
}
14+

clang/test/Driver/fast-math.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,27 @@
287287
// RUN: %clang -### -ftrapping-math -fno-trapping-math -c %s 2>&1 \
288288
// RUN: | FileCheck --check-prefix=CHECK-NO-TRAPPING-MATH %s
289289
// CHECK-NO-TRAPPING-MATH: "-fno-trapping-math"
290+
291+
// This isn't fast-math, but the option is handled in the same place as other FP params.
292+
// Last option wins, and the flag is *not* passed by default.
293+
294+
// RUN: %clang -### -ffp-cast-overflow-workaround -c %s 2>&1 \
295+
// RUN: | FileCheck --check-prefix=CHECK-FPOV-WORKAROUND %s
296+
// CHECK-FPOV-WORKAROUND: "-cc1"
297+
// CHECK-FPOV-WORKAROUND: "-ffp-cast-overflow-workaround"
298+
299+
// RUN: %clang -### -c %s 2>&1 \
300+
// RUN: | FileCheck --check-prefix=CHECK-FPOV-WORKAROUND-DEFAULT %s
301+
// CHECK-FPOV-WORKAROUND-DEFAULT: "-cc1"
302+
// CHECK-FPOV-WORKAROUND-DEFAULT-NOT: "-ffp-cast-overflow-workaround"
303+
304+
// RUN: %clang -### -fno-fp-cast-overflow-workaround -c %s 2>&1 \
305+
// RUN: | FileCheck --check-prefix=CHECK-NO-FPOV-WORKAROUND %s
306+
// CHECK-NO-FPOV-WORKAROUND: "-cc1"
307+
// CHECK-NO-FPOV-WORKAROUND-NOT: "-ffp-cast-overflow-workaround"
308+
309+
// RUN: %clang -### -ffp-cast-overflow-workaround -fno-fp-cast-overflow-workaround -c %s 2>&1 \
310+
// RUN: | FileCheck --check-prefix=CHECK-NO-FPOV-WORKAROUND-OVERRIDE %s
311+
// CHECK-NO-FPOV-WORKAROUND-OVERRIDE: "-cc1"
312+
// CHECK-NO-FPOV-WORKAROUND-OVERRIDE-NOT: "-ffp-cast-overflow-workaround"
313+

0 commit comments

Comments
 (0)