S/390: Allow relative addressing of literal pool entries
authorIlya Leoshkevich <iii@linux.ibm.com>
Fri, 9 Nov 2018 20:33:19 +0000 (20:33 +0000)
committerIlya Leoshkevich <iii@gcc.gnu.org>
Fri, 9 Nov 2018 20:33:19 +0000 (20:33 +0000)
r265490 allowed the compiler to choose in a more flexible way whether to
use load or load-address-relative-long (LARL) instruction.  When it
chose LARL for literal pool references, the latter ones were rewritten
by pass_s390_early_mach to use UNSPEC_LTREF, which assumes base register
usage, which in turn is not compatible with LARL.  The end result was an
ICE because of unrecognizable insn.

UNSPEC_LTREF and friends are necessary in order to communicate the
dependency on the base register to pass_sched2.  When relative
addressing is used, no base register is necessary, so in such cases the
rewrite must be avoided.

gcc/ChangeLog:

2018-11-09  Ilya Leoshkevich  <iii@linux.ibm.com>

PR target/87762
* config/s390/s390.c (s390_safe_relative_long_p): New function.
(annotate_constant_pool_refs): Skip insns which support
relative addressing.
(annotate_constant_pool_refs_1): New helper function.
(find_constant_pool_ref): Skip insns which support relative
addression.
(find_constant_pool_ref_1): New helper function.
(replace_constant_pool_ref): Skip insns which support
relative addressing.
(replace_constant_pool_ref_1): New helper function.
(s390_mainpool_start): Adapt to the new signature.
(s390_mainpool_finish): Likewise.
(s390_chunkify_start): Likewise.
(s390_chunkify_finish): Likewise.
(pass_s390_early_mach::execute): Likewise.
(s390_prologue_plus_offset): Likewise.
(s390_emit_prologue): Likewise.
(s390_emit_epilogue): Likewise.

From-SVN: r265991

gcc/ChangeLog
gcc/config/s390/s390.c

index 45629bbfc77709a4369ebb35c1b346e87e9031bd..6d1b40d1e946a84380c2fc2b49c2e9185675115f 100644 (file)
@@ -1,3 +1,25 @@
+2018-11-09  Ilya Leoshkevich  <iii@linux.ibm.com>
+
+       PR target/87762
+       * config/s390/s390.c (s390_safe_relative_long_p): New function.
+       (annotate_constant_pool_refs): Skip insns which support
+       relative addressing.
+       (annotate_constant_pool_refs_1): New helper function.
+       (find_constant_pool_ref): Skip insns which support relative
+       addression.
+       (find_constant_pool_ref_1): New helper function.
+       (replace_constant_pool_ref): Skip insns which support
+       relative addressing.
+       (replace_constant_pool_ref_1): New helper function.
+       (s390_mainpool_start): Adapt to the new signature.
+       (s390_mainpool_finish): Likewise.
+       (s390_chunkify_start): Likewise.
+       (s390_chunkify_finish): Likewise.
+       (pass_s390_early_mach::execute): Likewise.
+       (s390_prologue_plus_offset): Likewise.
+       (s390_emit_prologue): Likewise.
+       (s390_emit_epilogue): Likewise.
+
 2018-11-09  Jakub Jelinek  <jakub@redhat.com>
 
        * gimplify.c (gimplify_scan_omp_clauses): Call sorry_at for valid
index 0f33101d779306affd835e89824d3b166bdf51bb..ab06ada0a16532c96d30bfd25b54b1255fb627eb 100644 (file)
@@ -2731,6 +2731,17 @@ s390_safe_attr_type (rtx_insn *insn)
     return TYPE_NONE;
 }
 
+/* Return attribute relative_long of insn.  */
+
+static bool
+s390_safe_relative_long_p (rtx_insn *insn)
+{
+  if (recog_memoized (insn) >= 0)
+    return get_attr_relative_long (insn) == RELATIVE_LONG_YES;
+  else
+    return false;
+}
+
 /* Return true if DISP is a valid short displacement.  */
 
 static bool
@@ -8102,11 +8113,8 @@ s390_first_cycle_multipass_dfa_lookahead (void)
   return 4;
 }
 
-/* Annotate every literal pool reference in X by an UNSPEC_LTREF expression.
-   Fix up MEMs as required.  */
-
 static void
