This splits out the non-constant folding part of an earlier approved patch 
to make -ftrapv work better.

The constant folding case is still broken (also ubsan doesn't handle it
correctly).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2015-10-22  Richard Biener  <rguent...@suse.de>

        PR middle-end/68046
        PR middle-end/61893
        * optabs.c (emit_libcall_block_1): Allow a NULL_RTX equiv.
        (expand_binop): For -ftrapv optabs do not record an REG_EQUAL note.
        (expand_unop): Likewise.

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

Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c        (revision 229166)
+++ gcc/optabs.c        (working copy)
@@ -1748,11 +1748,12 @@ expand_binop (machine_mode mode, optab b
       insns = get_insns ();
       end_sequence ();
 
+      bool trapv = trapv_binoptab_p (binoptab);
       target = gen_reg_rtx (mode);
       emit_libcall_block_1 (insns, target, value,
-                           gen_rtx_fmt_ee (optab_to_code (binoptab),
-                                           mode, op0, op1),
-                           trapv_binoptab_p (binoptab));
+                           trapv ? NULL_RTX
+                           : gen_rtx_fmt_ee (optab_to_code (binoptab),
+                                             mode, op0, op1), trapv);
 
       return target;
     }
@@ -2880,13 +2881,19 @@ expand_unop (machine_mode mode, optab un
       end_sequence ();
 
       target = gen_reg_rtx (outmode);
-      eq_value = gen_rtx_fmt_e (optab_to_code (unoptab), mode, op0);
-      if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
-       eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
-      else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
-       eq_value = simplify_gen_unary (ZERO_EXTEND, outmode, eq_value, mode);
-      emit_libcall_block_1 (insns, target, value, eq_value,
-                           trapv_unoptab_p (unoptab));
+      bool trapv = trapv_unoptab_p (unoptab);
+      if (trapv)
+       eq_value = NULL_RTX;
+      else
+       {
+         eq_value = gen_rtx_fmt_e (optab_to_code (unoptab), mode, op0);
+         if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
+           eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
+         else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
+           eq_value = simplify_gen_unary (ZERO_EXTEND,
+                                          outmode, eq_value, mode);
+       }
+      emit_libcall_block_1 (insns, target, value, eq_value, trapv);
 
       return target;
     }
@@ -3573,7 +3580,8 @@ emit_libcall_block_1 (rtx_insn *insns, r
     }
 
   last = emit_move_insn (target, result);
-  set_dst_reg_note (last, REG_EQUAL, copy_rtx (equiv), target);
+  if (equiv)
+    set_dst_reg_note (last, REG_EQUAL, copy_rtx (equiv), target);
 
   if (final_dest != target)
     emit_move_insn (final_dest, target);
Index: gcc/testsuite/gcc.dg/torture/ftrapv-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/ftrapv-2.c     (revision 0)
--- gcc/testsuite/gcc.dg/torture/ftrapv-2.c     (working copy)
***************
*** 0 ****
--- 1,32 ----
+ /* { dg-do run } */
+ /* With -flto this degenerates to constant folding which doesn't work.  */
+ /* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+ /* { dg-additional-options "-ftrapv" } */
+ /* { dg-require-effective-target trapping } */
+ /* { dg-require-fork unused } */
+ 
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ 
+ /* Verify SImode operations properly trap.  PR middle-end/68046 */
+ 
+ int i = 0x7fffffff;
+ 
+ int main(void)
+ {
+   pid_t child = fork ();
+   int status = 0;
+   if (child == 0)
+     {
+       volatile int x = i + 1 < i;
+       exit (0);
+     }
+   else if (child == -1)
+     return 0;
+   if (wait (&status) == child 
+       && status == 0)
+     abort ();
+   return 0;
+ }

Reply via email to