i386 code label alignment patch

John Wehle john@feith.com
Mon May 4 10:53:00 GMT 1998


Hello,

This change implements the alignment of code labels following
the recommendations of the "Intel Architecture Optimization Manual".
This change seem to be worth about 33% speed increase in the simple
case of:

  main()
    {
    int a;
    int i;

    a = 0;
    for (i = 0; i < 1000000000; i++)
      a += i;

    return a;
    }

ChangeLog:

Sun May  3 21:52:18 EDT 1998  John Wehle  (john@feith.com)

	* acconfig.h (GAS_MAJOR_VERSION, GAS_MINOR_VERSION): New tag.
	* configure.in: Determine gas version.
	* i386/gas.h (ASM_OUTPUT_ALIGN,
	ASM_OUTPUT_LABEL_ALIGN_AFTER_BARRIER,
	ASM_OUTPUT_LOOP_ALIGN): Define based on gas version.
	* final.c (uid_align, uid_shuid, label_align): Make static.
	(label_align): Change type to struct label_alignment pointer.
	(LABEL_TO_ALIGNMENT, shorten_branches): Update due to type change.
	(LABEL_TO_ALIGNMENT_CODE): Define.
	(shorten_branches): Record the insn code which aligns the label.
	(final_scan_insn): Use the recorded insn code to determine the proper
	macro for aligning the label.
	* i386.c (override_options): i386_align_jumps defaults to 4 if
	ASM_OUTPUT_LABEL_ALIGN_AFTER_BARRIER is available.  Likewise
	i386_align_loops defaults to 4 if ASM_OUTPUT_LOOP_ALIGN is available.
	* i386/386bsd.h (ASM_OUTPUT_ALIGN): Delete.
	* i386/freebsd.h (ASM_OUTPUT_ALIGN): Delete.
	* i386/netbsd.h (ASM_OUTPUT_ALIGN): Delete.
	* invoke.texi: Document new i386 align-loops and align-jumps behavior.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/acconfig.h.ORIGINAL	Sat Apr  4 12:37:22 1998
--- gcc/acconfig.h	Sat May  2 20:46:22 1998
***************
*** 1,3 ****
--- 1,7 ----
+ /* Define if using gas. */
+ #undef GAS_MAJOR_VERSION
+ #undef GAS_MINOR_VERSION
+ 
  /* Define to "%p" if printf supports it, else machmode.h will define it.  */
  #undef HOST_PTR_PRINTF
  
*** gcc/configure.in.ORIGINAL	Fri Apr 24 10:58:22 1998
--- gcc/configure.in	Sat May  2 20:45:45 1998
***************
*** 3184,3189 ****
--- 3184,3205 ----
  #	fi
  fi
  
+ # Figure out what version of gas is being used.
+ AC_MSG_CHECKING(gas version)
+ gcc_cv_gas=as$host_exeext
+ gcc_cv_gas_major_version=
+ gcc_cv_gas_minor_verion=
+ if [[ -x as$host_exeext ]]; then
+ 	gcc_cv_gas=./as$host_exeext
+ fi
+ gcc_cv_gas_major_version=`$gcc_cv_gas -v -o conftest.o < /dev/null 2>&1 | sed -n 's/^GNU assembler version \([[0-9]]*\)\..*/\1/p'; rm -f conftest.o`
+ gcc_cv_gas_minor_version=`$gcc_cv_gas -v -o conftest.o < /dev/null 2>&1 | sed -n 's/^GNU assembler version [[0-9]]*\.\([[0-9]]*\).*/\1/p'; rm -f conftest.o`
+ AC_MSG_RESULT($gcc_cv_gas_major_version.$gcc_cv_gas_minor_version)
+ if [[ x$gcc_cv_gas_major_version != x ]]; then
+ 	AC_DEFINE_UNQUOTED(GAS_MAJOR_VERSION,$gcc_cv_gas_major_version)
+ 	AC_DEFINE_UNQUOTED(GAS_MINOR_VERSION,$gcc_cv_gas_minor_version)
+ fi
+ 
  # Figure out what language subdirectories are present.
  subdirs=
  for lang in ${srcdir}/*/config-lang.in ..
*** gcc/config/i386/gas.h.ORIGINAL	Mon Mar  2 06:54:19 1998
--- gcc/config/i386/gas.h	Sun May  3 15:28:34 1998
***************
*** 80,89 ****
     doubt or guess work, and since this file is used for both a.out and other
     file formats, we use one of them.  */
  