-annotate_constant_pool_refs (rtx *x)
+annotate_constant_pool_refs_1 (rtx *x)
 {
   int i, j;
   const char *fmt;
@@ -8185,26 +8193,31 @@ annotate_constant_pool_refs (rtx *x)
     {
       if (fmt[i] == 'e')
        {
-         annotate_constant_pool_refs (&XEXP (*x, i));
+         annotate_constant_pool_refs_1 (&XEXP (*x, i));
        }
       else if (fmt[i] == 'E')
        {
          for (j = 0; j < XVECLEN (*x, i); j++)
-           annotate_constant_pool_refs (&XVECEXP (*x, i, j));
+           annotate_constant_pool_refs_1 (&XVECEXP (*x, i, j));
        }
     }
 }
 
-/* Find an annotated literal pool symbol referenced in RTX X,
-   and store it at REF.  Will abort if X contains references to
-   more than one such pool symbol; multiple references to the same
-   symbol are allowed, however.
+/* Annotate every literal pool reference in INSN by an UNSPEC_LTREF expression.
+   Fix up MEMs as required.
+   Skip insns which support relative addressing, because they do not use a base
+   register.  */
 
-   The rtx pointed to by REF must be initialized to NULL_RTX
-   by the caller before calling this routine.  */
+static void
+annotate_constant_pool_refs (rtx_insn *insn)
+{
+  if (s390_safe_relative_long_p (insn))
+    return;
+  annotate_constant_pool_refs_1 (&PATTERN (insn));
+}
 
 static void
-find_constant_pool_ref (rtx x, rtx *ref)
+find_constant_pool_ref_1 (rtx x, rtx *ref)
 {
   int i, j;
   const char *fmt;
@@ -8236,21 +8249,37 @@ find_constant_pool_ref (rtx x, rtx *ref)
     {
       if (fmt[i] == 'e')
        {
-         find_constant_pool_ref (XEXP (x, i), ref);
+         find_constant_pool_ref_1 (XEXP (x, i), ref);
        }
       else if (fmt[i] == 'E')
        {
          for (j = 0; j < XVECLEN (x, i); j++)
-           find_constant_pool_ref (XVECEXP (x, i, j), ref);
+           find_constant_pool_ref_1 (XVECEXP (x, i, j), ref);
        }
     }
 }
 
-/* Replace every reference to the annotated literal pool
-   symbol REF in X by its base plus OFFSET.  */
+/* Find an annotated literal pool symbol referenced in INSN,
+   and store it at REF.  Will abort if INSN contains references to
+   more than one such pool symbol; multiple references to the same
+   symbol are allowed, however.
+
+   The rtx pointed to by REF must be initialized to NULL_RTX
+   by the caller before calling this routine.
+
+   Skip insns which support relative addressing, because they do not use a base
+   register.  */
+
+static void
+find_constant_pool_ref (rtx_insn *insn, rtx *ref)
+{
+  if (s390_safe_relative_long_p (insn))
+    return;
+  find_constant_pool_ref_1 (PATTERN (insn), ref);
+}
 
 static void
-replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
+replace_constant_pool_ref_1 (rtx *x, rtx ref, rtx offset)
 {
   int i, j;
   const char *fmt;
@@ -8281,16 +8310,29 @@ replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
     {
       if (fmt[i] == 'e')
        {
-         replace_constant_pool_ref (&XEXP (*x, i), ref, offset);
+         replace_constant_pool_ref_1 (&XEXP (*x, i), ref, offset);
        }
       else if (fmt[i] == 'E')
        {
          for (j = 0; j < XVECLEN (*x, i); j++)
-           replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
+           replace_constant_pool_ref_1 (&XVECEXP (*x, i, j), ref, offset);
        }
     }
 }
 
+/* Replace every reference to the annotated literal pool
+   symbol REF in INSN by its base plus OFFSET.
+   Skip insns which support relative addressing, because they do not use a base
+   register.  */
+
+static void
+replace_constant_pool_ref (rtx_insn *insn, rtx ref, rtx offset)
+{
+  if (s390_safe_relative_long_p (insn))
+    return;
+  replace_constant_pool_ref_1 (&PATTERN (insn), ref, offset);
+}
+
 /* We keep a list of constants which we have to add to internal
    constant tables in the middle of large functions.  */
 
