Hi! CCing Andrew, because powerpcspe needs the same thing.
On powerpc with sysv4 -fPIC we emit something like .LCL0: .long .LCTOC1-.LCF0 before we start emitting the function, and in the prologue we emit .LCF0: and some code. This fails to assemble if the prologue is emitted in a different partition from the start of the function, as e.g. the following testcase, where the start of the function is hot, i.e. in .text section, but the shrink-wrapped prologue is cold, emitted in .text.unlikely section. .LCL0 is still emitted in the section the function starts, thus .text, and there is no relocation for subtraction of two symbols in other sections (the second - operand has to be in the current section so that a PC-relative relocation can be used). This probably never worked, but is now more severe, as we enable hot/cold partitioning in GCC 8, where it has been previously only enabled for -fprofile-use. Fixed thusly, bootstrapped on powerpc64-linux, regtested with --target_board=unix\{,-m32\}, ok for trunk? 2017-09-05 Jakub Jelinek <ja...@redhat.com> PR target/81979 * 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/config/rs6000/rs6000.c.jj 2017-09-04 09:55:28.000000000 +0200 +++ gcc/config/rs6000/rs6000.c 2017-09-04 16:36:49.033213325 +0200 @@ -25248,12 +25248,15 @@ 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)) @@ -25270,10 +25273,14 @@ uses_TOC (void) sub = XEXP (sub, 0); if (GET_CODE (sub) == UNSPEC && XINT (sub, 1) == UNSPEC_TOC) - return 1; + return ret; } } } + else if (crtl->has_bb_partition + && NOTE_P (insn) + && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS) + ret = 2; return 0; } #endif @@ -33304,14 +33311,20 @@ 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) + { + in_cold_section_p = !in_cold_section_p; + switch_to_section (current_function_section ()); + } (*targetm.asm_out.internal_label) (file, "LCL", rs6000_pic_labelno); fprintf (file, "\t.long "); @@ -33321,6 +33334,11 @@ 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) + { + in_cold_section_p = !in_cold_section_p; + switch_to_section (current_function_section ()); + } } ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); --- gcc/testsuite/gcc.dg/pr81979.c.jj 2017-09-04 16:49:08.839334897 +0200 +++ gcc/testsuite/gcc.dg/pr81979.c 2017-09-04 16:48:54.000000000 +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