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

Reply via email to