Since 4c4a180d, LTO has turned off flag_pic when linking a fixed position executable. This results in flag_pic being zero in rs6000_file_start, and no definition of ".LCTOC1".
However, when we get to actually emitting code, flag_pic may be on again, and references made to ".LCTOC1". How flag_pic comes to be enabled again is quite a story. It goes like this.. If a function is compiled with -fPIC then sysv4.h SUBTARGET_OVERRIDE_OPTIONS will set TARGET_RELOCATABLE. Conversely, if TARGET_RELOCATABLE is set and flag_pic is zero, then SUBTARGET_OVERRIDE_OPTIONS will set flag_pic=2. It also happens that TARGET_RELOCATABLE is a bit in rs6000_isa_flags, which is handled by rs6000_function_specific_save and rs6000_function_specific_restore. That last fact means lto streaming keeps track of the state of TARGET_RELOCATABLE for functions, and when options are restored for a given function we'll set flag_pic=2 if the function was originally compiled with -fPIC. That's bad because it defeats the purpose of the 4c4a180d lto change, resulting in worse optimization of ppc32 executables. What's more, we don't seem to turn off flag_pic once it is on. We should really untangle the flag_pic/TARGET_RELOCATABLE mess, but that change is probably a little dangerous for stage4. Instead, this patch removes the toc symbol initialization from file_start and does so when the first item is emitted to the toc, or after the function epilogue in the cases where we emit code to initialize a toc pointer but don't actually use it (-O0 mostly, I think). Bootstrapped and regression tested powerpc64-linux biarch with all languages enabled. OK to apply? PR target/68662 * config/rs6000/rs6000.c (need_toc_init): New var, set it whenever toc_label_name used. (rs6000_file_start): Don't set up toc section here, (rs6000_output_function_epilogue): do so here instead, (rs6000_xcoff_file_start): and here. * config/rs6000/rs6000.md (load_toc_aix_si): Set need_toc_init. (load_toc_aix_di): Likewise. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4704d00..4ea4efb 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -209,7 +209,7 @@ tree rs6000_builtin_types[RS6000_BTI_MAX]; tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT]; /* Flag to say the TOC is initialized */ -int toc_initialized; +int toc_initialized, need_toc_init; char toc_label_name[10]; /* Cached value of rs6000_variable_issue. This is cached in @@ -5682,13 +5682,6 @@ rs6000_file_start (void) if (DEFAULT_ABI == ABI_ELFv2) fprintf (file, "\t.abiversion 2\n"); - - if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 - || (TARGET_ELF && flag_pic == 2)) - { - switch_to_section (toc_section); - switch_to_section (text_section); - } } @@ -20375,6 +20368,7 @@ rs6000_output_addr_const_extra (FILE *file, rtx x) { putc ('-', file); assemble_name (file, toc_label_name); + need_toc_init = 1; } else if (TARGET_ELF) fputs ("@toc", file); @@ -24003,7 +23997,10 @@ rs6000_emit_load_toc_table (int fromprolog) ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (lab)); lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); if (flag_pic == 2) - got = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name)); + { + got = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name)); + need_toc_init = 1; + } else got = rs6000_got_sym (); tmp1 = tmp2 = dest; @@ -24048,6 +24045,7 @@ rs6000_emit_load_toc_table (int fromprolog) rtx tocsym, lab; tocsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name)); + need_toc_init = 1; lab = gen_label_rtx (); emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab)); emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO)); @@ -24062,6 +24060,7 @@ rs6000_emit_load_toc_table (int fromprolog) /* This is for AIX code running in non-PIC ELF32. */ rtx realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name)); + need_toc_init = 1; emit_insn (gen_elf_high (dest, realsym)); emit_insn (gen_elf_low (dest, dest, realsym)); } @@ -27598,6 +27597,17 @@ rs6000_output_function_epilogue (FILE *file, fputs ("\t.align 2\n", file); } + + /* Arrange to define .LCTOC1 label, if not already done. */ + if (need_toc_init) + { + need_toc_init = 0; + if (!toc_initialized) + { + switch_to_section (toc_section); + switch_to_section (current_function_section ()); + } + } } /* -fsplit-stack support. */ @@ -31745,6 +31755,7 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl) fprintf (file, "\t.long "); assemble_name (file, toc_label_name); + need_toc_init = 1; putc ('-', file); ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno); assemble_name (file, buf); @@ -32137,6 +32148,7 @@ rs6000_xcoff_file_start (void) fputc ('\n', asm_out_file); if (write_symbols != NO_DEBUG) switch_to_section (private_data_section); + switch_to_section (toc_section); switch_to_section (text_section); if (profile_flag) fprintf (asm_out_file, "\t.extern %s\n", RS6000_MCOUNT); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6e22c52..fe19853 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -9475,6 +9475,8 @@ "* { char buf[30]; + extern int need_toc_init; + need_toc_init = 1; ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\", 1); operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); operands[2] = gen_rtx_REG (Pmode, 2); @@ -9492,6 +9494,8 @@ "* { char buf[30]; + extern int need_toc_init; + need_toc_init = 1; #ifdef TARGET_RELOCATABLE ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\", !TARGET_MINIMAL_TOC || TARGET_RELOCATABLE); -- Alan Modra Australia Development Lab, IBM