On Wed, Sep 06, 2017 at 11:48:00AM -0500, Segher Boessenkool wrote: > On Wed, Sep 06, 2017 at 06:26:10PM +0200, Jakub Jelinek wrote: > > > Maybe this "switch to the other section" thing should be abstracted out? > > > Messing with in_cold_section_p is a bit dirty. > > > > But it reflects the reality, and is what final.c and varasm.c also do. > > Yes, but those aren't target code :-) > > I'm suggesting adding a generic > switch_from_hot_to_cold_or_the_other_way_around > function (but with a better name ;-) ) that just does these same two lines, > only not in target code. Seems cleaner to me, less surprising.
Richard, is this generic change ok? 2017-09-07 Jakub Jelinek <ja...@redhat.com> PR target/81979 * output.h (switch_to_other_text_partition): New declaration. * varasm.c (switch_to_other_text_partition): New function. * config/rs6000/rs6000.c (uses_TOC): Return 2 if NOTE_INSN_SWITCH_TEXT_SECTIONS is seen before finding load_toc_* insn. (rs6000_elf_declare_function_name): If uses_TOC returned 2, switch to the other text partition before emitting LCL label and switch back after emitting the word after it. * gcc.dg/pr81979.c: New test. --- gcc/output.h.jj 2017-09-01 09:26:48.000000000 +0200 +++ gcc/output.h 2017-09-07 11:38:48.668090305 +0200 @@ -537,6 +537,7 @@ extern section *mergeable_constant_secti extern section *function_section (tree); extern section *unlikely_text_section (void); extern section *current_function_section (void); +extern void switch_to_other_text_partition (void); /* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if not) section for PRIORITY. */ --- gcc/varasm.c.jj 2017-09-06 11:09:39.000000000 +0200 +++ gcc/varasm.c 2017-09-07 11:35:34.366442544 +0200 @@ -695,6 +695,16 @@ unlikely_text_section_p (section *sect) return sect == function_section_1 (current_function_decl, true); } +/* Switch to the other function partition (if inside of hot section + into cold section, otherwise into the hot section). */ + +void +switch_to_other_text_partition (void) +{ + in_cold_section_p = !in_cold_section_p; + switch_to_section (current_function_section ()); +} + /* Return the read-only data section associated with function DECL. */ section * --- gcc/config/rs6000/rs6000.c.jj 2017-09-05 23:28:22.238928428 +0200 +++ gcc/config/rs6000/rs6000.c 2017-09-07 11:39:25.781640963 +0200 @@ -25324,32 +25324,41 @@ get_TOC_alias_set (void) /* This returns nonzero if the current function uses the TOC. This is determined by the presence of (use (unspec ... UNSPEC_TOC)), which - is generated by the ABI_V4 load_toc_* patterns. */ + is generated by the ABI_V4 load_toc_* patterns. + Return 2 instead of 1 if the load_toc_* pattern is in the function + partition that doesn't start the function. */ #if TARGET_ELF static int uses_TOC (void) { rtx_insn *insn; + int ret = 1; for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (INSN_P (insn)) - { - rtx pat = PATTERN (insn); - int i; + { + if (INSN_P (insn)) + { + rtx pat = PATTERN (insn); + int i; - if (GET_CODE (pat) == PARALLEL) - for (i = 0; i < XVECLEN (pat, 0); i++) - { - rtx sub = XVECEXP (pat, 0, i); - if (GET_CODE (sub) == USE) - { - sub = XEXP (sub, 0); - if (GET_CODE (sub) == UNSPEC - && XINT (sub, 1) == UNSPEC_TOC) - return 1; - } - } - } + if (GET_CODE (pat) == PARALLEL) + for (i = 0; i < XVECLEN (pat, 0); i++) + { + rtx sub = XVECEXP (pat, 0, i); + if (GET_CODE (sub) == USE) + { + sub = XEXP (sub, 0); + if (GET_CODE (sub) == UNSPEC + && XINT (sub, 1) == UNSPEC_TOC) + return ret; + } + } + } + else if (crtl->has_bb_partition + && NOTE_P (insn) + && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS) + ret = 2; + } return 0; } #endif @@ -33380,14 +33389,17 @@ rs6000_elf_declare_function_name (FILE * return; } + int uses_toc; if (DEFAULT_ABI == ABI_V4 && (TARGET_RELOCATABLE || flag_pic > 1) && !TARGET_SECURE_PLT && (!constant_pool_empty_p () || crtl->profile) - && uses_TOC ()) + && (uses_toc = uses_TOC ())) { char buf[256]; + if (uses_toc == 2) + switch_to_other_text_partition (); (*targetm.asm_out.internal_label) (file, "LCL", rs6000_pic_labelno); fprintf (file, "\t.long "); @@ -33397,6 +33409,8 @@ rs6000_elf_declare_function_name (FILE * ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno); assemble_name (file, buf); putc ('\n', file); + if (uses_toc == 2) + switch_to_other_text_partition (); } ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); --- gcc/testsuite/gcc.dg/pr81979.c.jj 2017-09-07 11:31:15.893566211 +0200 +++ gcc/testsuite/gcc.dg/pr81979.c 2017-09-07 11:31:15.893566211 +0200 @@ -0,0 +1,32 @@ +/* PR target/81979 */ +/* { dg-do link } */ +/* { dg-options "-O2 -w" } */ +/* { dg-additional-options "-fPIC" { target fpic } } */ +/* { dg-additional-options "-freorder-blocks-and-partition" { target freorder } } */ + +int d; + +__attribute__((noinline, noclone)) void +foo (int x) +{ + int c; + while (c < 1) + { + int o; + for (o = 0; o < 4; ++o) + c /= (x != 0) ? 2 : x; + } + + d = 1; + for (;;) + ; +} + +int +main () +{ + asm volatile ("" : : "r" (&d) : "memory"); + foo (d); + asm volatile ("" : : "r" (&d) : "memory"); + return 0; +} Jakub