This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Add option for whether ceil etc. can raise "inexact", adjust x86 conditions
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: Uros Bizjak <ubizjak at gmail dot com>
- Cc: Joseph Myers <joseph at codesourcery dot com>, "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, Jan Hubicka <hubicka at ucw dot cz>
- Date: Thu, 26 May 2016 19:59:51 +0200
- Subject: Re: Add option for whether ceil etc. can raise "inexact", adjust x86 conditions
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot DEB dot 2 dot 20 dot 1605252344370 dot 15050 at digraph dot polyomino dot org dot uk> <CAFULd4Y_p4S-2ZYxhndF9UbJgO2dH2r1w2Z3Ae4dLZpZ80YMLA at mail dot gmail dot com>
> > +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.
When adding new codegen option which affects the correctness, it is also
necessary to update can_inline_edge_p and inline_call.
(In general it would be great if we had fewer such flags and more stuff
explicitly represented in IL. I am not sure how hard that would be here and
if it is worth the effort.)
Honza
> > +
> > ; 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
> > joseph@codesourcery.com