+2016-06-03 Joseph Myers <joseph@codesourcery.com>
+
+ PR target/71276
+ PR target/71277
+ * common.opt (ffp-int-builtin-inexact): New option.
+ * doc/invoke.texi (-fno-fp-int-builtin-inexact): Document.
+ * doc/md.texi (floor@var{m}2, btrunc@var{m}2, round@var{m}2)
+ (ceil@var{m}2): Document dependence on this option.
+ * ipa-inline-transform.c (inline_call): Handle
+ flag_fp_int_builtin_inexact.
+ * ipa-inline.c (can_inline_edge_p): Likewise.
+ * config/i386/i386.md (rintxf2): Do not test
+ flag_unsafe_math_optimizations.
+ (rint<mode>2_frndint): New define_insn.
+ (rint<mode>2): Do not test flag_unsafe_math_optimizations for 387
+ or !flag_trapping_math for SSE. Just use gen_rint<mode>2_frndint
+ for 387 instead of extending and truncating.
+ (frndintxf2_<rounding>): Test flag_fp_int_builtin_inexact ||
+ !flag_trapping_math instead of flag_unsafe_math_optimizations.
+ Change to frndint<mode>2_<rounding>.
+ (frndintxf2_<rounding>_i387): Likewise. Change to
+ frndint<mode>2_<rounding>_i387.
+ (<rounding_insn>xf2): Likewise.
+ (<rounding_insn><mode>2): Test flag_fp_int_builtin_inexact ||
+ !flag_trapping_math instead of flag_unsafe_math_optimizations for
+ x87. Test TARGET_ROUND || !flag_trapping_math ||
+ flag_fp_int_builtin_inexact instead of !flag_trapping_math for
+ SSE. Use ROUND_NO_EXC in constant operand of
+ gen_sse4_1_round<mode>2. Just use gen_frndint<mode>2_<rounding>
+ for 387 instead of extending and truncating.
+
2016-06-03 H.J. Lu <hongjiu.lu@intel.com>
Julia Koval <julia.koval@intel.com>
EnumValue
Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST)
+ffp-int-builtin-inexact
+Common Report Var(flag_fp_int_builtin_inexact) Init(1) Optimization
+Allow built-in functions ceil, floor, round, trunc to raise \"inexact\" exceptions.
+
; Nonzero means don't put addresses of constant functions in registers.
; Used for compiling the Unix kernel, where strange substitutions are
; done on the assembly output.
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
UNSPEC_FRNDINT))]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
+ "TARGET_USE_FANCY_MATH_387"
"frndint"
[(set_attr "type" "fpspc")
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
+(define_insn "rint<mode>2_frndint"
+ [(set (match_operand:MODEF 0 "register_operand" "=f")
+ (unspec:MODEF [(match_operand:MODEF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT))]
+ "TARGET_USE_FANCY_MATH_387"
+ "frndint"
+ [(set_attr "type" "fpspc")
+ (set_attr "znver1_decode" "vector")
+ (set_attr "mode" "<MODE>")])
+
(define_expand "rint<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
(use (match_operand:MODEF 1 "register_operand"))]
"(TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations)
- || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && !flag_trapping_math)"
+ || TARGET_MIX_SSE_I387))
+ || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
{
- if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && !flag_trapping_math)
+ if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
{
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
ix86_expand_rint (operands[0], operands[1]);
}
else
- {
- rtx op0 = gen_reg_rtx (XFmode);
- rtx op1 = gen_reg_rtx (XFmode);
-
- emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
- emit_insn (gen_rintxf2 (op0, op1));
-
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
- }
+ emit_insn (gen_rint<mode>2_frndint (operands[0], operands[1]));
DONE;
})
(UNSPEC_FIST_CEIL "CEIL")])
;; Rounding mode control word calculation could clobber FLAGS_REG.
-(define_insn_and_split "frndintxf2_<rounding>"
- [(set (match_operand:XF 0 "register_operand")
- (unspec:XF [(match_operand:XF 1 "register_operand")]
+(define_insn_and_split "frndint<mode>2_<rounding>"
+ [(set (match_operand:X87MODEF 0 "register_operand")
+ (unspec:X87MODEF [(match_operand:X87MODEF 1 "register_operand")]
FRNDINT_ROUNDING))
(clobber (reg:CC FLAGS_REG))]
"TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations
+ && (flag_fp_int_builtin_inexact || !flag_trapping_math)
&& can_create_pseudo_p ()"
"#"
"&& 1"
operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
operands[3] = assign_386_stack_local (HImode, SLOT_CW_<ROUNDING>);
- emit_insn (gen_frndintxf2_<rounding>_i387 (operands[0], operands[1],
- operands[2], operands[3]));
+ emit_insn (gen_frndint<mode>2_<rounding>_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}
[(set_attr "type" "frndint")
(set_attr "i387_cw" "<rounding>")
- (set_attr "mode" "XF")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "frndintxf2_<rounding>_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
- FRNDINT_ROUNDING))
+(define_insn "frndint<mode>2_<rounding>_i387"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f")
+ (unspec:X87MODEF [(match_operand:X87MODEF 1 "register_operand" "0")]
+ FRNDINT_ROUNDING))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))]
"TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
+ && (flag_fp_int_builtin_inexact || !flag_trapping_math)"
"fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
[(set_attr "type" "frndint")
(set_attr "i387_cw" "<rounding>")
- (set_attr "mode" "XF")])
+ (set_attr "mode" "<MODE>")])
(define_expand "<rounding_insn>xf2"
[(parallel [(set (match_operand:XF 0 "register_operand")
FRNDINT_ROUNDING))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations")
+ && (flag_fp_int_builtin_inexact || !flag_trapping_math)")
(define_expand "<rounding_insn><mode>2"
[(parallel [(set (match_operand:MODEF 0 "register_operand")
"(TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations)
+ && (flag_fp_int_builtin_inexact || !flag_trapping_math))
|| (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && !flag_trapping_math)"
+ && (TARGET_ROUND || !flag_trapping_math || flag_fp_int_builtin_inexact))"
{
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && !flag_trapping_math)
+ && (TARGET_ROUND || !flag_trapping_math || flag_fp_int_builtin_inexact))
{
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
- (operands[0], operands[1], GEN_INT (ROUND_<ROUNDING>)));
+ (operands[0], operands[1], GEN_INT (ROUND_<ROUNDING>
+ | ROUND_NO_EXC)));
else if (TARGET_64BIT || (<MODE>mode != DFmode))
{
if (ROUND_<ROUNDING> == ROUND_FLOOR)
}
}
else
- {
- rtx op0, op1;
-
- op0 = gen_reg_rtx (XFmode);
- op1 = gen_reg_rtx (XFmode);
- emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
- emit_insn (gen_frndintxf2_<rounding> (op0, op1));
-
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
- }
+ emit_insn (gen_frndint<mode>2_<rounding> (operands[0], operands[1]));
DONE;
})
-flto-partition=@var{alg} -fmerge-all-constants @gol
-fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
-fmove-loop-invariants -fno-branch-count-reg @gol
--fno-defer-pop -fno-function-cse -fno-guess-branch-probability @gol
--fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
--fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
+-fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol
+-fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol
+-fno-peephole2 -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
-fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
-fomit-frame-pointer -foptimize-sibling-calls @gol
-fpartial-inlining -fpeel-loops -fpredictive-commoning @gol
This option is experimental and does not currently guarantee to
disable all GCC optimizations that affect signaling NaN behavior.
+@item -fno-fp-int-builtin-inexact
+@opindex fno-fp-int-builtin-inexact
+Do not allow the built-in functions @code{ceil}, @code{floor},
+@code{round} and @code{trunc}, and their @code{float} and @code{long
+double} variants, to generate code that raises the ``inexact''
+floating-point exception for noninteger arguments. ISO C99 and C11
+allow these functions to raise the ``inexact'' exception, but ISO/IEC
+TS 18661-1:2014, the C bindings to IEEE 754-2008, does not allow these
+functions to do so.
+
+The default is @option{-ffp-int-builtin-inexact}, allowing the
+exception to be raised. This option does nothing unless
+@option{-ftrapping-math} is in effect.
+
+Even if @option{-fno-fp-int-builtin-inexact} is used, if the functions
+generate a call to a library function then the ``inexact'' exception
+may be raised if the library implementation does not follow TS 18661.
+
@item -fsingle-precision-constant
@opindex fsingle-precision-constant
Treat floating-point constants as single precision instead of
@item @samp{floor@var{m}2}
Store the largest integral value not greater than operand 1 in operand 0.
Both operands have mode @var{m}, which is a scalar or vector
-floating-point mode.
+floating-point mode. If @option{-ffp-int-builtin-inexact} is in
+effect, the ``inexact'' exception may be raised for noninteger
+operands; otherwise, it may not.
This pattern is not allowed to @code{FAIL}.
@item @samp{btrunc@var{m}2}
Round operand 1 to an integer, towards zero, and store the result in
operand 0. Both operands have mode @var{m}, which is a scalar or
-vector floating-point mode.
+vector floating-point mode. If @option{-ffp-int-builtin-inexact} is
+in effect, the ``inexact'' exception may be raised for noninteger
+operands; otherwise, it may not.
This pattern is not allowed to @code{FAIL}.
@item @samp{round@var{m}2}
Round operand 1 to the nearest integer, rounding away from zero in the
event of a tie, and store the result in operand 0. Both operands have
-mode @var{m}, which is a scalar or vector floating-point mode.
+mode @var{m}, which is a scalar or vector floating-point mode. If
+@option{-ffp-int-builtin-inexact} is in effect, the ``inexact''
+exception may be raised for noninteger operands; otherwise, it may
+not.
This pattern is not allowed to @code{FAIL}.
@item @samp{ceil@var{m}2}
Store the smallest integral value not less than operand 1 in operand 0.
Both operands have mode @var{m}, which is a scalar or vector
-floating-point mode.
+floating-point mode. If @option{-ffp-int-builtin-inexact} is in
+effect, the ``inexact'' exception may be raised for noninteger
+operands; otherwise, it may not.
This pattern is not allowed to @code{FAIL}.
!= opt_for_fn (to->decl, flag_associative_math)
|| opt_for_fn (callee->decl, flag_reciprocal_math)
!= opt_for_fn (to->decl, flag_reciprocal_math)
+ || opt_for_fn (callee->decl, flag_fp_int_builtin_inexact)
+ != opt_for_fn (to->decl, flag_fp_int_builtin_inexact)
|| opt_for_fn (callee->decl, flag_errno_math)
!= opt_for_fn (to->decl, flag_errno_math))
{
= opt_for_fn (callee->decl, flag_associative_math);
opts.x_flag_reciprocal_math
= opt_for_fn (callee->decl, flag_reciprocal_math);
+ opts.x_flag_fp_int_builtin_inexact
+ = opt_for_fn (callee->decl, flag_fp_int_builtin_inexact);
opts.x_flag_errno_math
= opt_for_fn (callee->decl, flag_errno_math);
if (dump_file)
|| check_maybe_up (flag_signed_zeros)
|| check_maybe_down (flag_associative_math)
|| check_maybe_down (flag_reciprocal_math)
+ || check_maybe_down (flag_fp_int_builtin_inexact)
/* Strictly speaking only when the callee contains function
calls that may end up setting errno. */
|| check_maybe_up (flag_errno_math)))
+2016-06-03 Joseph Myers <joseph@codesourcery.com>
+
+ PR target/71276
+ PR target/71277
+ * gcc.dg/torture/builtin-fp-int-inexact.c,
+ gcc.target/i386/387-builtin-fp-int-inexact.c,
+ gcc.target/i386/387-rint-inline-1.c,
+ gcc.target/i386/387-rint-inline-2.c,
+ gcc.target/i386/sse2-builtin-fp-int-inexact.c,
+ gcc.target/i386/sse2-rint-inline-1.c,
+ gcc.target/i386/sse2-rint-inline-2.c,
+ gcc.target/i386/sse4_1-builtin-fp-int-inexact.c,
+ gcc.target/i386/sse4_1-rint-inline.c: New tests.
+
2016-06-03 H.J. Lu <hongjiu.lu@intel.com>
Julia Koval <julia.koval@intel.com>
--- /dev/null
+/* Test -fno-fp-int-builtin-inexact. */
+/* { dg-do run } */
+/* { dg-options "-fno-fp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+/* Define functions locally to ensure that if the calls are not
+ expanded inline, failures do not occur because of libm raising
+ "inexact". */
+
+#define LOCAL_FN(NAME, TYPE) \
+ __attribute__ ((noinline, noclone)) TYPE \
+ NAME (TYPE x) \
+ { \
+ return x; \
+ }
+
+#define LOCAL_FNS(NAME) \
+ LOCAL_FN (NAME, double) \
+ LOCAL_FN (NAME ## f, float) \
+ LOCAL_FN (NAME ## l, long double)
+
+LOCAL_FNS (ceil)
+LOCAL_FNS (floor)
+LOCAL_FNS (round)
+LOCAL_FNS (trunc)
+
+extern void abort (void);
+extern void exit (int);
+
+#define TEST(FN, TYPE) \
+ do \
+ { \
+ volatile TYPE a = 1.5, b; \
+ b = FN (a); \
+ if (fetestexcept (FE_INEXACT)) \
+ abort (); \
+ } \
+ while (0)
+
+#define FN_TESTS(FN) \
+ do \
+ { \
+ TEST (__builtin_ ## FN, double); \
+ TEST (__builtin_ ## FN ## f, float); \
+ TEST (__builtin_ ## FN ## l, long double); \
+ } \
+ while (0)
+
+static void
+main_test (void)
+{
+ FN_TESTS (ceil);
+ FN_TESTS (floor);
+ FN_TESTS (round);
+ FN_TESTS (trunc);
+}
+
+/* This file may be included by architecture-specific tests. */
+
+#ifndef ARCH_MAIN
+
+int
+main (void)
+{
+ main_test ();
+ exit (0);
+}
+
+#endif
--- /dev/null
+/* Test -fno-fp-int-builtin-inexact for 387. */
+/* { dg-do run } */
+/* { dg-options "-O2 -mfancy-math-387 -mfpmath=387 -fno-fp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include "../../gcc.dg/torture/builtin-fp-int-inexact.c"
--- /dev/null
+/* Test rint and related functions expanded inline for 387. All
+ should be expanded when spurious "inexact" allowed. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfancy-math-387 -mfpmath=387 -ffp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+
+#define TEST(FN, TYPE) \
+ do \
+ { \
+ volatile TYPE a = 1.5, b; \
+ b = FN (a); \
+ } \
+ while (0)
+
+#define FN_TESTS(FN) \
+ do \
+ { \
+ TEST (__builtin_ ## FN, double); \
+ TEST (__builtin_ ## FN ## f, float); \
+ TEST (__builtin_ ## FN ## l, long double); \
+ } \
+ while (0)
+
+void
+test (void)
+{
+ FN_TESTS (rint);
+ FN_TESTS (ceil);
+ FN_TESTS (floor);
+ FN_TESTS (trunc);
+}
+
+/* { dg-final { scan-assembler-not "\[ \t\]rint" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]ceil" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]floor" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]trunc" } } */
--- /dev/null
+/* Test rint and related functions expanded inline for 387. rint
+ should be expanded even when spurious "inexact" not allowed. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfancy-math-387 -mfpmath=387 -fno-fp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+
+#define TEST(FN, TYPE) \
+ do \
+ { \
+ volatile TYPE a = 1.5, b; \
+ b = FN (a); \
+ } \
+ while (0)
+
+#define FN_TESTS(FN) \
+ do \
+ { \
+ TEST (__builtin_ ## FN, double); \
+ TEST (__builtin_ ## FN ## f, float); \
+ TEST (__builtin_ ## FN ## l, long double); \
+ } \
+ while (0)
+
+void
+test (void)
+{
+ FN_TESTS (rint);
+}
+
+/* { dg-final { scan-assembler-not "\[ \t\]rint" } } */
--- /dev/null
+/* Test -fno-fp-int-builtin-inexact for SSE 2. */
+/* { dg-do run } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -fno-fp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-require-effective-target sse2 } */
+
+#include "sse2-check.h"
+
+#define main_test sse2_test
+#define ARCH_MAIN
+#include "../../gcc.dg/torture/builtin-fp-int-inexact.c"
--- /dev/null
+/* Test rint and related functions expanded inline for SSE2. All
+ should be expanded when spurious "inexact" allowed. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -ffp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target sse2 } */
+
+#define TEST(FN, TYPE) \
+ do \
+ { \
+ volatile TYPE a = 1.5, b; \
+ b = FN (a); \
+ } \
+ while (0)
+
+#define FN_TESTS(FN) \
+ do \
+ { \
+ TEST (__builtin_ ## FN, double); \
+ TEST (__builtin_ ## FN ## f, float); \
+ } \
+ while (0)
+
+void
+test (void)
+{
+ FN_TESTS (rint);
+ FN_TESTS (ceil);
+ FN_TESTS (floor);
+ FN_TESTS (trunc);
+}
+
+/* { dg-final { scan-assembler-not "\[ \t\]rint" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]ceil" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]floor" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]trunc" } } */
--- /dev/null
+/* Test rint and related functions expanded inline for SSE2. rint
+ should be expanded even when spurious "inexact" not allowed. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -fno-fp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target sse2 } */
+
+#define TEST(FN, TYPE) \
+ do \
+ { \
+ volatile TYPE a = 1.5, b; \
+ b = FN (a); \
+ } \
+ while (0)
+
+#define FN_TESTS(FN) \
+ do \
+ { \
+ TEST (__builtin_ ## FN, double); \
+ TEST (__builtin_ ## FN ## f, float); \
+ } \
+ while (0)
+
+void
+test (void)
+{
+ FN_TESTS (rint);
+}
+
+/* { dg-final { scan-assembler-not "\[ \t\]rint" } } */
--- /dev/null
+/* Test -fno-fp-int-builtin-inexact for SSE 4.1. */
+/* { dg-do run } */
+/* { dg-options "-O2 -msse4.1 -mfpmath=sse -fno-fp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-require-effective-target sse4 } */
+
+#include "sse4_1-check.h"
+
+#define main_test sse4_1_test
+#define ARCH_MAIN
+#include "../../gcc.dg/torture/builtin-fp-int-inexact.c"
--- /dev/null
+/* Test rint and related functions expanded inline for SSE4.1, even
+ when spurious "inexact" not allowed. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse4.1 -mfpmath=sse -fno-fp-int-builtin-inexact" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target sse4 } */
+
+#define TEST(FN, TYPE) \
+ do \
+ { \
+ volatile TYPE a = 1.5, b; \
+ b = FN (a); \
+ } \
+ while (0)
+
+#define FN_TESTS(FN) \
+ do \
+ { \
+ TEST (__builtin_ ## FN, double); \
+ TEST (__builtin_ ## FN ## f, float); \
+ } \
+ while (0)
+
+void
+test (void)
+{
+ FN_TESTS (rint);
+ FN_TESTS (ceil);
+ FN_TESTS (floor);
+ FN_TESTS (trunc);
+}
+
+/* { dg-final { scan-assembler-not "\[ \t\]rint" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]ceil" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]floor" } } */
+/* { dg-final { scan-assembler-not "\[ \t\]trunc" } } */