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]

[Patch]: Fix pb in delete_output_reload


Hi!

I've found a nasty problem in reload1.c in delete_output_reload.
It deletes a previous output reload where it should not do that.
The problem is also related to register elimination.


During reload, I have the following insns:

(insn 63 265 268 (set (reg:QI 1 d)
        (and:QI (reg:QI 1 d)
            (const_int -16 [0xfffffff0]))) 60 {andqi3} (nil)
    (expr_list:REG_DEAD (reg:QI 72)
        (nil)))

(insn 268 63 64 (set (mem:QI (plus:HI (reg:HI 2 y)
                (const_int 36 [0x24])) 0)
        (reg:QI 1 d)) -1 (nil)
    (nil))

(insn 64 268 66 (set (mem:QI (plus:HI (reg:HI 9 *frame)
                (const_int 36 [0x24])) 0)
        (ior:QI (mem:QI (plus:HI (reg:HI 9 *frame)
                    (const_int 41 [0x29])) 0)
            (mem:QI (plus:HI (reg:HI 9 *frame)
                    (const_int 36 [0x24])) 0))) 64 {iorqi3} (nil)
    (expr_list:REG_DEAD (reg:QI 71)
        (nil)))                                                             

and insn 268 is an output reload of insn 63 (that one that'll be killed).
(reg:HI 2 y  ==  reg:HI 9 *frame before insn 63).


When insn 64 is processed, the following reloads are found:

Reload 0: reload_in (HI) = (reg:HI 9 *frame)
        A_REGS, RELOAD_OTHER (opnum = 0)
        reload_in_reg: (reg:HI 9 *frame)
        reload_reg_rtx: (reg:HI 2 y)
Reload 1: A_REGS, RELOAD_FOR_OTHER_ADDRESS (opnum = 0)
        reload_in_reg: (reg:HI 9 *frame)
        reload_reg_rtx: (reg:HI 2 y)
Reload 2: A_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 2)
        reload_in_reg: (reg:HI 9 *frame)
        reload_reg_rtx: (reg:HI 2 y)
Reload 3: reload_in (QI) = (mem:QI (plus:HI (reg:HI 9 *frame)
                                                        (const_int 41 [0x29])) 0)
        reload_out (QI) = (mem:QI (plus:HI (reg:HI 9 *frame)
                                                        (const_int 36 [0x24])) 0)
        D_REGS, RELOAD_OTHER (opnum = 0), can't combine
        reload_in_reg: (reg:QI 71)
        reload_out_reg: (reg:QI 73)
        reload_reg_rtx: (reg:QI 1 d)                                        


In 'do_output_reload', when processing reload 3, we try to see if
we can eliminate an output reload.  All the conditions are met for
that and we call 'delete_output_reload'. I understand that the purpose
is to try to delete insn 268.

In 'delete_output_reload', the reload register we observe
is (reg:QI 73) and I have:

substed = reg_equiv_memory_loc[73] = (mem:QI (plus:HI (reg:HI 46 *sframe)
        					(const_int 36 [0x24])) 0)

which corresponds to (mem:QI (plus:HI (reg:HI 9 *frame)
        			(const_int 36 [0x24])) 0)
and also to          (mem:QI (plus:HI (reg:HI 2 y)
				(const_int 36 [0x24])) 0)

In this function, we try to see if the 'substed' occurs
in the insn 64.  Since we check with reg_equiv_memory_loc[], it
does not occur: the memory rtx refers to register 46 and not 9.

After getting the value of reg_equiv_memory_loc[73], we must eliminate
the registers with eliminate_regs, so that we have a chance
to find the same expression.  The insn itself, was eliminated
already since we are reloading it.  The elimination of reg:HI 46,
gives me reg:HI 9 (offset is 0 this time).

I've made a quick check of other places in reload1.c, and it seems to
me this is the only place such problem can happen. If you can double-check,
it's better.

Can you integrate this patch?

Thanks,
	Stephane

ChangeLog

2000-06-27  Stephane Carrez  <Stephane.Carrez@worldnet.fr>

	* reload1.c (delete_output_reload): Eliminate the eliminable
	registers from the raw pseudo register before searching for 
	occurrences in the insn.
--- /src/gnu/cygnus/gcc/gcc/reload1.c	Thu Jun 15 23:38:33 2000
+++ gcc/gcc/reload1.c	Wed Jun 28 01:02:09 2000
@@ -7383,6 +7383,10 @@ delete_output_reload (insn, j, last_relo
     reg = SUBREG_REG (reg);
   substed = reg_equiv_memory_loc[REGNO (reg)];
 
+  /* And eliminate some of the registers if possible.  */
+  if (substed)
+    substed = eliminate_regs (substed, 0, NULL_RTX);
+
   /* This is unsafe if the operand occurs more often in the current
      insn than it is inherited.  */
   for (k = n_reloads - 1; k >= 0; k--)

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