! #if 0 /* ??? However, not every port uses binutils 2.6 yet.  */
! #undef ASM_OUTPUT_ALIGN
! #define ASM_OUTPUT_ALIGN(FILE,LOG) \
!   if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG))
  #endif
  
  /* A C statement or statements which output an assembler instruction
--- 80,109 ----
     doubt or guess work, and since this file is used for both a.out and other
     file formats, we use one of them.  */
  
! #ifdef GAS_MAJOR_VERSION
! #  if GAS_MAJOR_VERSION > 2 || (GAS_MAJOR_VERSION == 2 && GAS_MINOR_VERSION >= 7)
! #    undef ASM_OUTPUT_ALIGN
! #    define ASM_OUTPUT_ALIGN(FILE,LOG) \
!        if ((LOG)!=0) fprintf ((FILE), "\t.p2align %d\n", (LOG))
! #  elif GAS_MAJOR_VERSION < 2
! #    undef ASM_OUTPUT_ALIGN
! #    define ASM_OUTPUT_ALIGN(FILE,LOG) \
!        if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))
! #  endif
! #endif
! 
! /* Default to skipping less than 8 bytes when aligning
!    loop entry labels or labels which are after a barrier. */
! 
! #ifdef GAS_MAJOR_VERSION
! #  if GAS_MAJOR_VERSION > 2 || (GAS_MAJOR_VERSION == 2 && GAS_MINOR_VERSION >= 8)
! #    define ASM_OUTPUT_LABEL_ALIGN_AFTER_BARRIER(FILE,LOG) \
!        if ((LOG)!=0) fprintf ((FILE), (i386_align_jumps_string ? \
!                               "\t.p2align %d\n" : "\t.p2align %d,,7\n"), (LOG))
! #    define ASM_OUTPUT_LOOP_ALIGN(FILE,LOG) \
!        if ((LOG)!=0) fprintf ((FILE), (i386_align_loops_string ? \
!                               "\t.p2align %d\n" : "\t.p2align %d,,7\n"), (LOG))
! #  endif
  #endif
  
  /* A C statement or statements which output an assembler instruction
*** gcc/final.c.ORIGINAL	Wed Apr 22 08:57:04 1998
--- gcc/final.c	Sun May  3 15:15:37 1998
***************
*** 634,642 ****
     for each insn we'll call the alignment chain of this insn in the following
     comments.  */
  
! rtx *uid_align;
! int *uid_shuid;
! short *label_align;
  
  /* Indicate that branch shortening hasn't yet been done.  */
  
--- 634,647 ----
     for each insn we'll call the alignment chain of this insn in the following
     comments.  */
  
! struct label_alignment {
!   short alignment;
!   RTX_CODE code;
! };
! 
! static rtx *uid_align;
! static int *uid_shuid;
! static struct label_alignment *label_align;
  
  /* Indicate that branch shortening hasn't yet been done.  */
  
***************
*** 811,817 ****
  static int min_labelno, max_labelno;
  
  #define LABEL_TO_ALIGNMENT(LABEL) \
!   (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno])
  
  /* For the benefit of port specific code do this also as a function.  */
  int
--- 816,825 ----
  static int min_labelno, max_labelno;
  
  #define LABEL_TO_ALIGNMENT(LABEL) \
!   (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].alignment)
! 
! #define LABEL_TO_ALIGNMENT_CODE(LABEL) \
!   (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].code)
  
  /* For the benefit of port specific code do this also as a function.  */
  int
***************
*** 947,952 ****
--- 955,961 ----
    int max_uid;
    int i;
    int max_log;
+   RTX_CODE max_log_code;
  #ifdef HAVE_ATTR_length
  #define MAX_CODE_ALIGN 16
    rtx seq;
***************
*** 986,994 ****
  
    max_labelno = max_label_num ();
    min_labelno = get_first_label_num ();
!   label_align
!     = (short*) xmalloc ((max_labelno - min_labelno + 1) * sizeof (short));
!   bzero (label_align, (max_labelno - min_labelno + 1) * sizeof (short));
  
    uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
  
