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