@@ -8691,7 +8733,7 @@ s390_mainpool_start (void)
       if (NONJUMP_INSN_P (insn) || CALL_P (insn))
        {
          rtx pool_ref = NULL_RTX;
-         find_constant_pool_ref (PATTERN (insn), &pool_ref);
+         find_constant_pool_ref (insn, &pool_ref);
          if (pool_ref)
            {
              rtx constant = get_pool_constant (pool_ref);
@@ -8778,7 +8820,7 @@ s390_mainpool_finish (struct constant_pool *pool)
       if (NONJUMP_INSN_P (insn) || CALL_P (insn))
        {
          rtx addr, pool_ref = NULL_RTX;
-         find_constant_pool_ref (PATTERN (insn), &pool_ref);
+         find_constant_pool_ref (insn, &pool_ref);
          if (pool_ref)
            {
              if (s390_execute_label (insn))
@@ -8787,7 +8829,7 @@ s390_mainpool_finish (struct constant_pool *pool)
                addr = s390_find_constant (pool, get_pool_constant (pool_ref),
                                                 get_pool_mode (pool_ref));
 
-             replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
+             replace_constant_pool_ref (insn, pool_ref, addr);
              INSN_CODE (insn) = -1;
            }
        }
@@ -8821,7 +8863,7 @@ s390_chunkify_start (void)
       if (NONJUMP_INSN_P (insn) || CALL_P (insn))
        {
          rtx pool_ref = NULL_RTX;
-         find_constant_pool_ref (PATTERN (insn), &pool_ref);
+         find_constant_pool_ref (insn, &pool_ref);
          if (pool_ref)
            {
              rtx constant = get_pool_constant (pool_ref);
@@ -8978,7 +9020,7 @@ s390_chunkify_finish (struct constant_pool *pool_list)
       if (NONJUMP_INSN_P (insn) || CALL_P (insn))
        {
          rtx addr, pool_ref = NULL_RTX;
-         find_constant_pool_ref (PATTERN (insn), &pool_ref);
+         find_constant_pool_ref (insn, &pool_ref);
          if (pool_ref)
            {
              if (s390_execute_label (insn))
@@ -8988,7 +9030,7 @@ s390_chunkify_finish (struct constant_pool *pool_list)
                                           get_pool_constant (pool_ref),
                                           get_pool_mode (pool_ref));
 
-             replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
+             replace_constant_pool_ref (insn, pool_ref, addr);
              INSN_CODE (insn) = -1;
            }
        }
@@ -10581,7 +10623,7 @@ pass_s390_early_mach::execute (function *fun)
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     if (INSN_P (insn))
       {
-       annotate_constant_pool_refs (&PATTERN (insn));
+       annotate_constant_pool_refs (insn);
        df_insn_rescan (insn);
       }
   return 0;
@@ -10602,7 +10644,7 @@ make_pass_s390_early_mach (gcc::context *ctxt)
 static rtx
 s390_prologue_plus_offset (rtx target, rtx reg, rtx offset, bool frame_related_p)
 {
-  rtx insn;
+  rtx_insn *insn;
   rtx orig_offset = offset;
 
   gcc_assert (REG_P (target));
@@ -10636,7 +10678,7 @@ s390_prologue_plus_offset (rtx target, rtx reg, rtx offset, bool frame_related_p
 
       if (!CONST_INT_P (offset))
        {
-         annotate_constant_pool_refs (&PATTERN (insn));
+         annotate_constant_pool_refs (insn);
 
          if (frame_related_p)
            add_reg_note (insn, REG_FRAME_RELATED_EXPR,
@@ -11076,7 +11118,7 @@ s390_emit_prologue (void)
       rtx_insn *insns = s390_load_got ();
 
       for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
-       annotate_constant_pool_refs (&PATTERN (insn));
+       annotate_constant_pool_refs (insn);
 
       emit_insn (insns);
     }
@@ -11140,7 +11182,8 @@ s390_emit_epilogue (bool sibcall)
     }
   else
     {
-      rtx insn, frame_off, cfa;
+      rtx_insn *insn;
+      rtx frame_off, cfa;
 
       offset = area_bottom < 0 ? -area_bottom : 0;
       frame_off = GEN_INT (cfun_frame_layout.frame_size - offset);
@@ -11149,9 +11192,11 @@ s390_emit_epilogue (bool sibcall)
                         gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
       if (DISP_IN_RANGE (INTVAL (frame_off)))
        {
-         insn = gen_rtx_SET (frame_pointer,
-                             gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
-         insn = emit_insn (insn);
+         rtx set;
+
+         set = gen_rtx_SET (frame_pointer,
+                            gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
+         insn = emit_insn (set);
        }
       else
        {
@@ -11159,7 +11204,7 @@ s390_emit_epilogue (bool sibcall)
            frame_off = force_const_mem (Pmode, frame_off);
 
          insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
-         annotate_constant_pool_refs (&PATTERN (insn));
+         annotate_constant_pool_refs (insn);
        }
       add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa);
       RTX_FRAME_RELATED_P (insn) = 1;