--- 995,1004 ----
  
    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 (label_align,
!     (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
  
    uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
  
***************
*** 998,1004 ****
       impose on the next CODE_LABEL (or the current one if we are processing
       the CODE_LABEL itself).  */
       
!   for (max_log = 0, insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn))
      {
        int log;
  
--- 1008,1017 ----
       impose on the next CODE_LABEL (or the current one if we are processing
       the CODE_LABEL itself).  */
       
!   max_log = 0;
!   max_log_code = CODE_LABEL;
! 
!   for (insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn))
      {
        int log;
  
***************
*** 1017,1023 ****
  
  	  log = LABEL_ALIGN (insn);
  	  if (max_log < log)
! 	    max_log = log;
  	  next = NEXT_INSN (insn);
  /* ADDR_VECs only take room if read-only data goes into the text section.  */
  #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
--- 1030,1039 ----
  
  	  log = LABEL_ALIGN (insn);
  	  if (max_log < log)
! 	    {
! 	      max_log = log;
! 	      max_log_code = GET_CODE (insn);
! 	    }
  	  next = NEXT_INSN (insn);
  /* ADDR_VECs only take room if read-only data goes into the text section.  */
  #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
***************
*** 1029,1040 ****
  		{
  		  log = ADDR_VEC_ALIGN (next);
  		  if (max_log < log)
! 		    max_log = log;
  		}
  	    }
  #endif
  	  LABEL_TO_ALIGNMENT (insn) = max_log;
  	  max_log = 0;
  	}
        else if (GET_CODE (insn) == BARRIER)
  	{
--- 1045,1061 ----
  		{
  		  log = ADDR_VEC_ALIGN (next);
  		  if (max_log < log)
! 		    {
! 		      max_log = log;
! 		      max_log_code = GET_CODE (insn);
! 		    }
  		}
  	    }
  #endif
  	  LABEL_TO_ALIGNMENT (insn) = max_log;
+ 	  LABEL_TO_ALIGNMENT_CODE (insn) = max_log_code;
  	  max_log = 0;
+ 	  max_log_code = CODE_LABEL;
  	}
        else if (GET_CODE (insn) == BARRIER)
  	{
***************
*** 1046,1052 ****
  	      {
  		log = LABEL_ALIGN_AFTER_BARRIER (insn);
  		if (max_log < log)
! 		  max_log = log;
  		break;
  	      }
  	}
--- 1067,1076 ----
  	      {
  		log = LABEL_ALIGN_AFTER_BARRIER (insn);
  		if (max_log < log)
! 		  {
! 		    max_log = log;
! 		    max_log_code = GET_CODE (insn);
! 		  }
  		break;
  	      }
  	}
***************
*** 1062,1068 ****
  	      {
  		log = LOOP_ALIGN (insn);
  		if (max_log < log)
! 		  max_log = log;
  		break;
  	      }
  	}
--- 1086,1095 ----
  	      {
  		log = LOOP_ALIGN (insn);
  		if (max_log < log)
! 		  {
! 		    max_log = log;
! 		    max_log_code = GET_CODE (insn);
! 		  }
  		break;
  	      }
  	}
***************
*** 2203,2209 ****
  	  int align = LABEL_TO_ALIGNMENT (insn);
  
  	  if (align && NEXT_INSN (insn))
! 	    ASM_OUTPUT_ALIGN (file, align);
  	}
        CC_STATUS_INIT;
        if (prescan > 0)
--- 2230,2253 ----
  	  int align = LABEL_TO_ALIGNMENT (insn);
  
  	  if (align && NEXT_INSN (insn))
! 	    {
! 	      switch ( LABEL_TO_ALIGNMENT_CODE (insn) )
! 		{
! #ifdef ASM_OUTPUT_LABEL_ALIGN_AFTER_BARRIER
! 		  case BARRIER:
! 		    ASM_OUTPUT_LABEL_ALIGN_AFTER_BARRIER (file, align);
! 		    break;
! #endif
! #ifdef ASM_OUTPUT_LOOP_ALIGN
! 		  case NOTE:
! 		    ASM_OUTPUT_LOOP_ALIGN (file, align);
! 		    break;
! #endif
! 		  default:
! 		    ASM_OUTPUT_ALIGN (file, align);
! 		    break;
! 		}
! 	    }
  	}
        CC_STATUS_INIT;
        if (prescan > 0)
*** gcc/config/i386/i386.c.ORIGINAL	Mon Apr 20 03:41:41 1998
--- gcc/config/i386/i386.c	Sun May  3 13:28:55 1998
***************
*** 331,337 ****
--- 331,341 ----
  	       i386_align_loops, MAX_CODE_ALIGN);
      }
    else
+ #ifdef ASM_OUTPUT_LOOP_ALIGN
+     i386_align_loops = 4;
+ #else
      i386_align_loops = 2;
+ #endif
  
    /* Validate -malign-jumps= value, or provide default.  */
    if (i386_align_jumps_string)
