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; + }