PATCH: Avoid unncessary identifier lookups
Mark Mitchell
mark@codesourcery.com
Mon Dec 20 02:14:00 GMT 2004
The assemble_name function tries to look up the name to see if there
is an existing IDENTIFIER_NODE with that name, and, if so, set
TREE_SYMBOL_REFERENCED. That's a design bug; the argument to
assemble_name should be a tree directly in that case -- it's a bad
idea to try to get back to the IDENTIFIER_NODE via the identifier hash
table. However, it's hard to fix that, especially at this point.
This inefficiency was significant for Qt builds; profiling showed that
as many as 25% of all identifier hash table lookups were coming from
assemble_name, because that was used by both default_internal_label
and darwin_asm_output_dwarf_delta. Eliminating the inefficiency is
worth about 0.3% on Qt builds. (I have three patches which together
produce a clearly measurable 1% improvement; it's hard to isolate the
exact amount for each patch because there is enough measurement noise
that it would take a ton of runs to get very precise.)
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-12-19 Mark Mitchell <mark@codesourcery.com>
* defaults.h (ASM_OUTPUT_INTERNAL_LABEL): New macro.
* output.h (assemble_name_raw): Declare it.
* system.h (ASM_OUTPUT_INTERNAL_LABEL): Do not poison it.
* varasm.c (assemble_name_raw): New function.
(assemble_name): Use it.
(default_internal_label): Likewise.
* config/darwin.c (darwin_asm_output_dwarf_delta): Likewise.
* doc/tm.texi (ASM_OUTPUT_INTERNAL_LABEL): Document.
Index: defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.164
diff -c -5 -p -r1.164 defaults.h
*** defaults.h 13 Dec 2004 16:03:36 -0000 1.164
--- defaults.h 20 Dec 2004 02:05:36 -0000
*************** do { fputs (integer_asm_op (POINTER_SIZE
*** 143,152 ****
--- 143,161 ----
#ifndef ASM_OUTPUT_LABEL
#define ASM_OUTPUT_LABEL(FILE,NAME) \
do { assemble_name ((FILE), (NAME)); fputs (":\n", (FILE)); } while (0)
#endif
+ /* Output the definition of a compiler-generated label named NAME. */
+ #ifndef ASM_OUTPUT_INTERNAL_LABEL
+ #define ASM_OUTPUT_INTERNAL_LABEL(FILE,NAME) \
+ do { \
+ assemble_name_raw ((FILE), (NAME)); \
+ fputs (":\n", (FILE)); \
+ } while (0)
+ #endif
+
/* This is how to output a reference to a user-level label named NAME. */
#ifndef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE,NAME) asm_fprintf ((FILE), "%U%s", (NAME))
#endif
Index: output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.149
diff -c -5 -p -r1.149 output.h
*** output.h 17 Nov 2004 22:05:59 -0000 1.149
--- output.h 20 Dec 2004 02:05:36 -0000
*************** extern void assemble_string (const char
*** 289,303 ****
extern void assemble_external_libcall (rtx);
/* Assemble a label named NAME. */
extern void assemble_label (const char *);
! /* Output to FILE a reference to the assembler name of a C-level name NAME.
! If NAME starts with a *, the rest of NAME is output verbatim.
! Otherwise NAME is transformed in an implementation-defined way
! (usually by the addition of an underscore).
! Many macros in the tm file are defined to call this function. */
extern void assemble_name (FILE *, const char *);
/* Return the assembler directive for creating a given kind of integer
object. SIZE is the number of bytes in the object and ALIGNED_P
indicates whether it is known to be aligned. Return NULL if the
--- 289,308 ----
extern void assemble_external_libcall (rtx);
/* Assemble a label named NAME. */
extern void assemble_label (const char *);
! /* Output to FILE (an assembly file) a reference to NAME. If NAME
! starts with a *, the rest of NAME is output verbatim. Otherwise
! NAME is transformed in a target-specific way (usually by the
! addition of an underscore). */
! extern void assemble_name_raw (FILE *, const char *);
!
! /* Like assemble_name_raw, but should be used when NAME might refer to
! an entity that is also represented as a tree (like a function or
! variable). If NAME does refer to such an entity, that entity will
! be marked as referenced. */
extern void assemble_name (FILE *, const char *);
/* Return the assembler directive for creating a given kind of integer
object. SIZE is the number of bytes in the object and ALIGNED_P
indicates whether it is known to be aligned. Return NULL if the
Index: system.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/system.h,v
retrieving revision 1.238
diff -c -5 -p -r1.238 system.h
*** system.h 29 Nov 2004 20:46:11 -0000 1.238
--- system.h 20 Dec 2004 02:05:36 -0000
*************** extern void fancy_abort (const char *, i
*** 629,639 ****
TRADITIONAL_RETURN_FLOAT NO_BUILTIN_SIZE_TYPE \
NO_BUILTIN_PTRDIFF_TYPE NO_BUILTIN_WCHAR_TYPE NO_BUILTIN_WINT_TYPE \
BLOCK_PROFILER BLOCK_PROFILER_CODE FUNCTION_BLOCK_PROFILER \
FUNCTION_BLOCK_PROFILER_EXIT MACHINE_STATE_SAVE \
MACHINE_STATE_RESTORE SCCS_DIRECTIVE SECTION_ASM_OP \
! ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL ASM_OUTPUT_INTERNAL_LABEL \
OBJC_PROLOGUE ALLOCATE_TRAMPOLINE HANDLE_PRAGMA ROUND_TYPE_SIZE \
ROUND_TYPE_SIZE_UNIT CONST_SECTION_ASM_OP CRT_GET_RFIB_TEXT \
DBX_LBRAC_FIRST DBX_OUTPUT_ENUM DBX_OUTPUT_SOURCE_FILENAME \
DBX_WORKING_DIRECTORY INSN_CACHE_DEPTH INSN_CACHE_SIZE \
INSN_CACHE_LINE_WIDTH INIT_SECTION_PREAMBLE NEED_ATEXIT ON_EXIT \
--- 629,639 ----
TRADITIONAL_RETURN_FLOAT NO_BUILTIN_SIZE_TYPE \
NO_BUILTIN_PTRDIFF_TYPE NO_BUILTIN_WCHAR_TYPE NO_BUILTIN_WINT_TYPE \
BLOCK_PROFILER BLOCK_PROFILER_CODE FUNCTION_BLOCK_PROFILER \
FUNCTION_BLOCK_PROFILER_EXIT MACHINE_STATE_SAVE \
MACHINE_STATE_RESTORE SCCS_DIRECTIVE SECTION_ASM_OP \
! ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL \
OBJC_PROLOGUE ALLOCATE_TRAMPOLINE HANDLE_PRAGMA ROUND_TYPE_SIZE \
ROUND_TYPE_SIZE_UNIT CONST_SECTION_ASM_OP CRT_GET_RFIB_TEXT \
DBX_LBRAC_FIRST DBX_OUTPUT_ENUM DBX_OUTPUT_SOURCE_FILENAME \
DBX_WORKING_DIRECTORY INSN_CACHE_DEPTH INSN_CACHE_SIZE \
INSN_CACHE_LINE_WIDTH INIT_SECTION_PREAMBLE NEED_ATEXIT ON_EXIT \
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.469
diff -c -5 -p -r1.469 varasm.c
*** varasm.c 18 Dec 2004 21:49:53 -0000 1.469
--- varasm.c 20 Dec 2004 02:05:36 -0000
*************** mark_decl_referenced (tree decl)
*** 1887,1901 ****
cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
/* else do nothing - we can get various sorts of CST nodes here,
which do not need to be marked. */
}
! /* Output to FILE a reference to the assembler name of a C-level name NAME.
! If NAME starts with a *, the rest of NAME is output verbatim.
! Otherwise NAME is transformed in an implementation-defined way
! (usually by the addition of an underscore).
! Many macros in the tm file are defined to call this function. */
void
assemble_name (FILE *file, const char *name)
{
const char *real_name;
--- 1887,1914 ----
cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
/* else do nothing - we can get various sorts of CST nodes here,
which do not need to be marked. */
}
! /* Output to FILE (an assembly file) a reference to NAME. If NAME
! starts with a *, the rest of NAME is output verbatim. Otherwise
! NAME is transformed in a target-specific way (usually by the
! addition of an underscore). */
!
! void
! assemble_name_raw (FILE *file, const char *name)
! {
! if (name[0] == '*')
! fputs (&name[1], file);
! else
! ASM_OUTPUT_LABELREF (file, name);
! }
!
! /* Like assemble_name_raw, but should be used when NAME might refer to
! an entity that is also represented as a tree (like a function or
! variable). If NAME does refer to such an entity, that entity will
! be marked as referenced. */
void
assemble_name (FILE *file, const char *name)
{
const char *real_name;
*************** assemble_name (FILE *file, const char *n
*** 1905,1918 ****
id = maybe_get_identifier (real_name);
if (id)
mark_referenced (id);
! if (name[0] == '*')
! fputs (&name[1], file);
! else
! ASM_OUTPUT_LABELREF (file, name);
}
/* Allocate SIZE bytes writable static space with a gensym name
and return an RTX to refer to its address. */
--- 1918,1928 ----
id = maybe_get_identifier (real_name);
if (id)
mark_referenced (id);
! assemble_name_raw (file, name);
}
/* Allocate SIZE bytes writable static space with a gensym name
and return an RTX to refer to its address. */
*************** void
*** 5202,5212 ****
default_internal_label (FILE *stream, const char *prefix,
unsigned long labelno)
{
char *const buf = alloca (40 + strlen (prefix));
ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
! ASM_OUTPUT_LABEL (stream, buf);
}
/* This is the default behavior at the beginning of a file. It's
controlled by two other target-hook toggles. */
void
--- 5212,5222 ----
default_internal_label (FILE *stream, const char *prefix,
unsigned long labelno)
{
char *const buf = alloca (40 + strlen (prefix));
ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
! ASM_OUTPUT_INTERNAL_LABEL (stream, buf);
}
/* This is the default behavior at the beginning of a file. It's
controlled by two other target-hook toggles. */
void
Index: config/darwin.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/darwin.c,v
retrieving revision 1.99
diff -c -5 -p -r1.99 darwin.c
*** config/darwin.c 17 Dec 2004 00:25:06 -0000 1.99
--- config/darwin.c 20 Dec 2004 02:05:37 -0000
*************** darwin_asm_output_dwarf_delta (FILE *fil
*** 1365,1377 ****
if (islocaldiff)
fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
else
fprintf (file, "\t%s\t", ".long");
! assemble_name (file, lab1);
fprintf (file, "-");
! assemble_name (file, lab2);
if (islocaldiff)
fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
}
void
--- 1365,1377 ----
if (islocaldiff)
fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
else
fprintf (file, "\t%s\t", ".long");
! assemble_name_raw (file, lab1);
fprintf (file, "-");
! assemble_name_raw (file, lab2);
if (islocaldiff)
fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
}
void
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.405
diff -c -5 -p -r1.405 tm.texi
*** doc/tm.texi 13 Dec 2004 06:57:12 -0000 1.405
--- doc/tm.texi 20 Dec 2004 02:05:37 -0000
*************** Use the expression @code{assemble_name (
*** 6667,6676 ****
--- 6667,6683 ----
output the name itself; before and after that, output the additional
assembler syntax for defining the name, and a newline. A default
definition of this macro is provided which is correct for most systems.
@end defmac
+ @findex assemble_name_raw
+ @defmac ASM_OUTPUT_INTERNAL_LABEL (@var{stream}, @var{name})
+ Identical to @code{ASM_OUTPUT_lABEL}, except that @var{name} is known
+ to refer to a compiler-generated label. The default definition uses
+ @code{assemble_name_raw}, which is like @code{assemble_name} except
+ that it is more efficient.
+
@defmac SIZE_ASM_OP
A C string containing the appropriate assembler directive to specify the
size of a symbol, without any arguments. On systems that use ELF, the
default (in @file{config/elfos.h}) is @samp{"\t.size\t"}; on other
systems, the default is not to define this macro.
More information about the Gcc-patches
mailing list