***************
*** 342,348 ****
--- 346,356 ----
  	       i386_align_jumps, MAX_CODE_ALIGN);
      }
    else
+ #ifdef ASM_OUTPUT_LABEL_ALIGN_AFTER_BARRIER
+     i386_align_jumps = 4;
+ #else
      i386_align_jumps = def_align;
+ #endif
  
    /* Validate -malign-functions= value, or provide default. */
    if (i386_align_funcs_string)
*** gcc/config/i386/bsd386.h.ORIGINAL	Tue Apr 14 06:33:09 1998
--- gcc/config/i386/bsd386.h	Sat May  2 20:51:06 1998
***************
*** 24,33 ****
  /* Until they use ELF or something that handles dwarf2 unwinds
     and initialization stuff better.  */
  #define DWARF2_UNWIND_INFO 0
- 
- /* BSD/OS still uses old binutils that don't insert nops by default
-    when the .align directive demands to insert extra space in the text
-    segment.  */
- #undef ASM_OUTPUT_ALIGN
- #define ASM_OUTPUT_ALIGN(FILE,LOG) \
-   if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))
--- 24,26 ----
*** gcc/config/i386/freebsd.h.ORIGINAL	Fri Mar 27 18:23:10 1998
--- gcc/config/i386/freebsd.h	Sat May  2 20:48:57 1998
***************
*** 90,102 ****
     we want to retain compatibility with older gcc versions.  */
  #define DEFAULT_PCC_STRUCT_RETURN 0
  
- /* i386 freebsd still uses old binutils that don't insert nops by default
-    when the .align directive demands to insert extra space in the text
-    segment.  */
- #undef ASM_OUTPUT_ALIGN
- #define ASM_OUTPUT_ALIGN(FILE,LOG) \
-   if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))
- 
  /* Profiling routines, partially copied from i386/osfrose.h.  */
  
  /* Redefine this to use %eax instead of %edx.  */
--- 90,95 ----
*** gcc/config/i386/netbsd.h.ORIGINAL	Wed Mar 18 07:52:07 1998
--- gcc/config/i386/netbsd.h	Sat May  2 20:50:12 1998
***************
*** 56,68 ****
     we want to retain compatibility with older gcc versions.  */
  #define DEFAULT_PCC_STRUCT_RETURN 0
  
- /* i386 netbsd still uses old binutils that don't insert nops by default
-    when the .align directive demands to insert extra space in the text
-    segment.  */
- #undef ASM_OUTPUT_ALIGN
- #define ASM_OUTPUT_ALIGN(FILE,LOG) \
-   if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))
- 
  /* Profiling routines, partially copied from i386/osfrose.h.  */
  
  /* Redefine this to use %eax instead of %edx.  */
--- 56,61 ----
*** gcc/invoke.texi.ORIGINAL	Sun Apr 12 16:31:54 1998
--- gcc/invoke.texi	Sun May  3 22:27:13 1998
***************
*** 4879,4890 ****
  
  @item -malign-loops=@var{num}
  Align loops to a 2 raised to a @var{num} byte boundary.  If
! @samp{-malign-loops} is not specified, the default is 2.
  
  @item -malign-jumps=@var{num}
  Align instructions that are only jumped to to a 2 raised to a @var{num}
  byte boundary.  If @samp{-malign-jumps} is not specified, the default is
! 2 if optimizing for a 386, and 4 if optimizing for a 486.
  
  @item -malign-functions=@var{num}
  Align the start of functions to a 2 raised to @var{num} byte boundary.
--- 4879,4896 ----
  
  @item -malign-loops=@var{num}
  Align loops to a 2 raised to a @var{num} byte boundary.  If
! @samp{-malign-loops} is not specified, the default is 2 unless
! gas 2.8 (or later) is being used in which case the default is
! to align the loop on a 16 byte boundary if it is less than 8
! bytes away.
  
  @item -malign-jumps=@var{num}
  Align instructions that are only jumped to to a 2 raised to a @var{num}
  byte boundary.  If @samp{-malign-jumps} is not specified, the default is
! 2 if optimizing for a 386, and 4 if optimizing for a 486 unless
! gas 2.8 (or later) is being used in which case the default is
! to align the instruction on a 16 byte boundary if it is less
! than 8 bytes away.
  
  @item -malign-functions=@var{num}
  Align the start of functions to a 2 raised to @var{num} byte boundary.
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------




More information about the Gcc-bugs mailing list