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