s390-protos.h (s390_load_got): Update prototype.
* config/s390/s390-protos.h (s390_load_got): Update prototype. * config/s390/s390.c (struct machine_function): Add member base_reg. (s390_decompose_address): Accept UNSPEC_LTREF. Simplify logic. (s390_split_branches): Annotate late pool references. (annotate_constant_pool_refs): New function. (find_constant_pool_ref): Work on annotated pool references. (replace_constant_pool_ref): Likewise. Use explicit base. (replace_ltrel_base): Use explicit base. (s390_mainpool_start): Reflect main_pool pattern change. (s390_mainpool_finish): Use base register from main_pool. Update calls to replace_ltrel_base and replace_constant_pool_ref. (s390_chunkify_start): Use base_reg from struct machine_function. (s390_chunkify_finish): Remove base_reg argument. Update calls to replace_ltrel_base and replace_constant_pool_ref. (s390_reorg): Don't decide upon base register. Update calls. (s390_load_got): Remove MAYBE_DEAD handling. Do not emit insns but return sequence instead. (s390_emit_prologue): Decide upon base register to use. Annotate all literal pool references. Adapt to main_pool pattern change. Update s390_load_got call; move MAYBE_DEAD handling here. (s390_emit_epilogue): Annotate late literal pool references. Remove barrier before register restore instruction. * config/s390/s390.md (UNSPEC_LTREF): New constant. ("builtin_setjmp_receiver"): Update s390_load_got call. ("main_pool"): Explicitly reference base register. From-SVN: r83735
This commit is contained in:
parent
0f6cd83f96
commit
585539a1e9
4 changed files with 385 additions and 212 deletions
|
@ -1,3 +1,31 @@
|
|||
2004-06-27 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* config/s390/s390-protos.h (s390_load_got): Update prototype.
|
||||
* config/s390/s390.c (struct machine_function): Add member base_reg.
|
||||
(s390_decompose_address): Accept UNSPEC_LTREF. Simplify logic.
|
||||
(s390_split_branches): Annotate late pool references.
|
||||
(annotate_constant_pool_refs): New function.
|
||||
(find_constant_pool_ref): Work on annotated pool references.
|
||||
(replace_constant_pool_ref): Likewise. Use explicit base.
|
||||
(replace_ltrel_base): Use explicit base.
|
||||
(s390_mainpool_start): Reflect main_pool pattern change.
|
||||
(s390_mainpool_finish): Use base register from main_pool.
|
||||
Update calls to replace_ltrel_base and replace_constant_pool_ref.
|
||||
(s390_chunkify_start): Use base_reg from struct machine_function.
|
||||
(s390_chunkify_finish): Remove base_reg argument. Update calls
|
||||
to replace_ltrel_base and replace_constant_pool_ref.
|
||||
(s390_reorg): Don't decide upon base register. Update calls.
|
||||
(s390_load_got): Remove MAYBE_DEAD handling. Do not emit insns
|
||||
but return sequence instead.
|
||||
(s390_emit_prologue): Decide upon base register to use. Annotate
|
||||
all literal pool references. Adapt to main_pool pattern change.
|
||||
Update s390_load_got call; move MAYBE_DEAD handling here.
|
||||
(s390_emit_epilogue): Annotate late literal pool references.
|
||||
Remove barrier before register restore instruction.
|
||||
* config/s390/s390.md (UNSPEC_LTREF): New constant.
|
||||
("builtin_setjmp_receiver"): Update s390_load_got call.
|
||||
("main_pool"): Explicitly reference base register.
|
||||
|
||||
2004-06-27 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* fold-const.c (fold) <BIT_IOR_EXPR>: Optimize ~X|X and X|~X as -1.
|
||||
|
|
|
@ -24,7 +24,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
extern void optimization_options (int, int);
|
||||
extern void override_options (void);
|
||||
extern HOST_WIDE_INT s390_arg_frame_offset (void);
|
||||
extern void s390_load_got (int);
|
||||
extern void s390_emit_prologue (void);
|
||||
extern void s390_emit_epilogue (bool);
|
||||
extern void s390_function_profiler (FILE *, int);
|
||||
|
@ -92,6 +91,7 @@ extern void s390_initialize_trampoline (rtx, rtx, rtx);
|
|||
extern rtx s390_gen_rtx_const_DI (int, int);
|
||||
extern void s390_output_dwarf_dtprel (FILE*, int, rtx);
|
||||
extern int s390_agen_dep_p (rtx, rtx);
|
||||
extern rtx s390_load_got (void);
|
||||
|
||||
#endif /* RTX_CODE */
|
||||
|
||||
|
|
|
@ -217,6 +217,9 @@ struct machine_function GTY(())
|
|||
/* Size of stack frame. */
|
||||
HOST_WIDE_INT frame_size;
|
||||
|
||||
/* Literal pool base register. */
|
||||
rtx base_reg;
|
||||
|
||||
/* Some local-dynamic TLS symbol name. */
|
||||
const char *some_ld_name;
|
||||
};
|
||||
|
@ -236,10 +239,11 @@ static int get_some_local_dynamic_name_1 (rtx *, void *);
|
|||
static int reg_used_in_mem_p (int, rtx);
|
||||
static int addr_generation_dependency_p (rtx, rtx);
|
||||
static int s390_split_branches (void);
|
||||
static void annotate_constant_pool_refs (rtx *x);
|
||||
static void find_constant_pool_ref (rtx, rtx *);
|
||||
static void replace_constant_pool_ref (rtx *, rtx, rtx);
|
||||
static rtx find_ltrel_base (rtx);
|
||||
static void replace_ltrel_base (rtx *, rtx);
|
||||
static void replace_ltrel_base (rtx *);
|
||||
static void s390_optimize_prolog (bool);
|
||||
static int find_unused_clobbered_reg (void);
|
||||
static void s390_frame_info (int, int);
|
||||
|
@ -2069,9 +2073,11 @@ s390_expand_plus_operand (register rtx target, register rtx src,
|
|||
static int
|
||||
s390_decompose_address (register rtx addr, struct s390_address *out)
|
||||
{
|
||||
HOST_WIDE_INT offset = 0;
|
||||
rtx base = NULL_RTX;
|
||||
rtx indx = NULL_RTX;
|
||||
rtx disp = NULL_RTX;
|
||||
rtx orig_disp;
|
||||
int pointer = FALSE;
|
||||
int base_ptr = FALSE;
|
||||
int indx_ptr = FALSE;
|
||||
|
@ -2119,16 +2125,69 @@ s390_decompose_address (register rtx addr, struct s390_address *out)
|
|||
else
|
||||
disp = addr; /* displacement */
|
||||
|
||||
/* Extract integer part of displacement. */
|
||||
orig_disp = disp;
|
||||
if (disp)
|
||||
{
|
||||
if (GET_CODE (disp) == CONST_INT)
|
||||
{
|
||||
offset = INTVAL (disp);
|
||||
disp = NULL_RTX;
|
||||
}
|
||||
else if (GET_CODE (disp) == CONST
|
||||
&& GET_CODE (XEXP (disp, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
|
||||
{
|
||||
offset = INTVAL (XEXP (XEXP (disp, 0), 1));
|
||||
disp = XEXP (XEXP (disp, 0), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Strip off CONST here to avoid special case tests later. */
|
||||
if (disp && GET_CODE (disp) == CONST)
|
||||
disp = XEXP (disp, 0);
|
||||
|
||||
/* We can convert literal pool addresses to
|
||||
displacements by basing them off the base register. */
|
||||
if (disp && GET_CODE (disp) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (disp))
|
||||
{
|
||||
/* Either base or index must be free to hold the base register. */
|
||||
if (!base)
|
||||
base = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
else if (!indx)
|
||||
indx = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
/* Mark up the displacement. */
|
||||
disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),
|
||||
UNSPEC_LTREL_OFFSET);
|
||||
}
|
||||
|
||||
/* Validate base register. */
|
||||
if (base)
|
||||
{
|
||||
if (GET_CODE (base) == UNSPEC)
|
||||
{
|
||||
if (XVECLEN (base, 0) != 1 || XINT (base, 1) != UNSPEC_LTREL_BASE)
|
||||
switch (XINT (base, 1))
|
||||
{
|
||||
case UNSPEC_LTREF:
|
||||
if (!disp)
|
||||
disp = gen_rtx_UNSPEC (Pmode,
|
||||
gen_rtvec (1, XVECEXP (base, 0, 0)),
|
||||
UNSPEC_LTREL_OFFSET);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
base = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
break;
|
||||
|
||||
case UNSPEC_LTREL_BASE:
|
||||
base = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
base = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
|
||||
return FALSE;
|
||||
|
@ -2149,11 +2208,26 @@ s390_decompose_address (register rtx addr, struct s390_address *out)
|
|||
if (indx)
|
||||
{
|
||||
if (GET_CODE (indx) == UNSPEC)
|
||||
{
|
||||
if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != UNSPEC_LTREL_BASE)
|
||||
switch (XINT (indx, 1))
|
||||
{
|
||||
case UNSPEC_LTREF:
|
||||
if (!disp)
|
||||
disp = gen_rtx_UNSPEC (Pmode,
|
||||
gen_rtvec (1, XVECEXP (indx, 0, 0)),
|
||||
UNSPEC_LTREL_OFFSET);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
indx = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
break;
|
||||
|
||||
case UNSPEC_LTREL_BASE:
|
||||
indx = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
indx = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
|
||||
return FALSE;
|
||||
|
@ -2180,106 +2254,63 @@ s390_decompose_address (register rtx addr, struct s390_address *out)
|
|||
}
|
||||
|
||||
/* Validate displacement. */
|
||||
if (disp)
|
||||
if (!disp)
|
||||
{
|
||||
/* Allow integer constant in range. */
|
||||
if (GET_CODE (disp) == CONST_INT)
|
||||
{
|
||||
/* If the argument pointer is involved, the displacement will change
|
||||
later anyway as the argument pointer gets eliminated. This could
|
||||
make a valid displacement invalid, but it is more likely to make
|
||||
an invalid displacement valid, because we sometimes access the
|
||||
register save area via negative offsets to the arg pointer.
|
||||
Thus we don't check the displacement for validity here. If after
|
||||
elimination the displacement turns out to be invalid after all,
|
||||
this is fixed up by reload in any case. */
|
||||
if (base != arg_pointer_rtx && indx != arg_pointer_rtx)
|
||||
{
|
||||
if (!DISP_IN_RANGE (INTVAL (disp)))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/* If the argument pointer is involved, the displacement will change
|
||||
later anyway as the argument pointer gets eliminated. This could
|
||||
make a valid displacement invalid, but it is more likely to make
|
||||
an invalid displacement valid, because we sometimes access the
|
||||
register save area via negative offsets to the arg pointer.
|
||||
Thus we don't check the displacement for validity here. If after
|
||||
elimination the displacement turns out to be invalid after all,
|
||||
this is fixed up by reload in any case. */
|
||||
if (base != arg_pointer_rtx && indx != arg_pointer_rtx)
|
||||
if (!DISP_IN_RANGE (offset))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All the special cases are pointers. */
|
||||
pointer = TRUE;
|
||||
|
||||
/* In the small-PIC case, the linker converts @GOT
|
||||
and @GOTNTPOFF offsets to possible displacements. */
|
||||
else if (GET_CODE (disp) == CONST
|
||||
&& GET_CODE (XEXP (disp, 0)) == UNSPEC
|
||||
&& (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT
|
||||
|| XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
|
||||
if (GET_CODE (disp) == UNSPEC
|
||||
&& (XINT (disp, 1) == UNSPEC_GOT
|
||||
|| XINT (disp, 1) == UNSPEC_GOTNTPOFF)
|
||||
&& offset == 0
|
||||
&& flag_pic == 1)
|
||||
{
|
||||
if (flag_pic != 1)
|
||||
return FALSE;
|
||||
|
||||
pointer = TRUE;
|
||||
;
|
||||
}
|
||||
|
||||
/* Accept chunkfied literal pool symbol references. */
|
||||
else if (GET_CODE (disp) == CONST
|
||||
&& GET_CODE (XEXP (disp, 0)) == MINUS
|
||||
&& GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF
|
||||
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == LABEL_REF)
|
||||
/* Accept chunkified literal pool symbol references. */
|
||||
else if (GET_CODE (disp) == MINUS
|
||||
&& GET_CODE (XEXP (disp, 0)) == LABEL_REF
|
||||
&& GET_CODE (XEXP (disp, 1)) == LABEL_REF)
|
||||
{
|
||||
pointer = TRUE;
|
||||
;
|
||||
}
|
||||
|
||||
/* Likewise if a constant offset is present. */
|
||||
else if (GET_CODE (disp) == CONST
|
||||
&& GET_CODE (XEXP (disp, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT
|
||||
&& GET_CODE (XEXP (XEXP (disp, 0), 0)) == MINUS
|
||||
&& GET_CODE (XEXP (XEXP (XEXP (disp, 0), 0), 0)) == LABEL_REF
|
||||
&& GET_CODE (XEXP (XEXP (XEXP (disp, 0), 0), 1)) == LABEL_REF)
|
||||
/* Accept literal pool references. */
|
||||
else if (GET_CODE (disp) == UNSPEC
|
||||
&& XINT (disp, 1) == UNSPEC_LTREL_OFFSET)
|
||||
{
|
||||
pointer = TRUE;
|
||||
orig_disp = gen_rtx_CONST (Pmode, disp);
|
||||
if (offset)
|
||||
{
|
||||
/* If we have an offset, make sure it does not
|
||||
exceed the size of the constant pool entry. */
|
||||
rtx sym = XVECEXP (disp, 0, 0);
|
||||
if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))
|
||||
return FALSE;
|
||||
|
||||
orig_disp = plus_constant (orig_disp, offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* We can convert literal pool addresses to
|
||||
displacements by basing them off the base register. */
|
||||
else
|
||||
{
|
||||
/* In some cases, we can accept an additional
|
||||
small constant offset. Split these off here. */
|
||||
|
||||
unsigned int offset = 0;
|
||||
|
||||
if (GET_CODE (disp) == CONST
|
||||
&& GET_CODE (XEXP (disp, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
|
||||
{
|
||||
offset = INTVAL (XEXP (XEXP (disp, 0), 1));
|
||||
disp = XEXP (XEXP (disp, 0), 0);
|
||||
}
|
||||
|
||||
/* Now we must have a literal pool address. */
|
||||
if (GET_CODE (disp) != SYMBOL_REF
|
||||
|| !CONSTANT_POOL_ADDRESS_P (disp))
|
||||
return FALSE;
|
||||
|
||||
/* If we have an offset, make sure it does not
|
||||
exceed the size of the constant pool entry. */
|
||||
if (offset && offset >= GET_MODE_SIZE (get_pool_mode (disp)))
|
||||
return FALSE;
|
||||
|
||||
/* Either base or index must be free to
|
||||
hold the base register. */
|
||||
if (base && indx)
|
||||
return FALSE;
|
||||
|
||||
/* Convert the address. */
|
||||
if (base)
|
||||
indx = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
else
|
||||
base = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
|
||||
disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),
|
||||
UNSPEC_LTREL_OFFSET);
|
||||
disp = gen_rtx_CONST (Pmode, disp);
|
||||
|
||||
if (offset)
|
||||
disp = plus_constant (disp, offset);
|
||||
|
||||
pointer = TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!base && !indx)
|
||||
|
@ -2289,7 +2320,7 @@ s390_decompose_address (register rtx addr, struct s390_address *out)
|
|||
{
|
||||
out->base = base;
|
||||
out->indx = indx;
|
||||
out->disp = disp;
|
||||
out->disp = orig_disp;
|
||||
out->pointer = pointer;
|
||||
}
|
||||
|
||||
|
@ -4058,6 +4089,7 @@ s390_split_branches (void)
|
|||
tmp = force_const_mem (Pmode, *label);
|
||||
tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
|
||||
INSN_ADDRESSES_NEW (tmp, -1);
|
||||
annotate_constant_pool_refs (&PATTERN (tmp));
|
||||
|
||||
target = temp_reg;
|
||||
}
|
||||
|
@ -4070,8 +4102,10 @@ s390_split_branches (void)
|
|||
target = force_const_mem (Pmode, target);
|
||||
tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
|
||||
INSN_ADDRESSES_NEW (tmp, -1);
|
||||
annotate_constant_pool_refs (&PATTERN (tmp));
|
||||
|
||||
target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (target, 0)),
|
||||
target = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XEXP (target, 0),
|
||||
cfun->machine->base_reg),
|
||||
UNSPEC_LTREL_BASE);
|
||||
target = gen_rtx_PLUS (Pmode, temp_reg, target);
|
||||
}
|
||||
|
@ -4083,11 +4117,115 @@ s390_split_branches (void)
|
|||
return new_literal;
|
||||
}
|
||||
|
||||
/* Annotate every literal pool reference in X by an UNSPEC_LTREF expression.
|
||||
Fix up MEMs as required. */
|
||||
|
||||
/* Find a 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.
|
||||
static void
|
||||
annotate_constant_pool_refs (rtx *x)
|
||||
{
|
||||
int i, j;
|
||||
const char *fmt;
|
||||
|
||||
if (GET_CODE (*x) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (*x))
|
||||
abort ();
|
||||
|
||||
/* Literal pool references can only occur inside a MEM ... */
|
||||
if (GET_CODE (*x) == MEM)
|
||||
{
|
||||
rtx memref = XEXP (*x, 0);
|
||||
|
||||
if (GET_CODE (memref) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (memref))
|
||||
{
|
||||
rtx base = cfun->machine->base_reg;
|
||||
rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, memref, base),
|
||||
UNSPEC_LTREF);
|
||||
|
||||
*x = replace_equiv_address (*x, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_CODE (memref) == CONST
|
||||
&& GET_CODE (XEXP (memref, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
|
||||
&& GET_CODE (XEXP (XEXP (memref, 0), 0)) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (memref, 0), 0)))
|
||||
{
|
||||
HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
|
||||
rtx sym = XEXP (XEXP (memref, 0), 0);
|
||||
rtx base = cfun->machine->base_reg;
|
||||
rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
|
||||
UNSPEC_LTREF);
|
||||
|
||||
*x = replace_equiv_address (*x, plus_constant (addr, off));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* ... or a load-address type pattern. */
|
||||
if (GET_CODE (*x) == SET)
|
||||
{
|
||||
rtx addrref = SET_SRC (*x);
|
||||
|
||||
if (GET_CODE (addrref) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (addrref))
|
||||
{
|
||||
rtx base = cfun->machine->base_reg;
|
||||
rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, addrref, base),
|
||||
UNSPEC_LTREF);
|
||||
|
||||
SET_SRC (*x) = addr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_CODE (addrref) == CONST
|
||||
&& GET_CODE (XEXP (addrref, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
|
||||
&& GET_CODE (XEXP (XEXP (addrref, 0), 0)) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (addrref, 0), 0)))
|
||||
{
|
||||
HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
|
||||
rtx sym = XEXP (XEXP (addrref, 0), 0);
|
||||
rtx base = cfun->machine->base_reg;
|
||||
rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
|
||||
UNSPEC_LTREF);
|
||||
|
||||
SET_SRC (*x) = plus_constant (addr, off);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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--)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
{
|
||||
annotate_constant_pool_refs (&XEXP (*x, i));
|
||||
}
|
||||
else if (fmt[i] == 'E')
|
||||
{
|
||||
for (j = 0; j < XVECLEN (*x, i); j++)
|
||||
annotate_constant_pool_refs (&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.
|
||||
|
||||
The rtx pointed to by REF must be initialized to NULL_RTX
|
||||
by the caller before calling this routine. */
|
||||
|
@ -4109,11 +4247,21 @@ find_constant_pool_ref (rtx x, rtx *ref)
|
|||
|
||||
if (GET_CODE (x) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (x))
|
||||
abort ();
|
||||
|
||||
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_LTREF)
|
||||
{
|
||||
rtx sym = XVECEXP (x, 0, 0);
|
||||
if (GET_CODE (sym) != SYMBOL_REF
|
||||
|| !CONSTANT_POOL_ADDRESS_P (sym))
|
||||
abort ();
|
||||
|
||||
if (*ref == NULL_RTX)
|
||||
*ref = x;
|
||||
else if (*ref != x)
|
||||
abort();
|
||||
*ref = sym;
|
||||
else if (*ref != sym)
|
||||
abort ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (x));
|
||||
|
@ -4131,11 +4279,11 @@ find_constant_pool_ref (rtx x, rtx *ref)
|
|||
}
|
||||
}
|
||||
|
||||
/* Replace every reference to the literal pool symbol REF
|
||||
in X by the address ADDR. Fix up MEMs as required. */
|
||||
/* 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 addr)
|
||||
replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
|
||||
{
|
||||
int i, j;
|
||||
const char *fmt;
|
||||
|
@ -4143,48 +4291,23 @@ replace_constant_pool_ref (rtx *x, rtx ref, rtx addr)
|
|||
if (*x == ref)
|
||||
abort ();
|
||||
|
||||
/* Literal pool references can only occur inside a MEM ... */
|
||||
if (GET_CODE (*x) == MEM)
|
||||
if (GET_CODE (*x) == UNSPEC
|
||||
&& XINT (*x, 1) == UNSPEC_LTREF
|
||||
&& XVECEXP (*x, 0, 0) == ref)
|
||||
{
|
||||
rtx memref = XEXP (*x, 0);
|
||||
|
||||
if (memref == ref)
|
||||
{
|
||||
*x = replace_equiv_address (*x, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_CODE (memref) == CONST
|
||||
&& GET_CODE (XEXP (memref, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
|
||||
&& XEXP (XEXP (memref, 0), 0) == ref)
|
||||
{
|
||||
HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
|
||||
*x = replace_equiv_address (*x, plus_constant (addr, off));
|
||||
return;
|
||||
}
|
||||
*x = gen_rtx_PLUS (Pmode, XVECEXP (*x, 0, 1), offset);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ... or a load-address type pattern. */
|
||||
if (GET_CODE (*x) == SET)
|
||||
if (GET_CODE (*x) == PLUS
|
||||
&& GET_CODE (XEXP (*x, 1)) == CONST_INT
|
||||
&& GET_CODE (XEXP (*x, 0)) == UNSPEC
|
||||
&& XINT (XEXP (*x, 0), 1) == UNSPEC_LTREF
|
||||
&& XVECEXP (XEXP (*x, 0), 0, 0) == ref)
|
||||
{
|
||||
rtx addrref = SET_SRC (*x);
|
||||
|
||||
if (addrref == ref)
|
||||
{
|
||||
SET_SRC (*x) = addr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_CODE (addrref) == CONST
|
||||
&& GET_CODE (XEXP (addrref, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
|
||||
&& XEXP (XEXP (addrref, 0), 0) == ref)
|
||||
{
|
||||
HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
|
||||
SET_SRC (*x) = plus_constant (addr, off);
|
||||
return;
|
||||
}
|
||||
rtx addr = gen_rtx_PLUS (Pmode, XVECEXP (XEXP (*x, 0), 0, 1), offset);
|
||||
*x = plus_constant (addr, INTVAL (XEXP (*x, 1)));
|
||||
return;
|
||||
}
|
||||
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (*x));
|
||||
|
@ -4192,12 +4315,12 @@ replace_constant_pool_ref (rtx *x, rtx ref, rtx addr)
|
|||
{
|
||||
if (fmt[i] == 'e')
|
||||
{
|
||||
replace_constant_pool_ref (&XEXP (*x, i), ref, addr);
|
||||
replace_constant_pool_ref (&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, addr);
|
||||
replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4238,10 +4361,10 @@ find_ltrel_base (rtx x)
|
|||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Replace any occurrence of UNSPEC_LTREL_BASE in X with BASE. */
|
||||
/* Replace any occurrence of UNSPEC_LTREL_BASE in X with its base. */
|
||||
|
||||
static void
|
||||
replace_ltrel_base (rtx *x, rtx base)
|
||||
replace_ltrel_base (rtx *x)
|
||||
{
|
||||
int i, j;
|
||||
const char *fmt;
|
||||
|
@ -4249,7 +4372,7 @@ replace_ltrel_base (rtx *x, rtx base)
|
|||
if (GET_CODE (*x) == UNSPEC
|
||||
&& XINT (*x, 1) == UNSPEC_LTREL_BASE)
|
||||
{
|
||||
*x = base;
|
||||
*x = XVECEXP (*x, 0, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4258,12 +4381,12 @@ replace_ltrel_base (rtx *x, rtx base)
|
|||
{
|
||||
if (fmt[i] == 'e')
|
||||
{
|
||||
replace_ltrel_base (&XEXP (*x, i), base);
|
||||
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), base);
|
||||
replace_ltrel_base (&XVECEXP (*x, i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4302,11 +4425,11 @@ struct constant_pool
|
|||
};
|
||||
|
||||
static struct constant_pool * s390_mainpool_start (void);
|
||||
static void s390_mainpool_finish (struct constant_pool *, rtx base_reg);
|
||||
static void s390_mainpool_finish (struct constant_pool *);
|
||||
static void s390_mainpool_cancel (struct constant_pool *);
|
||||
|
||||
static struct constant_pool * s390_chunkify_start (rtx base_reg);
|
||||
static void s390_chunkify_finish (struct constant_pool *, rtx base_reg);
|
||||
static struct constant_pool * s390_chunkify_start (void);
|
||||
static void s390_chunkify_finish (struct constant_pool *);
|
||||
static void s390_chunkify_cancel (struct constant_pool *);
|
||||
|
||||
static struct constant_pool *s390_start_pool (struct constant_pool **, rtx);
|
||||
|
@ -4560,8 +4683,9 @@ s390_mainpool_start (void)
|
|||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (GET_CODE (insn) == INSN
|
||||
&& GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
|
||||
&& XINT (PATTERN (insn), 1) == UNSPECV_MAIN_POOL)
|
||||
&& GET_CODE (PATTERN (insn)) == SET
|
||||
&& GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE
|
||||
&& XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL)
|
||||
{
|
||||
if (pool->pool_insn)
|
||||
abort ();
|
||||
|
@ -4599,12 +4723,12 @@ s390_mainpool_start (void)
|
|||
|
||||
/* POOL holds the main literal pool as collected by s390_mainpool_start.
|
||||
Modify the current function to output the pool constants as well as
|
||||
the pool register setup instruction. BASE_REG is the register to
|
||||
be used as pool base register. */
|
||||
the pool register setup instruction. */
|
||||
|
||||
static void
|
||||
s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
|
||||
s390_mainpool_finish (struct constant_pool *pool)
|
||||
{
|
||||
rtx base_reg = SET_DEST (PATTERN (pool->pool_insn));
|
||||
rtx insn;
|
||||
|
||||
/* If the pool is empty, we're done. */
|
||||
|
@ -4684,7 +4808,7 @@ s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
|
|||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
replace_ltrel_base (&PATTERN (insn), base_reg);
|
||||
replace_ltrel_base (&PATTERN (insn));
|
||||
|
||||
if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
|
||||
{
|
||||
|
@ -4694,7 +4818,6 @@ s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
|
|||
{
|
||||
addr = s390_find_constant (pool, get_pool_constant (pool_ref),
|
||||
get_pool_mode (pool_ref));
|
||||
addr = gen_rtx_PLUS (Pmode, base_reg, addr);
|
||||
replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
|
||||
INSN_CODE (insn) = -1;
|
||||
}
|
||||
|
@ -4718,14 +4841,13 @@ s390_mainpool_cancel (struct constant_pool *pool)
|
|||
}
|
||||
|
||||
|
||||
/* Chunkify the literal pool. BASE_REG is to be used as pool
|
||||
register. */
|
||||
/* Chunkify the literal pool. */
|
||||
|
||||
#define S390_POOL_CHUNK_MIN 0xc00
|
||||
#define S390_POOL_CHUNK_MAX 0xe00
|
||||
|
||||
static struct constant_pool *
|
||||
s390_chunkify_start (rtx base_reg)
|
||||
s390_chunkify_start (void)
|
||||
{
|
||||
struct constant_pool *curr_pool = NULL, *pool_list = NULL;
|
||||
int extra_size = 0;
|
||||
|
@ -4952,7 +5074,8 @@ s390_chunkify_start (rtx base_reg)
|
|||
|
||||
for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
|
||||
{
|
||||
rtx new_insn = gen_reload_base (base_reg, curr_pool->label);
|
||||
rtx new_insn = gen_reload_base (cfun->machine->base_reg,
|
||||
curr_pool->label);
|
||||
rtx insn = curr_pool->first_insn;
|
||||
INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
|
||||
}
|
||||
|
@ -4966,7 +5089,8 @@ s390_chunkify_start (rtx base_reg)
|
|||
struct constant_pool *pool = s390_find_pool (pool_list, insn);
|
||||
if (pool)
|
||||
{
|
||||
rtx new_insn = gen_reload_base (base_reg, pool->label);
|
||||
rtx new_insn = gen_reload_base (cfun->machine->base_reg,
|
||||
pool->label);
|
||||
INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
|
||||
}
|
||||
}
|
||||
|
@ -4985,11 +5109,10 @@ s390_chunkify_start (rtx base_reg)
|
|||
|
||||
/* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
|
||||
After we have decided to use this list, finish implementing
|
||||
all changes to the current function as required. BASE_REG is
|
||||
to be used as pool base register. */
|
||||
all changes to the current function as required. */
|
||||
|
||||
static void
|
||||
s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg)
|
||||
s390_chunkify_finish (struct constant_pool *pool_list)
|
||||
{
|
||||
struct constant_pool *curr_pool = NULL;
|
||||
rtx insn;
|
||||
|
@ -5000,7 +5123,7 @@ s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg)
|
|||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
replace_ltrel_base (&PATTERN (insn), base_reg);
|
||||
replace_ltrel_base (&PATTERN (insn));
|
||||
|
||||
curr_pool = s390_find_pool (pool_list, insn);
|
||||
if (!curr_pool)
|
||||
|
@ -5014,7 +5137,6 @@ s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg)
|
|||
{
|
||||
addr = s390_find_constant (curr_pool, get_pool_constant (pool_ref),
|
||||
get_pool_mode (pool_ref));
|
||||
addr = gen_rtx_PLUS (Pmode, base_reg, addr);
|
||||
replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
|
||||
INSN_CODE (insn) = -1;
|
||||
}
|
||||
|
@ -5273,7 +5395,6 @@ s390_optimize_prolog (bool base_used)
|
|||
static void
|
||||
s390_reorg (void)
|
||||
{
|
||||
rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
bool base_used = false;
|
||||
bool pool_overflow = false;
|
||||
|
||||
|
@ -5282,12 +5403,6 @@ s390_reorg (void)
|
|||
split_all_insns_noflow ();
|
||||
|
||||
|
||||
/* In small leaf functions, try to use an unused call-clobbered
|
||||
register as base register to avoid save/restore overhead. */
|
||||
if (current_function_is_leaf && !regs_ever_live[5])
|
||||
base_reg = gen_rtx_REG (Pmode, 5);
|
||||
|
||||
|
||||
/* Install the main literal pool and the associated base
|
||||
register load insns.
|
||||
|
||||
|
@ -5335,7 +5450,7 @@ s390_reorg (void)
|
|||
|
||||
/* If literal pool overflowed, start to chunkify it. */
|
||||
if (pool_overflow)
|
||||
pool = s390_chunkify_start (base_reg);
|
||||
pool = s390_chunkify_start ();
|
||||
|
||||
/* Split out-of-range branches. If this has created new
|
||||
literal pool entries, cancel current chunk list and
|
||||
|
@ -5354,13 +5469,13 @@ s390_reorg (void)
|
|||
/* If we made it up to here, both conditions are satisfied.
|
||||
Finish up literal pool related changes. */
|
||||
if ((pool_overflow || pool->size > 0)
|
||||
&& REGNO (base_reg) == BASE_REGISTER)
|
||||
&& REGNO (cfun->machine->base_reg) == BASE_REGISTER)
|
||||
base_used = true;
|
||||
|
||||
if (pool_overflow)
|
||||
s390_chunkify_finish (pool, base_reg);
|
||||
s390_chunkify_finish (pool);
|
||||
else
|
||||
s390_mainpool_finish (pool, base_reg);
|
||||
s390_mainpool_finish (pool);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -5649,49 +5764,47 @@ restore_gprs (rtx base, int offset, int first, int last)
|
|||
return insn;
|
||||
}
|
||||
|
||||
/* Emit code to load the GOT register. If MAYBE_DEAD is true,
|
||||
annotate generated insns with REG_MAYBE_DEAD notes. */
|
||||
/* Return insn sequence to load the GOT register. */
|
||||
|
||||
static GTY(()) rtx got_symbol;
|
||||
void
|
||||
s390_load_got (int maybe_dead)
|
||||
rtx
|
||||
s390_load_got (void)
|
||||
{
|
||||
rtx insns;
|
||||
|
||||
if (!got_symbol)
|
||||
{
|
||||
got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
|
||||
SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
|
||||
}
|
||||
|
||||
start_sequence ();
|
||||
|
||||
if (TARGET_CPU_ZARCH)
|
||||
{
|
||||
rtx insn = emit_move_insn (pic_offset_table_rtx, got_symbol);
|
||||
if (maybe_dead)
|
||||
REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
|
||||
REG_NOTES (insn));
|
||||
emit_move_insn (pic_offset_table_rtx, got_symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx offset, insn;
|
||||
rtx offset;
|
||||
|
||||
offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
|
||||
UNSPEC_LTREL_OFFSET);
|
||||
offset = gen_rtx_CONST (Pmode, offset);
|
||||
offset = force_const_mem (Pmode, offset);
|
||||
|
||||
insn = emit_move_insn (pic_offset_table_rtx, offset);
|
||||
if (maybe_dead)
|
||||
REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
|
||||
REG_NOTES (insn));
|
||||
emit_move_insn (pic_offset_table_rtx, offset);
|
||||
|
||||
offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)),
|
||||
UNSPEC_LTREL_BASE);
|
||||
offset = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
|
||||
|
||||
insn = emit_move_insn (pic_offset_table_rtx, offset);
|
||||
if (maybe_dead)
|
||||
REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
|
||||
REG_NOTES (insn));
|
||||
emit_move_insn (pic_offset_table_rtx, offset);
|
||||
}
|
||||
|
||||
insns = get_insns ();
|
||||
end_sequence ();
|
||||
return insns;
|
||||
}
|
||||
|
||||
/* Expand the prologue into a bunch of separate insns. */
|
||||
|
@ -5712,6 +5825,17 @@ s390_emit_prologue (void)
|
|||
|| regs_ever_live[RETURN_REGNUM])
|
||||
cfun->machine->save_return_addr_p = 1;
|
||||
|
||||
/* Decide which register to use as literal pool base. In small leaf
|
||||
functions, try to use an unused call-clobbered register as base
|
||||
register to avoid save/restore overhead. */
|
||||
|
||||
if (current_function_is_leaf && !regs_ever_live[5])
|
||||
cfun->machine->base_reg = gen_rtx_REG (Pmode, 5);
|
||||
else
|
||||
cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGISTER);
|
||||
|
||||
regs_ever_live[REGNO (cfun->machine->base_reg)] = 1;
|
||||
|
||||
/* Compute frame info. Note that at this point, we assume the base
|
||||
register and -on S/390- the return register always need to be saved.
|
||||
This is done because the usage of these registers might change even
|
||||
|
@ -5727,6 +5851,17 @@ s390_emit_prologue (void)
|
|||
|| cfun->machine->save_return_addr_p;
|
||||
regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
|
||||
|
||||
/* Annotate all constant pool references to let the scheduler know
|
||||
they implicitly use the base register. */
|
||||
|
||||
push_topmost_sequence ();
|
||||
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn))
|
||||
annotate_constant_pool_refs (&PATTERN (insn));
|
||||
|
||||
pop_topmost_sequence ();
|
||||
|
||||
/* Choose best register to use for temp use within prologue.
|
||||
See below for why TPF must use the register 1. */
|
||||
|
||||
|
@ -5744,7 +5879,7 @@ s390_emit_prologue (void)
|
|||
|
||||
/* Dummy insn to mark literal pool slot. */
|
||||
|
||||
emit_insn (gen_main_pool ());
|
||||
emit_insn (gen_main_pool (cfun->machine->base_reg));
|
||||
|
||||
/* Save fprs for variable args. */
|
||||
|
||||
|
@ -5790,6 +5925,7 @@ s390_emit_prologue (void)
|
|||
frame_off = force_const_mem (Pmode, frame_off);
|
||||
|
||||
insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
|
||||
annotate_constant_pool_refs (&PATTERN (insn));
|
||||
}
|
||||
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
@ -5854,7 +5990,19 @@ s390_emit_prologue (void)
|
|||
/* Set up got pointer, if needed. */
|
||||
|
||||
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
|
||||
s390_load_got(true);
|
||||
{
|
||||
rtx insns = s390_load_got ();
|
||||
|
||||
for (insn = insns; insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
annotate_constant_pool_refs (&PATTERN (insn));
|
||||
|
||||
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
|
||||
REG_NOTES (insn));
|
||||
}
|
||||
|
||||
emit_insn (insns);
|
||||
}
|
||||
|
||||
if (TARGET_TPF_PROFILING)
|
||||
{
|
||||
|
@ -5965,6 +6113,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6044,12 +6193,6 @@ s390_emit_epilogue (bool sibcall)
|
|||
}
|
||||
}
|
||||
|
||||
/* ??? As references to the base register are not made
|
||||
explicit in insn RTX code, we have to add a barrier here
|
||||
to prevent incorrect scheduling. */
|
||||
|
||||
emit_insn (gen_blockage());
|
||||
|
||||
insn = restore_gprs (frame_pointer, offset,
|
||||
cfun->machine->first_restore_gpr,
|
||||
cfun->machine->last_restore_gpr);
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
; Literal pool
|
||||
(UNSPEC_RELOAD_BASE 210)
|
||||
(UNSPEC_MAIN_BASE 211)
|
||||
(UNSPEC_LTREF 212)
|
||||
|
||||
; TLS relocation specifiers
|
||||
(UNSPEC_TLSGD 500)
|
||||
|
@ -7394,7 +7395,7 @@
|
|||
[(match_operand 0 "" "")]
|
||||
"flag_pic"
|
||||
{
|
||||
s390_load_got (false);
|
||||
emit_insn (s390_load_got ());
|
||||
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
|
||||
DONE;
|
||||
})
|
||||
|
@ -7561,8 +7562,9 @@
|
|||
(set_attr "type" "larl")])
|
||||
|
||||
(define_insn "main_pool"
|
||||
[(unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL)]
|
||||
""
|
||||
[(set (match_operand 0 "register_operand" "=a")
|
||||
(unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL))]
|
||||
"GET_MODE (operands[0]) == Pmode"
|
||||
"* abort ();"
|
||||
[(set_attr "op_type" "NN")])
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue