On Thu, May 26, 2016 at 1:46 AM, Joseph Myers <jos...@codesourcery.com> wrote:
> In ISO C99/C11, the ceil, floor, round and trunc functions may or may
> not raise the "inexact" exception for noninteger arguments.  Under TS
> 18661-1:2014, the C bindings for IEEE 754-2008, these functions are
> prohibited from raising "inexact", in line with the general rule that
> "inexact" is only when the mathematical infinite precision result of a
> function differs from the result after rounding to the target type.
>
> GCC has no option to select TS 18661 requirements for not raising
> "inexact" when expanding built-in versions of these functions inline.
> Furthermore, even given such requirements, the conditions on the x86
> insn patterns for these functions are unnecessarily restrictive.  I'd
> like to make the out-of-line glibc versions follow the TS 18661
> requirements; in the cases where this slows them down (the cases using
> x87 floating point), that makes it more important for inline versions
> to be used when the user does not care about "inexact".
>
> This patch fixes these issues.  A new option
> -fno-fp-int-builtin-inexact is added to request TS 18661 rules for
> these functions; the default -ffp-int-builtin-inexact reflects that
> such exceptions are allowed by C99 and C11.  (The intention is that if
> C2x incorporates TS 18661-1, then the default would change in C2x
> mode.)
>
> The x86 built-ins for rint (x87, SSE2 and SSE4.1) are made
> unconditionally available (no longer depending on
> -funsafe-math-optimizations or -fno-trapping-math); "inexact" is
> correct for noninteger arguments to rint.  For floor, ceil and trunc,
> the x87 and SSE2 built-ins are OK if -ffp-int-builtin-inexact or
> -fno-trapping-math (they may raise "inexact" for noninteger
> arguments); the SSE4.1 built-ins are made to use ROUND_NO_EXC so that
> they do not raise "inexact" and so are OK unconditionally.
>
> Now, while there was no semantic reason for depending on
> -funsafe-math-optimizations, the insn patterns had such a dependence
> because of use of gen_truncxf<mode>2_i387_noop to truncate back to
> SFmode or DFmode after using frndint in XFmode.  In this case a no-op
> truncation is safe because rounding to integer always produces an
> exactly representable value (the same reason why IEEE semantics say it
> shouldn't produce "inexact") - but of course that insn pattern isn't
> safe because it would also match cases where the truncation is not in
> fact a no-op.  To allow frndint to be used for SFmode and DFmode
> without that unsafe pattern, the relevant frndint patterns are
> extended to SFmode and DFmode or new SFmode and DFmode patterns added,
> so that the frndint operation can be represented in RTL as an
> operation acting directly on SFmode or DFmode without the extension
> and the problematic truncation.
>
> A generic test of the new option is added, as well as x86-specific
> tests, both execution tests including the generic test with different
> x86 options and scan-assembler tests verifying that functions that
> should be inlined with different options are indeed inlined.
>
> I think other architectures are OK for TS 18661-1 semantics already.
> Considering those defining "ceil" patterns: aarch64, arm, rs6000, s390
> use instructions that do not raise "inexact"; nvptx does not support
> floating-point exceptions.  (This does mean the -f option in fact only
> affects one architecture, but I think it should still be a -f option;
> it's logically architecture-independent and is expected to be affected
> by future -std options, so is similar to e.g. -fexcess-precision=,
> which also does nothing on most architectures but is implied by -std
> options.)
>
> Bootstrapped with no regressions on x86_64-pc-linux-gnu.  OK to
> commit?
>
> gcc:
> 2016-05-26  Joseph Myers  <jos...@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.
>         * 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.
>
> gcc/testsuite:
> 2016-05-26  Joseph Myers  <jos...@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.

x86 part is OK.

(We can make several patterns anonymous, but this should be part of
possibly another cleanup patch).

Thanks,
Uros.

> Index: gcc/common.opt
> ===================================================================
> --- gcc/common.opt      (revision 236740)
> +++ gcc/common.opt      (working copy)
> @@ -1330,6 +1330,10 @@ Enum(fp_contract_mode) String(on) Value(FP_CONTRAC
>  EnumValue
>  Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST)
>
> +ffp-int-builtin-inexact
> +Common Report Var(flag_fp_int_builtin_inexact) 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.
> Index: gcc/config/i386/i386.md
> ===================================================================
> --- gcc/config/i386/i386.md     (revision 236740)
> +++ gcc/config/i386/i386.md     (working copy)
> @@ -15512,25 +15512,31 @@
>    [(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
> @@ -15539,15 +15545,7 @@
>         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;
>  })
>
> @@ -15770,13 +15768,13 @@
>          (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"
> @@ -15787,26 +15785,26 @@
>    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")
> @@ -15814,7 +15812,7 @@
>                               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")
> @@ -15824,16 +15822,17 @@
>    "(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)
> @@ -15858,16 +15857,7 @@
>         }
>      }
>    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;
>  })
>
> Index: gcc/doc/invoke.texi
> ===================================================================
> --- gcc/doc/invoke.texi (revision 236740)
> +++ gcc/doc/invoke.texi (working copy)
> @@ -370,9 +370,9 @@ Objective-C and Objective-C++ Dialects}.
>  -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
> @@ -8531,6 +8531,24 @@ The default is @option{-fno-signaling-nans}.
>  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
> Index: gcc/testsuite/gcc.dg/torture/builtin-fp-int-inexact.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/torture/builtin-fp-int-inexact.c       (nonexistent)
> +++ gcc/testsuite/gcc.dg/torture/builtin-fp-int-inexact.c       (working copy)
> @@ -0,0 +1,72 @@
> +/* 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
> Index: gcc/testsuite/gcc.target/i386/387-builtin-fp-int-inexact.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/387-builtin-fp-int-inexact.c  (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/387-builtin-fp-int-inexact.c  (working copy)
> @@ -0,0 +1,7 @@
> +/* 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"
> Index: gcc/testsuite/gcc.target/i386/387-rint-inline-1.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/387-rint-inline-1.c   (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/387-rint-inline-1.c   (working copy)
> @@ -0,0 +1,36 @@
> +/* 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" } } */
> Index: gcc/testsuite/gcc.target/i386/387-rint-inline-2.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/387-rint-inline-2.c   (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/387-rint-inline-2.c   (working copy)
> @@ -0,0 +1,30 @@
> +/* 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" } } */
> Index: gcc/testsuite/gcc.target/i386/sse2-builtin-fp-int-inexact.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/sse2-builtin-fp-int-inexact.c (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/sse2-builtin-fp-int-inexact.c (working copy)
> @@ -0,0 +1,12 @@
> +/* 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"
> Index: gcc/testsuite/gcc.target/i386/sse2-rint-inline-1.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/sse2-rint-inline-1.c  (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/sse2-rint-inline-1.c  (working copy)
> @@ -0,0 +1,36 @@
> +/* 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" } } */
> Index: gcc/testsuite/gcc.target/i386/sse2-rint-inline-2.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/sse2-rint-inline-2.c  (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/sse2-rint-inline-2.c  (working copy)
> @@ -0,0 +1,30 @@
> +/* 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" } } */
> Index: gcc/testsuite/gcc.target/i386/sse4_1-builtin-fp-int-inexact.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/sse4_1-builtin-fp-int-inexact.c       
> (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/sse4_1-builtin-fp-int-inexact.c       
> (working copy)
> @@ -0,0 +1,12 @@
> +/* 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"
> Index: gcc/testsuite/gcc.target/i386/sse4_1-rint-inline.c
> ===================================================================
> --- gcc/testsuite/gcc.target/i386/sse4_1-rint-inline.c  (nonexistent)
> +++ gcc/testsuite/gcc.target/i386/sse4_1-rint-inline.c  (working copy)
> @@ -0,0 +1,36 @@
> +/* 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" } } */
>
> --
> Joseph S. Myers
> jos...@codesourcery.com

Reply via email to