diff options
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r-- | gcc/varasm.c | 276 |
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); |