@@ -151,9 +151,7 @@
if (GET_CODE (op) == LABEL_REF)
return true;
if (SYMBOL_REF_P (op))
- return (!SYMBOL_FLAG_NOTALIGN2_P (op)
- && SYMBOL_REF_TLS_MODEL (op) == 0
- && s390_rel_address_ok_p (op));
+ return s390_symbol_larl_p (op);
/* Everything else must have a CONST, so strip it. */
if (GET_CODE (op) != CONST)
@@ -176,10 +174,7 @@
if (GET_CODE (op) == LABEL_REF)
return true;
if (SYMBOL_REF_P (op))
- return (!SYMBOL_FLAG_NOTALIGN2_P (op)
- && SYMBOL_REF_TLS_MODEL (op) == 0
- && s390_rel_address_ok_p (op));
-
+ return s390_symbol_larl_p (op);
/* Now we must have a @GOTENT offset or @PLT stub
or an @INDNTPOFF TLS offset. */
@@ -157,6 +157,7 @@ extern void s390_indirect_branch_via_thunk (unsigned int regno,
rtx comparison_operator,
enum s390_indirect_branch_type type);
extern void s390_indirect_branch_via_inline_thunk (rtx execute_target);
+extern bool s390_symbol_larl_p (rtx);
#endif /* RTX_CODE */
/* s390-c.c routines */
@@ -2816,6 +2816,25 @@ s390_decompose_constant_pool_ref (rtx *ref, rtx *disp, bool *is_ptr,
return true;
}
+/* Return true iff SYMBOL_REF X can be used with a LARL instruction. */
+
+bool
+s390_symbol_larl_p (rtx x)
+{
+ return (!SYMBOL_FLAG_NOTALIGN2_P (x)
+ && SYMBOL_REF_TLS_MODEL (x) == 0
+ && s390_rel_address_ok_p (x));
+}
+
+/* Return true iff X is a pattern describing a LARL instruction. */
+
+static bool
+s390_larl_pattern_p (rtx x)
+{
+ return (GET_CODE (x) == SET
+ && larl_operand (SET_SRC (x), VOIDmode));
+}
+
/* Decompose a RTL expression ADDR for a memory address into
its components, returned in OUT.
@@ -8111,11 +8130,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;
@@ -8184,7 +8200,8 @@ annotate_constant_pool_refs (rtx *x)
rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
UNSPEC_LTREF);
- SET_SRC (*x) = plus_constant (Pmode, addr, off);
+ SET_SRC (*x) = gen_rtx_CONST (Pmode,
+ plus_constant (Pmode, addr, off));
return;
}
}
@@ -8194,16 +8211,28 @@ 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));
}
}
}
+/* Annotate every literal pool reference in X by an UNSPEC_LTREF expression.
+ Fix up MEMs as required.
+ Do nothing if X is a pattern describing a LARL instruction. */
+
+static void
+annotate_constant_pool_refs (rtx *x)
+{
+ if (s390_larl_pattern_p (*x))
+ return;
+ annotate_constant_pool_refs_1 (x);
+}
+
/* 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
@@ -8223,6 +8252,18 @@ find_constant_pool_ref (rtx x, rtx *ref)
&& XINT (x, 1) == UNSPECV_POOL_ENTRY)
return;
+ if (SYMBOL_REF_P (x)
+ && CONSTANT_POOL_ADDRESS_P (x)
+ && s390_symbol_larl_p (x))
+ {
+ if (*ref == NULL_RTX)
+ *ref = x;
+ else
+ gcc_assert (*ref == x);
+
+ return;
+ }
+
gcc_assert (GET_CODE (x) != SYMBOL_REF
|| !CONSTANT_POOL_ADDRESS_P (x));
@@ -8255,11 +8296,8 @@ find_constant_pool_ref (rtx x, rtx *ref)
}
}
-/* Replace every reference to the annotated literal pool
- symbol REF in X by its base plus OFFSET. */
-
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;
@@ -8290,16 +8328,28 @@ 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 X by its base plus OFFSET.
+ Do nothing if X is a pattern describing a LARL instruction. */
+
+static void
+replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
+{
+ if (s390_larl_pattern_p (*x))
+ return;
+ replace_constant_pool_ref_1 (x, ref, offset);
+}
+
/* We keep a list of constants which we have to add to internal
constant tables in the middle of large functions. */