return false;
}
-/* Attempts to split `ref', which should be either UNSPEC_LTREF or
- UNSPEC_LTREL_BASE, into (base + `disp'). In case pool base is not known,
- caller-provided `pool_base' is used. If successful, also determines the
+/* Attempts to split `ref', which should be UNSPEC_LTREF, into (base + `disp').
+ If successful, also determines the
following characteristics of `ref': `is_ptr' - whether it can be an
LA argument, `is_base_ptr' - whether the resulting base is a well-known
base register (stack/frame pointer, etc), `is_pool_ptr` - whether it is
literal pool pointers per insn during or after reload (`B' constraint). */
static bool
s390_decompose_constant_pool_ref (rtx *ref, rtx *disp, bool *is_ptr,
- bool *is_base_ptr, bool *is_pool_ptr,
- rtx pool_base)
+ bool *is_base_ptr, bool *is_pool_ptr)
{
if (!*ref)
return true;
*ref = XVECEXP (*ref, 0, 1);
break;
- case UNSPEC_LTREL_BASE:
- if (XVECLEN (*ref, 0) == 1)
- *ref = pool_base, *is_pool_ptr = true;
- else
- *ref = XVECEXP (*ref, 0, 1);
- break;
-
default:
return false;
}
/* Validate base register. */
if (!s390_decompose_constant_pool_ref (&base, &disp, &pointer, &base_ptr,
- &literal_pool, fake_pool_base))
+ &literal_pool))
return false;
/* Validate index register. */
if (!s390_decompose_constant_pool_ref (&indx, &disp, &pointer, &indx_ptr,
- &literal_pool, fake_pool_base))
+ &literal_pool))
return false;
/* Prefer to use pointer as base, not index. */
}
}
- /* Annotate LTREL_BASE as well. */
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_LTREL_BASE)
- {
- rtx base = cfun->machine->base_reg;
- *x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XVECEXP (*x, 0, 0), base),
- UNSPEC_LTREL_BASE);
- return;
- }
-
fmt = GET_RTX_FORMAT (GET_CODE (*x));
for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
{
int i, j;
const char *fmt;
- /* Ignore LTREL_BASE references. */
- if (GET_CODE (x) == UNSPEC
- && XINT (x, 1) == UNSPEC_LTREL_BASE)
- return;
/* Likewise POOL_ENTRY insns. */
if (GET_CODE (x) == UNSPEC_VOLATILE
&& XINT (x, 1) == UNSPECV_POOL_ENTRY)
}
}
-/* Check whether X contains an UNSPEC_LTREL_BASE.
- Return its constant pool symbol if found, NULL_RTX otherwise. */
-
-static rtx
-find_ltrel_base (rtx x)
-{
- int i, j;
- const char *fmt;
-
- if (GET_CODE (x) == UNSPEC
- && XINT (x, 1) == UNSPEC_LTREL_BASE)
- return XVECEXP (x, 0, 0);
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- rtx fnd = find_ltrel_base (XEXP (x, i));
- if (fnd)
- return fnd;
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (x, i); j++)
- {
- rtx fnd = find_ltrel_base (XVECEXP (x, i, j));
- if (fnd)
- return fnd;
- }
- }
- }
-
- return NULL_RTX;
-}
-
-/* Replace any occurrence of UNSPEC_LTREL_BASE in X with its base. */
-
-static void
-replace_ltrel_base (rtx *x)
-{
- int i, j;
- const char *fmt;
-
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_LTREL_BASE)
- {
- *x = XVECEXP (*x, 0, 1);
- return;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (*x));
- for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- replace_ltrel_base (&XEXP (*x, i));
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (*x, i); j++)
- replace_ltrel_base (&XVECEXP (*x, i, j));
- }
- }
-}
-
-
/* We keep a list of constants which we have to add to internal
constant tables in the middle of large functions. */
for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn));
-
if (NONJUMP_INSN_P (insn) || CALL_P (insn))
{
rtx addr, pool_ref = NULL_RTX;
{
struct constant_pool *curr_pool = NULL, *pool_list = NULL;
bitmap far_labels;
- rtx pending_ltrel = NULL_RTX;
rtx_insn *insn;
/* We need correct insn addresses. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- /* Check for pending LTREL_BASE. */
- if (INSN_P (insn))
- {
- rtx ltrel_base = find_ltrel_base (PATTERN (insn));
- if (ltrel_base)
- {
- gcc_assert (ltrel_base == pending_ltrel);
- pending_ltrel = NULL_RTX;
- }
- }
-
if (NONJUMP_INSN_P (insn) || CALL_P (insn))
{
rtx pool_ref = NULL_RTX;
s390_add_constant (curr_pool, constant, mode);
s390_add_pool_insn (curr_pool, insn);
-
- /* Don't split the pool chunk between a LTREL_OFFSET load
- and the corresponding LTREL_BASE. */
- if (GET_CODE (constant) == CONST
- && GET_CODE (XEXP (constant, 0)) == UNSPEC
- && XINT (XEXP (constant, 0), 1) == UNSPEC_LTREL_OFFSET)
- {
- gcc_assert (!pending_ltrel);
- pending_ltrel = pool_ref;
- }
}
}
{
if (curr_pool)
s390_add_pool_insn (curr_pool, insn);
- /* An LTREL_BASE must follow within the same basic block. */
- gcc_assert (!pending_ltrel);
}
if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
if (curr_pool)
s390_end_pool (curr_pool, NULL);
- gcc_assert (!pending_ltrel);
/* Find all labels that are branched into
from an insn belonging to a different chunk. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn));
-
curr_pool = s390_find_pool (pool_list, insn);
if (!curr_pool)
continue;