+2017-09-07 Jakub Jelinek <jakub@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.
+
2017-09-07 Richard Biener <rguenther@suse.de>
* passes.def (pass_split_crit_edges): Remove instance before PRE.
/* 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
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 ");
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");
--- /dev/null
+/* 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;
+}
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 *