This patch updates the basic support for pc-relative addressing that will be added in a future machine.
It was originally proposed as patch #4: https://gcc.gnu.org/ml/gcc-patches/2019-06/msg01866.html Segher suggested that I split out moving create_TOC_reference back to rs6000.c as a separate patch, which I did in this patch that has been committed: https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00719.html In working on the other suggestions from Segher about the second argument to create_TOC_reference (which is where to put the HIGH value after register allocation), I came to the conclusion it wasn't worth it to try and combine TOC and pc-relative addressing. There are two places in rs6000_emit_move that deal with the creation of TOC/pc-relative addressing. There is also one place in rs6000.md that created TOC addressing that needed to support pc-relative addressing also. It does the compare of two __ibm128 floating point values when the -mcompat-xl switch is used, and the comparison needs to compare the values against 0 and +infinity, and it needs to load up the two constants. Instead of trying to combine the two addressing forms, I added separate support for pc-relative addressing, and added extra checks in supporting TOC addressing. The one place where I combined TOC and pc-relative addressing is using a common function to set the memory alias set group. Originally it was called get_TOC_alias_set, and I renamed it to get_data_alias_set and I changed all of the callers. There will be several other patches before all of the pc-relative support is available and turned on by default. I have bootstraped the compiler on a little endian power8 system and there were no regressions in the test suite. Can I check it into the trunk? 2019-07-09 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/rs6000-protos.h (get_data_alias_set): Rename get_TOC_alias_set for use with both TOC & pc-relative addressing. * config/rs6000/rs6000.c (create_TOC_reference): Add gcc_assert. (rs6000_legitimize_address): Add check for not pc-relative in TOC support. (rs6000_legitimize_tls_address_aix): Call get_data_alias_set instead of get_TOC_alias_set. (use_toc_relative_ref): Add check for SYMBOL_REF and not pc-relative to simplify callers. Make tests easier to understand. (use_pc_relative_ref): New helper function. (rs6000_emit_move): Add basic support for pc-relative addressing. Call get_data_alias_set instead of get_TOC_alias_set. (data_alias_set): Rename static variable. (get_data_alias_set): Rename get_TOC_alias_set since it is now used for both TOC and pc-relative addressing. * config/rs6000/rs6000.md (cmp<mode>_internal2): Add support for pc-relative addressing. Call get_data_alias_set instead of get_TOC_alias_set. Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 273255) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -189,7 +189,7 @@ extern void rs6000_gen_section_name (cha extern void output_function_profiler (FILE *, int); extern void output_profile_hook (int); extern int rs6000_trampoline_size (void); -extern alias_set_type get_TOC_alias_set (void); +extern alias_set_type get_data_alias_set (void); extern void rs6000_emit_prologue (void); extern void rs6000_emit_load_toc_table (int); extern unsigned int rs6000_dbx_register_number (unsigned int, unsigned int); Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 273310) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -7740,6 +7740,8 @@ create_TOC_reference (rtx symbol, rtx la { rtx tocrel, tocreg, hi; + gcc_assert (TARGET_TOC && !TARGET_PCREL); + if (TARGET_DEBUG_ADDR) { if (SYMBOL_REF_P (symbol)) @@ -8137,7 +8139,7 @@ rs6000_legitimize_address (rtx x, rtx ol emit_insn (gen_macho_high (reg, x)); return gen_rtx_LO_SUM (Pmode, reg, x); } - else if (TARGET_TOC + else if (TARGET_TOC && !TARGET_PCREL && SYMBOL_REF_P (x) && constant_pool_expr_p (x) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode)) @@ -8441,7 +8443,7 @@ rs6000_legitimize_tls_address_aix (rtx a { tocref = create_TOC_reference (XEXP (sym, 0), NULL_RTX); mem = gen_const_mem (Pmode, tocref); - set_mem_alias_set (mem, get_TOC_alias_set ()); + set_mem_alias_set (mem, get_data_alias_set ()); } else return sym; @@ -8459,7 +8461,7 @@ rs6000_legitimize_tls_address_aix (rtx a SYMBOL_REF_FLAGS (modaddr) |= SYMBOL_FLAG_LOCAL; tocref = create_TOC_reference (modaddr, NULL_RTX); rtx modmem = gen_const_mem (Pmode, tocref); - set_mem_alias_set (modmem, get_TOC_alias_set ()); + set_mem_alias_set (modmem, get_data_alias_set ()); rtx modreg = gen_reg_rtx (Pmode); emit_insn (gen_rtx_SET (modreg, modmem)); @@ -8760,12 +8762,34 @@ rs6000_cannot_force_const_mem (machine_m static bool use_toc_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)); + if (!SYMBOL_REF_P (sym) || TARGET_PCREL || !TARGET_TOC) + return false; + + if (constant_pool_expr_p (sym) + && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym), + get_pool_mode (sym))) + return true; + + return (TARGET_CMODEL == CMODEL_MEDIUM && SYMBOL_REF_LOCAL_P (sym) + && GET_MODE_SIZE (mode) <= POWERPC64_TOC_POINTER_ALIGNMENT); +} + +/* Return true iff the given SYMBOL_REF refers to a constant pool entry that we + have put in the pc-relative constant area, or for cmodel=medium, if the + SYMBOL_REF can be addressed via pc-relative instructions. */ + +static bool +use_pc_relative_ref (rtx sym) +{ + if (!SYMBOL_REF_P (sym) || !TARGET_PCREL) + return false; + + if (constant_pool_expr_p (sym) + && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym), + get_pool_mode (sym))) + return true; + + return (TARGET_CMODEL == CMODEL_MEDIUM && SYMBOL_REF_LOCAL_P (sym)); } /* TARGET_LEGITIMATE_ADDRESS_P recognizes an RTL expression @@ -9865,10 +9889,14 @@ rs6000_emit_move (rtx dest, rtx source, /* If this is a SYMBOL_REF that refers to a constant pool entry, and we have put it in the TOC, we just need to make a TOC-relative reference to it. */ - if (TARGET_TOC - && SYMBOL_REF_P (operands[1]) - && use_toc_relative_ref (operands[1], mode)) + if (use_toc_relative_ref (operands[1], mode)) operands[1] = create_TOC_reference (operands[1], operands[0]); + + /* If this is a pc-relative reference, we don't have to do anything + fancy. */ + else if (use_pc_relative_ref (operands[1])) + ; + else if (mode == Pmode && CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != HIGH @@ -9919,14 +9947,18 @@ rs6000_emit_move (rtx dest, rtx source, operands[1] = force_const_mem (mode, operands[1]); - if (TARGET_TOC - && SYMBOL_REF_P (XEXP (operands[1], 0)) - && use_toc_relative_ref (XEXP (operands[1], 0), mode)) + rtx addr = XEXP (operands[1], 0); + if (use_toc_relative_ref (addr, mode)) { - rtx tocref = create_TOC_reference (XEXP (operands[1], 0), - operands[0]); + rtx tocref = create_TOC_reference (addr, operands[0]); operands[1] = gen_const_mem (mode, tocref); - set_mem_alias_set (operands[1], get_TOC_alias_set ()); + set_mem_alias_set (operands[1], get_data_alias_set ()); + } + + else if (use_pc_relative_ref (addr)) + { + operands[1] = gen_const_mem (mode, addr); + set_mem_alias_set (operands[1], get_data_alias_set ()); } } break; @@ -23732,14 +23764,16 @@ rs6000_split_multireg_move (rtx dst, rtx } } -static GTY(()) alias_set_type set = -1; +/* Return the alias set for constants stored in either the TOC or via + pc-relative addressing. */ +static GTY(()) alias_set_type data_alias_set = -1; alias_set_type -get_TOC_alias_set (void) +get_data_alias_set (void) { - if (set == -1) - set = new_alias_set (); - return set; + if (data_alias_set == -1) + data_alias_set = new_alias_set (); + return data_alias_set; } /* Return the internal arg pointer used for function incoming Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 273255) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -11606,15 +11606,23 @@ (define_insn_and_split "*cmp<mode>_inter operands[15] = force_const_mem (DFmode, const_double_from_real_value (dconst0, DFmode)); - if (TARGET_TOC) + if (TARGET_PCREL) + { + operands[14] = gen_const_mem (DFmode, XEXP (operands[14], 0)); + operands[15] = gen_const_mem (DFmode, XEXP (operands[15], 0)); + set_mem_alias_set (operands[14], get_data_alias_set ()); + set_mem_alias_set (operands[15], get_data_alias_set ()); + } + + else if (TARGET_TOC) { rtx tocref; tocref = create_TOC_reference (XEXP (operands[14], 0), operands[11]); operands[14] = gen_const_mem (DFmode, tocref); tocref = create_TOC_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 ()); + set_mem_alias_set (operands[14], get_data_alias_set ()); + set_mem_alias_set (operands[15], get_data_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