This patch fixes PR52353 towards a point we no longer ICE.  We fail
to properly treat -ftrapv operations (or rather their libcall block)
as trapping after RTL expansion because we simply check may_trap_p
on the REG_EQUAL note.  The following patch re-arranges
emit_libcall_block to take an additional argument overriding that
result properly.

The testcase is still miscompiled later by RTL DCE, I'll open a
bug for that once this patch is in.  Thus, no testcase, but it
avoids an existing one from ICEing after preserving loops over RTL

The new predicates will help fixing PR52478 as well (trying a fix now).

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.


2012-03-05  Richard Guenther  <>

        PR middle-end/52353
        * optabs.h (trapv_unoptab_p): New function.
        (trapv_binoptab_p): Likewise.
        * optabs.c (expand_binop): Use emit_libcall_block_1 with
        a proper equiv_may_trap argument.
        (expand_unop): Likewise.
        (emit_libcall_block_1): Take extra argument whether the
        instruction may trap.  Renamed from ...
        (emit_libcall_block): ... this.  New wrapper.

Index: gcc/optabs.h
--- gcc/optabs.h        (revision 184918)
+++ gcc/optabs.h        (working copy)
@@ -1103,6 +1103,25 @@ set_direct_optab_handler (direct_optab o
   op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing;
+/* Return true if UNOPTAB is for a trapping-on-overflow operation.  */
+static inline bool
+trapv_unoptab_p (optab unoptab)
+  return (unoptab == negv_optab
+         || unoptab == absv_optab); 
+/* Return true if BINOPTAB is for a trapping-on-overflow operation.  */
+static inline bool
+trapv_binoptab_p (optab binoptab)
+  return (binoptab == addv_optab
+         || binoptab == subv_optab
+         || binoptab == smulv_optab);
 extern rtx optab_libfunc (optab optab, enum machine_mode mode);
 extern rtx convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
                                  enum machine_mode mode2);
Index: gcc/optabs.c
--- gcc/optabs.c        (revision 184918)
+++ gcc/optabs.c        (working copy)
@@ -60,6 +60,7 @@ optab code_to_optab[NUM_RTX_CODE + 1];
 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
                                   enum machine_mode *);
 static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
+static void emit_libcall_block_1 (rtx, rtx, rtx, rtx, bool);
 /* Debug facility for use in GDB.  */
 void debug_optab_libfuncs (void);
@@ -2115,8 +2116,9 @@ expand_binop (enum machine_mode mode, op
       end_sequence ();
       target = gen_reg_rtx (mode);
-      emit_libcall_block (insns, target, value,
-                         gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
+      emit_libcall_block_1 (insns, target, value,
+                           gen_rtx_fmt_ee (binoptab->code, mode, op0, op1),
+                           trapv_binoptab_p (binoptab));
       return target;
@@ -3197,7 +3199,8 @@ expand_unop (enum machine_mode mode, opt
        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 (insns, target, value, eq_value);
+      emit_libcall_block_1 (insns, target, value, eq_value,
+                           trapv_unoptab_p (unoptab));
       return target;
@@ -3775,8 +3778,9 @@ no_conflict_move_test (rtx dest, const_r
    an insn to move RESULT to TARGET.  This last insn will have a REQ_EQUAL
    note with an operand of EQUIV.  */
-emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
+static void
+emit_libcall_block_1 (rtx insns, rtx target, rtx result, rtx equiv,
+                     bool equiv_may_trap)
   rtx final_dest = target;
   rtx next, last, insn;
@@ -3789,7 +3793,8 @@ emit_libcall_block (rtx insns, rtx targe
   /* If we're using non-call exceptions, a libcall corresponding to an
      operation that may trap may also trap.  */
   /* ??? See the comment in front of make_reg_eh_region_note.  */
-  if (cfun->can_throw_non_call_exceptions && may_trap_p (equiv))
+  if (cfun->can_throw_non_call_exceptions
+      && (equiv_may_trap || may_trap_p (equiv)))
       for (insn = insns; insn; insn = NEXT_INSN (insn))
        if (CALL_P (insn))
@@ -3870,6 +3875,12 @@ emit_libcall_block (rtx insns, rtx targe
   if (final_dest != target)
     emit_move_insn (final_dest, target);
+emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
+  emit_libcall_block_1 (insns, target, result, equiv, false);
 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
    PURPOSE describes how this comparison will be used.  CODE is the rtx

Reply via email to