===================================================================
@@ -404,8 +404,9 @@ invariant_or_equiv_p (cselib_val *v)
&& v->locs->next == NULL)
{
if (CONSTANT_P (v->locs->loc)
- && (GET_CODE (v->locs->loc) != CONST
- || !references_value_p (v->locs->loc, 0)))
+ && !((GET_CODE (v->locs->loc) == CONST
+ || GET_CODE (v->locs->loc) == HIGH)
+ && references_value_p (v->locs->loc, 0)))
return true;
/* Although a debug expr may be bound to different expressions,
we can preserve it as if it was constant, to get unification
===================================================================
@@ -263,7 +263,13 @@ insert_set_in_table (rtx dest, rtx src, rtx insn,
static bool
cprop_constant_p (const_rtx x)
{
- return CONSTANT_P (x) && (GET_CODE (x) != CONST || shared_const_p (x));
+ if (!CONSTANT_P (x))
+ return false;
+ if (GET_CODE (x) == CONST)
+ return shared_const_p (x);
+ if (GET_CODE (x) == HIGH)
+ return !references_value_p (x, false);
+ return true;
}
/* Scan SET present in INSN and add an entry to the hash TABLE.
===================================================================
@@ -5285,15 +5285,33 @@ constant_pool_expr_p (rtx op)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode));
}
-static rtx tocrel_base, tocrel_offset;
+static const_rtx tocrel_base, tocrel_offset;
bool
-toc_relative_expr_p (rtx op)
+toc_relative_expr_p (const_rtx op, bool strict)
{
- if (GET_CODE (op) != CONST)
+ if (!TARGET_TOC)
return false;
- split_const (op, &tocrel_base, &tocrel_offset);
+ if (TARGET_CMODEL != CMODEL_SMALL)
+ {
+ /* Only match the low part. */
+ if (GET_CODE (op) == LO_SUM
+ && REG_P (XEXP (op, 0))
+ && INT_REG_OK_FOR_BASE_P (XEXP (op, 0), strict))
+ op = XEXP (op, 1);
+ else
+ return false;
+ }
+
+ tocrel_base = op;
+ tocrel_offset = const0_rtx;
+ if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1)))
+ {
+ tocrel_base = XEXP (op, 0);
+ tocrel_offset = XEXP (op, 1);
+ }
+
return (GET_CODE (tocrel_base) == UNSPEC
&& XINT (tocrel_base, 1) == UNSPEC_TOCREL);
}
@@ -5305,14 +5323,7 @@ bool
legitimate_constant_pool_address_p (const_rtx x, enum machine_mode mode,
bool strict)
{
- return (TARGET_TOC
- && (GET_CODE (x) == PLUS || GET_CODE (x) == LO_SUM)
- && GET_CODE (XEXP (x, 0)) == REG
- && (REGNO (XEXP (x, 0)) == TOC_REGISTER
- || ((TARGET_MINIMAL_TOC
- || TARGET_CMODEL != CMODEL_SMALL)
- && INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict)))
- && toc_relative_expr_p (XEXP (x, 1))
+ return (toc_relative_expr_p (x, strict)
&& (TARGET_CMODEL != CMODEL_MEDIUM
|| constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0))
|| mode == QImode
@@ -5778,49 +5789,55 @@ rs6000_output_dwarf_dtprel (FILE *file, int size,
static rtx
rs6000_delegitimize_address (rtx orig_x)
{
- rtx x, y;
+ rtx x, y, offset;
orig_x = delegitimize_mem_from_attrs (orig_x);
x = orig_x;
if (MEM_P (x))
x = XEXP (x, 0);
- if (GET_CODE (x) == (TARGET_CMODEL != CMODEL_SMALL ? LO_SUM : PLUS)
- && GET_CODE (XEXP (x, 1)) == CONST)
+ y = x;
+ if (TARGET_CMODEL != CMODEL_SMALL
+ && GET_CODE (y) == LO_SUM)
+ y = XEXP (y, 1);
+
+ offset = NULL_RTX;
+ if (GET_CODE (y) == PLUS
+ && GET_MODE (y) == Pmode
+ && CONST_INT_P (XEXP (y, 1)))
{
- rtx offset = NULL_RTX;
+ offset = XEXP (y, 1);
+ y = XEXP (y, 0);
+ }
- y = XEXP (XEXP (x, 1), 0);
- if (GET_CODE (y) == PLUS
- && GET_MODE (y) == Pmode
- && CONST_INT_P (XEXP (y, 1)))
+ if (GET_CODE (y) == UNSPEC
+ && XINT (y, 1) == UNSPEC_TOCREL)
+ {
+#ifdef ENABLE_CHECKING
+ if (REG_P (XVECEXP (y, 0, 1))
+ && REGNO (XVECEXP (y, 0, 1)) == TOC_REGISTER)
{
- offset = XEXP (y, 1);
- y = XEXP (y, 0);
+ /* All good. */
}
- if (GET_CODE (y) == UNSPEC
- && XINT (y, 1) == UNSPEC_TOCREL
- && ((GET_CODE (XEXP (x, 0)) == REG
- && (REGNO (XEXP (x, 0)) == TOC_REGISTER
- || TARGET_MINIMAL_TOC
- || TARGET_CMODEL != CMODEL_SMALL))
- || (TARGET_CMODEL != CMODEL_SMALL
- && GET_CODE (XEXP (x, 0)) == CONST
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
- && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == REG
- && REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == TOC_REGISTER
- && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == HIGH
- && rtx_equal_p (XEXP (x, 1),
- XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0)))))
+ else if (GET_CODE (XVECEXP (y, 0, 1)) == DEBUG_EXPR)
{
- y = XVECEXP (y, 0, 0);
- if (offset != NULL_RTX)
- y = gen_rtx_PLUS (Pmode, y, offset);
- if (!MEM_P (orig_x))
- return y;
- else
- return replace_equiv_address_nv (orig_x, y);
+ /* Weirdness alert. df_note_compute can replace r2 with a
+ debug_expr when this unspec is in a debug_insn.
+ Seen in gcc.dg/pr51957-1.c */
}
+ else
+ {
+ debug_rtx (orig_x);
+ abort ();
+ }
+#endif
+ y = XVECEXP (y, 0, 0);
+ if (offset != NULL_RTX)
+ y = gen_rtx_PLUS (Pmode, y, offset);
+ if (!MEM_P (orig_x))
+ return y;
+ else
+ return replace_equiv_address_nv (orig_x, y);
}
if (TARGET_MACHO
@@ -6082,9 +6099,8 @@ rs6000_tls_referenced_p (rtx x)
static bool
rs6000_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
- if (GET_CODE (x) == CONST
- && GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH)
+ if (GET_CODE (x) == HIGH
+ && GET_CODE (XEXP (x, 0)) == UNSPEC)
return true;
return rs6000_tls_referenced_p (x);
@@ -6099,6 +6115,21 @@ rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIB
return RS6000_SYMBOL_REF_TLS_P (*x);
}
+/* Return true iff the given SYMBOL_REF refers to a constant pool entry
+ that we have put in the TOC, or for cmodel=medium, if the SYMBOL_REF
+ can be addressed relative to the toc pointer. */
+
+static bool
+use_toc_relative_ref (rtx sym)
+{
+ return ((constant_pool_expr_p (sym)
+ && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym),
+ get_pool_mode (sym)))
+ || (TARGET_CMODEL == CMODEL_MEDIUM
+ && !CONSTANT_POOL_ADDRESS_P (sym)
+ && SYMBOL_REF_LOCAL_P (sym)));
+}
+
/* Our implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to
replace the input X, or the original X if no replacement is called for.
The output parameter *WIN is 1 if the calling macro should goto WIN,
@@ -6136,7 +6167,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach
{
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ opnum, (enum reload_type) type);
*win = 1;
return x;
}
@@ -6147,7 +6178,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach
{
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ opnum, (enum reload_type) type);
*win = 1;
return x;
}
@@ -6165,31 +6196,12 @@ rs6000_legitimize_reload_address (rtx x, enum mach
floating point constant. */
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ opnum, (enum reload_type) type);
*win = 1;
return x;
}
#endif
- if (TARGET_CMODEL != CMODEL_SMALL
- && GET_CODE (x) == LO_SUM
- && GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
- && REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST
- && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == HIGH
- && GET_CODE (XEXP (x, 1)) == CONST
- && GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
- && XINT (XEXP (XEXP (x, 1), 0), 1) == UNSPEC_TOCREL
- && rtx_equal_p (XEXP (XEXP (XEXP (XEXP (x, 0), 1), 0), 0), XEXP (x, 1)))
- {
- push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type) type);
- *win = 1;
- return x;
- }
-
/* Force ld/std non-word aligned offset into base register by wrapping
in offset 0. */
if (GET_CODE (x) == PLUS
@@ -6245,7 +6257,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ opnum, (enum reload_type) type);
*win = 1;
return x;
}
@@ -6286,7 +6298,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ opnum, (enum reload_type) type);
*win = 1;
return x;
}
@@ -6313,8 +6325,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach
if (TARGET_TOC
&& reg_offset_p
&& GET_CODE (x) == SYMBOL_REF
- && constant_pool_expr_p (x)
- && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
+ && use_toc_relative_ref (x))
{
x = create_TOC_reference (x, NULL_RTX);
if (TARGET_CMODEL != CMODEL_SMALL)
@@ -6549,9 +6560,13 @@ rs6000_debug_mode_dependent_address (const_rtx add
rtx
rs6000_find_base_term (rtx op)
{
- rtx base, offset;
+ rtx base;
- split_const (op, &base, &offset);
+ base = op;
+ if (GET_CODE (base) == CONST)
+ base = XEXP (base, 0);
+ if (GET_CODE (base) == PLUS)
+ base = XEXP (base, 0);
if (GET_CODE (base) == UNSPEC)
switch (XINT (base, 1))
{
@@ -7203,15 +7218,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machi
/* If this is a SYMBOL_REF that refers to a constant pool entry,
and we have put it in the TOC, we just need to make a TOC-relative
reference to it. */
- if ((TARGET_TOC
- && GET_CODE (operands[1]) == SYMBOL_REF
- && constant_pool_expr_p (operands[1])
- && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
- get_pool_mode (operands[1])))
- || (TARGET_CMODEL == CMODEL_MEDIUM
- && GET_CODE (operands[1]) == SYMBOL_REF
- && !CONSTANT_POOL_ADDRESS_P (operands[1])
- && SYMBOL_REF_LOCAL_P (operands[1])))
+ if (TARGET_TOC
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && use_toc_relative_ref (operands[1]))
{
rtx reg = NULL_RTX;
if (TARGET_CMODEL != CMODEL_SMALL)
@@ -7226,10 +7235,6 @@ rs6000_emit_move (rtx dest, rtx source, enum machi
else if (mode == Pmode
&& CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH
- && !(TARGET_CMODEL != CMODEL_SMALL
- && GET_CODE (operands[1]) == CONST
- && GET_CODE (XEXP (operands[1], 0)) == PLUS
- && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == HIGH)
&& ((GET_CODE (operands[1]) != CONST_INT
&& ! easy_fp_constant (operands[1], mode))
|| (GET_CODE (operands[1]) == CONST_INT
@@ -7237,9 +7242,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machi
> (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2)))
|| (GET_CODE (operands[0]) == REG
&& FP_REGNO_P (REGNO (operands[0]))))
- && ! legitimate_constant_pool_address_p (operands[1], mode,
- false)
- && ! toc_relative_expr_p (operands[1])
+ && !toc_relative_expr_p (operands[1], false)
&& (TARGET_CMODEL == CMODEL_SMALL
|| can_create_pseudo_p ()
|| (REG_P (operands[0])
@@ -14718,7 +14721,7 @@ print_operand (FILE *file, rtx x, int code)
case 'D':
/* Like 'J' but get to the GT bit only. */
- gcc_assert (GET_CODE (x) == REG);
+ gcc_assert (REG_P (x));
/* Bit 1 is GT bit. */
i = 4 * (REGNO (x) - CR0_REGNO) + 1;
@@ -14838,9 +14841,9 @@ print_operand (FILE *file, rtx x, int code)
case 'L':
/* Write second word of DImode or DFmode reference. Works on register
or non-indexed memory only. */
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fputs (reg_names[REGNO (x) + 1], file);
- else if (GET_CODE (x) == MEM)
+ else if (MEM_P (x))
{
/* Handle possible auto-increment. Since it is pre-increment and
we have already done it, we can just use an offset of word. */
@@ -15009,7 +15012,7 @@ print_operand (FILE *file, rtx x, int code)
case 't':
/* Like 'J' but get to the OVERFLOW/UNORDERED bit. */
- gcc_assert (GET_CODE (x) == REG && GET_MODE (x) == CCmode);
+ gcc_assert (REG_P (x) && GET_MODE (x) == CCmode);
/* Bit 3 is OV bit. */
i = 4 * (REGNO (x) - CR0_REGNO) + 3;
@@ -15049,7 +15052,7 @@ print_operand (FILE *file, rtx x, int code)
case 'U':
/* Print `u' if this has an auto-increment or auto-decrement. */
- if (GET_CODE (x) == MEM
+ if (MEM_P (x)
&& (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC
|| GET_CODE (XEXP (x, 0)) == PRE_MODIFY))
@@ -15158,7 +15161,7 @@ print_operand (FILE *file, rtx x, int code)
return;
case 'X':
- if (GET_CODE (x) == MEM
+ if (MEM_P (x)
&& (legitimate_indexed_address_p (XEXP (x, 0), 0)
|| (GET_CODE (XEXP (x, 0)) == PRE_MODIFY
&& legitimate_indexed_address_p (XEXP (XEXP (x, 0), 1), 0))))
@@ -15167,9 +15170,9 @@ print_operand (FILE *file, rtx x, int code)
case 'Y':
/* Like 'L', for third word of TImode */
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fputs (reg_names[REGNO (x) + 2], file);
- else if (GET_CODE (x) == MEM)
+ else if (MEM_P (x))
{
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
@@ -15217,9 +15220,9 @@ print_operand (FILE *file, rtx x, int code)
case 'Z':
/* Like 'L', for last word of TImode. */
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fputs (reg_names[REGNO (x) + 3], file);
- else if (GET_CODE (x) == MEM)
+ else if (MEM_P (x))
{
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
@@ -15239,7 +15242,7 @@ print_operand (FILE *file, rtx x, int code)
{
rtx tmp;
- gcc_assert (GET_CODE (x) == MEM);
+ gcc_assert (MEM_P (x));
tmp = XEXP (x, 0);
@@ -15250,7 +15253,7 @@ print_operand (FILE *file, rtx x, int code)
|| GET_MODE (x) == TImode))
{
/* Handle [reg]. */
- if (GET_CODE (tmp) == REG)
+ if (REG_P (tmp))
{
fprintf (file, "0(%s)", reg_names[REGNO (tmp)]);
break;
@@ -15261,7 +15264,7 @@ print_operand (FILE *file, rtx x, int code)
{
int x;
- gcc_assert (GET_CODE (XEXP (tmp, 0)) == REG);
+ gcc_assert (REG_P (XEXP (tmp, 0)));
x = INTVAL (XEXP (tmp, 1));
fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]);
@@ -15278,7 +15281,7 @@ print_operand (FILE *file, rtx x, int code)
else if (VECTOR_MEM_VSX_P (GET_MODE (x))
&& GET_CODE (tmp) == PRE_MODIFY)
tmp = XEXP (tmp, 1);
- if (GET_CODE (tmp) == REG)
+ if (REG_P (tmp))
fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
else
{
@@ -15301,9 +15304,9 @@ print_operand (FILE *file, rtx x, int code)
}
case 0:
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fprintf (file, "%s", reg_names[REGNO (x)]);
- else if (GET_CODE (x) == MEM)
+ else if (MEM_P (x))
{
/* We need to handle PRE_INC and PRE_DEC here, since we need to
know the width from the mode. */
@@ -15320,14 +15323,14 @@ print_operand (FILE *file, rtx x, int code)
}
else
{
- if (toc_relative_expr_p (x))
+ if (toc_relative_expr_p (x, false))
/* This hack along with a corresponding hack in
rs6000_output_addr_const_extra arranges to output addends
where the assembler expects to find them. eg.
- (const (plus (unspec [symbol_ref ("x") tocrel]) 4))
+ (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 4)
without this hack would be output as "x@toc+4". We
want "x+4@toc". */
- output_addr_const (file, tocrel_base);
+ output_addr_const (file, CONST_CAST_RTX (tocrel_base));
else
output_addr_const (file, x);
}
@@ -15347,7 +15350,7 @@ print_operand (FILE *file, rtx x, int code)
void
print_operand_address (FILE *file, rtx x)
{
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);
else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST
|| GET_CODE (x) == LABEL_REF)
@@ -15359,9 +15362,9 @@ print_operand_address (FILE *file, rtx x)
else
gcc_assert (!TARGET_TOC);
}
- else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
+ else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
+ && REG_P (XEXP (x, 1)))
{
- gcc_assert (REG_P (XEXP (x, 0)));
if (REGNO (XEXP (x, 0)) == 0)
fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
reg_names[ REGNO (XEXP (x, 0)) ]);
@@ -15369,11 +15372,12 @@ print_operand_address (FILE *file, rtx x)
fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ],
reg_names[ REGNO (XEXP (x, 1)) ]);
}
- else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]);
#if TARGET_MACHO
- else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
+ else if (GET_CODE (x) == LO_SUM && REG_P (XEXP (x, 0))
&& CONSTANT_P (XEXP (x, 1)))
{
fprintf (file, "lo16(");
@@ -15381,29 +15385,29 @@ print_operand_address (FILE *file, rtx x)
fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
}
#endif
- else if (legitimate_constant_pool_address_p (x, QImode, true))
+#if TARGET_ELF
+ else if (GET_CODE (x) == LO_SUM && REG_P (XEXP (x, 0))
+ && CONSTANT_P (XEXP (x, 1)))
{
+ output_addr_const (file, XEXP (x, 1));
+ fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
+ }
+#endif
+ else if (toc_relative_expr_p (x, false))
+ {
/* This hack along with a corresponding hack in
rs6000_output_addr_const_extra arranges to output addends
where the assembler expects to find them. eg.
(lo_sum (reg 9)
- . (const (plus (unspec [symbol_ref ("x") tocrel]) 8)))
+ . (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 8))
without this hack would be output as "x@toc+8@l(9)". We
want "x+8@toc@l(9)". */
- output_addr_const (file, tocrel_base);
+ output_addr_const (file, CONST_CAST_RTX (tocrel_base));
if (GET_CODE (x) == LO_SUM)
- fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
+ fprintf (file, "@l(%s)", reg_names[REGNO (XEXP (x, 0))]);
else
- fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
+ fprintf (file, "(%s)", reg_names[REGNO (XVECEXP (tocrel_base, 0, 1))]);
}
-#if TARGET_ELF
- else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
- && CONSTANT_P (XEXP (x, 1)))
- {
- output_addr_const (file, XEXP (x, 1));
- fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
- }
-#endif
else
gcc_unreachable ();
}
@@ -15417,13 +15421,15 @@ rs6000_output_addr_const_extra (FILE *file, rtx x)
switch (XINT (x, 1))
{
case UNSPEC_TOCREL:
- gcc_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF);
+ gcc_checking_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF
+ && REG_P (XVECEXP (x, 0, 1))
+ && REGNO (XVECEXP (x, 0, 1)) == TOC_REGISTER);
output_addr_const (file, XVECEXP (x, 0, 0));
if (x == tocrel_base && tocrel_offset != const0_rtx)
{
if (INTVAL (tocrel_offset) >= 0)
fprintf (file, "+");
- output_addr_const (file, tocrel_offset);
+ output_addr_const (file, CONST_CAST_RTX (tocrel_offset));
}
if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC))
{
@@ -18466,7 +18472,7 @@ uses_TOC (void)
rtx
create_TOC_reference (rtx symbol, rtx largetoc_reg)
{
- rtx tocrel, tocreg;
+ rtx tocrel, tocreg, hi;
if (TARGET_DEBUG_ADDR)
{
@@ -18484,24 +18490,18 @@ create_TOC_reference (rtx symbol, rtx largetoc_reg
if (!can_create_pseudo_p ())
df_set_regs_ever_live (TOC_REGISTER, true);
- tocrel = gen_rtx_CONST (Pmode,
- gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol),
- UNSPEC_TOCREL));
tocreg = gen_rtx_REG (Pmode, TOC_REGISTER);
- if (TARGET_CMODEL != CMODEL_SMALL)
+ tocrel = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, symbol, tocreg), UNSPEC_TOCREL);
+ if (TARGET_CMODEL == CMODEL_SMALL)
+ return tocrel;
+
+ hi = gen_rtx_HIGH (Pmode, copy_rtx (tocrel));
+ if (largetoc_reg != NULL)
{
- rtx hi = gen_rtx_CONST (Pmode,
- gen_rtx_PLUS (Pmode, tocreg,
- gen_rtx_HIGH (Pmode, tocrel)));
- if (largetoc_reg != NULL)
- {
- emit_move_insn (largetoc_reg, hi);
- hi = largetoc_reg;
- }
- return gen_rtx_LO_SUM (Pmode, hi, copy_rtx (tocrel));
+ emit_move_insn (largetoc_reg, hi);
+ hi = largetoc_reg;
}
- else
- return gen_rtx_PLUS (Pmode, tocreg, tocrel);
+ return gen_rtx_LO_SUM (Pmode, hi, tocrel);
}
/* Issue assembly directives that create a reference to the given DWARF
===================================================================
@@ -825,7 +825,7 @@
;; Return 1 if this operand is a valid input for a move insn.
(define_predicate "input_operand"
(match_code "label_ref,symbol_ref,const,high,reg,subreg,mem,
- const_double,const_vector,const_int,plus")
+ const_double,const_vector,const_int,plus,unspec")
{
/* Memory is always valid. */
if (memory_operand (op, mode))
@@ -833,7 +833,6 @@
/* For floating-point, easy constants are valid. */
if (SCALAR_FLOAT_MODE_P (mode)
- && CONSTANT_P (op)
&& easy_fp_constant (op, mode))
return 1;
@@ -867,13 +866,9 @@
return 1;
/* A SYMBOL_REF referring to the TOC is valid. */
- if (legitimate_constant_pool_address_p (op, mode, false))
+ if (toc_relative_expr_p (op, false))
return 1;
- /* A constant pool expression (relative to the TOC) is valid */
- if (toc_relative_expr_p (op))
- return 1;
-
/* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region
to be valid. */
if (DEFAULT_ABI == ABI_V4
===================================================================
@@ -11549,10 +11549,8 @@
"addi %0,%1,%2@got@tlsgd"
"&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 3)
- (const:TLSmode
- (plus:TLSmode (match_dup 1)
- (high:TLSmode
- (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))))
+ (high:TLSmode
+ (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))
(set (match_dup 0)
(lo_sum:TLSmode (match_dup 3)
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))]
@@ -11567,11 +11565,10 @@
(define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
- (const:TLSmode
- (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
- (high:TLSmode
- (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
- UNSPEC_TLSGD)))))]
+ (high:TLSmode
+ (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
+ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSGD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%2@got@tlsgd@ha"
[(set_attr "length" "4")])
@@ -11686,10 +11683,8 @@
"addi %0,%1,%&@got@tlsld"
"&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 2)
- (const:TLSmode
- (plus:TLSmode (match_dup 1)
- (high:TLSmode
- (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))))
+ (high:TLSmode
+ (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))
(set (match_dup 0)
(lo_sum:TLSmode (match_dup 2)
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
@@ -11704,10 +11699,10 @@
(define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
- (const:TLSmode
- (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
- (high:TLSmode
- (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))))]
+ (high:TLSmode
+ (unspec:TLSmode [(const_int 0)
+ (match_operand:TLSmode 1 "gpc_reg_operand" "b")]
+ UNSPEC_TLSLD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%&@got@tlsld@ha"
[(set_attr "length" "4")])
@@ -11783,10 +11778,8 @@
"l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)"
"&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 3)
- (const:TLSmode
- (plus:TLSmode (match_dup 1)
- (high:TLSmode
- (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))))
+ (high:TLSmode
+ (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL)))
(set (match_dup 0)
(lo_sum:TLSmode (match_dup 3)
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))]
@@ -11801,11 +11794,10 @@
(define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
- (const:TLSmode
- (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
- (high:TLSmode
- (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
- UNSPEC_TLSGOTDTPREL)))))]
+ (high:TLSmode
+ (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
+ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSGOTDTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%2@got@dtprel@ha"
[(set_attr "length" "4")])
@@ -11855,10 +11847,8 @@
"l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)"
"&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 3)
- (const:TLSmode
- (plus:TLSmode (match_dup 1)
- (high:TLSmode
- (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))))
+ (high:TLSmode
+ (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))
(set (match_dup 0)
(lo_sum:TLSmode (match_dup 3)
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))]
@@ -11873,11 +11863,10 @@
(define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
- (const:TLSmode
- (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
- (high:TLSmode
- (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
- UNSPEC_TLSGOTTPREL)))))]
+ (high:TLSmode
+ (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
+ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSGOTTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%2@got@tprel@ha"
[(set_attr "length" "4")])
@@ -12223,6 +12212,25 @@
DONE;
}")
+;; Largetoc support
+(define_insn "largetoc_high"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
+ (high:DI
+ (unspec [(match_operand:DI 1 "" "")
+ (match_operand:DI 2 "gpc_reg_operand" "b")]
+ UNSPEC_TOCREL)))]
+ "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+ "{cau|addis} %0,%2,%1@toc@ha")
+
+(define_insn "largetoc_low"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,!*r")
+ (match_operand:DI 2 "" "")))]
+ "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+ "@
+ {cal %0,%2@l(%1)|addi %0,%1,%2@l}
+ {ai|addic} %0,%1,%2@l")
+
;; Elf specific ways of loading addresses for non-PIC code.
;; The output of this could be r0, but we make a very strong
;; preference for a base register because it will usually
@@ -12241,22 +12249,6 @@
"@
{cal|la} %0,%2@l(%1)
{ai|addic} %0,%1,%K2")
-
-;; Largetoc support
-(define_insn "largetoc_high"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
- (const:DI
- (plus:DI (match_operand:DI 1 "gpc_reg_operand" "b")
- (high:DI (match_operand:DI 2 "" "")))))]
- "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
- "{cau|addis} %0,%1,%2@ha")
-
-(define_insn "largetoc_low"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
- (match_operand:DI 2 "" "")))]
- "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
- "{cal %0,%2@l(%1)|addi %0,%1,%2@l}")
;; Call and call_value insns
(define_expand "call"
===================================================================
@@ -38,7 +38,7 @@ extern bool macho_lo_sum_memory_operand (rtx, enum
extern int num_insns_constant (rtx, enum machine_mode);
extern int num_insns_constant_wide (HOST_WIDE_INT);
extern int small_data_operand (rtx, enum machine_mode);
-extern bool toc_relative_expr_p (rtx);
+extern bool toc_relative_expr_p (const_rtx, bool);
extern bool invalid_e500_subreg (rtx, enum machine_mode);
extern void validate_condition_mode (enum rtx_code, enum machine_mode);
extern bool legitimate_constant_pool_address_p (const_rtx, enum machine_mode,