This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Combine looses libcall notes


The attached patch fixes an ICE that showed up on csl-arm-branch. This looks 
like a latent bug in distribute_notes.

The testcase includes the following code:

return (((a % 10000)) & 0xFF) >> 8;

Which results in the following RTL before combine (slightly edited):

(insn 25 4 26 0 (set (reg:SI 0 r0 [ a ])
        (reg/v:SI 102 [ a ])) 141 {*thumb_movsi_insn} (insn_list 3 (nil))
    (expr_list:REG_DEAD (reg/v:SI 102 [ a ])
        (insn_list:REG_LIBCALL 28 (nil))))

(insn 26 25 27 0 (set (reg:SI 1 r1) (const_int 10000)

(call_insn/u 27 26 28 0 (parallel [
            (set (reg:DI 0 r0)
                (call (mem:SI (symbol_ref:SI ("__aeabi_uidivmod"))
                    (const_int 0 [0x0])))
            (use (const_int 0 [0x0]))
            (clobber (reg:SI 14 lr))
        ]) 226 {*call_value_insn} (insn_list 25 (insn_list 26 (nil))))))

(insn 28 27 29 0 (set (reg:SI 124 [+4 ])
        (reg:SI 1 r1 [+4 ])) 141 {*thumb_movsi_insn} (nil)
    (expr_list:REG_DEAD (reg:SI 1 r1 [+4 ])
        (insn_list:REG_RETVAL 25
             (expr_list:REG_EQUAL (umod:SI (reg/v:SI 102 [ a ]])
                    (const_int 10000 [0x2710]))
                (nil)))))

(insn 29 28 30 0 (set (reg:SI 126)
        (const_int 255 [0xff])) 141 {*thumb_movsi_insn} (nil)
    (nil))

(insn 30 29 31 0 (set (reg:SI 125)
        (and:SI (reg:SI 124 [+4 ])
            (reg:SI 126))) 55 {*thumb_andsi3_insn}
    (expr_list:REG_DEAD (reg:SI 124 [+4 ])
        (expr_list:REG_DEAD (reg:SI 126)
            (expr_list:REG_EQUAL (and:SI (reg:SI 124 [+4 ])
                    (const_int 255 [0xff]))
                (nil)))))

(insn 31 30 36 0 (set (reg:SI 103)
        (lshiftrt:SI (reg:SI 125)
            (const_int 8 [0x8]))) 94 {*thumb_lshrsi3} 
    (expr_list:REG_DEAD (reg:SI 125) (nil)))

The first thing that happens is combine (correctly) turns insns 29-31 into 
(set (reg:SI 103) (const_int 0))
It then propagates (REG_DEAD 124) into insn 28. We notice that this insn is a 
single set of a dead reg, so decide to remove it. 

The code in distribute_notes at around line 12190 is responsible for 
distributing the appropriate notes before they are discarded, which is where 
the fun starts.

The case for REG_RETVAL in distribute_notes checks !NOTE_P(from_insn) to see 
if we can put the note back on the original insn. Unfortunately this 
condition holds for the temporary RTX used when deleting dead sets.

The attached patch modifies the condition to ensure the notes are not put back 
onto the soon-to-be-deleted insns.

It appears that in most cases insn 28 is deleted before we combine insns 
28-13. I'm not sure what's special about csl-arm-branch that tickles this 
bug.

I considered doing SET_INSN_DELETED before calling distribute_notes, but 
couldn't convince myself that this was safe.

Tested on arm-none-eabi, and bootstrapped i686-linux.
Ok for mainline?

Paul

2005-04-07  Paul Brook  <paul@codesourcery.com>

 * combine.c (distribute_notes): Don't put notes on temporary insns.
Index: gcc/combine.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/combine.c,v
retrieving revision 1.485
diff -u -p -r1.485 combine.c
--- gcc/combine.c	5 Apr 2005 14:50:28 -0000	1.485
+++ gcc/combine.c	6 Apr 2005 14:51:49 -0000
@@ -12062,7 +12062,7 @@ distribute_notes (rtx notes, rtx from_in
 	  /* If the insn previously containing this note still exists,
 	     put it back where it was.  Otherwise move it to the previous
 	     insn.  Adjust the corresponding REG_LIBCALL note.  */
-	  if (!NOTE_P (from_insn))
+	  if (!NOTE_P (from_insn) && PATTERN (from_insn) != pc_rtx)
 	    place = from_insn;
 	  else
 	    {
@@ -12082,7 +12082,7 @@ distribute_notes (rtx notes, rtx from_in
 
 	case REG_LIBCALL:
 	  /* This is handled similarly to REG_RETVAL.  */
-	  if (!NOTE_P (from_insn))
+	  if (!NOTE_P (from_insn) && PATTERN (from_insn) != pc_rtx)
 	    place = from_insn;
 	  else
 	    {
@@ -12187,6 +12187,7 @@ distribute_notes (rtx notes, rtx from_in
 			  REG_NOTES (tem) = NULL;
 
 			  distribute_notes (old_notes, tem, tem, NULL_RTX);
+			  gcc_assert (REG_NOTES (tem) == NULL);
 			  distribute_links (LOG_LINKS (tem));
 
 			  SET_INSN_DELETED (tem);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]