Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 236794)
+++ 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) 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.
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md	(revision 236794)
+++ gcc/config/i386/i386.md	(working copy)
@@ -15515,25 +15515,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
@@ -15542,15 +15548,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;
 })
 
@@ -15773,13 +15771,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"
@@ -15790,26 +15788,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")
@@ -15817,7 +15815,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")
@@ -15827,16 +15825,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)
@@ -15861,16 +15860,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 236794)
+++ 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/doc/md.texi
===================================================================
--- gcc/doc/md.texi	(revision 236794)
+++ gcc/doc/md.texi	(working copy)
@@ -5554,7 +5554,9 @@ This pattern is not allowed to @code{FAIL}.
 @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}.
 
@@ -5562,7 +5564,9 @@ 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}.
 
@@ -5570,7 +5574,10 @@ 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}.
 
@@ -5578,7 +5585,9 @@ 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}.
 
Index: gcc/ipa-inline-transform.c
===================================================================
--- gcc/ipa-inline-transform.c	(revision 236794)
+++ gcc/ipa-inline-transform.c	(working copy)
@@ -369,6 +369,8 @@ inline_call (struct cgraph_edge *e, bool update_or
 	     != 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))
 	{
@@ -393,6 +395,8 @@ inline_call (struct cgraph_edge *e, bool update_or
 	    = 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)
Index: gcc/ipa-inline.c
===================================================================
--- gcc/ipa-inline.c	(revision 236794)
+++ gcc/ipa-inline.c	(working copy)
@@ -429,6 +429,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool rep
 		      || 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)))
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" } } */
