From db22231044df03bbcb987496f3f29f0462b2e9ee Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 10 Feb 2019 04:34:10 -0800 Subject: [PATCH] gas: Pass max_bytes to TC_FRAG_INIT ommit 3ae729d5a4f63740ed9a778960b17c2912b0bbdd Author: H.J. Lu Date: Wed Mar 7 04:18:45 2018 -0800 x86: Rewrite NOP generation for fill and alignment increased MAX_MEM_FOR_RS_ALIGN_CODE to 4095 which resulted in increase of assembler time and memory usage by 5 times for inputs with many .p2align directives, which is typical for LTO output. This patch passes max_bytes to TC_FRAG_INIT so that MAX_MEM_FOR_RS_ALIGN_CODE can be set as needed and tracked by backend it so that HANDLE_ALIGN can check the maximum alignment for each rs_align_code frag. Wall time to assemble the same cc1plus.s: before: 423.78user 0.89system 7:05.71elapsed 99%CPU after: 102.35user 0.27system 1:42.89elapsed 99%CPU PR gas/24165 * frags.c (frag_var_init): Pass max_chars to TC_FRAG_INIT as max_bytes. * config/tc-aarch64.h (TC_FRAG_INIT): Add and pass max_bytes to aarch64_init_frag. * /config/tc-arm.h (TC_FRAG_INIT): And and pass max_bytes to arm_init_frag. * config/tc-avr.h (TC_FRAG_INIT): And and ignore max_bytes. * config/tc-ia64.h (TC_FRAG_INIT): Likewise. * config/tc-mmix.h (TC_FRAG_INIT): Likewise. * config/tc-nds32.h (TC_FRAG_INIT): Likewise. * config/tc-ns32k.h (TC_FRAG_INIT): Likewise. * config/tc-rl78.h (TC_FRAG_INIT): Likewise. * config/tc-rx.h (TC_FRAG_INIT): Likewise. * config/tc-score.h (TC_FRAG_INIT): Likewise. * config/tc-tic54x.h (TC_FRAG_INIT): Likewise. * config/tc-tic6x.h (TC_FRAG_INIT): Likewise. * config/tc-xtensa.h (TC_FRAG_INIT): Likewise. * config/tc-i386.h (MAX_MEM_FOR_RS_ALIGN_CODE): Set to (alignment ? ((1 << alignment) - 1) : 1) (i386_tc_frag_data): Add max_bytes. (TC_FRAG_INIT): Add and track max_bytes. (HANDLE_ALIGN): Replace MAX_MEM_FOR_RS_ALIGN_CODE with fragP->tc_frag_data.max_bytes. * doc/internals.texi: Update TC_FRAG_TYPE with max_bytes. --- gas/ChangeLog | 28 ++++++++++++++++++++++++++++ gas/config/tc-aarch64.h | 3 +-- gas/config/tc-arm.h | 3 +-- gas/config/tc-avr.h | 2 +- gas/config/tc-i386.h | 9 ++++++--- gas/config/tc-ia64.h | 2 +- gas/config/tc-mmix.h | 2 +- gas/config/tc-nds32.h | 2 +- gas/config/tc-ns32k.h | 2 +- gas/config/tc-rl78.h | 2 +- gas/config/tc-rx.h | 2 +- gas/config/tc-score.h | 2 +- gas/config/tc-tic54x.h | 2 +- gas/config/tc-tic6x.h | 2 +- gas/config/tc-xtensa.h | 2 +- gas/doc/internals.texi | 7 ++++--- gas/frags.c | 2 +- 17 files changed, 52 insertions(+), 22 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index aadf6e148b..04ad383e89 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,31 @@ +2019-02-10 H.J. Lu + + PR gas/24165 + * frags.c (frag_var_init): Pass max_chars to TC_FRAG_INIT as + max_bytes. + * config/tc-aarch64.h (TC_FRAG_INIT): Add and pass max_bytes to + aarch64_init_frag. + * /config/tc-arm.h (TC_FRAG_INIT): And and pass max_bytes to + arm_init_frag. + * config/tc-avr.h (TC_FRAG_INIT): And and ignore max_bytes. + * config/tc-ia64.h (TC_FRAG_INIT): Likewise. + * config/tc-mmix.h (TC_FRAG_INIT): Likewise. + * config/tc-nds32.h (TC_FRAG_INIT): Likewise. + * config/tc-ns32k.h (TC_FRAG_INIT): Likewise. + * config/tc-rl78.h (TC_FRAG_INIT): Likewise. + * config/tc-rx.h (TC_FRAG_INIT): Likewise. + * config/tc-score.h (TC_FRAG_INIT): Likewise. + * config/tc-tic54x.h (TC_FRAG_INIT): Likewise. + * config/tc-tic6x.h (TC_FRAG_INIT): Likewise. + * config/tc-xtensa.h (TC_FRAG_INIT): Likewise. + * config/tc-i386.h (MAX_MEM_FOR_RS_ALIGN_CODE): Set to + (alignment ? ((1 << alignment) - 1) : 1) + (i386_tc_frag_data): Add max_bytes. + (TC_FRAG_INIT): Add and track max_bytes. + (HANDLE_ALIGN): Replace MAX_MEM_FOR_RS_ALIGN_CODE with + fragP->tc_frag_data.max_bytes. + * doc/internals.texi: Update TC_FRAG_TYPE with max_bytes. + 2019-02-08 Jim Wilson * config/tc-riscv.c (validate_riscv_insn) <'C'>: Add 'z' support. diff --git a/gas/config/tc-aarch64.h b/gas/config/tc-aarch64.h index 50b76d3019..b54907218c 100644 --- a/gas/config/tc-aarch64.h +++ b/gas/config/tc-aarch64.h @@ -173,8 +173,7 @@ struct aarch64_frag_type }; #define TC_FRAG_TYPE struct aarch64_frag_type -/* NOTE: max_chars is a local variable from frag_var / frag_variant. */ -#define TC_FRAG_INIT(fragp) aarch64_init_frag (fragp, max_chars) +#define TC_FRAG_INIT(fragp, max_bytes) aarch64_init_frag (fragp, max_bytes) #define HANDLE_ALIGN(fragp) aarch64_handle_align (fragp) #define md_do_align(N, FILL, LEN, MAX, LABEL) \ diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h index f095d0a892..0d5e79c7ad 100644 --- a/gas/config/tc-arm.h +++ b/gas/config/tc-arm.h @@ -229,8 +229,7 @@ arm_min (int am_p1, int am_p2) } #define TC_FRAG_TYPE struct arm_frag_type -/* NOTE: max_chars is a local variable from frag_var / frag_variant. */ -#define TC_FRAG_INIT(fragp) arm_init_frag (fragp, max_chars) +#define TC_FRAG_INIT(fragp, max_bytes) arm_init_frag (fragp, max_bytes) #define TC_ALIGN_ZERO_IS_DEFAULT 1 #define HANDLE_ALIGN(fragp) arm_handle_align (fragp) /* PR gas/19276: COFF/PE segment alignment is already handled in coff_frob_section(). */ diff --git a/gas/config/tc-avr.h b/gas/config/tc-avr.h index efbf8ddba7..d58222ec77 100644 --- a/gas/config/tc-avr.h +++ b/gas/config/tc-avr.h @@ -243,5 +243,5 @@ struct avr_frag_data unsigned int prev_opcode; }; #define TC_FRAG_TYPE struct avr_frag_data -#define TC_FRAG_INIT(frag) avr_frag_init (frag) +#define TC_FRAG_INIT(frag, max_bytes) avr_frag_init (frag) extern void avr_frag_init (fragS *); diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index f10b00df9c..1f740e419c 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -206,7 +206,7 @@ if ((n) \ goto around; \ } -#define MAX_MEM_FOR_RS_ALIGN_CODE 4095 +#define MAX_MEM_FOR_RS_ALIGN_CODE (alignment ? ((1 << alignment) - 1) : 1) void i386_print_statistics (FILE *); #define tc_print_statistics i386_print_statistics @@ -251,6 +251,7 @@ struct i386_tc_frag_data enum processor_type isa; i386_cpu_flags isa_flags; enum processor_type tune; + unsigned int max_bytes; }; /* We need to emit the right NOP pattern in .align frags. This is @@ -258,12 +259,13 @@ struct i386_tc_frag_data the isa/tune settings at the time the .align was assembled. */ #define TC_FRAG_TYPE struct i386_tc_frag_data -#define TC_FRAG_INIT(FRAGP) \ +#define TC_FRAG_INIT(FRAGP, MAX_BYTES) \ do \ { \ (FRAGP)->tc_frag_data.isa = cpu_arch_isa; \ (FRAGP)->tc_frag_data.isa_flags = cpu_arch_isa_flags; \ (FRAGP)->tc_frag_data.tune = cpu_arch_tune; \ + (FRAGP)->tc_frag_data.max_bytes = (MAX_BYTES); \ } \ while (0) @@ -280,7 +282,8 @@ if (fragP->fr_type == rs_align_code) \ offsetT __count = (fragP->fr_next->fr_address \ - fragP->fr_address \ - fragP->fr_fix); \ - if (__count > 0 && __count <= MAX_MEM_FOR_RS_ALIGN_CODE) \ + if (__count > 0 \ + && (unsigned int) __count <= fragP->tc_frag_data.max_bytes) \ md_generate_nops (fragP, fragP->fr_literal + fragP->fr_fix, \ __count, 0); \ } diff --git a/gas/config/tc-ia64.h b/gas/config/tc-ia64.h index f221b20d8f..b478532549 100644 --- a/gas/config/tc-ia64.h +++ b/gas/config/tc-ia64.h @@ -166,7 +166,7 @@ void ia64_vms_note (void); /* Record if an alignment frag should end with a stop bit. */ #define TC_FRAG_TYPE int -#define TC_FRAG_INIT(FRAGP) do {(FRAGP)->tc_frag_data = 0;}while (0) +#define TC_FRAG_INIT(FRAGP, MAX_BYTES) do {(FRAGP)->tc_frag_data = 0;}while (0) /* Give an error if a frag containing code is not aligned to a 16 byte boundary. */ diff --git a/gas/config/tc-mmix.h b/gas/config/tc-mmix.h index b44749c583..c984f7ae08 100644 --- a/gas/config/tc-mmix.h +++ b/gas/config/tc-mmix.h @@ -179,7 +179,7 @@ extern long md_pcrel_from_section (struct fix *, segT); extern fragS *mmix_opcode_frag; #define TC_FRAG_TYPE fragS * -#define TC_FRAG_INIT(frag) (frag)->tc_frag_data = mmix_opcode_frag +#define TC_FRAG_INIT(frag, max_bytes) (frag)->tc_frag_data = mmix_opcode_frag /* We need to associate each section symbol with a list of GREGs defined for that section/segment and sorted on offset, between the point where diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h index 22e940604c..4d4da274d2 100644 --- a/gas/config/tc-nds32.h +++ b/gas/config/tc-nds32.h @@ -191,7 +191,7 @@ struct nds32_frag_type extern void nds32_frag_init (fragS *); #define TC_FRAG_TYPE struct nds32_frag_type -#define TC_FRAG_INIT(fragP) nds32_frag_init (fragP) +#define TC_FRAG_INIT(fragP, max_bytes) nds32_frag_init (fragP) /* CFI directive. */ extern void nds32_elf_frame_initial_instructions (void); diff --git a/gas/config/tc-ns32k.h b/gas/config/tc-ns32k.h index 4cb8e85f8b..a53ef976e4 100644 --- a/gas/config/tc-ns32k.h +++ b/gas/config/tc-ns32k.h @@ -73,7 +73,7 @@ extern const struct relax_type md_relax_table[]; char fr_bsr; \ } -#define TC_FRAG_INIT(X) \ +#define TC_FRAG_INIT(X, MAX_BYTES) \ do \ { \ frag_opcode_frag (X) = NULL; \ diff --git a/gas/config/tc-rl78.h b/gas/config/tc-rl78.h index 738484b69c..315bd7e7d3 100644 --- a/gas/config/tc-rl78.h +++ b/gas/config/tc-rl78.h @@ -53,7 +53,7 @@ extern void rl78_md_end (void); extern int rl78_relax_frag (segT, fragS *, long); #define TC_FRAG_TYPE struct rl78_bytesT * -#define TC_FRAG_INIT rl78_frag_init +#define TC_FRAG_INIT(fragp, max_bytes) rl78_frag_init (fragp) extern void rl78_frag_init (fragS *); /* Call md_pcrel_from_section(), not md_pcrel_from(). */ diff --git a/gas/config/tc-rx.h b/gas/config/tc-rx.h index 7dca68c8d4..09c50f9471 100644 --- a/gas/config/tc-rx.h +++ b/gas/config/tc-rx.h @@ -58,7 +58,7 @@ extern void rx_md_end (void); extern int rx_relax_frag (segT, fragS *, long); #define TC_FRAG_TYPE struct rx_bytesT * -#define TC_FRAG_INIT rx_frag_init +#define TC_FRAG_INIT(fragp, max_bytes) rx_frag_init (fragp) extern void rx_frag_init (fragS *); /* Call md_pcrel_from_section(), not md_pcrel_from(). */ diff --git a/gas/config/tc-score.h b/gas/config/tc-score.h index 4da0be9a55..34cf5fdcd2 100644 --- a/gas/config/tc-score.h +++ b/gas/config/tc-score.h @@ -62,7 +62,7 @@ struct score_tc_frag_data #define TC_FRAG_TYPE struct score_tc_frag_data -#define TC_FRAG_INIT(FRAGP) \ +#define TC_FRAG_INIT(FRAGP, MAX_BYTES) \ do \ { \ (FRAGP)->tc_frag_data.is_insn = (((FRAGP)->fr_type == rs_machine_dependent) ? 1 : 0); \ diff --git a/gas/config/tc-tic54x.h b/gas/config/tc-tic54x.h index 5409d704dc..0eda39603e 100644 --- a/gas/config/tc-tic54x.h +++ b/gas/config/tc-tic54x.h @@ -62,7 +62,7 @@ struct bit_info /* We sometimes need to keep track of bit offsets within words */ #define TC_FRAG_TYPE int -#define TC_FRAG_INIT(FRAGP) do {(FRAGP)->tc_frag_data = 0;}while (0) +#define TC_FRAG_INIT(FRAGP, MAX_BYTES) do {(FRAGP)->tc_frag_data = 0;}while (0) /* tell GAS whether the given token is indeed a code label */ #define TC_START_LABEL_WITHOUT_COLON(NUL_CHAR, NEXT_CHAR) \ diff --git a/gas/config/tc-tic6x.h b/gas/config/tc-tic6x.h index 735cddb178..fbca6376c2 100644 --- a/gas/config/tc-tic6x.h +++ b/gas/config/tc-tic6x.h @@ -130,7 +130,7 @@ typedef struct bfd_boolean can_cross_fp_boundary; } tic6x_frag_info; #define TC_FRAG_TYPE tic6x_frag_info -#define TC_FRAG_INIT(fragP) tic6x_frag_init (fragP) +#define TC_FRAG_INIT(fragP, max_bytes) tic6x_frag_init (fragP) extern void tic6x_frag_init (fragS *fragp); typedef struct diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h index ed7b08da13..6889d92a4f 100644 --- a/gas/config/tc-xtensa.h +++ b/gas/config/tc-xtensa.h @@ -356,7 +356,7 @@ extern void xtensa_init (int, char **); #define TC_FIX_TYPE xtensa_fix_data #define TC_INIT_FIX_DATA(x) xtensa_init_fix_data (x) #define TC_FRAG_TYPE struct xtensa_frag_type -#define TC_FRAG_INIT(frag) xtensa_frag_init (frag) +#define TC_FRAG_INIT(frag, max_bytes) xtensa_frag_init (frag) #define TC_FORCE_RELOCATION(fix) xtensa_force_relocation (fix) #define TC_FORCE_RELOCATION_SUB_SAME(fix, seg) \ (GENERIC_FORCE_RELOCATION_SUB_SAME (fix, seg) \ diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi index 00083679bc..a50880d635 100644 --- a/gas/doc/internals.texi +++ b/gas/doc/internals.texi @@ -1118,10 +1118,11 @@ These fields are defined with the @code{TC_FIX_TYPE} macro. A C statement to output target specific debugging information for fixup @var{fixp} to @var{stream}. This macro is called by @code{print_fixup}. -@item TC_FRAG_INIT (@var{fragp}) +@item TC_FRAG_INIT (@var{fragp}, @var{max_bytes}) @cindex TC_FRAG_INIT -A C statement to initialize the target specific fields of frag @var{fragp}. -These fields are defined with the @code{TC_FRAG_TYPE} macro. +A C statement to initialize the target specific fields of frag @var{fragp} +with maximum number of bytes @var{max_bytes}. These fields are defined +with the @code{TC_FRAG_TYPE} macro. @item md_number_to_chars @cindex md_number_to_chars diff --git a/gas/frags.c b/gas/frags.c index 0ee31078ca..90096ff696 100644 --- a/gas/frags.c +++ b/gas/frags.c @@ -238,7 +238,7 @@ frag_var_init (relax_stateT type, size_t max_chars, size_t var, frag_now->fr_cgen.opinfo = 0; #endif #ifdef TC_FRAG_INIT - TC_FRAG_INIT (frag_now); + TC_FRAG_INIT (frag_now, max_chars); #endif frag_now->fr_file = as_where (&frag_now->fr_line); -- 2.34.1