Shorten_branches and max_skip patch

Jan Hubicka hubicka@atrey.karlin.mff.cuni.cz
Tue Jul 20 11:06:00 GMT 1999


Hi
This is patch to shorten branches that has two goals. First one is to make
it working with max_skip alignments. The guesses done by old shorten_branches
code that ignores max_skip alignments are wrong. Consider for example
.p2align 5,,15
jump label
.p2align 4
label

align_fuzz will not expect growth in second align label, that actually may
happen when first align is not done.

I've implemented align_fuzz in a way that it combines old guessing algorithm
with new one that never guess larger padding than max_skip and always
choose better result. The old one gives better result for many accumulated
alignemnts while the new one gives better results otherwise.

Because of this I was also forced to relax uid_align and link all labels
into one chain, because the max_skip alignments ought to be in all chains.
Hope this will not cause any performance problems in align fuzz.

The patch also add support for max_skips into address calculation code and
improves choosing of maximal alignment (that don't means just picking one
with maximal log anymore).

The second change is macro INSN_ALIGNMENT that can be used to define
alignment per insn basis. This is very usefull for AMD processor familly
that don't like instruction with two byte opcode to straddle over cache
line boundary.

This forced few changes in the global arrays.  The insn_lengths no more
combines two different thinks together (length of padding for CODE_LABELS
and real length for insns) and I've changed label_align to insn_align that
is now indexed by uid instad of labelno.

Honza

Tue Jul 20 13:47:56 EDT 1999  Jan Hubicka  <hubicka@freesoft.cz>
	* final.c (merge_alignment): New function.
	(align_fuzz): Add static modifier and prototype, handle max_skip
	value correctly.
	(insn_align_lengths): New global variable.
	(label_align): Changed to insn_align and indexed by uid instead
	of labelno.
	(LABEL_TO_ALIGNEMNT): Modified and renamed to INSN_TO_ALIGNENT.
	(LABEL_TO_MAX_SKIP): Modified and renamed to INSN_TO_MAX_SKIP.
	(init_insn_lengths): Handle insn_align and insn_align_lengths.
	(insn_reference_addresses): Update call of align_fuzz.
	(shorten_branches): Handle max_skip value correctly, 
	use merge_alignments, update call of align_fuzz and other functions.
	Use INSN_ALIGNMENT.
	(final_scan_insn): Output alignment for non CODE_LABEL insns too.
	* tm.texi (INSN_ALIGMENT): Document.

