re PR target/21412 (ICE loading TLS address)
PR target/21412 * config/ia64/ia64.c (TARGET_CANNOT_FORCE_CONST_MEM): New. (ia64_cannot_force_const_mem): New. (tls_symbolic_operand_type): New. (ia64_legitimate_constant_p): New. (ia64_expand_load_address): Return true on success. Improve checks for when we should not split. (ia64_expand_tls_address): New addend operand. Distribute it as appropriate to the tls_kind. Delay referencing gp. (ia64_expand_move): Split symbolic addend as necessary. Handle tls symbols with addends. * config/ia64/ia64-protos.h: Update. * config/ia64/ia64.h (CALL_REALLY_USED_REGISTERS): False for r0, p0, f0, f1, and r13. (LEGITIMATE_CONSTANT_P): Move to ia64_legitimate_constant_p. * config/ia64/ia64.md (UNSPEC_DTPMOD): New. (symbolic_operand splitter): Pass everything through ia64_expand_load_address and FAIL or DONE as appropriate. (load_fptr): Only accept after reload. (load_fptr_internal1, gprel64_offset, load_gprel64, load_symptr_high, load_symptr_low, load_ltoff_dtpmod, (load_dtpmod): New. (load_dtprel): Only accept tls symbols. (load_dtprel64, load_dtprel22): Likewise. (load_tprel, load_tprel64, load_tprel22): Likewise. (load_dtprel_gd, load_ltoff_dtprel, load_tprel_ie): New. (add_dtprel): Only accept tls symbols. Canonicalize PLUS. (add_dtprel14, add_dtprel22): Likewise. (add_tprel, add_tprel14, add_tprel22): Likewise. * config/ia64/predicates.md (small_addr_symbolic_operand): New. (any_offset_symbol_operand, aligned_offset_symbol_operand): New. (got_symbolic_operand): Check CONST offsets. (tls_symbolic_operand, ld_tls_symbolic_operand): New. (ie_tls_symbolic_operand, le_tls_symbolic_operand): New. (move_operand): Don't handle tls here. Check CONST offsets. From-SVN: r99596
This commit is contained in:
parent
b331525311
commit
5e6c8b6428
@ -1,3 +1,41 @@
|
||||
2005-05-11 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR target/21412
|
||||
* config/ia64/ia64.c (TARGET_CANNOT_FORCE_CONST_MEM): New.
|
||||
(ia64_cannot_force_const_mem): New.
|
||||
(tls_symbolic_operand_type): New.
|
||||
(ia64_legitimate_constant_p): New.
|
||||
(ia64_expand_load_address): Return true on success. Improve
|
||||
checks for when we should not split.
|
||||
(ia64_expand_tls_address): New addend operand. Distribute it
|
||||
as appropriate to the tls_kind. Delay referencing gp.
|
||||
(ia64_expand_move): Split symbolic addend as necessary. Handle
|
||||
tls symbols with addends.
|
||||
* config/ia64/ia64-protos.h: Update.
|
||||
* config/ia64/ia64.h (CALL_REALLY_USED_REGISTERS): False for r0,
|
||||
p0, f0, f1, and r13.
|
||||
(LEGITIMATE_CONSTANT_P): Move to ia64_legitimate_constant_p.
|
||||
* config/ia64/ia64.md (UNSPEC_DTPMOD): New.
|
||||
(symbolic_operand splitter): Pass everything through
|
||||
ia64_expand_load_address and FAIL or DONE as appropriate.
|
||||
(load_fptr): Only accept after reload.
|
||||
(load_fptr_internal1, gprel64_offset, load_gprel64, load_symptr_high,
|
||||
load_symptr_low, load_ltoff_dtpmod,
|
||||
(load_dtpmod): New.
|
||||
(load_dtprel): Only accept tls symbols.
|
||||
(load_dtprel64, load_dtprel22): Likewise.
|
||||
(load_tprel, load_tprel64, load_tprel22): Likewise.
|
||||
(load_dtprel_gd, load_ltoff_dtprel, load_tprel_ie): New.
|
||||
(add_dtprel): Only accept tls symbols. Canonicalize PLUS.
|
||||
(add_dtprel14, add_dtprel22): Likewise.
|
||||
(add_tprel, add_tprel14, add_tprel22): Likewise.
|
||||
* config/ia64/predicates.md (small_addr_symbolic_operand): New.
|
||||
(any_offset_symbol_operand, aligned_offset_symbol_operand): New.
|
||||
(got_symbolic_operand): Check CONST offsets.
|
||||
(tls_symbolic_operand, ld_tls_symbolic_operand): New.
|
||||
(ie_tls_symbolic_operand, le_tls_symbolic_operand): New.
|
||||
(move_operand): Don't handle tls here. Check CONST offsets.
|
||||
|
||||
2005-05-11 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* config/mips/7000.md (rm7_impy_si_mult): Just match imul and imadd.
|
||||
|
@ -37,6 +37,7 @@ extern int ia64_produce_address_p (rtx);
|
||||
extern bool ia64_const_ok_for_letter_p (HOST_WIDE_INT, char);
|
||||
extern bool ia64_const_double_ok_for_letter_p (rtx, char);
|
||||
extern bool ia64_extra_constraint (rtx, char);
|
||||
extern bool ia64_legitimate_constant_p (rtx);
|
||||
|
||||
extern rtx ia64_expand_move (rtx, rtx);
|
||||
extern int ia64_move_ok (rtx, rtx);
|
||||
@ -58,7 +59,7 @@ extern void ia64_expand_prologue (void);
|
||||
extern void ia64_expand_epilogue (int);
|
||||
|
||||
extern int ia64_direct_return (void);
|
||||
extern void ia64_expand_load_address (rtx, rtx);
|
||||
extern bool ia64_expand_load_address (rtx, rtx);
|
||||
extern int ia64_hard_regno_rename_ok (int, int);
|
||||
|
||||
extern void ia64_initialize_trampoline (rtx, rtx, rtx);
|
||||
|
@ -163,7 +163,6 @@ static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx);
|
||||
static int ia64_dfa_new_cycle (FILE *, int, rtx, int, int, int *);
|
||||
static rtx gen_tls_get_addr (void);
|
||||
static rtx gen_thread_pointer (void);
|
||||
static rtx ia64_expand_tls_address (enum tls_model, rtx, rtx);
|
||||
static int find_gr_spill (int);
|
||||
static int next_scratch_gr_reg (void);
|
||||
static void mark_reg_gr_used_mask (rtx, void *);
|
||||
@ -264,7 +263,7 @@ static rtx ia64_struct_value_rtx (tree, int);
|
||||
static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
|
||||
static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
|
||||
static bool ia64_vector_mode_supported_p (enum machine_mode mode);
|
||||
|
||||
static bool ia64_cannot_force_const_mem (rtx);
|
||||
|
||||
/* Table of valid machine attributes. */
|
||||
static const struct attribute_spec ia64_attribute_table[] =
|
||||
@ -424,6 +423,9 @@ static const struct attribute_spec ia64_attribute_table[] =
|
||||
#undef TARGET_HANDLE_OPTION
|
||||
#define TARGET_HANDLE_OPTION ia64_handle_option
|
||||
|
||||
#undef TARGET_CANNOT_FORCE_CONST_MEM
|
||||
#define TARGET_CANNOT_FORCE_CONST_MEM ia64_cannot_force_const_mem
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
typedef enum
|
||||
@ -693,12 +695,64 @@ ia64_depz_field_mask (rtx rop, rtx rshift)
|
||||
return exact_log2 (op + 1);
|
||||
}
|
||||
|
||||
/* Return the TLS model to use for ADDR. */
|
||||
|
||||
static enum tls_model
|
||||
tls_symbolic_operand_type (rtx addr)
|
||||
{
|
||||
enum tls_model tls_kind = 0;
|
||||
|
||||
if (GET_CODE (addr) == CONST)
|
||||
{
|
||||
if (GET_CODE (XEXP (addr, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF)
|
||||
tls_kind = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (addr, 0), 0));
|
||||
}
|
||||
else if (GET_CODE (addr) == SYMBOL_REF)
|
||||
tls_kind = SYMBOL_REF_TLS_MODEL (addr);
|
||||
|
||||
return tls_kind;
|
||||
}
|
||||
|
||||
/* Return true if X is a constant that is valid for some immediate
|
||||
field in an instruction. */
|
||||
|
||||
bool
|
||||
ia64_legitimate_constant_p (rtx x)
|
||||
{
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case CONST_INT:
|
||||
case LABEL_REF:
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (GET_MODE (x) == VOIDmode)
|
||||
return true;
|
||||
return CONST_DOUBLE_OK_FOR_G (x);
|
||||
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
return tls_symbolic_operand_type (x) == 0;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't allow TLS addresses to get spilled to memory. */
|
||||
|
||||
static bool
|
||||
ia64_cannot_force_const_mem (rtx x)
|
||||
{
|
||||
return tls_symbolic_operand_type (x) != 0;
|
||||
}
|
||||
|
||||
/* Expand a symbolic constant load. */
|
||||
|
||||
void
|
||||
bool
|
||||
ia64_expand_load_address (rtx dest, rtx src)
|
||||
{
|
||||
gcc_assert (GET_CODE (src) != SYMBOL_REF || !SYMBOL_REF_TLS_MODEL (src));
|
||||
gcc_assert (GET_CODE (dest) == REG);
|
||||
|
||||
/* ILP32 mode still loads 64-bits of data from the GOT. This avoids
|
||||
@ -706,57 +760,59 @@ ia64_expand_load_address (rtx dest, rtx src)
|
||||
computation below are also more natural to compute as 64-bit quantities.
|
||||
If we've been given an SImode destination register, change it. */
|
||||
if (GET_MODE (dest) != Pmode)
|
||||
dest = gen_rtx_REG (Pmode, REGNO (dest));
|
||||
dest = gen_rtx_REG_offset (dest, Pmode, REGNO (dest), 0);
|
||||
|
||||
if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_SMALL_ADDR_P (src))
|
||||
{
|
||||
emit_insn (gen_rtx_SET (VOIDmode, dest, src));
|
||||
return;
|
||||
}
|
||||
else if (TARGET_AUTO_PIC)
|
||||
{
|
||||
emit_insn (gen_load_gprel64 (dest, src));
|
||||
return;
|
||||
}
|
||||
if (TARGET_NO_PIC)
|
||||
return false;
|
||||
if (small_addr_symbolic_operand (src, VOIDmode))
|
||||
return false;
|
||||
|
||||
if (TARGET_AUTO_PIC)
|
||||
emit_insn (gen_load_gprel64 (dest, src));
|
||||
else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (src))
|
||||
{
|
||||
emit_insn (gen_load_fptr (dest, src));
|
||||
return;
|
||||
}
|
||||
emit_insn (gen_load_fptr (dest, src));
|
||||
else if (sdata_symbolic_operand (src, VOIDmode))
|
||||
{
|
||||
emit_insn (gen_load_gprel (dest, src));
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_CODE (src) == CONST
|
||||
&& GET_CODE (XEXP (src, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT
|
||||
&& (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x3fff) != 0)
|
||||
{
|
||||
rtx sym = XEXP (XEXP (src, 0), 0);
|
||||
HOST_WIDE_INT ofs, hi, lo;
|
||||
|
||||
/* Split the offset into a sign extended 14-bit low part
|
||||
and a complementary high part. */
|
||||
ofs = INTVAL (XEXP (XEXP (src, 0), 1));
|
||||
lo = ((ofs & 0x3fff) ^ 0x2000) - 0x2000;
|
||||
hi = ofs - lo;
|
||||
|
||||
ia64_expand_load_address (dest, plus_constant (sym, hi));
|
||||
emit_insn (gen_adddi3 (dest, dest, GEN_INT (lo)));
|
||||
}
|
||||
emit_insn (gen_load_gprel (dest, src));
|
||||
else
|
||||
{
|
||||
HOST_WIDE_INT addend = 0;
|
||||
rtx tmp;
|
||||
|
||||
/* We did split constant offsets in ia64_expand_move, and we did try
|
||||
to keep them split in move_operand, but we also allowed reload to
|
||||
rematerialize arbitrary constants rather than spill the value to
|
||||
the stack and reload it. So we have to be prepared here to split
|
||||
them apart again. */
|
||||
if (GET_CODE (src) == CONST)
|
||||
{
|
||||
HOST_WIDE_INT hi, lo;
|
||||
|
||||
hi = INTVAL (XEXP (XEXP (src, 0), 1));
|
||||
lo = ((hi & 0x3fff) ^ 0x2000) - 0x2000;
|
||||
hi = hi - lo;
|
||||
|
||||
if (lo != 0)
|
||||
{
|
||||
addend = lo;
|
||||
src = plus_constant (XEXP (XEXP (src, 0), 0), hi);
|
||||
}
|
||||
}
|
||||
|
||||
tmp = gen_rtx_HIGH (Pmode, src);
|
||||
tmp = gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
|
||||
emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
|
||||
|
||||
tmp = gen_rtx_LO_SUM (GET_MODE (dest), dest, src);
|
||||
tmp = gen_rtx_LO_SUM (Pmode, dest, src);
|
||||
emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
|
||||
|
||||
if (addend)
|
||||
{
|
||||
tmp = gen_rtx_PLUS (Pmode, dest, GEN_INT (addend));
|
||||
emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static GTY(()) rtx gen_tls_tga;
|
||||
@ -778,10 +834,15 @@ gen_thread_pointer (void)
|
||||
}
|
||||
|
||||
static rtx
|
||||
ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
|
||||
ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1,
|
||||
HOST_WIDE_INT addend)
|
||||
{
|
||||
rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
|
||||
rtx orig_op0 = op0;
|
||||
rtx orig_op0 = op0, orig_op1 = op1;
|
||||
HOST_WIDE_INT addend_lo, addend_hi;
|
||||
|
||||
addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
|
||||
addend_hi = addend - addend_lo;
|
||||
|
||||
switch (tls_kind)
|
||||
{
|
||||
@ -789,12 +850,10 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
|
||||
start_sequence ();
|
||||
|
||||
tga_op1 = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
|
||||
tga_op1 = gen_const_mem (Pmode, tga_op1);
|
||||
emit_insn (gen_load_dtpmod (tga_op1, op1));
|
||||
|
||||
tga_op2 = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
|
||||
tga_op2 = gen_const_mem (Pmode, tga_op2);
|
||||
emit_insn (gen_load_dtprel (tga_op2, op1));
|
||||
|
||||
tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
|
||||
LCT_CONST, Pmode, 2, tga_op1,
|
||||
@ -816,7 +875,7 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
|
||||
start_sequence ();
|
||||
|
||||
tga_op1 = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
|
||||
emit_insn (gen_load_dtpmod (tga_op1, op1));
|
||||
tga_op1 = gen_const_mem (Pmode, tga_op1);
|
||||
|
||||
tga_op2 = const0_rtx;
|
||||
@ -841,14 +900,15 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
|
||||
emit_insn (gen_adddi3 (op0, tmp, op0));
|
||||
}
|
||||
else
|
||||
emit_insn (gen_add_dtprel (op0, tmp, op1));
|
||||
emit_insn (gen_add_dtprel (op0, op1, tmp));
|
||||
break;
|
||||
|
||||
case TLS_MODEL_INITIAL_EXEC:
|
||||
op1 = plus_constant (op1, addend_hi);
|
||||
addend = addend_lo;
|
||||
|
||||
tmp = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_load_ltoff_tprel (tmp, op1));
|
||||
tmp = gen_const_mem (Pmode, tmp);
|
||||
tmp = force_reg (Pmode, tmp);
|
||||
emit_insn (gen_load_tprel (tmp, op1));
|
||||
|
||||
if (!register_operand (op0, Pmode))
|
||||
op0 = gen_reg_rtx (Pmode);
|
||||
@ -858,19 +918,25 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
|
||||
case TLS_MODEL_LOCAL_EXEC:
|
||||
if (!register_operand (op0, Pmode))
|
||||
op0 = gen_reg_rtx (Pmode);
|
||||
|
||||
op1 = orig_op1;
|
||||
addend = 0;
|
||||
if (TARGET_TLS64)
|
||||
{
|
||||
emit_insn (gen_load_tprel (op0, op1));
|
||||
emit_insn (gen_adddi3 (op0, gen_thread_pointer (), op0));
|
||||
emit_insn (gen_adddi3 (op0, op0, gen_thread_pointer ()));
|
||||
}
|
||||
else
|
||||
emit_insn (gen_add_tprel (op0, gen_thread_pointer (), op1));
|
||||
emit_insn (gen_add_tprel (op0, op1, gen_thread_pointer ()));
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (addend)
|
||||
op0 = expand_simple_binop (Pmode, PLUS, op0, GEN_INT (addend),
|
||||
orig_op0, 1, OPTAB_DIRECT);
|
||||
if (orig_op0 == op0)
|
||||
return NULL_RTX;
|
||||
if (GET_MODE (orig_op0) == Pmode)
|
||||
@ -888,15 +954,58 @@ ia64_expand_move (rtx op0, rtx op1)
|
||||
|
||||
if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
|
||||
{
|
||||
HOST_WIDE_INT addend = 0;
|
||||
enum tls_model tls_kind;
|
||||
if (GET_CODE (op1) == SYMBOL_REF
|
||||
&& (tls_kind = SYMBOL_REF_TLS_MODEL (op1)))
|
||||
return ia64_expand_tls_address (tls_kind, op0, op1);
|
||||
rtx sym = op1;
|
||||
|
||||
if (!TARGET_NO_PIC && reload_completed)
|
||||
if (GET_CODE (op1) == CONST
|
||||
&& GET_CODE (XEXP (op1, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (op1, 0), 1)) == CONST_INT)
|
||||
{
|
||||
ia64_expand_load_address (op0, op1);
|
||||
return NULL_RTX;
|
||||
addend = INTVAL (XEXP (XEXP (op1, 0), 1));
|
||||
sym = XEXP (XEXP (op1, 0), 0);
|
||||
}
|
||||
|
||||
tls_kind = tls_symbolic_operand_type (sym);
|
||||
if (tls_kind)
|
||||
return ia64_expand_tls_address (tls_kind, op0, sym, addend);
|
||||
|
||||
if (any_offset_symbol_operand (sym, mode))
|
||||
addend = 0;
|
||||
else if (aligned_offset_symbol_operand (sym, mode))
|
||||
{
|
||||
HOST_WIDE_INT addend_lo, addend_hi;
|
||||
|
||||
addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
|
||||
addend_hi = addend - addend_lo;
|
||||
|
||||
if (addend_lo != 0)
|
||||
{
|
||||
op1 = plus_constant (sym, addend_hi);
|
||||
addend = addend_lo;
|
||||
}
|
||||
}
|
||||
else
|
||||
op1 = sym;
|
||||
|
||||
if (reload_completed)
|
||||
{
|
||||
/* We really should have taken care of this offset earlier. */
|
||||
gcc_assert (addend == 0);
|
||||
if (ia64_expand_load_address (op0, op1))
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
if (addend)
|
||||
{
|
||||
rtx subtarget = no_new_pseudos ? op0 : gen_reg_rtx (mode);
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, subtarget, op1));
|
||||
|
||||
op1 = expand_simple_binop (mode, PLUS, subtarget,
|
||||
GEN_INT (addend), op0, 1, OPTAB_DIRECT);
|
||||
if (op0 == op1)
|
||||
return NULL_RTX;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,7 @@ while (0)
|
||||
|
||||
#define CALL_REALLY_USED_REGISTERS \
|
||||
{ /* General registers. */ \
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, \
|
||||
0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
@ -463,7 +463,7 @@ while (0)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* Floating-point registers. */ \
|
||||
1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
@ -472,7 +472,7 @@ while (0)
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* Predicate registers. */ \
|
||||
1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
@ -1410,10 +1410,7 @@ do { \
|
||||
/* A C expression that is nonzero if X is a legitimate constant for an
|
||||
immediate operand on the target machine. */
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) \
|
||||
(GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode \
|
||||
|| GET_MODE (X) == DImode || CONST_DOUBLE_OK_FOR_G (X)) \
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) ia64_legitimate_constant_p (X)
|
||||
|
||||
/* Condition Code Status */
|
||||
|
||||
|
@ -56,6 +56,7 @@
|
||||
(UNSPEC_DTPREL 2)
|
||||
(UNSPEC_LTOFF_TPREL 3)
|
||||
(UNSPEC_TPREL 4)
|
||||
(UNSPEC_DTPMOD 5)
|
||||
|
||||
(UNSPEC_LD_BASE 9)
|
||||
(UNSPEC_GR_SPILL 10)
|
||||
@ -373,53 +374,54 @@
|
||||
(define_split
|
||||
[(set (match_operand 0 "register_operand" "")
|
||||
(match_operand 1 "symbolic_operand" ""))]
|
||||
"reload_completed && ! TARGET_NO_PIC"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
ia64_expand_load_address (operands[0], operands[1]);
|
||||
DONE;
|
||||
if (ia64_expand_load_address (operands[0], operands[1]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
})
|
||||
|
||||
(define_expand "load_fptr"
|
||||
[(set (match_dup 2)
|
||||
(plus:DI (reg:DI 1) (match_operand 1 "function_operand" "")))
|
||||
(set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
|
||||
""
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(plus:DI (match_dup 2) (match_operand 1 "function_operand" "")))
|
||||
(set (match_dup 0) (match_dup 3))]
|
||||
"reload_completed"
|
||||
{
|
||||
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
|
||||
operands[3] = gen_const_mem (DImode, operands[2]);
|
||||
operands[2] = pic_offset_table_rtx;
|
||||
operands[3] = gen_const_mem (DImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_insn "*load_fptr_internal1"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))]
|
||||
""
|
||||
"reload_completed"
|
||||
"addl %0 = @ltoff(@fptr(%1)), gp"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_insn "load_gprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (reg:DI 1) (match_operand 1 "sdata_symbolic_operand" "s")))]
|
||||
""
|
||||
"reload_completed"
|
||||
"addl %0 = @gprel(%1), gp"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_insn "gprel64_offset"
|
||||
(define_insn "*gprel64_offset"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(minus:DI (match_operand:DI 1 "symbolic_operand" "") (reg:DI 1)))]
|
||||
""
|
||||
"reload_completed"
|
||||
"movl %0 = @gprel(%1)"
|
||||
[(set_attr "itanium_class" "long_i")])
|
||||
|
||||
(define_expand "load_gprel64"
|
||||
[(set (match_dup 2)
|
||||
(minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 3)))
|
||||
(set (match_operand:DI 0 "register_operand" "")
|
||||
(plus:DI (match_dup 3) (match_dup 2)))]
|
||||
""
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 2)))
|
||||
(set (match_dup 0)
|
||||
(plus:DI (match_dup 2) (match_dup 0)))]
|
||||
"reload_completed"
|
||||
{
|
||||
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
|
||||
operands[3] = pic_offset_table_rtx;
|
||||
operands[2] = pic_offset_table_rtx;
|
||||
})
|
||||
|
||||
;; This is used as a placeholder for the return address during early
|
||||
@ -445,7 +447,7 @@
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s"))
|
||||
(match_operand:DI 2 "register_operand" "a")))]
|
||||
""
|
||||
"reload_completed"
|
||||
{
|
||||
if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
|
||||
return "%,addl %0 = @ltoffx(%1), %2";
|
||||
@ -458,7 +460,7 @@
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
|
||||
(match_operand 2 "got_symbolic_operand" "s")))]
|
||||
""
|
||||
"reload_completed"
|
||||
{
|
||||
if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
|
||||
return "%,ld8.mov %0 = [%1], %2";
|
||||
@ -467,34 +469,41 @@
|
||||
}
|
||||
[(set_attr "itanium_class" "ld")])
|
||||
|
||||
(define_insn "load_ltoff_dtpmod"
|
||||
(define_insn_and_split "load_dtpmod"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (reg:DI 1)
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
UNSPEC_LTOFF_DTPMOD)))]
|
||||
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPMOD))]
|
||||
""
|
||||
"addl %0 = @ltoff(@dtpmod(%1)), gp"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPMOD)
|
||||
(match_dup 2)))
|
||||
(set (match_dup 0) (match_dup 3))]
|
||||
{
|
||||
operands[2] = pic_offset_table_rtx;
|
||||
operands[3] = gen_const_mem (DImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_insn "load_ltoff_dtprel"
|
||||
(define_insn "*load_ltoff_dtpmod"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (reg:DI 1)
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
UNSPEC_LTOFF_DTPREL)))]
|
||||
""
|
||||
"addl %0 = @ltoff(@dtprel(%1)), gp"
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_LTOFF_DTPMOD)
|
||||
(match_operand:DI 2 "register_operand" "a")))]
|
||||
"reload_completed"
|
||||
"addl %0 = @ltoff(@dtpmod(%1)), %2"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_expand "load_dtprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPREL))]
|
||||
""
|
||||
"")
|
||||
|
||||
(define_insn "*load_dtprel64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
(unspec:DI [(match_operand:DI 1 "ld_tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPREL))]
|
||||
"TARGET_TLS64"
|
||||
"movl %0 = @dtprel(%1)"
|
||||
@ -502,57 +511,73 @@
|
||||
|
||||
(define_insn "*load_dtprel22"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
(unspec:DI [(match_operand:DI 1 "ld_tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPREL))]
|
||||
""
|
||||
"addl %0 = @dtprel(%1), r0"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_insn_and_split "*load_dtprel_gd"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPREL))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPREL)
|
||||
(match_dup 2)))
|
||||
(set (match_dup 0) (match_dup 3))]
|
||||
{
|
||||
operands[2] = pic_offset_table_rtx;
|
||||
operands[3] = gen_const_mem (DImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_insn "*load_ltoff_dtprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_LTOFF_DTPREL)
|
||||
(match_operand:DI 2 "register_operand" "a")))]
|
||||
""
|
||||
"addl %0 = @ltoff(@dtprel(%1)), %2"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_expand "add_dtprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(plus:DI (match_operand:DI 1 "register_operand" "")
|
||||
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
|
||||
UNSPEC_DTPREL)))]
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "ld_tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPREL)
|
||||
(match_operand:DI 2 "register_operand" "")))]
|
||||
"!TARGET_TLS64"
|
||||
"")
|
||||
|
||||
(define_insn "*add_dtprel14"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (match_operand:DI 1 "register_operand" "r")
|
||||
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
|
||||
UNSPEC_DTPREL)))]
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "ld_tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPREL)
|
||||
(match_operand:DI 2 "register_operand" "r")))]
|
||||
"TARGET_TLS14"
|
||||
"adds %0 = @dtprel(%2), %1"
|
||||
"adds %0 = @dtprel(%1), %2"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_insn "*add_dtprel22"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (match_operand:DI 1 "register_operand" "a")
|
||||
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
|
||||
UNSPEC_DTPREL)))]
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "ld_tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPREL)
|
||||
(match_operand:DI 2 "register_operand" "a")))]
|
||||
"TARGET_TLS22"
|
||||
"addl %0 = @dtprel(%2), %1"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_insn "load_ltoff_tprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (reg:DI 1)
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
UNSPEC_LTOFF_TPREL)))]
|
||||
""
|
||||
"addl %0 = @ltoff(@tprel(%1)), gp"
|
||||
"addl %0 = @dtprel(%1), %2"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_expand "load_tprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_TPREL))]
|
||||
""
|
||||
"")
|
||||
|
||||
(define_insn "*load_tprel64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
(unspec:DI [(match_operand:DI 1 "le_tls_symbolic_operand" "")]
|
||||
UNSPEC_TPREL))]
|
||||
"TARGET_TLS64"
|
||||
"movl %0 = @tprel(%1)"
|
||||
@ -560,36 +585,61 @@
|
||||
|
||||
(define_insn "*load_tprel22"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
|
||||
(unspec:DI [(match_operand:DI 1 "le_tls_symbolic_operand" "")]
|
||||
UNSPEC_TPREL))]
|
||||
""
|
||||
"addl %0 = @tprel(%1), r0"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_insn_and_split "*load_tprel_ie"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(match_operand:DI 1 "ie_tls_symbolic_operand" "")]
|
||||
UNSPEC_TPREL))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_TPREL)
|
||||
(match_dup 2)))
|
||||
(set (match_dup 0) (match_dup 3))]
|
||||
{
|
||||
operands[2] = pic_offset_table_rtx;
|
||||
operands[3] = gen_const_mem (DImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_insn "*load_ltoff_tprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "ie_tls_symbolic_operand" "")]
|
||||
UNSPEC_LTOFF_TPREL)
|
||||
(match_operand:DI 2 "register_operand" "a")))]
|
||||
""
|
||||
"addl %0 = @ltoff(@tprel(%1)), %2"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_expand "add_tprel"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(plus:DI (match_operand:DI 1 "register_operand" "")
|
||||
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
|
||||
UNSPEC_TPREL)))]
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "le_tls_symbolic_operand" "")]
|
||||
UNSPEC_TPREL)
|
||||
(match_operand:DI 2 "register_operand" "")))]
|
||||
"!TARGET_TLS64"
|
||||
"")
|
||||
|
||||
(define_insn "*add_tprel14"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (match_operand:DI 1 "register_operand" "r")
|
||||
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
|
||||
UNSPEC_TPREL)))]
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "le_tls_symbolic_operand" "")]
|
||||
UNSPEC_TPREL)
|
||||
(match_operand:DI 2 "register_operand" "r")))]
|
||||
"TARGET_TLS14"
|
||||
"adds %0 = @tprel(%2), %1"
|
||||
"adds %0 = @tprel(%1), %2"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
(define_insn "*add_tprel22"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(plus:DI (match_operand:DI 1 "register_operand" "a")
|
||||
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
|
||||
UNSPEC_TPREL)))]
|
||||
(plus:DI (unspec:DI [(match_operand:DI 1 "le_tls_symbolic_operand" "")]
|
||||
UNSPEC_TPREL)
|
||||
(match_operand:DI 2 "register_operand" "a")))]
|
||||
"TARGET_TLS22"
|
||||
"addl %0 = @tprel(%2), %1"
|
||||
"addl %0 = @tprel(%1), %2"
|
||||
[(set_attr "itanium_class" "ialu")])
|
||||
|
||||
;; With no offsettable memory references, we've got to have a scratch
|
||||
|
@ -34,42 +34,6 @@
|
||||
(and (match_code "symbol_ref")
|
||||
(match_test "SYMBOL_REF_FUNCTION_P (op)")))
|
||||
|
||||
;; True if OP refers to a symbol, and is appropriate for a GOT load.
|
||||
(define_predicate "got_symbolic_operand"
|
||||
(match_operand 0 "symbolic_operand" "")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case LABEL_REF:
|
||||
return true;
|
||||
|
||||
case SYMBOL_REF:
|
||||
/* This sort of load should not be used for things in sdata. */
|
||||
return !SYMBOL_REF_SMALL_ADDR_P (op);
|
||||
|
||||
case CONST:
|
||||
/* Accept only (plus (symbol_ref) (const_int)). */
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != PLUS
|
||||
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
|
||||
return false;
|
||||
|
||||
/* Ok if we're not using GOT entries at all. */
|
||||
if (TARGET_NO_PIC || TARGET_AUTO_PIC)
|
||||
return true;
|
||||
|
||||
/* The low 14 bits of the constant have been forced to zero
|
||||
by ia64_expand_load_address, so that we do not use up so
|
||||
many GOT entries. Prevent cse from undoing this. */
|
||||
op = XEXP (op, 1);
|
||||
return (INTVAL (op) & 0x3fff) == 0;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
})
|
||||
|
||||
;; True if OP refers to a symbol in the sdata section.
|
||||
(define_predicate "sdata_symbolic_operand"
|
||||
(match_code "symbol_ref,const")
|
||||
@ -129,6 +93,187 @@
|
||||
}
|
||||
})
|
||||
|
||||
;; True if OP refers to a symbol in the small address area.
|
||||
(define_predicate "small_addr_symbolic_operand"
|
||||
(match_code "symbol_ref,const")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case CONST:
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != PLUS
|
||||
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
|
||||
return false;
|
||||
op = XEXP (op, 0);
|
||||
/* FALLTHRU */
|
||||
|
||||
case SYMBOL_REF:
|
||||
return SYMBOL_REF_SMALL_ADDR_P (op);
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
})
|
||||
|
||||
;; True if OP refers to a symbol with which we may use any offset.
|
||||
(define_predicate "any_offset_symbol_operand"
|
||||
(match_code "symbol_ref")
|
||||
{
|
||||
if (TARGET_NO_PIC || TARGET_AUTO_PIC)
|
||||
return true;
|
||||
if (SYMBOL_REF_SMALL_ADDR_P (op))
|
||||
return true;
|
||||
if (SYMBOL_REF_FUNCTION_P (op))
|
||||
return false;
|
||||
if (sdata_symbolic_operand (op, mode))
|
||||
return true;
|
||||
return false;
|
||||
})
|
||||
|
||||
;; True if OP refers to a symbol with which we may use 14-bit aligned offsets.
|
||||
;; False if OP refers to a symbol with which we may not use any offset at any
|
||||
;; time.
|
||||
(define_predicate "aligned_offset_symbol_operand"
|
||||
(and (match_code "symbol_ref")
|
||||
(match_test "! SYMBOL_REF_FUNCTION_P (op)")))
|
||||
|
||||
;; True if OP refers to a symbol, and is appropriate for a GOT load.
|
||||
(define_predicate "got_symbolic_operand"
|
||||
(match_operand 0 "symbolic_operand" "")
|
||||
{
|
||||
HOST_WIDE_INT addend = 0;
|
||||
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case LABEL_REF:
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
/* Accept only (plus (symbol_ref) (const_int)). */
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != PLUS
|
||||
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
|
||||
return false;
|
||||
|
||||
addend = INTVAL (XEXP (op, 1));
|
||||
op = XEXP (op, 0);
|
||||
/* FALLTHRU */
|
||||
|
||||
case SYMBOL_REF:
|
||||
/* These symbols shouldn't be used with got loads. */
|
||||
if (SYMBOL_REF_SMALL_ADDR_P (op))
|
||||
return false;
|
||||
if (SYMBOL_REF_TLS_MODEL (op) != 0)
|
||||
return false;
|
||||
|
||||
if (any_offset_symbol_operand (op, mode))
|
||||
return true;
|
||||
|
||||
/* The low 14 bits of the constant have been forced to zero
|
||||
so that we do not use up so many GOT entries. Prevent cse
|
||||
from undoing this. */
|
||||
if (aligned_offset_symbol_operand (op, mode))
|
||||
return (addend & 0x3fff) == 0;
|
||||
|
||||
return addend == 0;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
})
|
||||
|
||||
;; Return true if OP is a valid thread local storage symbolic operand.
|
||||
(define_predicate "tls_symbolic_operand"
|
||||
(match_code "symbol_ref,const")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case SYMBOL_REF:
|
||||
return SYMBOL_REF_TLS_MODEL (op) != 0;
|
||||
|
||||
case CONST:
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != PLUS
|
||||
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
|
||||
return false;
|
||||
|
||||
/* We only allow certain offsets for certain tls models. */
|
||||
switch (SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
|
||||
{
|
||||
case TLS_MODEL_GLOBAL_DYNAMIC:
|
||||
case TLS_MODEL_LOCAL_DYNAMIC:
|
||||
return false;
|
||||
|
||||
case TLS_MODEL_INITIAL_EXEC:
|
||||
return (INTVAL (XEXP (op, 1)) & 0x3fff) == 0;
|
||||
|
||||
case TLS_MODEL_LOCAL_EXEC:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
})
|
||||
|
||||
;; Return true if OP is a local-dynamic thread local storage symbolic operand.
|
||||
(define_predicate "ld_tls_symbolic_operand"
|
||||
(and (match_code "symbol_ref")
|
||||
(match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
|
||||
|
||||
;; Return true if OP is an initial-exec thread local storage symbolic operand.
|
||||
(define_predicate "ie_tls_symbolic_operand"
|
||||
(match_code "symbol_ref,const")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case CONST:
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != PLUS
|
||||
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 1)) != CONST_INT
|
||||
|| (INTVAL (XEXP (op, 1)) & 0x3fff) != 0)
|
||||
return false;
|
||||
op = XEXP (op, 0);
|
||||
/* FALLTHRU */
|
||||
|
||||
case SYMBOL_REF:
|
||||
return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
})
|
||||
|
||||
;; Return true if OP is a local-exec thread local storage symbolic operand.
|
||||
(define_predicate "le_tls_symbolic_operand"
|
||||
(match_code "symbol_ref,const")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case CONST:
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != PLUS
|
||||
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
|
||||
return false;
|
||||
op = XEXP (op, 0);
|
||||
/* FALLTHRU */
|
||||
|
||||
case SYMBOL_REF:
|
||||
return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
})
|
||||
|
||||
;; Like nonimmediate_operand, but don't allow MEMs that try to use a
|
||||
;; POST_MODIFY with a REG as displacement.
|
||||
(define_predicate "destination_operand"
|
||||
@ -142,11 +287,51 @@
|
||||
(and (match_operand 0 "memory_operand")
|
||||
(match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC")))
|
||||
|
||||
;; True if OP is a general operand, excluding tls symbolic operands.
|
||||
;; True if OP is a general operand, with some restrictions on symbols.
|
||||
(define_predicate "move_operand"
|
||||
(and (match_operand 0 "general_operand")
|
||||
(not (match_test
|
||||
"GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (op)"))))
|
||||
(match_operand 0 "general_operand")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case CONST:
|
||||
{
|
||||
HOST_WIDE_INT addend;
|
||||
|
||||
/* Accept only (plus (symbol_ref) (const_int)). */
|
||||
op = XEXP (op, 0);
|
||||
if (GET_CODE (op) != PLUS
|
||||
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|
||||
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
|
||||
return false;
|
||||
|
||||
addend = INTVAL (XEXP (op, 1));
|
||||
op = XEXP (op, 0);
|
||||
|
||||
/* After reload, we want to allow any offset whatsoever. This
|
||||
allows reload the opportunity to avoid spilling addresses to
|
||||
the stack, and instead simply substitute in the value from a
|
||||
REG_EQUIV. We'll split this up again when splitting the insn. */
|
||||
if (reload_in_progress || reload_completed)
|
||||
return true;
|
||||
|
||||
/* Some symbol types we allow to use with any offset. */
|
||||
if (any_offset_symbol_operand (op, mode))
|
||||
return true;
|
||||
|
||||
/* Some symbol types we allow offsets with the low 14 bits of the
|
||||
constant forced to zero so that we do not use up so many GOT
|
||||
entries. We want to prevent cse from undoing this. */
|
||||
if (aligned_offset_symbol_operand (op, mode))
|
||||
return (addend & 0x3fff) == 0;
|
||||
|
||||
/* The remaining symbol types may never be used with an offset. */
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
;; True if OP is a register operand that is (or could be) a GR reg.
|
||||
(define_predicate "gr_register_operand"
|
||||
|
Loading…
Reference in New Issue
Block a user