This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix for latent twolf spec2000 test failures
- To: aj at suse dot de, rth at cygnus dot com, patches at x86-64 dot org, gcc-patches at gcc dot gnu dot org
- Subject: Fix for latent twolf spec2000 test failures
- From: Jan Hubicka <jh at suse dot cz>
- Date: Fri, 3 Aug 2001 15:37:50 +0200
Hi,
this was tricky bug to hunt down. It has shown as misscompilation of twolf
spec2000 benchmark with -funroll-all-loops. The function in question is large,
BASIC-like code, containing many fors iterating over global variables. The
GCSE introduces many dumy copies. (like:
(set (reg) (expr))
(set (reg2) (reg)) <- reg dies here
that comes from originally memory references (where caching expression in register makes sense).
No one cleans them up and try_swap_copy_prop reach sequence
(set (reg A) (plus (reg B) (const_int 1))
(set (reg B) (reg A)
(REG_EQUAL (plus (reg B) (const_int 1))
Note that the code is already wrong, as it says B == B+1, but I am
sending another patch, as there is still (reproducible) bug in loop.
The code in question attempts to do transformation:
We have:
(set (reg regno) (expr))
(set (reg new_regno) (reg regno))
so try converting this to:
(set (reg new_regno) (expr))
(set (reg regno) (reg new_regno))
But after converting it keeps the notes at place. It should move the
notes to first place, as and REG_EQUAL mentioning REGNO or NEW_REGNO is
wrong.
As I've mentioned we still can create such reg_equal notes, that basically
says reg == reg, but in a way like reg == reg + 0, as the effect of constant
propagation.
With some luck I was able to construct testcase, so we must kill the notes
here. The patch also re-distributes them to the first set.
Honza
Pá srp 3 16:07:14 CEST 2001 Jan Hubicka <jh@suse.cz>
* loop.c (try_swap_copy_prop): Take care to update loop notes
and REGNO_LAST_UID.
*** loop.c.old Fri Aug 3 14:31:40 2001
--- loop.c Fri Aug 3 16:06:49 2001
*************** try_swap_copy_prop (loop, replacement, r
*** 9432,9437 ****
--- 9435,9441 ----
if (apply_change_group ())
{
+ rtx *pnote = ®_NOTES (insn);
if (loop_dump_stream)
fprintf (loop_dump_stream,
" Swapped set of reg %d at %d with reg %d at %d.\n",
*************** try_swap_copy_prop (loop, replacement, r
*** 9440,9446 ****
/* Update first use of REGNO. */
if (REGNO_FIRST_UID (regno) == INSN_UID (prev_insn))
! REGNO_FIRST_UID (regno) = INSN_UID (insn);
/* Now perform copy propagation to hopefully
remove all uses of REGNO within the loop. */
--- 9444,9476 ----
/* Update first use of REGNO. */
if (REGNO_FIRST_UID (regno) == INSN_UID (prev_insn))
! {
! REGNO_FIRST_UID (regno) = INSN_UID (insn);
! /* In case register appears to be used only as an temporary
! for computation above, kill it. */
! if (REGNO_LAST_UID (regno) == INSN_UID (insn))
! delete_insn (insn);
! }
! if (REGNO_LAST_UID (regno) == INSN_UID (insn))
! REGNO_LAST_UID (regno) = INSN_UID (insn);
!
! /* Move the REG_EQUIV notes. Take care to avoid notes mentioning
! original values of the registers. Such notes are no longer
! valid. */
! while (*pnote)
! {
! if (REG_NOTE_KIND (*pnote) == REG_EQUAL)
! {
! if (!reg_mentioned_p (SET_DEST (set), XEXP (*pnote, 0))
! && !reg_mentioned_p (replacement, XEXP (*pnote, 0)))
! REG_NOTES (prev_insn)
! = gen_rtx_EXPR_LIST (REG_EQUAL,
! XEXP (*pnote, 0), REG_NOTES (prev_insn));
! *pnote = XEXP (*pnote, 1);
! }
! else
! pnote = &XEXP (*pnote, 1);
! }
/* Now perform copy propagation to hopefully
remove all uses of REGNO within the loop. */