New Compiler Flags
------------------
-- :option:`-ffp-cast-overflow-workaround` and
- :option:`-fno-fp-cast-overflow-workaround`
- enable (disable) 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:`-fstrict-float-cast-overflow` and
+ :option:`-fno-strict-float-cast-overflow` -
+ When a floating-point value is not representable in a destination integer
+ type, the code has undefined behavior according to the language standard.
+ By default, Clang will not guarantee any particular result in that case.
+ With the 'no-strict' option, Clang attempts to match the overflowing behavior
+ of the target's native float-to-int conversion instructions.
- ...
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:: -f[no-]strict-float-cast-overflow
+
+ When a floating-point value is not representable in a destination integer
+ type, the code has undefined behavior according to the language standard.
+ By default, Clang will not guarantee any particular result in that case.
+ With the 'no-strict' option, Clang attempts to match the overflowing behavior
+ of the target's native float-to-int conversion instructions.
.. option:: -fwhole-program-vtables
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 fstrict_float_cast_overflow : Flag<["-"],
+ "fstrict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Assume that overflowing float-to-int casts are undefined (default)">;
+def fno_strict_float_cast_overflow : Flag<["-"],
+ "fno-strict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Relax language rules and try to match the behavior of the target's native float-to-int conversion instructions">;
def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
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)
+/// When false, 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(StrictFloatCastOverflow, 1, 1)
CODEGENOPT(UniformWGSize , 1, 0) ///< -cl-uniform-work-group-size
CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
FuncAttrs.addAttribute("no-trapping-math",
llvm::toStringRef(CodeGenOpts.NoTrappingMath));
- if (CodeGenOpts.FPCastOverflowWorkaround)
- FuncAttrs.addAttribute("fp-cast-overflow-workaround", "true");
+ // Strict (compliant) code is the default, so only add this attribute to
+ // indicate that we are trying to workaround a problem case.
+ if (!CodeGenOpts.StrictFloatCastOverflow)
+ FuncAttrs.addAttribute("strict-float-cast-overflow", "false");
// TODO: Are these all needed?
// unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
}
// 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");
+ if (Args.hasFlag(options::OPT_fno_strict_float_cast_overflow,
+ options::OPT_fstrict_float_cast_overflow, false))
+ CmdArgs.push_back("-fno-strict-float-cast-overflow");
}
static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
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.StrictFloatCastOverflow =
+ !Args.hasArg(OPT_fno_strict_float_cast_overflow);
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
-// 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"{{.*}}
+// RUN: %clang_cc1 -S -fno-strict-float-cast-overflow %s -emit-llvm -o - | FileCheck %s --check-prefix=NOSTRICT
+// NOSTRICT-LABEL: main
+// NOSTRICT: attributes #0 = {{.*}}"strict-float-cast-overflow"="false"{{.*}}
// The workaround attribute is not applied by default.
+// RUN: %clang_cc1 -S %s -fstrict-float-cast-overflow -emit-llvm -o - | FileCheck %s --check-prefix=STRICT
+// STRICT-LABEL: main
+// STRICT-NOT: strict-float-cast-overflow
+
// RUN: %clang_cc1 -S %s -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT
// DEFAULT-LABEL: main
-// DEFAULT-NOT: fp-cast-overflow-workaround
+// DEFAULT-NOT: strict-float-cast-overflow
int main() {
return 0;
// 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.
+// Last option wins, and strict behavior is assumed by default.
-// RUN: %clang -### -ffp-cast-overflow-workaround -c %s 2>&1 \
+// RUN: %clang -### -fno-strict-float-cast-overflow -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPOV-WORKAROUND %s
// CHECK-FPOV-WORKAROUND: "-cc1"
-// CHECK-FPOV-WORKAROUND: "-ffp-cast-overflow-workaround"
+// CHECK-FPOV-WORKAROUND: "-fno-strict-float-cast-overflow"
// 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"
+// CHECK-FPOV-WORKAROUND-DEFAULT-NOT: "strict-float-cast-overflow"
-// RUN: %clang -### -fno-fp-cast-overflow-workaround -c %s 2>&1 \
+// RUN: %clang -### -fstrict-float-cast-overflow -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"
+// CHECK-NO-FPOV-WORKAROUND-NOT: "strict-float-cast-overflow"
-// RUN: %clang -### -ffp-cast-overflow-workaround -fno-fp-cast-overflow-workaround -c %s 2>&1 \
+// RUN: %clang -### -fno-strict-float-cast-overflow -fstrict-float-cast-overflow -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"
+// CHECK-NO-FPOV-WORKAROUND-OVERRIDE-NOT: "strict-float-cast-overflow"