summaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c276
1 files changed, 160 insertions, 116 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 6171e30799a..fc996f1f8cd 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -368,69 +368,6 @@ create_block_symbol (const char *label, struct object_block *block,
return symbol;
}
-static void
-initialize_cold_section_name (void)
-{
- const char *stripped_name;
- char *name, *buffer;
- tree dsn;
-
- gcc_assert (cfun && current_function_decl);
- if (crtl->subsections.unlikely_text_section_name)
- return;
-
- dsn = DECL_SECTION_NAME (current_function_decl);
- if (flag_function_sections && dsn)
- {
- name = (char *) alloca (TREE_STRING_LENGTH (dsn) + 1);
- memcpy (name, TREE_STRING_POINTER (dsn), TREE_STRING_LENGTH (dsn) + 1);
-
- stripped_name = targetm.strip_name_encoding (name);
-
- buffer = ACONCAT ((stripped_name, "_unlikely", NULL));
- crtl->subsections.unlikely_text_section_name = ggc_strdup (buffer);
- }
- else
- crtl->subsections.unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
-}
-
-/* Tell assembler to switch to unlikely-to-be-executed text section. */
-
-section *
-unlikely_text_section (void)
-{
- if (cfun)
- {
- if (!crtl->subsections.unlikely_text_section_name)
- initialize_cold_section_name ();
-
- return get_named_section (NULL, crtl->subsections.unlikely_text_section_name, 0);
- }
- else
- return get_named_section (NULL, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0);
-}
-
-/* When called within a function context, return true if the function
- has been assigned a cold text section and if SECT is that section.
- When called outside a function context, return true if SECT is the
- default cold section. */
-
-bool
-unlikely_text_section_p (section *sect)
-{
- const char *name;
-
- if (cfun)
- name = crtl->subsections.unlikely_text_section_name;
- else
- name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
-
- return (name
- && sect
- && SECTION_STYLE (sect) == SECTION_NAMED
- && strcmp (name, sect->named.name) == 0);
-}
-
/* Return a section with a particular name and with whatever SECTION_*
flags section_type_flags deems appropriate. The name of the section
is taken from NAME if nonnull, otherwise it is taken from DECL's
@@ -462,7 +399,10 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
&& targetm.have_named_sections
&& (flag_function_or_data_sections
|| DECL_ONE_ONLY (decl)))
- targetm.asm_out.unique_section (decl, reloc);
+ {
+ targetm.asm_out.unique_section (decl, reloc);
+ DECL_HAS_IMPLICIT_SECTION_NAME_P (decl) = true;
+ }
}
#ifdef BSS_SECTION_ASM_OP
@@ -539,49 +479,176 @@ hot_function_section (tree decl)
}
#endif
+/* Return section for TEXT_SECTION_NAME if DECL or DECL_SECTION_NAME (DECL)
+ is NULL.
+
+ When DECL_SECTION_NAME is non-NULL and it is implicit section and
+ NAMED_SECTION_SUFFIX is non-NULL, then produce section called
+ concatenate the name with NAMED_SECTION_SUFFIX.
+ Otherwise produce "TEXT_SECTION_NAME.IMPLICIT_NAME". */
+
+section *
+get_named_text_section (tree decl,
+ const char *text_section_name,
+ const char *named_section_suffix)
+{
+ if (decl && DECL_SECTION_NAME (decl))
+ {
+ if (named_section_suffix)
+ {
+ tree dsn = DECL_SECTION_NAME (decl);
+ const char *stripped_name;
+ char *name, *buffer;
+
+ name = (char *) alloca (TREE_STRING_LENGTH (dsn) + 1);
+ memcpy (name, TREE_STRING_POINTER (dsn),
+ TREE_STRING_LENGTH (dsn) + 1);
+
+ stripped_name = targetm.strip_name_encoding (name);
+
+ buffer = ACONCAT ((stripped_name, named_section_suffix, NULL));
+ return get_named_section (decl, buffer, 0);
+ }
+ else if (DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
+ {
+ const char *name;
+
+ /* Do not try to split gnu_linkonce functions. This gets somewhat
+ slipperly. */
+ if (DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP)
+ return NULL;
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = targetm.strip_name_encoding (name);
+ return get_named_section (decl, ACONCAT ((text_section_name, ".",
+ name, NULL)), 0);
+ }
+ else
+ return NULL;
+ }
+ return get_named_section (decl, text_section_name, 0);
+}
+
+/* Choose named function section based on its frequency. */
+
+section *
+default_function_section (tree decl, enum node_frequency freq,
+ bool startup, bool exit)
+{
+ /* Startup code should go to startup subsection unless it is
+ unlikely executed (this happens especially with function splitting
+ where we can split away unnecesary parts of static constructors. */
+ if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+ return get_named_text_section (decl, ".text.startup", NULL);
+
+ /* Similarly for exit. */
+ if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+ return get_named_text_section (decl, ".text.exit", NULL);
+
+ /* Group cold functions together, similarly for hot code. */
+ switch (freq)
+ {
+ case NODE_FREQUENCY_UNLIKELY_EXECUTED:
+ return get_named_text_section (decl, ".text.unlikely", NULL);
+ case NODE_FREQUENCY_HOT:
+ return get_named_text_section (decl, ".text.hot", NULL);
+ default:
+ return NULL;
+ }
+}
+
/* Return the section for function DECL.
If DECL is NULL_TREE, return the text section. We can be passed
- NULL_TREE under some circumstances by dbxout.c at least. */
+ NULL_TREE under some circumstances by dbxout.c at least.
-section *
-function_section (tree decl)
+ If FORCE_COLD is true, return cold function section ignoring
+ the frequency info of cgraph_node. */
+
+static section *
+function_section_1 (tree decl, bool force_cold)
{
- int reloc = 0;
+ section *section = NULL;
+ enum node_frequency freq = NODE_FREQUENCY_NORMAL;
+ bool startup = false, exit = false;
+
+ if (decl)
+ {
+ struct cgraph_node *node = cgraph_node (decl);
- if (first_function_block_is_cold)
- reloc = 1;
+ freq = node->frequency;
+ startup = node->only_called_at_startup;
+ exit = node->only_called_at_exit;
+ }
+ if (force_cold)
+ freq = NODE_FREQUENCY_UNLIKELY_EXECUTED;
#ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
if (decl != NULL_TREE
&& DECL_SECTION_NAME (decl) != NULL_TREE)
- return reloc ? unlikely_text_section ()
- : get_named_section (decl, NULL, 0);
+ {
+ if (targetm.asm_out.function_section)
+ section = targetm.asm_out.function_section (decl, freq,
+ startup, exit);
+ if (section)
+ return section;
+ return get_named_section (decl, NULL, 0);
+ }
else
- return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
+ return targetm.asm_out.select_section
+ (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
+ DECL_ALIGN (decl));
#else
- return reloc ? unlikely_text_section () : hot_function_section (decl);
+ if (targetm.asm_out.function_section)
+ section = targetm.asm_out.function_section (decl, freq, startup, exit);
+ if (section)
+ return section;
+ return hot_function_section (decl);
#endif
}
+/* Return the section for function DECL.
+
+ If DECL is NULL_TREE, return the text section. We can be passed
+ NULL_TREE under some circumstances by dbxout.c at least. */
+
+section *
+function_section (tree decl)
+{
+ /* Handle cases where function splitting code decides
+ to put function entry point into unlikely executed section
+ despite the fact that the function itself is not cold
+ (i.e. it is called rarely but contains a hot loop that is
+ better to live in hot subsection for the code locality). */
+ return function_section_1 (decl,
+ first_function_block_is_cold);
+}
+
+/* Return the section for the current function, take IN_COLD_SECTION_P
+ into account. */
+
section *
current_function_section (void)
{
-#ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
- if (current_function_decl != NULL_TREE
- && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
- return in_cold_section_p ? unlikely_text_section ()
- : get_named_section (current_function_decl,
- NULL, 0);
- else
- return targetm.asm_out.select_section (current_function_decl,
- in_cold_section_p,
- DECL_ALIGN (current_function_decl));
-#else
- return (in_cold_section_p
- ? unlikely_text_section ()
- : hot_function_section (current_function_decl));
-#endif
+ return function_section_1 (current_function_decl, in_cold_section_p);
+}
+
+/* Tell assembler to switch to unlikely-to-be-executed text section. */
+
+section *
+unlikely_text_section (void)
+{
+ return function_section_1 (current_function_decl, true);
+}
+
+/* When called within a function context, return true if the function
+ has been assigned a cold text section and if SECT is that section.
+ When called outside a function context, return true if SECT is the
+ default cold section. */
+
+bool
+unlikely_text_section_p (section *sect)
+{
+ return sect == function_section_1 (current_function_decl, true);
}
/* Return the read-only data section associated with function DECL. */
@@ -1454,8 +1521,6 @@ assemble_start_function (tree decl, const char *fnname)
char tmp_label[100];
bool hot_label_written = false;
- crtl->subsections.unlikely_text_section_name = NULL;
-
first_function_block_is_cold = false;
if (flag_reorder_blocks_and_partition)
{
@@ -1513,16 +1578,10 @@ assemble_start_function (tree decl, const char *fnname)
else if (DECL_SECTION_NAME (decl))
{
/* Calls to function_section rely on first_function_block_is_cold
- being accurate. The first block may be cold even if we aren't
- doing partitioning, if the entire function was decided by
- choose_function_section (predict.c) to be cold. */
-
- initialize_cold_section_name ();
-
- if (crtl->subsections.unlikely_text_section_name
- && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- crtl->subsections.unlikely_text_section_name) == 0)
- first_function_block_is_cold = true;
+ being accurate. */
+ first_function_block_is_cold
+ = (cgraph_node (current_function_decl)->frequency
+ == NODE_FREQUENCY_UNLIKELY_EXECUTED);
}
in_cold_section_p = first_function_block_is_cold;
@@ -5871,15 +5930,6 @@ default_section_type_flags (tree decl, const char *name, int reloc)
flags = SECTION_CODE;
else if (decl && decl_readonly_section (decl, reloc))
flags = 0;
- else if (current_function_decl
- && cfun
- && crtl->subsections.unlikely_text_section_name
- && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0)
- flags = SECTION_CODE;
- else if (!decl
- && (!current_function_decl || !cfun)
- && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
- flags = SECTION_CODE;
else
flags = SECTION_WRITE;
@@ -6810,12 +6860,6 @@ switch_to_section (section *new_section)
switch (SECTION_STYLE (new_section))
{
case SECTION_NAMED:
- if (cfun
- && !crtl->subsections.unlikely_text_section_name
- && strcmp (new_section->named.name,
- UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
- crtl->subsections.unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
-
targetm.asm_out.named_section (new_section->named.name,
new_section->named.common.flags,
new_section->named.decl);