* function.c (init_function_start): Call decide_function_section. * varasm.c (decide_function_section): New function. (assemble_start_function): When not using flag_reorder_blocks_and_partition, don't compute in_cold_section_p or first_function_block_is_cold. * rtl.h (decide_function_section): Declare. * gcc.target/arm/cold-lc.c: New test. Index: gcc/testsuite/gcc.target/arm/cold-lc.c =================================================================== --- gcc/testsuite/gcc.target/arm/cold-lc.c (revision 0) +++ gcc/testsuite/gcc.target/arm/cold-lc.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlong-calls" } */ +/* { dg-final { scan-assembler-not "bl\[^\n\]*dump_stack" } } */ + +extern void dump_stack (void) __attribute__ ((__cold__)) __attribute__ ((noinline)); +struct thread_info { + struct task_struct *task; +}; +extern struct thread_info *current_thread_info (void); + +void dump_stack (void) +{ + unsigned long stack; + show_stack ((current_thread_info ()->task), &stack); +} + +void die (char *str, void *fp, int nr) +{ + dump_stack (); + while (1); +} + Index: gcc/function.c =================================================================== --- gcc/function.c (revision 170052) +++ gcc/function.c (working copy) @@ -4227,6 +4227,7 @@ init_function_start (tree subr) else allocate_struct_function (subr, false); prepare_function_start (); + decide_function_section (subr); /* Warn if this value is an aggregate type, regardless of which calling convention we are using for it. */ Index: gcc/varasm.c =================================================================== --- gcc/varasm.c (revision 170052) +++ gcc/varasm.c (working copy) @@ -1687,6 +1687,38 @@ notice_global_symbol (tree decl) } } +/* If not using flag_reorder_blocks_and_partition, decide early whether the + current function goes into the cold section, so that targets can use + current_function_section during RTL expansion. DECL describes the + function. */ + +void +decide_function_section (tree decl) +{ + first_function_block_is_cold = false; + + if (flag_reorder_blocks_and_partition) + /* We will decide in assemble_start_function. */ + return; + + 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; + } + + in_cold_section_p = first_function_block_is_cold; +} + /* Output assembler code for the constant pool of a function and associated with defining the name of the function. DECL describes the function. NAME is the function's name. For the constant pool, we use the current @@ -1701,7 +1733,6 @@ assemble_start_function (tree decl, cons crtl->subsections.unlikely_text_section_name = NULL; - first_function_block_is_cold = false; if (flag_reorder_blocks_and_partition) { ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTB", const_labelno); @@ -1738,6 +1769,8 @@ assemble_start_function (tree decl, cons if (flag_reorder_blocks_and_partition) { + first_function_block_is_cold = false; + switch_to_section (unlikely_text_section ()); assemble_align (DECL_ALIGN (decl)); ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_label); @@ -1754,23 +1787,8 @@ assemble_start_function (tree decl, cons hot_label_written = true; first_function_block_is_cold = true; } + in_cold_section_p = first_function_block_is_cold; } - 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; - } - - in_cold_section_p = first_function_block_is_cold; /* Switch to the correct text section for the start of the function. */ Index: gcc/rtl.h =================================================================== --- gcc/rtl.h (revision 170052) +++ gcc/rtl.h (working copy) @@ -1644,6 +1644,7 @@ extern rtx get_pool_constant (rtx); extern rtx get_pool_constant_mark (rtx, bool *); extern enum machine_mode get_pool_mode (const_rtx); extern rtx simplify_subtraction (rtx); +extern void decide_function_section (tree); /* In function.c */ extern rtx assign_stack_local (enum machine_mode, HOST_WIDE_INT, int);