[new-regalloc-branch] bunch of things [9/10]

Michael Matz matzmich@cs.tu-berlin.de
Tue Jul 17 10:17:00 GMT 2001


The ninth.

We now handle (when conflicts are noted) a move insn involving subregs as
a copy insn.  I.e. in
(1) (set (subreg:SI (reg:DI x) 0) (reg:SI y))
(2) (use (reg:SI y))

y and low(x) do not conflict just because of the def in (1).  This
relaxes the conflict graph a bit in presence of multi-word by pieces
operations.

Those copy insns are nevertheless not remembered for coalescing, only
reg-reg moves.  It would need some infrastructure change, if I allowed to
coalesce subwebs to webs or other subwebs.  Although the latter would be
nice.


2001-07-07  Michael Matz <matzmich@cs.tu-berlin.de>

	* ra.c : (copy_insn_p): Subregs in move insns don't prevent them
	from being copy insns.
	(remember_move): Only add REG-REG moves into coalesce list.
	(live_out_1): Use subreg copies to limit conflicts made for copy
	insns.
	Kill some #if 0 code.

-- 
*** ra.c	2001/07/17 09:26:07	1.19
--- ra.c	2001/07/17 09:26:32	1.20
*************** copy_insn_p (insn, source, target)
*** 483,535 ****
      return 0;
    d = SET_DEST (insn);
    s = SET_SRC (insn);
-   while (GET_CODE (d) == STRICT_LOW_PART
- 	 || GET_CODE (d) == SUBREG)
-     {
-       if (GET_CODE (d) == SUBREG)
- 	subreg_seen = 1;
-       d = XEXP (d, 0);
-     }
-   if (GET_CODE (d) != REG)
-     return 0;
-   while (GET_CODE (s) == STRICT_LOW_PART
- 	 || GET_CODE (s) == ZERO_EXTRACT
- 	 || GET_CODE (s) == SIGN_EXTRACT)
-     {
-       /* For now don't allow bitfield extraction at all to be a copy
- 	 insn.  XXX */
-       if (GET_CODE (s) == ZERO_EXTRACT || GET_CODE (s) == SIGN_EXTRACT)
- 	return 0;
-       s = XEXP (s, 0);
-     }
-   /* (set (reg:SI a) (subreg:SI (reg:DI b) 0)) will be a noop
-      if a and b become the same register, so this move is a candidate
-      for coalescing.
-      (set (reg:SI a) (subreg:SI (reg:DI b) 1)) is similar,
-      if a becomes hardreg(b)+1, but this isn't really coalesing,
-      so for now we ignore such a move.  */
-   if (GET_CODE (s) == SUBREG)
-     {
-       return 0; /* XXX */
-       subreg_seen = 1;
-       if (SUBREG_WORD (s) != 0)
-         return 0;
-       else
-         s = XEXP (s, 0);
-     }
-   if (GET_CODE (s) != REG)
-     return 0;

!   /* XXX for now disallow copy insns involving a subreg of
!      a hardreg.  Those usually produce more than one def/use, and some
!      of the parts of the code can't handle this.  (It basically would
!      be a parallel copy of more than one register).  */
!   if (subreg_seen)
      return 0;

    /* Copies between hardregs are useless for us, as not coalesable anyway. */
!   if (REGNO (s) < FIRST_PSEUDO_REGISTER
!       && REGNO (d) < FIRST_PSEUDO_REGISTER)
      return 0;

    if (source)
--- 483,508 ----
      return 0;
    d = SET_DEST (insn);
    s = SET_SRC (insn);

