The following fixes one of the most annoying parts of non-working -ftrapv,
namely that we only support >= word_mode trappings (quite annoying on
64bit archs where 'int' is not handled).  At least on x86_64 libgcc
has all the libfuncs available for SImode so the following patch
arranges for them to be used.  RFC because I don't know whether
they are there by accident... (and thus the patch adds a requirement
that is not met by other targets - but a link error is better than
-ftrapv failure?)

The testcase relies on fork() to be able to capture both inline
and out-of-line trapv sequences.  dg-require-fork is unused but
present, so I use it.  I suppose we can restrict the testcase
to a few targets manually as well - not sure, any preferences?

At least the obvious testcase from PR52478 now works (until
you hit constant folding ... see PR61893 I just opened).

Bootstrap and regtest running on x86_64-unknown-linux-gnu, ok
for trunk?

Thanks,
Richard.


2014-07-24  Richard Biener  <rguent...@suse.de>

        PR middle-end/52478
        * optabs.c (gen_int_libfunc): For -ftrapv libfuncs make
        sure to register SImode ones, not only >= word_mode ones.
        * expr.c (expand_expr_real_2): When expanding -ftrapv
        binops do not use OPTAB_LIB_WIDEN.

        * gcc.dg/torture/ftrapv-1.c: New testcase.

Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c        (revision 212970)
--- gcc/optabs.c        (working copy)
*************** gen_int_libfunc (optab optable, const ch
*** 5559,5571 ****
                 enum machine_mode mode)
  {
    int maxsize = 2 * BITS_PER_WORD;
  
    if (GET_MODE_CLASS (mode) != MODE_INT)
      return;
    if (maxsize < LONG_LONG_TYPE_SIZE)
      maxsize = LONG_LONG_TYPE_SIZE;
!   if (GET_MODE_CLASS (mode) != MODE_INT
!       || GET_MODE_BITSIZE (mode) < BITS_PER_WORD
        || GET_MODE_BITSIZE (mode) > maxsize)
      return;
    gen_libfunc (optable, opname, suffix, mode);
--- 5559,5575 ----
                 enum machine_mode mode)
  {
    int maxsize = 2 * BITS_PER_WORD;
+   int minsize = BITS_PER_WORD;
  
    if (GET_MODE_CLASS (mode) != MODE_INT)
      return;
    if (maxsize < LONG_LONG_TYPE_SIZE)
      maxsize = LONG_LONG_TYPE_SIZE;
!   if (minsize > INT_TYPE_SIZE
!       && (trapv_binoptab_p (optable)
!         || trapv_unoptab_p (optable)))
!     minsize = INT_TYPE_SIZE;
!   if (GET_MODE_BITSIZE (mode) < minsize
        || GET_MODE_BITSIZE (mode) > maxsize)
      return;
    gen_libfunc (optable, opname, suffix, mode);
Index: gcc/expr.c
===================================================================
*** gcc/expr.c  (revision 212970)
--- gcc/expr.c  (working copy)
*************** expand_expr_real_2 (sepops ops, rtx targ
*** 9212,9218 ****
    if (modifier == EXPAND_STACK_PARM)
      target = 0;
    temp = expand_binop (mode, this_optab, op0, op1, target,
!                      unsignedp, OPTAB_LIB_WIDEN);
    gcc_assert (temp);
    /* Bitwise operations do not need bitfield reduction as we expect their
       operands being properly truncated.  */
--- 9212,9220 ----
    if (modifier == EXPAND_STACK_PARM)
      target = 0;
    temp = expand_binop (mode, this_optab, op0, op1, target,
!                      unsignedp,
!                      trapv_binoptab_p (this_optab)
!                      ? OPTAB_LIB : OPTAB_LIB_WIDEN);
    gcc_assert (temp);
    /* Bitwise operations do not need bitfield reduction as we expect their
       operands being properly truncated.  */
Index: gcc/testsuite/gcc.dg/torture/ftrapv-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/ftrapv-1.c     (revision 0)
--- gcc/testsuite/gcc.dg/torture/ftrapv-1.c     (working copy)
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do run } */
+ /* { dg-additional-options "-ftrapv" } */
+ /* { dg-require-effective-target trapping } */
+ /* { dg-require-fork } */
+ 
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ 
+ /* Verify SImode operations properly trap.  PR middle-end/52478  */
+ 
+ /* Disallow inlining/cloning which would constant propagate and trigger
+    unrelated bugs.  */
+ 
+ int __attribute__((noinline,noclone))
+ iaddv (int a, int b)
+ {
+   return a + b;
+ }
+ 
+ int main(void)
+ {
+   pid_t child = fork ();
+   int status = 0;
+   if (child == 0)
+     {
+       volatile int x = iaddv (__INT_MAX__, 1);
+       exit (0);
+     }
+   else if (child == -1)
+     return 0;
+   if (wait (&status) == child 
+       && status == 0)
+     abort ();
+   return 0;
+ }

Reply via email to