Serious code size regression from 3.0.2 to now

Joern Rennecke joern.rennecke@superh.com
Thu Jul 18 06:18:00 GMT 2002


tm wrote:
> Basically, GCC is now generating HUGE groups of jump instructions which
> are aligned to 32-byte boundaries.

Was it not generating these lone jump instructions before,
or did it align them less?
> 
> Can we possibly avoid aligning single jump instructions on 32-byte
> boundaries? This is seriously torpedoing the SH2-4 code density.

Yes, when we determine the alignment of a label after a barrier, we could limit
the alignment to the smallest power of two that is as least as large as the EBB
(extended basic block) that the label is in front of.
However, that could lead to trouble when reorg blows up the basic block size and
we end up with an out-of-range branch.  Unless we do this alignment limiting
only after reorg.

More effective still would be to use a max_skip that is one smaller than the EBB.
(Provided the EBB is smaller than a cache line.)
But the support for max_skip in branch shortening is lacking.
The issue is that align_fuzz assumes that a particular alignment is known, when
it is not actually known due to the possible alignment anullment due to max_skip.
We can't just use a known alignment of 0 in align_fuzz, since this would destroy
the base address independence of the maximum length calculations, i.e. would lead
to infinite loops and length underestimations.  We want align_fuzz to add in a
number that is independent of th current relaxation state.
That would be the allegedly known alignment - capped to the extent to which it
is potentially used, i.e. the potential maximum skip saved during the traversal
of the alignments between START and END - minus the actually known alignment,
i.e. what we know due to insn size granularity, due to hard (i.e. max-skip free)
alignments, or due to more elaborated alignment calculations if we feel like adding
these.

Something along the lines of the attached patch.
	
-- 
--------------------------
SuperH
2430 Aztec West / Almondsbury / BRISTOL / BS32 4AQ
T:+44 1454 462330
-------------- next part --------------
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.262
diff -p -u -r1.262 final.c
--- final.c	17 Jun 2002 17:47:20 -0000	1.262
+++ final.c	18 Jul 2002 12:16:13 -0000
@@ -235,7 +235,7 @@ static int alter_cond		PARAMS ((rtx));
 static int final_addr_vec_align PARAMS ((rtx));
 #endif
 #ifdef HAVE_ATTR_length
-static int align_fuzz		PARAMS ((rtx, rtx, int, unsigned));
+static int align_fuzz		PARAMS ((rtx, rtx, int, int, unsigned));
 #endif
 
 /* Initialize data in final at the beginning of a compilation.  */
@@ -845,26 +845,29 @@ label_to_alignment (label)
 /* Compute the maximum delta by which the difference of the addresses of
    START and END might grow / shrink due to a different address for start
    which changes the size of alignment insns between START and END.
-   KNOWN_ALIGN_LOG is the alignment known for START.
+   KNOWN_ALIGN_LOG is the alignment known for START, and MAX_SKIP
+   the associated max_skip value.
    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, growth)
+align_fuzz (start, end, known_align_log, max_skip, growth)
      rtx start, end;
-     int known_align_log;
+     int known_align_log, max_skip;
      unsigned growth;
 {
   int uid = INSN_UID (start);
   rtx align_label;
   int known_align = 1 << known_align_log;
+  int start_align = known_align;
   int end_shuid = INSN_SHUID (end);
   int fuzz = 0;
+  int new_align = 1;
 
   for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid])
     {
-      int align_addr, new_align;
+      int align_addr;
 
       uid = INSN_UID (align_label);
       align_addr = INSN_ADDRESSES (uid) - insn_lengths[uid];
@@ -877,6 +880,12 @@ align_fuzz (start, end, known_align_log,
       fuzz += (-align_addr ^ growth) & (new_align - known_align);
       known_align = new_align;
     }
+  if (max_skip)
+    {
+      if (start_align > new_align)
+	start_align = new_align;
+      fuzz += start_align - (1 << length_unit_log);
+    }
   return fuzz;
 }
 
@@ -919,13 +928,13 @@ insn_current_reference_address (branch)
     {
       /* Forward branch.  */
       return (insn_last_address + insn_lengths[seq_uid]
-	      - align_fuzz (seq, dest, length_unit_log, ~0));
+	      - align_fuzz (seq, dest, length_unit_log, 0, ~0));
     }
   else
     {
       /* Backward branch.  */
       return (insn_current_address
-	      + align_fuzz (dest, seq, length_unit_log, ~0));
+	      + align_fuzz (dest, seq, length_unit_log, 0, ~0));
     }
 }
 #endif /* HAVE_ATTR_length */
@@ -1261,11 +1270,13 @@ shorten_branches (first)
       if (GET_CODE (insn) == CODE_LABEL)
 	{
 	  int log = LABEL_TO_ALIGNMENT (insn);
+	  int max_skip = LABEL_TO_MAX_SKIP (insn);
 	  if (log)
 	    {
 	      int align = 1 << log;
 	      int new_address = (insn_current_address + align - 1) & -align;
-	      insn_lengths[uid] = new_address - insn_current_address;
+	      if (! max_skip || new_address - insn_current_address <= max_skip)
+		insn_lengths[uid] = new_address - insn_current_address;
 	    }
 	}
 
@@ -1366,10 +1377,13 @@ shorten_branches (first)
 	  if (GET_CODE (insn) == CODE_LABEL)
 	    {
 	      int log = LABEL_TO_ALIGNMENT (insn);
+	      int max_skip = LABEL_TO_MAX_SKIP (insn);
 	      if (log > insn_current_align)
 		{
 		  int align = 1 << log;
 		  int new_address= (insn_current_address + align - 1) & -align;
+		  if (max_skip && new_address - insn_current_address > max_skip)
+		    new_address = insn_current_address;
 		  insn_lengths[uid] = new_address - insn_current_address;
 		  insn_current_align = log;
 		  insn_current_address = new_address;
@@ -1401,6 +1415,7 @@ shorten_branches (first)
 	      int max_addr = INSN_ADDRESSES (INSN_UID (max_lab));
 	      rtx prev;
 	      int rel_align = 0;
+	      int rel_max_skip = 0;
 	      addr_diff_vec_flags flags;
 
 	      /* Avoid automatic aggregate initialization.  */
@@ -1415,6 +1430,7 @@ shorten_branches (first)
 		if (varying_length[INSN_UID (prev)] & 2)
 		  {
 		    rel_align = LABEL_TO_ALIGNMENT (prev);
+		    rel_max_skip = LABEL_TO_MAX_SKIP (prev);
 		    break;
 		  }
 
@@ -1442,21 +1458,23 @@ shorten_branches (first)
 		     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);
+		      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, 0);
+		    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);
-		      min_addr -= align_fuzz (insn, rel_lab, 0, ~0);
+		      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);
+		    min_addr -= align_fuzz (min_lab, rel_lab, 0, 0, ~0);
 		}
 	      /* Likewise, determine the highest lowest possible value
 		 for the offset of MAX_LAB.  */
@@ -1464,21 +1482,23 @@ shorten_branches (first)
 		{
 		  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);
+		      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, ~0);
+		    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);
-		      max_addr += align_fuzz (insn, rel_lab, 0, 0);
+		      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);
+		    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,


More information about the Gcc-bugs mailing list