This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] gas: Add TC_FRAG_INIT2
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: binutils at sourceware dot org
- Date: Sat, 9 Feb 2019 06:19:09 -0800
- Subject: [PATCH] gas: Add TC_FRAG_INIT2
ommit 3ae729d5a4f63740ed9a778960b17c2912b0bbdd
Author: H.J. Lu <hjl.tools@gmail.com>
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
introduces TC_FRAG_INIT2 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): Support TC_FRAG_INIT_WITH_MAX_CHARS.
* 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): Renamed to ...
(TC_FRAG_INIT2): This. Track max_bytes.
(HANDLE_ALIGN): Replace MAX_MEM_FOR_RS_ALIGN_CODE with
fragP->tc_frag_data.max_bytes.
---
gas/config/tc-i386.h | 9 ++++++---
gas/doc/internals.texi | 13 +++++++------
gas/frags.c | 11 ++++++++---
3 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index f10b00df9c..bcd8cd7c75 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_INIT2(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/doc/internals.texi b/gas/doc/internals.texi
index 00083679bc..c0a3421eef 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})
-@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.
+@item TC_FRAG_INIT2 (@var{fragp}, @var{max_bytes})
+@cindex TC_FRAG_INIT2
+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
@@ -1798,8 +1799,8 @@ If you need to emit fixups for the opcode field from inspection of the
relaxable frag, then you need to generate a common frag for both the basic
opcode and relaxable fields, or you need to provide the frag for the opcode to
pass to @code{fix_new}. The latter can be done for example by defining
-@code{TC_FRAG_TYPE} to include a pointer to it and defining @code{TC_FRAG_INIT}
-to set the pointer.
+@code{TC_FRAG_TYPE} to include a pointer to it and defining
+@code{TC_FRAG_INIT2} to set the pointer.
Sometimes @code{fr_var} is increased instead, and @code{frag_wane} is not
called. I'm not sure, but I think this is to keep @code{fr_fix} referring to
diff --git a/gas/frags.c b/gas/frags.c
index 0ee31078ca..6d270d404b 100644
--- a/gas/frags.c
+++ b/gas/frags.c
@@ -218,6 +218,13 @@ frag_more (size_t nchars)
return retval;
}
+#if !defined (TC_FRAG_INIT2) && defined (TC_FRAG_INIT)
+# define TC_FRAG_INIT2(FRAGP, MAX_BYTES) TC_FRAG_INIT (FRAGP)
+#endif
+#ifndef TC_FRAG_INIT2
+# define TC_FRAG_INIT2(FRAGP, MAX_BYTES)
+#endif
+
/* Close the current frag, setting its fields for a relaxable frag. Start a
new frag. */
@@ -237,9 +244,7 @@ frag_var_init (relax_stateT type, size_t max_chars, size_t var,
frag_now->fr_cgen.opindex = 0;
frag_now->fr_cgen.opinfo = 0;
#endif
-#ifdef TC_FRAG_INIT
- TC_FRAG_INIT (frag_now);
-#endif
+ TC_FRAG_INIT2 (frag_now, max_chars);
frag_now->fr_file = as_where (&frag_now->fr_line);
frag_new (max_chars);
--
2.20.1