(take 2) [RFA:] Fix g77.f-torture/compile/970915-0.f, -Os verify_local_live_at_start, MMIX

Hans-Peter Nilsson hp@bitrange.com
Tue Apr 16 18:52:00 GMT 2002


On Tue, 16 Apr 2002, Hans-Peter Nilsson wrote:
> The computed regsets are different from the start; they don't
> change with subsequent calls to update_life_info:
Ignore that, it was confused.

The inconsistency happens in that same first call to
update_live_info, the code *after* the loop that updates global
liveness and deletes dead code.  flow.c:~693:
...
  if (blocks)
    {
      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
        {
          basic_block bb = BASIC_BLOCK (i);

          COPY_REG_SET (tmp, bb->global_live_at_end);
          propagate_block (bb, tmp, NULL, NULL, prop_flags);

          if (extent == UPDATE_LIFE_LOCAL)
            verify_local_live_at_start (tmp, bb);
        });
    }
  else
    {
      for (i = n_basic_blocks - 1; i >= 0; --i)
        {
          basic_block bb = BASIC_BLOCK (i);

          COPY_REG_SET (tmp, bb->global_live_at_end);
          propagate_block (bb, tmp, NULL, NULL, prop_flags);

          if (extent == UPDATE_LIFE_LOCAL)
            verify_local_live_at_start (tmp, bb);
        }
    }
...

(blocks is NULL here).  propagate_block is here called with the
original flags.  It removes another hunk of dead stores (that
now fits below the capping on processed mems).  But, it *does
not update global liveness, which has changed by deleting the
dead store that was the only user of the presumed alive (but
incorrectly due to capping) register*.  As you noticed, the
inconsistency is spotted later on in an UPDATE_LIFE_LOCAL call
(same code above).

Now, what's the best way to have global liveness up to date?  I
can think of two choices: mask out PROP_SCAN_DEAD_CODE |
PROP_KILL_DEAD_CODE so that liveness doesn't change, or call
calculate_global_regs_live if something changed.  The latter
seems unclean; for one thing it duplicates the dead-code killing
in the first loop.  I'll go with masking out those flags.  It
solves the problem at hand.  I changed both if-arms; the first
doesn't trig for this case, but it looked wrong and inconsistent
not to fix it.  As a not strictly necessary improvement for
removal of the resulting dead code, ignoring the return value
from cleanup_cfg should be safe (first hunk; should have done
this in my first patch if I hadn't misinterpreted BB_DIRTY).
This solution should also be safe for 3.1; I'll check there too.

Ok trunk and branch if this passes (bootstrapping and checking
on the various cross-targets I listed for my first patch)?

	* flow.c (update_life_info): Ignore return value of cleanup_cfg.
	Mask out PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE in
	propagate_block calls after relaxation loop.

Index: flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.514
diff -p -c -r1.514 flow.c
*** flow.c	12 Apr 2002 07:52:02 -0000	1.514
--- flow.c	17 Apr 2002 01:41:48 -0000
*************** update_life_info (blocks, extent, prop_f
*** 677,684 ****
  					      | PROP_KILL_DEAD_CODE));
  	    }

! 	  if (! changed || ! cleanup_cfg (CLEANUP_EXPENSIVE))
  	    break;
  	}

        /* If asked, remove notes from the blocks we'll update.  */
--- 677,690 ----
  					      | PROP_KILL_DEAD_CODE));
  	    }

! 	  if (! changed)
  	    break;
+
+ 	  /* We repeat regardless of what cleanup_cfg says.  If there were
+ 	     instructions deleted above, that might have been only a
+ 	     partial improvement (see MAX_MEM_SET_LIST_LEN usage).
+ 	     Further improvement may be possible.  */
+ 	  cleanup_cfg (CLEANUP_EXPENSIVE);
  	}

        /* If asked, remove notes from the blocks we'll update.  */
*************** update_life_info (blocks, extent, prop_f
*** 696,703 ****
  	{
  	  basic_block bb = BASIC_BLOCK (i);

  	  COPY_REG_SET (tmp, bb->global_live_at_end);
! 	  propagate_block (bb, tmp, NULL, NULL, prop_flags);

  	  if (extent == UPDATE_LIFE_LOCAL)
  	    verify_local_live_at_start (tmp, bb);
--- 702,712 ----
  	{
  	  basic_block bb = BASIC_BLOCK (i);

+ 	  /* See below about the masking out of flags.  */
  	  COPY_REG_SET (tmp, bb->global_live_at_end);
! 	  propagate_block (bb, tmp, NULL, NULL,
! 			   prop_flags & ~(PROP_SCAN_DEAD_CODE
! 					  | PROP_KILL_DEAD_CODE));

  	  if (extent == UPDATE_LIFE_LOCAL)
  	    verify_local_live_at_start (tmp, bb);
*************** update_life_info (blocks, extent, prop_f
*** 710,716 ****
  	  basic_block bb = BASIC_BLOCK (i);

  	  COPY_REG_SET (tmp, bb->global_live_at_end);
! 	  propagate_block (bb, tmp, NULL, NULL, prop_flags);

  	  if (extent == UPDATE_LIFE_LOCAL)
  	    verify_local_live_at_start (tmp, bb);
--- 719,732 ----
  	  basic_block bb = BASIC_BLOCK (i);

  	  COPY_REG_SET (tmp, bb->global_live_at_end);
!
! 	  /* Don't pass PROP_SCAN_DEAD_CODE or PROP_KILL_DEAD_CODE here,
! 	     since removing or pretending to remove dead code can affect
! 	     global register liveness, which is supposed to be finalized
! 	     for this call at this point.  */
! 	  propagate_block (bb, tmp, NULL, NULL,
! 			   prop_flags & ~(PROP_SCAN_DEAD_CODE
! 					  | PROP_KILL_DEAD_CODE));

  	  if (extent == UPDATE_LIFE_LOCAL)
  	    verify_local_live_at_start (tmp, bb);

brgds, H-P



More information about the Gcc-patches mailing list