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] Fix PR optimization/13060


Hi,

This is a regression at -O on x86, present on mainline and 3.3 branch.  The 
compiler dies in fixup_var_refs_1 (called from the purge_addressof pass) 
because it can't recognize an insn after replacing a MEM by a REG.

It turns out that the culprit is fixup_var_refs_1 itself, but when called 
earlier during RTL expansion from put_var_into_stack.

We start with:

  (mult:SI  (subreg:SI (reg:DI 60) 0)
      (subreg:SI (reg:DI 60) 0))

(reg:DI 60) is put on the stack:

  (mult:SI  (subreg:SI (mem:SI (addressof:SI (reg:DI 63) 60)) 0)
      (subreg:SI (mem:SI (addressof:SI (reg:DI 63) 60)) 0))

and fixup_var_refs_1 is called with (mem:SI (addressof:SI (reg:DI 63) 60)) on 
this latter insn.

The first occurence is fixed:

  (mult:SI  (mem:SI (addressof:SI (reg:DI 63) 60))
      (subreg:SI (mem:SI (addressof:SI (reg:DI 63) 60)) 0))

and this insn is succesfully recognized since (mult REG MEM) is valid on x86.

Then the second occurence is fixed, but since the two operands were the same, 
the same replacement is used and the insn is _not_ recognized:

  (mult:SI  (mem:SI (addressof:SI (reg:DI 63) 60))
      (mem:SI (addressof:SI (reg:DI 63) 60)))

This insn is invalid on x86 and, when fixup_var_refs_1 tries later to fix the 
insn during the purge_addressof pass, it aborts.


The proposed fix is to recognize the insn even when the same replacement is 
used, and to fix again the whole insn if that fails. This gives

(insn 35 23 24 (set (reg:SI 67)
        (mem/s:SI (addressof:SI (reg/v:DI 63) 60 0x401e7798) [0 ne+0 S4 
A32])) -1 (nil)
    (nil))

(insn 24 35 25 (parallel [
            (set (reg:SI 61)
                (mult:SI (reg:SI 67)
                    (reg:SI 67)))
            (clobber (reg:CC %eflags))
        ]) -1 (nil)
    (nil))

in the 01.rtl file.

Bootstrapped/regtested on i586-redhat-linux-gnu (mainline except Ada).  Ok 
for mainline?

[I'm not requesting approval for the 3.3 branch because I'm not fully 
convinced that this approach is safe.  I would be happy if the reviewer feels 
differently :-)]


2003-12-06  Eric Botcazou  <ebotcazou@libertysurf.fr>

        PR optimization/13060
        * function.c (fixup_var_refs_1) [SUBREG]: Recognize even if a
	replacement already exists.  Fix again the whole insn if that fails.


2003-12-06  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* g77.f-torture/compile/20031206-1.f: New test.


-- 
Eric Botcazou
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.473
diff -u -p -r1.473 function.c
--- function.c	5 Dec 2003 06:46:28 -0000	1.473
+++ function.c	5 Dec 2003 10:47:25 -0000
@@ -2092,7 +2089,23 @@ fixup_var_refs_1 (rtx var, enum machine_
 	  replacement = find_fixup_replacement (replacements, x);
 	  if (replacement->new)
 	    {
+	      enum machine_mode mode = GET_MODE (x);
 	      *loc = replacement->new;
+
+	      /* Careful!  We may have just replaced a SUBREG by a MEM, which
+		 means that the insn may have become invalid again.  We can't
+		 in this case make a new replacement since we already have one
+		 and we must deal with MATCH_DUPs.  */
+	      if (GET_CODE (replacement->new) == MEM)
+		{
+		  INSN_CODE (insn) = -1;
+		  if (recog_memoized (insn) >= 0)
+		    return;
+
+		  fixup_var_refs_1 (replacement->new, mode, &PATTERN (insn),
+				    insn, replacements, no_share);
+		}
+
 	      return;
 	    }
 

Attachment: 20031206-1.f
Description: Text document


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