Patchwork PR48441 ICE in mark_oprs_set

login
register
mail settings
Submitter Steven Bosscher
Date April 5, 2011, 12:36 p.m.
Message ID <BANLkTikM_tVNZztiSP-z8yrWrnUuxogfuw@mail.gmail.com>
Download mbox | patch
Permalink /patch/89845/
State New
Headers show

Comments

Steven Bosscher - April 5, 2011, 12:36 p.m.
Hi,

My recent patch to cprop.c to use DF_INSN_INFO caches exposed a latent
bug in CPROP. The bug triggered on hppa-linux, but the problem is
generic.

The ICE looks like this:

Breakpoint 3, mark_oprs_set (insn=0x7ffff6edc140) at
../../trunk/gcc/cprop.c:538
538       struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
(gdb) p debug_rtx(insn)
(jump_insn 171 170 248 31 (set (pc)
        (if_then_else (eq (reg/v:SI 158 [ rval ])
                (const_int 7 [0x7]))
            (label_ref:SI 248)
            (pc))) ../../gcc/libcpp/charset.c:481 25 {*pa.md:1330}
     (expr_list:REG_BR_PROB (const_int 9550 [0x254e])
        (nil))
 -> 248)
$12 = void
(gdb) p insn_info
$14 = (struct df_insn_info *) 0x14ca078
(gdb) call df_insn_debug(insn,false,stderr)
insn 171 luid 0 defs { } uses { u226(158)} eq uses { } mws
(gdb) cont
Continuing.

Breakpoint 3, mark_oprs_set (insn=0x7ffff6edc140) at
../../trunk/gcc/cprop.c:538
538       struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
(gdb) p debug_rtx(insn)
(jump_insn/v 171 170 257 29 (set (pc)
        (if_then_else (eq (reg/v:SI 158 [ rval ])
                (const_int 7 [0x7]))
            (label_ref:SI 257)
            (pc))) ../../gcc/libcpp/charset.c:481 25 {*pa.md:1330}
     (expr_list:REG_BR_PROB (const_int 9550 [0x254e])
        (nil))
 -> 257)
$13 = void
(gdb) p insn_info
$15 = (struct df_insn_info *) 0x0
(gdb) ######### So the insn is not even known anymore in DF
(gdb) call df_insn_debug(insn,false,stderr)

Program received signal SIGSEGV, Segmentation fault.
0x000000000063d9cb in df_insn_uid_debug (uid=171, follow_chain=0 '\0',
file=0x7ffff7bd8860) at ../../trunk/gcc/df-core.c:2113
2113      fprintf (file, "insn %d luid %d",


What happens, is that cprop_insn makes the insn deleted, in the second
CPROP pass:

Breakpoint 3, one_cprop_pass () at ../../trunk/gcc/cprop.c:1799
1799                    changed |= cprop_insn (insn);
(gdb) p debug_rtx(insn)
(jump_insn 214 213 303 29 (set (pc)
        (if_then_else (eq (reg/v:SI 202 [ rval ])
                (const_int 7 [0x7]))
            (label_ref:SI 303)
            (pc))) charset.i:106 25 {*pa.md:1330}
     (expr_list:REG_BR_PROB (const_int 9550 [0x254e])
        (nil))
 -> 303)
$12 = void
(gdb) next
1805                    if (! NOTE_P (insn))
(gdb) p debug_rtx(insn)
(jump_insn/v 214 213 303 29 (set (pc)
        (if_then_else (eq (reg/v:SI 202 [ rval ])
                (const_int 7 [0x7]))
            (label_ref:SI 303)
            (pc))) charset.i:106 25 {*pa.md:1330}
     (expr_list:REG_BR_PROB (const_int 9550 [0x254e])
        (nil))
 -> 303)
$13 = void
(gdb)

CPROP finds that rval==22 and folds away the comparsion "(eq (rval==22) (7))"
in cprop_jump, and then goes on to:

  /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
  if (new_rtx == pc_rtx)
    delete_insn (jump);

I also verified that the same occurred before my patch, i.e. we were
doing mark_oprs_set on dead/deleted insns.

Patch is simple. Bootstrapped&tested on x86_64-unknown-linux-gnu. The
bug never triggered there, so I'll wait for confirmation that the
hppa-linux problem is fixed with this patch, and commit the patch
under the "obvious" rule.

Ciao!
Steven

PR middle-end/48441
* cprop.c (one_cprop_pass): Do not mark_oprs_set of deleted insns.

Patch

Index: cprop.c
===================================================================
--- cprop.c    (revision 171948)
+++ cprop.c    (working copy)
@@ -1797,8 +1797,8 @@  one_cprop_pass (void)
         /* Keep track of everything modified by this insn.  */
         /* ??? Need to be careful w.r.t. mods done to INSN.
                Don't call mark_oprs_set if we turned the
-               insn into a NOTE.  */
-        if (! NOTE_P (insn))
+               insn into a NOTE, or deleted the insn.  */
+        if (! NOTE_P (insn) && ! INSN_DELETED_P (insn))
           mark_oprs_set (insn);
           }
     }