At the moment, we have two functions that create and look at TOC references:
create_TOC_reference (global function) use_toc_relative_ref (static function in rs6000.c) Since I am adding pc-relative support that will be used instead of TOC support, this patch renames these two functions to be: create_data_reference use_toc_or_pc_relative_ref and it adds some of the foundation for adding pc-relative support. Note, it will need future patches to completely flesh out the pc-relative support. As per a previous private discussion, I kept the old create_TOC_reference and added a gcc assert if it is called when pc-relative addressing is used. There is currently one place that still calls create_TOC_reference (in a section using TLS addresses). I have done a bootstrap on a power8 little endian Linux system with no regressions. Can I check this into the trunk? 2019-06-28 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/rs6000-logue.c (create_TOC_reference): Move debug statements to create_data_reference. Add gcc_assert to make sure we are using TOCs and not pc-relative addressing. (create_data_reference): New function, create either a TOC style reference or a pc-relative reference to local symbols. * config/rs6000/rs6000-protos.h (create_data_reference): Add declaration. * config/rs6000/rs6000.c (rs6000_legitimize_address): Call create_data_reference instead of create_TOC_reference. (use_toc_or_pc_relative_ref): Rename from use_toc_relative_ref and add support for pc-relative addressing. (rs6000_emit_move): Call use_toc_or_pc_relative_ref and create_data_reference instead of use_toc_relative_ref and create_TOC_reference. * config/rs6000/rs6000.md (cmp<mode>_internal2): Call create_data_reference instead of create_TOC_reference. Index: gcc/config/rs6000/rs6000-logue.c =================================================================== --- gcc/config/rs6000/rs6000-logue.c (revision 272714) +++ gcc/config/rs6000/rs6000-logue.c (working copy) @@ -1406,23 +1406,13 @@ uses_TOC (void) } #endif +/* Create a TOC style reference for a symbol. */ rtx create_TOC_reference (rtx symbol, rtx largetoc_reg) { rtx tocrel, tocreg, hi; - if (TARGET_DEBUG_ADDR) - { - if (SYMBOL_REF_P (symbol)) - fprintf (stderr, "\ncreate_TOC_reference, (symbol_ref %s)\n", - XSTR (symbol, 0)); - else - { - fprintf (stderr, "\ncreate_TOC_reference, code %s:\n", - GET_RTX_NAME (GET_CODE (symbol))); - debug_rtx (symbol); - } - } + gcc_assert (TARGET_TOC && !TARGET_PCREL); if (!can_create_pseudo_p ()) df_set_regs_ever_live (TOC_REGISTER, true); @@ -1441,6 +1431,39 @@ create_TOC_reference (rtx symbol, rtx la return gen_rtx_LO_SUM (Pmode, hi, tocrel); } +/* Create either a TOC reference to a locally defined item or a pc-relative + reference, depending on the ABI. */ +rtx +create_data_reference (rtx symbol, rtx largetoc_reg) +{ + if (TARGET_DEBUG_ADDR) + { + const char *toc_or_pcrel = (TARGET_PCREL) ? "pc-relative" : "TOC"; + + if (SYMBOL_REF_P (symbol)) + fprintf (stderr, "\ncreate_data_reference, abi %s, (symbol_ref %s)\n", + toc_or_pcrel, XSTR (symbol, 0)); + else + { + fprintf (stderr, "\ncreate_data_reference, abi %s, code %s:\n", + toc_or_pcrel, GET_RTX_NAME (GET_CODE (symbol))); + debug_rtx (symbol); + } + } + + /* We don't have to do anything special for pc-relative references. The + SYMBOL_REF bits sayss whether the label is local where we can use + pc-relative addressing, or if we have to load the address from the GOT + section to use it on external addresses. */ + if (TARGET_PCREL) + { + gcc_assert (TARGET_CMODEL == CMODEL_MEDIUM); + return symbol; + } + + return create_TOC_reference (symbol, largetoc_reg); +} + /* Issue assembly directives that create a reference to the given DWARF FRAME_TABLE_LABEL from the current function section. */ void Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 272714) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -131,6 +131,7 @@ extern void rs6000_emit_swdiv (rtx, rtx, extern void rs6000_emit_swsqrt (rtx, rtx, bool); extern void output_toc (FILE *, rtx, int, machine_mode); extern void rs6000_fatal_bad_address (rtx); +extern rtx create_data_reference (rtx, rtx); extern rtx create_TOC_reference (rtx, rtx); extern void rs6000_split_multireg_move (rtx, rtx); extern void rs6000_emit_le_vsx_permute (rtx, rtx, machine_mode); Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 272766) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -8084,7 +8084,7 @@ rs6000_legitimize_address (rtx x, rtx ol && SYMBOL_REF_P (x) && constant_pool_expr_p (x) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode)) - return create_TOC_reference (x, NULL_RTX); + return create_data_reference (x, NULL_RTX); else return x; } @@ -8696,19 +8696,21 @@ rs6000_cannot_force_const_mem (machine_m return TARGET_ELF && tls_referenced_p (x); } -/* Return true iff the given SYMBOL_REF refers to a constant pool entry - that we have put in the TOC, or for cmodel=medium, if the SYMBOL_REF - can be addressed relative to the toc pointer. */ +/* Return true iff the given SYMBOL_REF refers to a constant pool entry that we + have put in the TOC or is referenced via a pc-relative reference. In + addition, for cmodel=medium, if the SYMBOL_REF can be addressed relative to + the either toc pointer or via a pc-relative reference. */ static bool -use_toc_relative_ref (rtx sym, machine_mode mode) +use_toc_or_pc_relative_ref (rtx sym, machine_mode mode) { return ((constant_pool_expr_p (sym) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym), get_pool_mode (sym))) || (TARGET_CMODEL == CMODEL_MEDIUM && SYMBOL_REF_LOCAL_P (sym) - && GET_MODE_SIZE (mode) <= POWERPC64_TOC_POINTER_ALIGNMENT)); + && (TARGET_PCREL + || GET_MODE_SIZE (mode) <= POWERPC64_TOC_POINTER_ALIGNMENT))); } /* TARGET_LEGITIMATE_ADDRESS_P recognizes an RTL expression @@ -9810,8 +9812,8 @@ rs6000_emit_move (rtx dest, rtx source, reference to it. */ if (TARGET_TOC && SYMBOL_REF_P (operands[1]) - && use_toc_relative_ref (operands[1], mode)) - operands[1] = create_TOC_reference (operands[1], operands[0]); + && use_toc_or_pc_relative_ref (operands[1], mode)) + operands[1] = create_data_reference (operands[1], operands[0]); else if (mode == Pmode && CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != HIGH @@ -9864,11 +9866,11 @@ rs6000_emit_move (rtx dest, rtx source, if (TARGET_TOC && SYMBOL_REF_P (XEXP (operands[1], 0)) - && use_toc_relative_ref (XEXP (operands[1], 0), mode)) + && use_toc_or_pc_relative_ref (XEXP (operands[1], 0), mode)) { - rtx tocref = create_TOC_reference (XEXP (operands[1], 0), - operands[0]); - operands[1] = gen_const_mem (mode, tocref); + rtx dataref = create_data_reference (XEXP (operands[1], 0), + operands[0]); + operands[1] = gen_const_mem (mode, dataref); set_mem_alias_set (operands[1], get_TOC_alias_set ()); } } Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 272757) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -11666,9 +11666,9 @@ (define_insn_and_split "*cmp<mode>_inter if (TARGET_TOC) { rtx tocref; - tocref = create_TOC_reference (XEXP (operands[14], 0), operands[11]); + tocref = create_data_reference (XEXP (operands[14], 0), operands[11]); operands[14] = gen_const_mem (DFmode, tocref); - tocref = create_TOC_reference (XEXP (operands[15], 0), operands[11]); + tocref = create_data_reference (XEXP (operands[15], 0), operands[11]); operands[15] = gen_const_mem (DFmode, tocref); set_mem_alias_set (operands[14], get_TOC_alias_set ()); set_mem_alias_set (operands[15], get_TOC_alias_set ()); -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797