This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch]: Fix pb in delete_output_reload
- To: gcc-patches at gcc dot gnu dot org
- Subject: [Patch]: Fix pb in delete_output_reload
- From: Stephane Carrez <Stephane dot Carrez at worldnet dot fr>
- Date: Wed, 28 Jun 2000 01:25:05 +0200
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--)