This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix aix -fcprop-register miscompilation
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 7 Jan 2002 22:17:14 -0800
- Subject: fix aix -fcprop-register miscompilation
Finally got around to examining this.
We miscompiled compute_dom_prob_ps in sched-rgn.c. The comment in the
first hunk of the patch describes the sequence of register moves that
led to the bug.
Bootstrapped and checked on aix4.3, i686 and alpha linux.
r~
* regrename.c (find_oldest_value_reg): Ignore the value chain if
the original register was copied in a mode with a fewer number of
hard registers than the desired mode.
(copyprop_hardreg_forward_1): Likewise.
(debug_value_data): Fix loop test.
* toplev.c (parse_options_and_default_flags): Reenable
-fcprop-registers at -O1.
Index: regrename.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regrename.c,v
retrieving revision 1.33
diff -c -p -d -r1.33 regrename.c
*** regrename.c 2001/12/31 23:16:05 1.33
--- regrename.c 2002/01/08 06:05:45
*************** find_oldest_value_reg (class, reg, vd)
*** 1282,1287 ****
--- 1282,1301 ----
enum machine_mode mode = GET_MODE (reg);
unsigned int i;
+ /* If we are accessing REG in some mode other that what we set it in,
+ make sure that the replacement is valid. In particular, consider
+ (set (reg:DI r11) (...))
+ (set (reg:SI r9) (reg:SI r11))
+ (set (reg:SI r10) (...))
+ (set (...) (reg:DI r9))
+ Replacing r9 with r11 is invalid. */
+ if (mode != vd->e[regno].mode)
+ {
+ if (HARD_REGNO_NREGS (regno, mode)
+ > HARD_REGNO_NREGS (regno, vd->e[regno].mode))
+ return NULL_RTX;
+ }
+
for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
if (TEST_HARD_REG_BIT (reg_class_contents[class], i)
&& (vd->e[i].mode == mode
*************** copyprop_hardreg_forward_1 (bb, vd)
*** 1544,1549 ****
--- 1558,1572 ----
unsigned int i;
rtx new;
+ /* If we are accessing SRC in some mode other that what we
+ set it in, make sure that the replacement is valid. */
+ if (mode != vd->e[regno].mode)
+ {
+ if (HARD_REGNO_NREGS (regno, mode)
+ > HARD_REGNO_NREGS (regno, vd->e[regno].mode))
+ goto no_move_special_case;
+ }
+
/* If the destination is also a register, try to find a source
register in the same class. */
if (REG_P (SET_DEST (set)))
*************** copyprop_hardreg_forward_1 (bb, vd)
*** 1578,1583 ****
--- 1601,1607 ----
}
}
}
+ no_move_special_case:
/* For each input operand, replace a hard register with the
eldest live copy that's in an appropriate register class. */
*************** debug_value_data (vd)
*** 1735,1741 ****
j != INVALID_REGNUM;
j = vd->e[j].next_regno)
{
! if (TEST_HARD_REG_BIT (set, vd->e[j].next_regno))
{
fprintf (stderr, "[%u] Loop in regno chain\n", j);
return;
--- 1759,1765 ----
j != INVALID_REGNUM;
j = vd->e[j].next_regno)
{
! if (TEST_HARD_REG_BIT (set, j))
{
fprintf (stderr, "[%u] Loop in regno chain\n", j);
return;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.566
diff -c -p -d -r1.566 toplev.c
*** toplev.c 2002/01/06 03:51:09 1.566
--- toplev.c 2002/01/08 06:05:45
*************** parse_options_and_default_flags (argc, a
*** 4663,4669 ****
flag_omit_frame_pointer = 1;
#endif
flag_guess_branch_prob = 1;
! /* flag_cprop_registers = 1; */
}
if (optimize >= 2)
--- 4663,4669 ----
flag_omit_frame_pointer = 1;
#endif
flag_guess_branch_prob = 1;
! flag_cprop_registers = 1;
}
if (optimize >= 2)