*** final.cc	Sat Jul 17 20:32:19 1999
--- final.c	Tue Jul 20 13:29:53 1999
*************** static void output_source_line	PROTO((FI
*** 302,313 ****
--- 302,317 ----
  static rtx walk_alter_subreg	PROTO((rtx));
  static void output_asm_name	PROTO((void));
  static void output_operand	PROTO((rtx, int));
+ static void merge_alignment     PROTO((int, int, short *, short *));
  #ifdef LEAF_REGISTERS
  static void leaf_renumber_regs	PROTO((rtx));
  #endif
  #ifdef HAVE_cc0
  static int alter_cond		PROTO((rtx));
  #endif
+ #ifdef HAVE_attr_length
+ static int align_fuzz 		PROTO((rtx, rtx, int, int, unsigned));
+ #endif
  
  extern char *getpwd ();
  
*************** dbr_sequence_length ()
*** 627,632 ****
--- 631,638 ----
     `insn_current_length'.  */
  
  static short *insn_lengths;
+ /* additional length of insn caused by alignment.  */
+ static short *insn_align_lengths;  
  int *insn_addresses;
  
  /* Max uid for which the above arrays are valid.  */
*************** int insn_last_address;
*** 642,673 ****
  int insn_current_align;
  
  /* After shorten_branches, for any insn, uid_align[INSN_UID (insn)]
!    gives the next following alignment insn that increases the known
!    alignment, or NULL_RTX if there is no such insn.
     For any alignment obtained this way, we can again index uid_align with
!    its uid to obtain the next following align that in turn increases the
!    alignment, till we reach NULL_RTX; the sequence obtained this way
!    for each insn we'll call the alignment chain of this insn in the following
!    comments.  */
  
! struct label_alignment {
    short alignment;
    short max_skip;
  };
  
  static rtx *uid_align;
  static int *uid_shuid;
! static struct label_alignment *label_align;
  
  /* Indicate that branch shortening hasn't yet been done.  */
  
  void
  init_insn_lengths ()
  {
!   if (label_align)
      {
!       free (label_align);
!       label_align = 0;
      }
    if (uid_shuid)
      {
--- 648,679 ----
  int insn_current_align;
  
  /* After shorten_branches, for any insn, uid_align[INSN_UID (insn)]
!    gives the next following alignment, or NULL_RTX if there is no such insn.
     For any alignment obtained this way, we can again index uid_align with
!    its uid to obtain the next following align, till we reach NULL_RTX; the
!    sequence obtained this way for each insn we'll call the alignment chain
!    of this insn in the following comments.  */
  
! struct insn_alignment {
    short alignment;
    short max_skip;
  };
  
  static rtx *uid_align;
  static int *uid_shuid;
! static struct insn_alignment *insn_align;
! static int insn_align_max_uid;
  
  /* Indicate that branch shortening hasn't yet been done.  */
  
  void
  init_insn_lengths ()
  {
!   if (insn_align)
      {
!       free (insn_align);
!       insn_align = 0;
!       insn_align_max_uid = 0;
      }
    if (uid_shuid)
      {
*************** init_insn_lengths ()
*** 680,685 ****
--- 686,696 ----
        insn_lengths = 0;
        insn_lengths_max_uid = 0;
      }
+   if (insn_align_lengths)
+     {
+       free (insn_align_lengths);
+       insn_align_lengths = 0;
+     }
    if (insn_addresses)
      {
        free (insn_addresses);
*************** get_attr_length (insn)
*** 795,801 ****
     for branch ranges starting before X, so we can just round what we have.
     But when X < Y, we don't know anything about the, so to speak,
     `middle bits', so we have to assume the worst when aligning up from an
!    address mod X to one mod Y, which is Y - X.  */
  
  #ifndef LABEL_ALIGN
  #define LABEL_ALIGN(LABEL) 0
--- 806,823 ----
     for branch ranges starting before X, so we can just round what we have.
     But when X < Y, we don't know anything about the, so to speak,
     `middle bits', so we have to assume the worst when aligning up from an
!    address mod X to one mod Y, which is Y - X.  
!    
!    We get even more complications with max_skip.  We can't really say much
!    about the alignment when X have max_skip value, so we behave like
!    X alignment is 0. The max_skip of Y is ignored for calculation and then
!    maximal padding is min (max_skip(X), OX - IX).
! 
!    Also the non_max_skip avare fuzz algorithm with start alignment set to 1
!    gives us another higher bound.  Sometimes this fuzz is lower than fuzz
!    caluclated by max_skip algorithm (when many max_skip alignments accumulate).
!    Use smaller one then.
!    */
  
  #ifndef LABEL_ALIGN
  #define LABEL_ALIGN(LABEL) 0
*************** final_addr_vec_align (addr_vec)
*** 842,861 ****
  
  #define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)])
  
! static int min_labelno, max_labelno;
  
! #define LABEL_TO_ALIGNMENT(LABEL) \
!   (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].alignment)
! 
! #define LABEL_TO_MAX_SKIP(LABEL) \
!   (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].max_skip)
  
  /* For the benefit of port specific code do this also as a function.  */
  int
  label_to_alignment (label)
       rtx label;
  {
!   return LABEL_TO_ALIGNMENT (label);
  }
  
  #ifdef HAVE_ATTR_length
--- 864,881 ----
  
  #define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)])
  
! #define INSN_TO_ALIGNMENT(INSN) \
!   (insn_align[INSN_UID (INSN)].alignment)
  
! #define INSN_TO_MAX_SKIP(INSN) \
!   (insn_align[INSN_UID (INSN)].max_skip)
  
  /* For the benefit of port specific code do this also as a function.  */
  int
  label_to_alignment (label)
       rtx label;
  {
!   return INSN_TO_ALIGNMENT (label);
  }
  
  #ifdef HAVE_ATTR_length
*************** label_to_alignment (label)
*** 887,920 ****
     GROWTH should be ~0 if the objective is to compute potential code size
     increase, and 0 if the objective is to compute potential shrink.
     The return value is undefined for any other value of GROWTH.  */
! int
! align_fuzz (start, end, known_align_log, growth)
       rtx start, end;
       int known_align_log;
       unsigned growth;
  {
    int uid = INSN_UID (start);
!   rtx align_label;
    int known_align = 1 << known_align_log;
    int end_shuid = INSN_SHUID (end);
    int fuzz = 0;
  
!   for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid])
      {
        int align_addr, new_align;
  
!       uid = INSN_UID (align_label);
!       align_addr = insn_addresses[uid] - insn_lengths[uid];
        if (uid_shuid[uid] > end_shuid)
  	break;
!       known_align_log = LABEL_TO_ALIGNMENT (align_label);
        new_align = 1 << known_align_log;
!       if (new_align < known_align)
! 	continue;
!       fuzz += (-align_addr ^ growth) & (new_align - known_align);
!       known_align = new_align;
      }
!   return fuzz;
  }
  
  /* Compute a worst-case reference address of a branch so that it
--- 907,967 ----
     GROWTH should be ~0 if the objective is to compute potential code size
     increase, and 0 if the objective is to compute potential shrink.
     The return value is undefined for any other value of GROWTH.  */
! static int
! align_fuzz (start, end, known_align_log, known_max_skip, growth)
       rtx start, end;
       int known_align_log;
+      int known_max_skip;
       unsigned growth;
  {
    int uid = INSN_UID (start);
!   int currentfuzz;
!   int currentfuzz_max_skip;
!   rtx align_insn;
    int known_align = 1 << known_align_log;
    int end_shuid = INSN_SHUID (end);
    int fuzz = 0;
+   int fuzz_max_skip = 0;
+   int max_skip_fuzz = 0;
+   int max_skip;
+ 
+   /* With max_skip start we can't say much about the alignemnt.  */
+   if (known_max_skip) known_align = 1;
  
!   for (align_insn = uid_align[uid]; align_insn; align_insn = uid_align[uid])
      {
        int align_addr, new_align;
  
!       uid = INSN_UID (align_insn);
        if (uid_shuid[uid] > end_shuid)
  	break;
!       known_align_log = INSN_TO_ALIGNMENT (align_insn);
!       max_skip = INSN_TO_MAX_SKIP (align_insn);
        new_align = 1 << known_align_log;
! 
!       /* Calculate maximal padding that can be added / removed.  */
! 
!       if (new_align <= known_align) 
!         currentfuzz = 0;
!       else
!         currentfuzz = (insn_align_lengths [uid] ^ growth) & (new_align - known_align);
!       currentfuzz_max_skip = (insn_align_lengths [uid] ^ growth) & (new_align - 1);
! 
!       /* When fuzz_max_skip guess is better than fuzz guess even after extra
!          overhead caused by forcing the alignment, use it.  */
!       if (fuzz + currentfuzz > fuzz_max_skip + currentfuzz_max_skip)
! 	fuzz = fuzz_max_skip + currentfuzz_max_skip;
!       else
! 	fuzz += currentfuzz;
! 
!       if (max_skip && currentfuzz_max_skip > max_skip)
! 	currentfuzz = max_skip;
!       fuzz_max_skip += currentfuzz_max_skip;
! 
!       /* Choose better guess.  */
!       if (fuzz_max_skip > fuzz) fuzz_max_skip = fuzz;
      }
!   return fuzz_max_skip;
  }
  
  /* Compute a worst-case reference address of a branch so that it
*************** insn_current_reference_address (branch)
*** 947,960 ****
    if (INSN_SHUID (branch) < INSN_SHUID (dest))
      {
        /* Forward branch. */
!       return (insn_last_address + insn_lengths[seq_uid]
! 	      - align_fuzz (seq, dest, length_unit_log, ~0));
      }
    else
      {
        /* Backward branch. */
        return (insn_current_address
! 	      + align_fuzz (dest, seq, length_unit_log, ~0));
      }
  }
  #endif /* HAVE_ATTR_length */
--- 994,1007 ----
    if (INSN_SHUID (branch) < INSN_SHUID (dest))
      {
        /* Forward branch. */
!       return (insn_last_address + insn_align_lengths[seq_uid]
! 	      - align_fuzz (seq, dest, length_unit_log, 0, ~0));
      }
    else
      {
        /* Backward branch. */
        return (insn_current_address
! 	      + align_fuzz (dest, seq, length_unit_log, 0, ~0));
      }
  }
  #endif /* HAVE_ATTR_length */
*************** insn_current_reference_address (branch)
*** 967,972 ****
--- 1014,1069 ----
  #ifndef FIRST_INSN_ADDRESS
  #define FIRST_INSN_ADDRESS 0
  #endif
+ /* Merge two alignments to single alignment.  In case this is inpossible,
+    do approximation.  */
+ static void
+ merge_alignment (align, max_skip, destalign1, destmax_skip1)
+      int align;
+      int max_skip;
+      short *destalign1;
+      short *destmax_skip1;
+ {
+   /* Avoid unnecesary memory references.  */
+   int destalign = *destalign1;
+   int destmax_skip = *destmax_skip1;
+ 
+   if (!align)
+     return;
+ 
+   if (max_skip >= (1 << align) || max_skip < 0 || align < 0 || align > 32
+       || destmax_skip >= (1 << destalign) || destmax_skip < 0
+       || destalign < 0 || destalign > 32)
+     abort ();
+ 
+ #ifndef ASM_OUTPUT_MAX_SKIP_ALIGN
+   /* Nice simple world w/o max_skip.  */
+   if (align < destalign)
+     return;
+   *destalign1 = align;
+ #else
+ 
+   if (!destalign)
+     {
+       *destalign1 = align;
+       *destmax_skip1 = max_skip;
+       return;
+     }
+ 
+   /* Recalculate max_skip to remaining values.  */
+   if (destmax_skip)
+     destmax_skip = (1 << destalign) - destmax_skip - 1;
+   if (max_skip)
+     max_skip = (1 << align) - max_skip - 1;
+ 
+   destalign = align < destalign ? destalign : align;
+   destmax_skip = ((1 << destalign)
+ 		  - (max_skip < destmax_skip ? max_skip : destmax_skip)) - 1;
+   if (destmax_skip == (1 << destalign) - 1)
+     destmax_skip = 0;
+   *destmax_skip1 = destmax_skip;
+   *destalign1 = destalign;
+ #endif
+ }
  
  /* shorten_branches might be called multiple times:  for example, the SH
     port splits out-of-range conditional branches in MACHINE_DEPENDENT_REORG.
*************** shorten_branches (first)
*** 983,990 ****
    rtx insn;
    int max_uid;
    int i;
!   int max_log;
!   int max_skip;
  #ifdef HAVE_ATTR_length
  #define MAX_CODE_ALIGN 16
    rtx seq;
--- 1080,1087 ----
    rtx insn;
    int max_uid;
    int i;
!   short max_log;
!   short max_skip;
  #ifdef HAVE_ATTR_length
  #define MAX_CODE_ALIGN 16
    rtx seq;
*************** shorten_branches (first)
*** 992,998 ****
    char *varying_length;
    rtx body;
    int uid;
!   rtx align_tab[MAX_CODE_ALIGN];
  
    /* In order to make sure that all instructions have valid length info,
       we must split them before we compute the address/length info.  */
--- 1089,1098 ----
    char *varying_length;
    rtx body;
    int uid;
!   rtx last_align;
! 
!   /* Compute maximum UID and allocate insn_align / uid_shuid.  */
!   max_uid = get_max_uid ();
  
    /* In order to make sure that all instructions have valid length info,
       we must split them before we compute the address/length info.  */
*************** shorten_branches (first)
*** 1019,1037 ****
  
    init_insn_lengths ();
  
!   /* Compute maximum UID and allocate label_align / uid_shuid.  */
!   max_uid = get_max_uid ();
! 
!   max_labelno = max_label_num ();
!   min_labelno = get_first_label_num ();
!   label_align = (struct label_alignment *) xmalloc (
!     (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
!   bzero ((char *) label_align,
!     (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
  
    uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
  
!   /* Initialize label_align and set up uid_shuid to be strictly
       monotonically rising with insn order.  */
    /* We use max_log here to keep track of the maximum alignment we want to
       impose on the next CODE_LABEL (or the current one if we are processing
--- 1119,1133 ----
  
    init_insn_lengths ();
  
!   insn_align = (struct insn_alignment *) xmalloc (
!     (max_uid + 1) * sizeof (struct insn_alignment));
!   insn_align_max_uid = max_uid;
!   bzero ((char *) insn_align,
!     (max_uid + 1) * sizeof (struct insn_alignment));
  
    uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
  
!   /* Initialize insn_align and set up uid_shuid to be strictly
       monotonically rising with insn order.  */
    /* We use max_log here to keep track of the maximum alignment we want to
       impose on the next CODE_LABEL (or the current one if we are processing
*************** shorten_branches (first)
*** 1045,1050 ****
--- 1141,1167 ----
        int log;
  
        INSN_SHUID (insn) = i++;
+ #ifdef INSN_ALIGNMENT
+       if (GET_CODE (insn) == INSN)
+ 	{
+ 	  int align, max_skip;
+ 	  INSN_ALIGNMENT (insn, &align, &max_skip);
+ 	  if (align)
+ 	    {
+ 	      rtx insn2 = prev_nonnote_insn (insn);
+ 	      if (insn2 && GET_CODE (insn2) == CODE_LABEL)
+ 	        merge_alignment (align, max_skip, &INSN_TO_ALIGNMENT (insn2),
+ 			         &INSN_TO_MAX_SKIP (insn2));
+ 	      else 
+ 	        {
+ 		  INSN_TO_ALIGNMENT (insn) = align;
+ #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+ 		  INSN_TO_MAX_SKIP (insn) = max_skip;
+ #endif
+ 	        }
+ 	    }
+ 	}
+ #endif
        if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
  	{
  	  /* reorg might make the first insn of a loop being run once only,
*************** shorten_branches (first)
*** 1058,1068 ****
  	  rtx next;
  
  	  log = LABEL_ALIGN (insn);
! 	  if (max_log < log)
! 	    {
! 	      max_log = log;
! 	      max_skip = LABEL_ALIGN_MAX_SKIP;
! 	    }
  	  next = NEXT_INSN (insn);
  	  /* ADDR_VECs only take room if read-only data goes into the text
  	     section.  */
--- 1175,1182 ----
  	  rtx next;
  
  	  log = LABEL_ALIGN (insn);
! 	  merge_alignment (log, LABEL_ALIGN_MAX_SKIP, 
! 			   &max_log, &max_skip);
  	  next = NEXT_INSN (insn);
  	  /* ADDR_VECs only take room if read-only data goes into the text
  	     section.  */
*************** shorten_branches (first)
*** 1078,1092 ****
  		    || GET_CODE (nextbody) == ADDR_DIFF_VEC)
  		  {
  		    log = ADDR_VEC_ALIGN (next);
! 		    if (max_log < log)
! 		      {
! 			max_log = log;
! 			max_skip = LABEL_ALIGN_MAX_SKIP;
! 		      }
  		  }
  	      }
! 	  LABEL_TO_ALIGNMENT (insn) = max_log;
! 	  LABEL_TO_MAX_SKIP (insn) = max_skip;
  	  max_log = 0;
  	  max_skip = 0;
  	}
--- 1192,1203 ----
  		    || GET_CODE (nextbody) == ADDR_DIFF_VEC)
  		  {
  		    log = ADDR_VEC_ALIGN (next);
! 		    merge_alignment (log, LABEL_ALIGN_MAX_SKIP, 
! 				     &max_log, &max_skip);
  		  }
  	      }
! 	  merge_alignment (max_log, max_skip, &INSN_TO_ALIGNMENT (insn),
! 			   &INSN_TO_MAX_SKIP (insn));
  	  max_log = 0;
  	  max_skip = 0;
  	}
*************** shorten_branches (first)
*** 1098,1109 ****
  	       label = NEXT_INSN (label))
  	    if (GET_CODE (label) == CODE_LABEL)
  	      {
! 		log = LABEL_ALIGN_AFTER_BARRIER (insn);
! 		if (max_log < log)
! 		  {
! 		    max_log = log;
! 		    max_skip = LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP;
! 		  }
  		break;
  	      }
  	}
--- 1209,1217 ----
  	       label = NEXT_INSN (label))
  	    if (GET_CODE (label) == CODE_LABEL)
  	      {
! 		log = LABEL_ALIGN_AFTER_BARRIER (label);
! 		merge_alignment (log, LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP, 
! 				 &max_log, &max_skip);
  		break;
  	      }
  	}
*************** shorten_branches (first)
*** 1117,1128 ****
  	  for (label = insn; label; label = NEXT_INSN (label))
  	    if (GET_CODE (label) == CODE_LABEL)
  	      {
! 		log = LOOP_ALIGN (insn);
! 		if (max_log < log)
! 		  {
! 		    max_log = log;
! 		    max_skip = LOOP_ALIGN_MAX_SKIP;
! 		  }
  		break;
  	      }
  	}
--- 1225,1233 ----
  	  for (label = insn; label; label = NEXT_INSN (label))
  	    if (GET_CODE (label) == CODE_LABEL)
  	      {
! 		log = LOOP_ALIGN (label);
! 		merge_alignment (log, LOOP_ALIGN_MAX_SKIP, 
! 				 &max_log, &max_skip);
  		break;
  	      }
  	}
*************** shorten_branches (first)
*** 1133,1138 ****
--- 1238,1244 ----
  
    /* Allocate the rest of the arrays.  */
    insn_lengths = (short *) xmalloc (max_uid * sizeof (short));
+   insn_align_lengths = (short *) xmalloc (max_uid * sizeof (short));
    insn_addresses = (int *) xmalloc (max_uid * sizeof (int));
    insn_lengths_max_uid = max_uid;
    /* Syntax errors can lead to labels being outside of the main insn stream.
*************** shorten_branches (first)
*** 1144,1172 ****
  
    bzero (varying_length, max_uid);
  
!   /* Initialize uid_align.  We scan instructions
!      from end to start, and keep in align_tab[n] the last seen insn
!      that does an alignment of at least n+1, i.e. the successor
!      in the alignment chain for an insn that does / has a known
!      alignment of n.  */
  
    bzero ((char *) uid_align, max_uid * sizeof *uid_align);
  
!   for (i = MAX_CODE_ALIGN; --i >= 0; )
!     align_tab[i] = NULL_RTX;
    seq = get_last_insn ();
    for (; seq; seq = PREV_INSN (seq))
      {
        int uid = INSN_UID (seq);
        int log;
!       log = (GET_CODE (seq) == CODE_LABEL ? LABEL_TO_ALIGNMENT (seq) : 0);
!       uid_align[uid] = align_tab[0];
        if (log)
  	{
  	  /* Found an alignment label.  */
! 	  uid_align[uid] = align_tab[log];
! 	  for (i = log - 1; i >= 0; i--)
! 	    align_tab[i] = seq;
  	}
      }
  #ifdef CASE_VECTOR_SHORTEN_MODE
--- 1250,1273 ----
  
    bzero (varying_length, max_uid);
  
!   /* Initialize uid_align.  */
  
    bzero ((char *) uid_align, max_uid * sizeof *uid_align);
  
!   last_align = NULL_RTX;
    seq = get_last_insn ();
    for (; seq; seq = PREV_INSN (seq))
      {
        int uid = INSN_UID (seq);
        int log;
!       log = INSN_TO_ALIGNMENT (seq);
!       uid_align[uid] = last_align;
        if (log)
  	{
  	  /* Found an alignment label.  */
! 	  if (INSN_TO_MAX_SKIP (seq)) log=0;
! 	  uid_align[uid] = last_align;
! 	  last_align = seq;
  	}
      }
  #ifdef CASE_VECTOR_SHORTEN_MODE
*************** shorten_branches (first)
*** 1208,1215 ****
  		  max = shuid;
  		  max_lab = lab;
  		}
! 	      if (min_align > LABEL_TO_ALIGNMENT (lab))
! 		min_align = LABEL_TO_ALIGNMENT (lab);
  	    }
  	  XEXP (pat, 2) = gen_rtx_LABEL_REF (VOIDmode, min_lab);
  	  XEXP (pat, 3) = gen_rtx_LABEL_REF (VOIDmode, max_lab);
--- 1309,1316 ----
  		  max = shuid;
  		  max_lab = lab;
  		}
! 	      if (min_align > INSN_TO_ALIGNMENT (lab))
! 		min_align = INSN_TO_ALIGNMENT (lab);
  	    }
  	  XEXP (pat, 2) = gen_rtx_LABEL_REF (VOIDmode, min_lab);
  	  XEXP (pat, 3) = gen_rtx_LABEL_REF (VOIDmode, max_lab);
*************** shorten_branches (first)
*** 1232,1249 ****
         insn != 0;
         insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
      {
        uid = INSN_UID (insn);
  
        insn_lengths[uid] = 0;
  
!       if (GET_CODE (insn) == CODE_LABEL)
  	{
! 	  int log = LABEL_TO_ALIGNMENT (insn);
! 	  if (log)
  	    {
! 	      int align = 1 << log;
! 	      int new_address = (insn_current_address + align - 1) & -align;
! 	      insn_lengths[uid] = new_address - insn_current_address;
  	      insn_current_address = new_address;
  	    }
  	}
--- 1333,1353 ----
         insn != 0;
         insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
      {
+       int log = INSN_TO_ALIGNMENT (insn);
        uid = INSN_UID (insn);
  
        insn_lengths[uid] = 0;
+       insn_align_lengths[uid] = 0;
  
!       if (log)
  	{
! 	  int align = 1 << log;
! 	  int new_address = (insn_current_address + align - 1) & -align;
! 	  int max_skip = INSN_TO_MAX_SKIP (insn);
! 
! 	  if (!max_skip || new_address - insn_current_address <= max_skip)
  	    {
! 	      insn_align_lengths[uid] = new_address - insn_current_address;
  	      insn_current_address = new_address;
  	    }
  	}
*************** shorten_branches (first)
*** 1303,1310 ****
  		  if ((varying_length[inner_uid]
  		       = insn_variable_length_p (inner_insn)) != 0)
  		    varying_length[uid] = 1;
! 		  insn_addresses[inner_uid] = (insn_current_address +
! 					       insn_lengths[uid]);
  		}
  	      else
  		varying_length[inner_uid] = 0;
--- 1407,1413 ----
  		  if ((varying_length[inner_uid]
  		       = insn_variable_length_p (inner_insn)) != 0)
  		    varying_length[uid] = 1;
! 		  insn_addresses[inner_uid] = (insn_current_address + insn_lengths[uid]);
  		}
  	      else
  		varying_length[inner_uid] = 0;
*************** shorten_branches (first)
*** 1342,1374 ****
  	  int tmp_length;
  #endif
  	  int length_align;
  
  	  uid = INSN_UID (insn);
  
! 	  if (GET_CODE (insn) == CODE_LABEL)
  	    {
! 	      int log = LABEL_TO_ALIGNMENT (insn);
! 	      if (log > insn_current_align)
! 		{
! 		  int align = 1 << log;
! 		  int new_address= (insn_current_address + align - 1) & -align;
! 		  insn_lengths[uid] = new_address - insn_current_address;
  		  insn_current_align = log;
! 		  insn_current_address = new_address;
! 		}
! 	      else
! 		insn_lengths[uid] = 0;
! 	      insn_addresses[uid] = insn_current_address;
! 	      continue;
  	    }
  
  	  length_align = INSN_LENGTH_ALIGNMENT (insn);
  	  if (length_align < insn_current_align)
  	    insn_current_align = length_align;
  
- 	  insn_last_address = insn_addresses[uid];
- 	  insn_addresses[uid] = insn_current_address;
- 
  #ifdef CASE_VECTOR_SHORTEN_MODE
  	  if (optimize && GET_CODE (insn) == JUMP_INSN
  	      && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
--- 1445,1478 ----
  	  int tmp_length;
  #endif
  	  int length_align;
+ 	  int log = INSN_TO_ALIGNMENT (insn);
  
  	  uid = INSN_UID (insn);
  
! 	  insn_align_lengths[uid] = 0;
! 	  if (log > insn_current_align)
  	    {
! 	      int align = 1 << log;
! 	      int new_address = (insn_current_address + align - 1) & -align;
! 	      int max_skip = INSN_TO_MAX_SKIP (insn);
! 
! 	      if (!max_skip || new_address - insn_current_address <= max_skip)
! 	        {
  		  insn_current_align = log;
! 		  insn_align_lengths[uid] = new_address - insn_current_address;
! 	        }
  	    }
+ 	  insn_current_address += insn_align_lengths[uid];
+ 	  insn_last_address = insn_addresses[uid];
+ 	  insn_addresses[uid] = insn_current_address;
+ 
+ 	  if (GET_CODE (insn) == CODE_LABEL)
+ 	      continue;
  
  	  length_align = INSN_LENGTH_ALIGNMENT (insn);
  	  if (length_align < insn_current_align)
  	    insn_current_align = length_align;
  
  #ifdef CASE_VECTOR_SHORTEN_MODE
  	  if (optimize && GET_CODE (insn) == JUMP_INSN
  	      && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
*************** shorten_branches (first)
*** 1384,1389 ****
--- 1488,1494 ----
  	      int max_addr = insn_addresses[INSN_UID (max_lab)];
  	      rtx prev;
  	      int rel_align = 0;
+ 	      int rel_max_skip = 0;
  
  	      /* Try to find a known alignment for rel_lab.  */
  	      for (prev = rel_lab;
*************** shorten_branches (first)
*** 1393,1399 ****
  		   prev = PREV_INSN (prev))
  		if (varying_length[INSN_UID (prev)] & 2)
  		  {
! 		    rel_align = LABEL_TO_ALIGNMENT (prev);
  		    break;
  		  }
  
--- 1498,1505 ----
  		   prev = PREV_INSN (prev))
  		if (varying_length[INSN_UID (prev)] & 2)
  		  {
! 		    rel_align = INSN_TO_ALIGNMENT (prev);
! 		    rel_max_skip = INSN_TO_MAX_SKIP (prev);
  		    break;
  		  }
  
*************** shorten_branches (first)
*** 1421,1441 ****
  		     it up into two parts that are independent.  */
  		  if (! flags.base_after_vec && flags.min_after_vec)
  		    {
! 		      min_addr -= align_fuzz (rel_lab, insn, rel_align, 0);
! 		      min_addr -= align_fuzz (insn, min_lab, 0, 0);
  		    }
  		  else
! 		    min_addr -= align_fuzz (rel_lab, min_lab, rel_align, 0);
  		}
  	      else
  		{
  		  if (flags.base_after_vec && ! flags.min_after_vec)
  		    {
! 		      min_addr -= align_fuzz (min_lab, insn, 0, ~0);
! 		      min_addr -= align_fuzz (insn, rel_lab, 0, ~0);
  		    }
  		  else
! 		    min_addr -= align_fuzz (min_lab, rel_lab, 0, ~0);
  		}
  	      /* Likewise, determine the highest lowest possible value
  		 for the offset of MAX_LAB.  */
--- 1527,1547 ----
  		     it up into two parts that are independent.  */
  		  if (! flags.base_after_vec && flags.min_after_vec)
  		    {
! 		      min_addr -= align_fuzz (rel_lab, insn, rel_align, rel_max_skip, 0);
! 		      min_addr -= align_fuzz (insn, min_lab, 0, 0, 0);
  		    }
  		  else
! 		    min_addr -= align_fuzz (rel_lab, min_lab, rel_align, rel_max_skip, 0);
  		}
  	      else
  		{
  		  if (flags.base_after_vec && ! flags.min_after_vec)
  		    {
! 		      min_addr -= align_fuzz (min_lab, insn, 0, 0, ~0);
! 		      min_addr -= align_fuzz (insn, rel_lab, 0, 0, ~0);
  		    }
  		  else
! 		    min_addr -= align_fuzz (min_lab, rel_lab, 0, 0, ~0);
  		}
  	      /* Likewise, determine the highest lowest possible value
  		 for the offset of MAX_LAB.  */
*************** shorten_branches (first)
*** 1443,1463 ****
  		{
  		  if (! flags.base_after_vec && flags.max_after_vec)
  		    {
! 		      max_addr += align_fuzz (rel_lab, insn, rel_align, ~0);
! 		      max_addr += align_fuzz (insn, max_lab, 0, ~0);
  		    }
  		  else
! 		    max_addr += align_fuzz (rel_lab, max_lab, rel_align, ~0);
  		}
  	      else
  		{
  		  if (flags.base_after_vec && ! flags.max_after_vec)
  		    {
! 		      max_addr += align_fuzz (max_lab, insn, 0, 0);
! 		      max_addr += align_fuzz (insn, rel_lab, 0, 0);
  		    }
  		  else
! 		    max_addr += align_fuzz (max_lab, rel_lab, 0, 0);
  		}
  	      PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
  							max_addr - rel_addr,
--- 1549,1569 ----
  		{
  		  if (! flags.base_after_vec && flags.max_after_vec)
  		    {
! 		      max_addr += align_fuzz (rel_lab, insn, rel_align, rel_max_skip, ~0);
! 		      max_addr += align_fuzz (insn, max_lab, 0, 0, ~0);
  		    }
  		  else
! 		    max_addr += align_fuzz (rel_lab, max_lab, rel_align, rel_max_skip, ~0);
  		}
  	      else
  		{
  		  if (flags.base_after_vec && ! flags.max_after_vec)
  		    {
! 		      max_addr += align_fuzz (max_lab, insn, 0, 0, 0);
! 		      max_addr += align_fuzz (insn, rel_lab, 0, 0, 0);
  		    }
  		  else
! 		    max_addr += align_fuzz (max_lab, rel_lab, 0, 0, 0);
  		}
  	      PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
  							max_addr - rel_addr,
*************** final_scan_insn (insn, file, optimize, p
*** 2051,2056 ****
--- 2157,2182 ----
    if (INSN_DELETED_P (insn))
      return NEXT_INSN (insn);
  
+   if (INSN_UID (insn) <= insn_align_max_uid)
+      {
+        int align = INSN_TO_ALIGNMENT (insn);
+ #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+        int max_skip = INSN_TO_MAX_SKIP (insn);
+ #endif
+ #if 0
+        if (insn_addresses && GET_CODE (insn) == INSN) 
+ 	 fprintf (asm_out_file, "\t # address: %x length: %i\n", insn_addresses[INSN_UID (insn)], get_attr_length (insn));
+ #endif
+ 
+        if (align)
+ 	 {
+ #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+            ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
+ #else
+            ASM_OUTPUT_ALIGN (file, align);
+ #endif
+        	}
+      }
    switch (GET_CODE (insn))
      {
      case NOTE:
*************** final_scan_insn (insn, file, optimize, p
*** 2285,2306 ****
        break;
  
      case CODE_LABEL:
-       /* The target port might emit labels in the output function for
- 	 some insn, e.g. sh.c output_branchy_insn.  */
-       if (CODE_LABEL_NUMBER (insn) <= max_labelno)
- 	{
- 	  int align = LABEL_TO_ALIGNMENT (insn);
- #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
- 	  int max_skip = LABEL_TO_MAX_SKIP (insn);
- #endif
- 
- 	  if (align && NEXT_INSN (insn))
- #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
- 	    ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
- #else
- 	    ASM_OUTPUT_ALIGN (file, align);
- #endif
- 	}
  #ifdef HAVE_cc0
        CC_STATUS_INIT;
        /* If this label is reached from only one place, set the condition
--- 2411,2416 ----
*** tm.texi2	Tue Jul 20 13:40:04 1999
--- tm.texi	Tue Jul 20 14:04:34 1999
*************** The alignment (log base 2) to put in fro
*** 6462,6467 ****
--- 6462,6471 ----
  If LABEL_ALIGN_AFTER_BARRIER / LOOP_ALIGN specify a different alignment,
  the maximum of the specified values is used.
  
+ @findex INSN_ALIGNMENT
+ @item INSN_ALIGNMENT (@var{label})
+ The alignment (log base 2) to put in front of @var{insn}.
+ 
  @findex ASM_OUTPUT_SKIP
  @item ASM_OUTPUT_SKIP (@var{stream}, @var{nbytes})
  A C statement to output to the stdio stream @var{stream} an assembler


More information about the Gcc-patches mailing list