!   /* We recognize moves between subreg's as copy insns.  This is used to avoid
!      conflicts of those subwebs.  But they are currently _not_ used for
!      coalescing (the check for this is in remember_move() below).  */
!   while (GET_CODE (d) == STRICT_LOW_PART)
!     d = XEXP (d, 0);
!   if (GET_CODE (d) != REG
!       && (GET_CODE (d) != SUBREG || GET_CODE (SUBREG_REG (d)) != REG))
!     return 0;
!   while (GET_CODE (s) == STRICT_LOW_PART)
!     s = XEXP (s, 0);
!   if (GET_CODE (s) != REG
!       && (GET_CODE (s) != SUBREG || GET_CODE (SUBREG_REG (s)) != REG))
      return 0;

    /* Copies between hardregs are useless for us, as not coalesable anyway. */
!   if (REGNO (GET_CODE (s) == SUBREG ? SUBREG_REG (s) : s)
!        < FIRST_PSEUDO_REGISTER
!       && REGNO (GET_CODE (d) == SUBREG ? SUBREG_REG (d) : d)
!          < FIRST_PSEUDO_REGISTER)
      return 0;

    if (source)
*************** remember_move (insn)
*** 748,761 ****
  {
    if (!TEST_BIT (move_handled, INSN_UID (insn)))
      {
!       struct move *m = (struct move *) xcalloc (1, sizeof (struct move));
!       struct move_list *ml;
        SET_BIT (move_handled, INSN_UID (insn));
!       m->insn = insn;
!       ml = (struct move_list *) xmalloc (sizeof (struct move_list));
!       ml->move = m;
!       ml->next = wl_moves;
!       wl_moves = ml;
      }
  }

--- 721,743 ----
  {
    if (!TEST_BIT (move_handled, INSN_UID (insn)))
      {
!       rtx s, d;
        SET_BIT (move_handled, INSN_UID (insn));
!       copy_insn_p (insn, &s, &d);
!       /* XXX for now we don't remember move insns involving any subregs.
! 	 Those would be difficult to coalesce (we would need to implement
! 	 handling of all the subwebs in the allocator, including that such
! 	 subwebs could be source and target of coalesing).  */
!       if (GET_CODE (s) == REG && GET_CODE (d) == REG)
! 	{
! 	  struct move *m = (struct move *) xcalloc (1, sizeof (struct move));
! 	  struct move_list *ml;
! 	  m->insn = insn;
! 	  ml = (struct move_list *) xmalloc (sizeof (struct move_list));
! 	  ml->move = m;
! 	  ml->next = wl_moves;
! 	  wl_moves = ml;
! 	}
      }
  }

*************** live_out_1 (df, use, insn)
*** 884,890 ****
        struct df_link *link;
        unsigned int source_regno = ~0;
        unsigned int regno = use->regno;
!       rtx s,t;
        wp = find_web_part (wp);
        wp->spanned_insns++;
        if (copy_insn_p (insn, &s, &t))
--- 866,872 ----
        struct df_link *link;
        unsigned int source_regno = ~0;
        unsigned int regno = use->regno;
!       rtx s = NULL, t;
        wp = find_web_part (wp);
        wp->spanned_insns++;
        if (copy_insn_p (insn, &s, &t))
*************** live_out_1 (df, use, insn)
*** 907,913 ****
  	  if (slink->next
  	      && DF_REF_REGNO (slink->next->ref) >= FIRST_PSEUDO_REGISTER)
  	    abort (); */
! 	  source_regno = REGNO (s);
  	  remember_move (insn);
  	}
        for (link = DF_INSN_DEFS (df, insn); link; link = link->next)
--- 889,895 ----
  	  if (slink->next
  	      && DF_REF_REGNO (slink->next->ref) >= FIRST_PSEUDO_REGISTER)
  	    abort (); */
! 	  source_regno = REGNO (GET_CODE (s) == SUBREG ? SUBREG_REG (s) : s);
  	  remember_move (insn);
  	}
        for (link = DF_INSN_DEFS (df, insn); link; link = link->next)
*************** live_out_1 (df, use, insn)
*** 959,1005 ****
  		   the web parts.  */
  		wp = union_web_parts (wp, &web_parts[DF_REF_ID (link->ref)]);
  	      }
! 	    else if (regno != source_regno)
! 	      /* This triggers, when either this was no copy insn
! 		 (source_regno being ~0 then, which is != regno), or if it
! 		 was, but the source wasn't the current reg.  */
  	      {
! 		struct web_part *cwp;
! 		unsigned HOST_WIDE_INT undef;
!
! #if 0
! 		if (find_regno_note (insn, REG_NO_CONFLICT, regno))
  		  {
! 		    /* The current use don't conflict with the DEF in this
! 		       insn.  */
! 		    in_no_conflict_block = 1;
! 		    continue;
  		  }
- 		/* We also don't conflict with the CLOBBER starting a
- 		   REG_NO_CONFLICT block.  */
- 		if (in_no_conflict_block
- 		    && GET_CODE (PATTERN (insn)) == CLOBBER
- 		    && find_reg_note (insn, REG_LIBCALL, NULL_RTX) != 0)
- 		  continue;
- #endif
-
- 		/* XXX Beware, for SUBREG tracking we can't use the IDs of the
- 		   webroots unconditionally to identify conflicts.  We need a
- 		   webroot for each mode/subregword pair (at least
- 		   conceptionally) in addition to the real root for the reg
- 		   itself.  */
- 		cwp = find_web_part (&web_parts[DF_REF_ID (link->ref)]);
- 		undef = use->undefined;
- 		while (undef)
- 		  bitmap_set_bit (undef_to_bitmap (wp, &undef),
- 				  DF_REF_ID (link /*cwp*/ ->ref));
- #if 0
- 		/* Use the un-unioned web_part for remembering conflicts.  */
- 		/*if (use->wp->conflicts)
- 		  bitmap_set_bit (use->wp->conflicts, DF_REF_ID (cwp->ref));
- 		else*/
- 		  bitmap_set_bit (wp->conflicts, DF_REF_ID (cwp->ref));
- #endif
  	      }
  	  }
      }
--- 941,986 ----
  		   the web parts.  */
  		wp = union_web_parts (wp, &web_parts[DF_REF_ID (link->ref)]);
  	      }
! 	    else
  	      {
! 		unsigned HOST_WIDE_INT undef = use->undefined;
! 		if (regno == source_regno)
! 		  /* This triggers only, when this was a copy insn and the
! 		     source is at least a part of the USE currently looked at.
! 		     In this case only the bits of the USE conflict with the
! 		     DEF, which are not covered by the source of this copy
! 		     insn, and which are still undefined.  I.e. in the best
! 		     case (the whole reg being the source), _no_ conflicts
! 		     between that USE and this DEF (the target of the move)
! 		     are created by this insn (though they might be by
! 		     others).  This is a super case of the normal copy insn
! 		     only between full regs.  */
  		  {
! 		    unsigned int bl = rtx_to_bits (s);
! 		    int b = BYTE_BEGIN (bl);
! 		    int e = b + BYTE_LENGTH (bl);
! 		    for (; b < e; b++)
! 		      undef &= ~((unsigned HOST_WIDE_INT)1 << b);
! 		  }
! 		if (undef)
! 		  {
! 		    /*struct web_part *cwp;
! 		    cwp = find_web_part (&web_parts[DF_REF_ID
! 		       (link->ref)]);*/
!
! 		    /* TODO: somehow instead of noting the ID of the LINK
! 		       use the an ID nearer to the root webpart of that LINK.
! 		       We can't use the root itself, because we later use the
! 		       ID to look at the form (reg or subreg, and if yes,
! 		       which subreg) of this conflict.  This means, that we
! 		       need to remember in the root an ID for each form, and
! 		       maintaining this, when merging web parts.  This makes
! 		       the bitmaps smaller.  */
! 		    do
! 		      bitmap_set_bit (undef_to_bitmap (wp, &undef),
! 				      DF_REF_ID (link->ref));
! 		    while (undef);
  		  }
  	      }
  	  }
      }



More information about the Gcc-patches mailing list