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

Reply via email to