* rs6000 toc reference rtl again
@ 2012-03-27 7:55 Alan Modra
2012-04-03 17:18 ` David Edelsohn
2012-04-03 18:49 ` Richard Sandiford
0 siblings, 2 replies; 9+ messages in thread
From: Alan Modra @ 2012-03-27 7:55 UTC (permalink / raw)
To: gcc-patches; +Cc: David Edelsohn
Now that we are back in stage1, I'd like to apply
http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00304.html, a change to
toc reference rtl in order to properly specify r2 dependencies. More
commentary in that url. I'm reposting the patch here since the old
one no longer applies cleanly, and I've added some ENABLE_CHECKING
code in rs6000_delegitimize_address.
Bootstrapped and regression tested powerpc64-linux. OK for mainline?
* cselib.c (preserve_only_constants): Remove HIGH rtx containing
value references.
* cprop.c (cprop_constant_p): Return false for HIGH rtx containing
value references.
* config/rs6000/predicates.md (input_operand): Match unspec. Remove
redundant tests.
* rs6000-protos.h (toc_relative_expr_p): Update prototype.
* const/rs6000/rs6000.c (tocrel_base, tocrel_offset): Make const.
(legitimate_constant_pool_address_p): Move TARGET_TOC test and
register checks to..
(toc_relative_expr_p): ..here. Add "strict" param. Match new rtl
generated by create_TOC_reference.
(rs6000_delegitimize_address): Handle new rtl for toc refs.
(rs6000_cannot_force_const_mem, rs6000_find_base_term): Likewise.
(use_toc_relative_ref): New function, split out from..
(rs6000_emit_move): ..here. Remove redundant tests.
(rs6000_legitimize_reload_address): Formatting. Remove redundant
code. Use use_toc_relative_ref.
(print_operand): Formatting, style. Adjust for toc changes.
(print_operand_address): Likewise.
(rs6000_output_addr_const_extra): Likewise.
(create_TOC_reference): Put TOC_REGISTER in UNSPEC_TOCREL rather
than a PLUS. Use this formulation for both high and low part
of -mcmodel=medium/large toc reference too.
* config/rs6000/rs6000.md (tls_gd, tls_gd_high): Similarly avoid
a PLUS in high part of addresses here.
(tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
(tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.
(largetoc_high, largetoc_low): Move earlier. Cope when no
base reg available.
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c (revision 185830)
+++ gcc/cselib.c (working copy)
@@ -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
Index: gcc/cprop.c
===================================================================
--- gcc/cprop.c (revision 185830)
+++ gcc/cprop.c (working copy)
@@ -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.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 185830)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -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
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md (revision 185830)
+++ gcc/config/rs6000/predicates.md (working copy)
@@ -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
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 185830)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -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}")
\f
;; Call and call_value insns
(define_expand "call"
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h (revision 185830)
+++ gcc/config/rs6000/rs6000-protos.h (working copy)
@@ -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,
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-03-27 7:55 rs6000 toc reference rtl again Alan Modra
@ 2012-04-03 17:18 ` David Edelsohn
2012-04-03 18:49 ` Richard Sandiford
1 sibling, 0 replies; 9+ messages in thread
From: David Edelsohn @ 2012-04-03 17:18 UTC (permalink / raw)
To: Alan Modra; +Cc: GCC Patches
On Tue, Mar 27, 2012 at 3:54 AM, Alan Modra <amodra@gmail.com> wrote:
> Now that we are back in stage1, I'd like to apply
> http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00304.html, a change to
> toc reference rtl in order to properly specify r2 dependencies. More
> commentary in that url. I'm reposting the patch here since the old
> one no longer applies cleanly, and I've added some ENABLE_CHECKING
> code in rs6000_delegitimize_address.
>
> Bootstrapped and regression tested powerpc64-linux. OK for mainline?
>
> * cselib.c (preserve_only_constants): Remove HIGH rtx containing
> value references.
> * cprop.c (cprop_constant_p): Return false for HIGH rtx containing
> value references.
> * config/rs6000/predicates.md (input_operand): Match unspec. Remove
> redundant tests.
> * rs6000-protos.h (toc_relative_expr_p): Update prototype.
> * const/rs6000/rs6000.c (tocrel_base, tocrel_offset): Make const.
> (legitimate_constant_pool_address_p): Move TARGET_TOC test and
> register checks to..
> (toc_relative_expr_p): ..here. Add "strict" param. Match new rtl
> generated by create_TOC_reference.
> (rs6000_delegitimize_address): Handle new rtl for toc refs.
> (rs6000_cannot_force_const_mem, rs6000_find_base_term): Likewise.
> (use_toc_relative_ref): New function, split out from..
> (rs6000_emit_move): ..here. Remove redundant tests.
> (rs6000_legitimize_reload_address): Formatting. Remove redundant
> code. Use use_toc_relative_ref.
> (print_operand): Formatting, style. Adjust for toc changes.
> (print_operand_address): Likewise.
> (rs6000_output_addr_const_extra): Likewise.
> (create_TOC_reference): Put TOC_REGISTER in UNSPEC_TOCREL rather
> than a PLUS. Use this formulation for both high and low part
> of -mcmodel=medium/large toc reference too.
> * config/rs6000/rs6000.md (tls_gd, tls_gd_high): Similarly avoid
> a PLUS in high part of addresses here.
> (tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
> (tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.
> (largetoc_high, largetoc_low): Move earlier. Cope when no
> base reg available.
Now that PPC bootstrap appears to be fixed, this patch is okay to apply.
However, I cannot approve the cselib.c and cprop.c changes.
Thanks, David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-03-27 7:55 rs6000 toc reference rtl again Alan Modra
2012-04-03 17:18 ` David Edelsohn
@ 2012-04-03 18:49 ` Richard Sandiford
2012-04-04 1:04 ` Alan Modra
1 sibling, 1 reply; 9+ messages in thread
From: Richard Sandiford @ 2012-04-03 18:49 UTC (permalink / raw)
To: gcc-patches; +Cc: David Edelsohn
Alan Modra <amodra@gmail.com> writes:
> Now that we are back in stage1, I'd like to apply
> http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00304.html, a change to
> toc reference rtl in order to properly specify r2 dependencies. More
> commentary in that url. I'm reposting the patch here since the old
> one no longer applies cleanly, and I've added some ENABLE_CHECKING
> code in rs6000_delegitimize_address.
Sorry to be a pain, but I don't think HIGH is supposed contain
regs either. Both HIGH and CONST are supposed to be true constants.
It's fine to have a non-HIGH expression as the first operand to
a LO_SUM though. Alpha and MIPS use this for small data, where
the first LO_SUM operand is the small data pointer. It can also
be an arbitrary rtx like a PLUS.
Richard
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-04-03 18:49 ` Richard Sandiford
@ 2012-04-04 1:04 ` Alan Modra
2012-04-04 9:25 ` Richard Sandiford
0 siblings, 1 reply; 9+ messages in thread
From: Alan Modra @ 2012-04-04 1:04 UTC (permalink / raw)
To: gcc-patches, David Edelsohn, rdsandiford
On Tue, Apr 03, 2012 at 07:49:04PM +0100, Richard Sandiford wrote:
> Alan Modra <amodra@gmail.com> writes:
> > Now that we are back in stage1, I'd like to apply
> > http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00304.html, a change to
> > toc reference rtl in order to properly specify r2 dependencies. More
> > commentary in that url. I'm reposting the patch here since the old
> > one no longer applies cleanly, and I've added some ENABLE_CHECKING
> > code in rs6000_delegitimize_address.
>
> Sorry to be a pain, but I don't think HIGH is supposed contain
> regs either. Both HIGH and CONST are supposed to be true constants.
Eh, so the existing use of CONST is wrong then. ;-)
I'm proposing
(unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL)
for the small model, and
(high (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL)))
(lo_sum (reg hi) (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL))
for medium/large model.
You can see why I'd like to keep it this way; The medium/large rtl is
a natural split of the small rtl. (I'm going to experiment with
splitting the small rtl after reload for medium/large to see whether
that helps our usage of call-saved regs in loops.)
I'm not wedded to the representation, *but* we do want gcc to treat
the high part as a constant. That's important because we don't ever
want reload saving the high part to a stack slot! Which is what does
happen if you don't somehow tell gcc it is a constant.
Besides, the high part *is* a constant within any given function. So
is the low part for that matter. The only reason I want r2 mentioned
in this rtl is for register liveness, eg. so that a load of a function
pointer (which loads r2) for an indirect call doesn't get scheduled
before any uses of the old r2.
The alternative of removing r2 from the unspec and attaching a
(use (reg r2)) to all instructions that have this addressing form
might be clean but will require major duplication of patterns in
rs6000.md, won't it?
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-04-04 1:04 ` Alan Modra
@ 2012-04-04 9:25 ` Richard Sandiford
2012-04-04 11:14 ` Alan Modra
0 siblings, 1 reply; 9+ messages in thread
From: Richard Sandiford @ 2012-04-04 9:25 UTC (permalink / raw)
To: gcc-patches; +Cc: David Edelsohn
Alan Modra <amodra@gmail.com> writes:
> On Tue, Apr 03, 2012 at 07:49:04PM +0100, Richard Sandiford wrote:
>> Alan Modra <amodra@gmail.com> writes:
>> > Now that we are back in stage1, I'd like to apply
>> > http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00304.html, a change to
>> > toc reference rtl in order to properly specify r2 dependencies. More
>> > commentary in that url. I'm reposting the patch here since the old
>> > one no longer applies cleanly, and I've added some ENABLE_CHECKING
>> > code in rs6000_delegitimize_address.
>>
>> Sorry to be a pain, but I don't think HIGH is supposed contain
>> regs either. Both HIGH and CONST are supposed to be true constants.
>
> Eh, so the existing use of CONST is wrong then. ;-)
Right :-) Sorry, I meant: although you're fixing the CONST,
the same problem really applies to the HIGH too.
> I'm proposing
> (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL)
> for the small model, and
> (high (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL)))
> (lo_sum (reg hi) (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL))
> for medium/large model.
>
> You can see why I'd like to keep it this way; The medium/large rtl is
> a natural split of the small rtl. (I'm going to experiment with
> splitting the small rtl after reload for medium/large to see whether
> that helps our usage of call-saved regs in loops.)
Yeah. FWIW, MIPS keeps both the small and large forms as constants
before reload, then splits them into (non-constant) forms that
reference the global pointer after reload. So the small version
is simply:
(set (match_operand 0 "register_operand" "=...")
(match_operand 1 "symbolic_constant" ""))
before reload, while the large form is a normal HIGH/LO_SUM pair.
That HIGH then gets split after reload too.
It seems to work well, although these days it does require the split
to happen before prologue/epilogue generation. (Hmm, the *lea_high64
patterns are probably wrong now that we have shrink-wrapping...)
With the loop thing, do you mean that you're seeing too many HIGHs
being hoisted? Would be nice to fix that in the loop optimisers
if so.
> I'm not wedded to the representation, *but* we do want gcc to treat
> the high part as a constant. That's important because we don't ever
> want reload saving the high part to a stack slot! Which is what does
> happen if you don't somehow tell gcc it is a constant.
Out of curiosity, does that still happen if you have a HIGH REG_EQUAL
note attached to the addition? I'd have expected reload to convert
the note into a REG_EQUIV and treat the source as a function invariant.
> Besides, the high part *is* a constant within any given function. So
> is the low part for that matter. The only reason I want r2 mentioned
> in this rtl is for register liveness, eg. so that a load of a function
> pointer (which loads r2) for an indirect call doesn't get scheduled
> before any uses of the old r2.
Right. But that's also true of, say, a constant that needs to be split
into a load-high and add. The result of the add is a function constant,
but the add itself is still not a constant from an rtl perspective.
I think it'd get too confusing if constants were allowed to reference
registers. That sort of thing is usually handled with REG_EQUAL notes
instead. But in the specific case of GOT references, where the GOT
register isn't really around until prologue/epilogue generation anyway,
there's less point exposing it before reload.
> The alternative of removing r2 from the unspec and attaching a
> (use (reg r2)) to all instructions that have this addressing form
> might be clean but will require major duplication of patterns in
> rs6000.md, won't it?
Yeah. It'd probably also not be as effective as splitting after reload.
Passes that want to optimise the load high are likely to be put off by
a (use ...).
Richard
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-04-04 9:25 ` Richard Sandiford
@ 2012-04-04 11:14 ` Alan Modra
2012-05-01 4:18 ` Alan Modra
0 siblings, 1 reply; 9+ messages in thread
From: Alan Modra @ 2012-04-04 11:14 UTC (permalink / raw)
To: gcc-patches, David Edelsohn, rdsandiford
On Wed, Apr 04, 2012 at 10:25:39AM +0100, Richard Sandiford wrote:
> With the loop thing, do you mean that you're seeing too many HIGHs
> being hoisted?
No, nothing as complicated as that. In a lot of cases, any hoisting
of the high part is bad, because the linker nops out the high part and
edits the low part insn when the r2 offset can be done in 16 bits. If
the high part insn was the only use of a call-saved reg, then the
function saves and restores a reg to no purpose.
> > I'm not wedded to the representation, *but* we do want gcc to treat
> > the high part as a constant. That's important because we don't ever
> > want reload saving the high part to a stack slot! Which is what does
> > happen if you don't somehow tell gcc it is a constant.
>
> Out of curiosity, does that still happen if you have a HIGH REG_EQUAL
> note attached to the addition? I'd have expected reload to convert
> the note into a REG_EQUIV and treat the source as a function invariant.
I saw that possibility in reload, and did try a REG_EQUIV note before
I wrapped the ADD in a CONST as we have currently. Some early pass
deleted the notes for me. I forget which one.
Oh well, I was going to try splitting after reload anyway.
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-04-04 11:14 ` Alan Modra
@ 2012-05-01 4:18 ` Alan Modra
2012-05-16 1:55 ` Alan Modra
2012-05-17 2:56 ` David Edelsohn
0 siblings, 2 replies; 9+ messages in thread
From: Alan Modra @ 2012-05-01 4:18 UTC (permalink / raw)
To: gcc-patches, David Edelsohn, rdsandiford
This revision splits the medium/large code model toc reference after
reload. I expected this to be more difficult, but it turned out
surprisingly easy. Besides creating the rtl that way, and tweaking
toc_relative_expr_p to match, it was just: Move the 'R' constraint
handling out of various movsi/di instructions into a new instruction
that is split after reload, and modify legitimize_reload_address to
handle all the other splits inside MEMs.
Bootstrapped and regression tested powerpc-linux. I also intend to
spec test this change. Generated code has the expected improvements:
libstdc++.so saw a small reduction in code size due to removing silly
uses of call-saved regs to hold the high part of a toc reference.
OK to apply?
* config/rs6000/predicates.md (input_operand): Don't match
constant pool addresses. Remove label_ref, high and plus from
match_code list. Remove redundant CONSTANT_P test.
(splat_input_operand): Similarly update match_code list.
(small_toc_ref): New predicate.
* config/rs6000/rs6000-protos.h (toc_relative_expr_p): Update prototype.
* config/rs6000/rs6000.c (tocrel_base, tocrel_offset): Make const.
(legitimate_constant_pool_address_p): Move TARGET_TOC test and
register checks to..
(toc_relative_expr_p): ..here. Add "strict" param. Match new rtl
generated by create_TOC_reference.
(rs6000_legitimize_address): Update cerate_TOC_reference call.
(rs6000_delegitimize_address): Handle new rtl for toc refs.
(rs6000_cannot_force_const_mem, rs6000_find_base_term): Likewise.
(use_toc_relative_ref): New function, split out from..
(rs6000_emit_move): ..here. Remove redundant tests. Update
create_TOC_reference calls.
(rs6000_legitimize_reload_address): Formatting. Handle splitting
of medium/large model toc addresses. Use use_toc_relative_ref.
(print_operand): Formatting, style. Adjust for toc changes.
(print_operand_address): Likewise.
(rs6000_output_addr_const_extra): Likewise.
(create_TOC_reference): Put TOC_REGISTER in UNSPEC_TOCREL rather
than a PLUS. Use this formulation for both high and low part
of -mcmodel=medium/large toc reference too. Before reload,
always use the small model formulation.
* config/rs6000/rs6000.md (tls_gd, tls_gd_high): Similarly avoid
a PLUS in high part of addresses here.
(tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
(tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.
(largetoc_high, largetoc_low): Move earlier. Cope when no
base reg available.
(largetoc_high_plus): New insn.
(movsi_internal1, movsi_internal1_single, movsf_softfloat,
movdi_mfpgpr, movdi_internal64): Don't handle 'R' constraint here..
(tocref): ..instead do so here, new insn and split.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 187010)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -5280,15 +5280,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 if (strict)
+ 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);
}
@@ -5300,14 +5318,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
@@ -5687,10 +5698,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBU
&& GET_CODE (x) == SYMBOL_REF
&& constant_pool_expr_p (x)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
- {
- rtx reg = TARGET_CMODEL != CMODEL_SMALL ? gen_reg_rtx (Pmode) : NULL_RTX;
- return create_TOC_reference (x, reg);
- }
+ return create_TOC_reference (x, NULL_RTX);
else
return x;
}
@@ -5773,49 +5781,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
@@ -6077,9 +6091,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);
@@ -6094,6 +6107,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,
@@ -6131,7 +6159,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;
}
@@ -6142,7 +6170,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;
}
@@ -6160,24 +6188,18 @@ 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)))
+ && reg_offset_p
+ && small_toc_ref (x, VOIDmode))
{
+ rtx hi = gen_rtx_HIGH (Pmode, copy_rtx (x));
+ x = gen_rtx_LO_SUM (Pmode, hi, x);
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
opnum, (enum reload_type) type);
@@ -6240,7 +6262,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;
}
@@ -6281,7 +6303,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;
}
@@ -6308,8 +6330,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)
@@ -6544,9 +6565,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))
{
@@ -7198,33 +7223,13 @@ 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])))
- {
- rtx reg = NULL_RTX;
- if (TARGET_CMODEL != CMODEL_SMALL)
- {
- if (can_create_pseudo_p ())
- reg = gen_reg_rtx (Pmode);
- else
- reg = operands[0];
- }
- operands[1] = create_TOC_reference (operands[1], reg);
- }
+ if (TARGET_TOC
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && use_toc_relative_ref (operands[1]))
+ operands[1] = create_TOC_reference (operands[1], operands[0]);
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
@@ -7232,9 +7237,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])
@@ -7284,16 +7287,8 @@ rs6000_emit_move (rtx dest, rtx source, enum machi
get_pool_constant (XEXP (operands[1], 0)),
get_pool_mode (XEXP (operands[1], 0))))
{
- rtx tocref;
- rtx reg = NULL_RTX;
- if (TARGET_CMODEL != CMODEL_SMALL)
- {
- if (can_create_pseudo_p ())
- reg = gen_reg_rtx (Pmode);
- else
- reg = operands[0];
- }
- tocref = create_TOC_reference (XEXP (operands[1], 0), reg);
+ rtx tocref = create_TOC_reference (XEXP (operands[1], 0),
+ operands[0]);
operands[1] = gen_const_mem (mode, tocref);
set_mem_alias_set (operands[1], get_TOC_alias_set ());
}
@@ -14704,7 +14699,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;
@@ -14824,9 +14819,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. */
@@ -14995,7 +14990,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;
@@ -15035,7 +15030,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))
@@ -15144,7 +15139,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))))
@@ -15153,9 +15148,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)
@@ -15203,9 +15198,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)
@@ -15225,7 +15220,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);
@@ -15236,7 +15231,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;
@@ -15247,7 +15242,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))]);
@@ -15264,7 +15259,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
{
@@ -15287,9 +15282,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. */
@@ -15306,14 +15301,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);
}
@@ -15333,7 +15328,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)
@@ -15345,9 +15340,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)) ]);
@@ -15355,11 +15350,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(");
@@ -15367,29 +15363,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 ();
}
@@ -15403,13 +15399,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))
{
@@ -18490,7 +18488,7 @@ uses_TOC (void)
rtx
create_TOC_reference (rtx symbol, rtx largetoc_reg)
{
- rtx tocrel, tocreg;
+ rtx tocrel, tocreg, hi;
if (TARGET_DEBUG_ADDR)
{
@@ -18508,24 +18506,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 || can_create_pseudo_p ())
+ 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
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md (revision 187010)
+++ gcc/config/rs6000/predicates.md (working copy)
@@ -824,8 +824,8 @@
;; 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")
+ (match_code "symbol_ref,const,reg,subreg,mem,
+ const_double,const_vector,const_int")
{
/* 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;
@@ -866,14 +865,6 @@
if (register_operand (op, mode))
return 1;
- /* A SYMBOL_REF referring to the TOC is valid. */
- if (legitimate_constant_pool_address_p (op, mode, 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
@@ -886,8 +877,8 @@
;; Return 1 if this operand is a valid input for a vsx_splat insn.
(define_predicate "splat_input_operand"
- (match_code "label_ref,symbol_ref,const,high,reg,subreg,mem,
- const_double,const_vector,const_int,plus")
+ (match_code "symbol_ref,const,reg,subreg,mem,
+ const_double,const_vector,const_int")
{
if (MEM_P (op))
{
@@ -1461,3 +1452,14 @@
&& GET_MODE (XEXP (XVECEXP (op, 0, 0), 0)) == BLKmode
&& XEXP (XVECEXP (op, 0, 0), 1) == const0_rtx);
})
+
+;; Match a small code model toc reference (or medium and large
+;; model toc references before reload).
+(define_predicate "small_toc_ref"
+ (match_code "unspec,plus")
+{
+ if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1)))
+ op = XEXP (op, 0);
+
+ return GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL;
+})
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 187010)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -9261,8 +9261,8 @@
(set_attr "length" "4")])
(define_insn "*movsi_internal1"
- [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
- (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))]
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,*q,*c*l,*h,*h")
+ (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,r,0"))]
"!TARGET_SINGLE_FPU &&
(gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))"
"@
@@ -9273,18 +9273,17 @@
{lil|li} %0,%1
{liu|lis} %0,%v1
#
- {cal|la} %0,%a1
mf%1 %0
mt%0 %1
mt%0 %1
mt%0 %1
{cror 0,0,0|nop}"
- [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*")
- (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")])
+ [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,*,mtjmpr,*,*")
+ (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4")])
(define_insn "*movsi_internal1_single"
- [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h,m,*f")
- (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0,f,m"))]
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,*q,*c*l,*h,*h,m,*f")
+ (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,r,0,f,m"))]
"TARGET_SINGLE_FPU &&
(gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))"
"@
@@ -9295,7 +9294,6 @@
{lil|li} %0,%1
{liu|lis} %0,%v1
#
- {cal|la} %0,%a1
mf%1 %0
mt%0 %1
mt%0 %1
@@ -9303,8 +9301,8 @@
{cror 0,0,0|nop}
stfs%U0%X0 %1, %0
lfs%U1%X1 %0, %1"
- [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*")
- (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4,4")])
+ [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*")
+ (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4")])
;; Split a load of a large constant into the appropriate two-insn
;; sequence.
@@ -9499,8 +9497,8 @@
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,8")])
(define_insn "*movsf_softfloat"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,r,*h")
- (match_operand:SF 1 "input_operand" "r,r,r,h,m,r,I,L,R,G,Fn,0"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,*h")
+ (match_operand:SF 1 "input_operand" "r,r,r,h,m,r,I,L,G,Fn,0"))]
"(gpc_reg_operand (operands[0], SFmode)
|| gpc_reg_operand (operands[1], SFmode))
&& (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
@@ -9513,12 +9511,11 @@
{st%U0%X0|stw%U0%X0} %1,%0
{lil|li} %0,%1
{liu|lis} %0,%v1
- {cal|la} %0,%a1
#
#
{cror 0,0,0|nop}"
- [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*")
- (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")])
+ [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,8,4")])
\f
(define_expand "movdf"
@@ -10146,8 +10143,8 @@
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_insn "*movdi_mfpgpr"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,r,*d")
- (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,*d,r"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*d,*d,m,r,*h,*h,r,*d")
+ (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,d,m,d,*h,r,0,*d,r"))]
"TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -10158,7 +10155,6 @@
li %0,%1
lis %0,%v1
#
- la %0,%a1
fmr %0,%1
lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0
@@ -10167,12 +10163,12 @@
{cror 0,0,0|nop}
mftgpr %0,%1
mffgpr %0,%1"
- [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,mftgpr,mffgpr")
- (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4")])
+ [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,mftgpr,mffgpr")
+ (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")])
(define_insn "*movdi_internal64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,?wa")
- (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,O"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*d,*d,m,r,*h,*h,?wa")
+ (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,d,m,d,*h,r,0,O"))]
"TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS)
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -10183,7 +10179,6 @@
li %0,%1
lis %0,%v1
#
- la %0,%a1
fmr %0,%1
lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0
@@ -10191,8 +10186,8 @@
mt%0 %1
{cror 0,0,0|nop}
xxlxor %x0,%x0,%x0"
- [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,vecsimple")
- (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")])
+ [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,vecsimple")
+ (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
;; immediate value valid for a single instruction hiding in a const_double
(define_insn ""
@@ -11548,10 +11543,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)))]
@@ -11566,11 +11559,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")])
@@ -11685,10 +11677,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)))]
@@ -11703,10 +11693,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")])
@@ -11782,10 +11772,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)))]
@@ -11800,11 +11788,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")])
@@ -11854,10 +11841,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)))]
@@ -11872,11 +11857,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")])
@@ -12233,6 +12217,45 @@
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_high_plus"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
+ (high:DI
+ (plus:DI
+ (unspec [(match_operand:DI 1 "" "")
+ (match_operand:DI 2 "gpc_reg_operand" "b")]
+ UNSPEC_TOCREL)
+ (match_operand 3 "const_int_operand" "n"))))]
+ "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+ "{cau|addis} %0,%2,%1+%3@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")
+
+(define_insn_and_split "*tocref<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b*r")
+ (match_operand:P 1 "small_toc_ref" "R"))]
+ "TARGET_TOC"
+ "{cal|la} %0,%a1"
+ "&& TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL && reload_completed"
+ [(set (match_dup 0) (high:P (match_dup 1)))
+ (set (match_dup 0) (lo_sum:P (match_dup 0) (match_dup 1)))])
+
;; 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
@@ -12251,22 +12274,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}")
\f
;; Call and call_value insns
(define_expand "call"
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h (revision 187010)
+++ gcc/config/rs6000/rs6000-protos.h (working copy)
@@ -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,
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-05-01 4:18 ` Alan Modra
@ 2012-05-16 1:55 ` Alan Modra
2012-05-17 2:56 ` David Edelsohn
1 sibling, 0 replies; 9+ messages in thread
From: Alan Modra @ 2012-05-16 1:55 UTC (permalink / raw)
To: gcc-patches, David Edelsohn
On Tue, May 01, 2012 at 01:47:51PM +0930, Alan Modra wrote:
> This revision splits the medium/large code model toc reference after
> reload.
Ping http://gcc.gnu.org/ml/gcc-patches/2012-05/msg00006.html
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: rs6000 toc reference rtl again
2012-05-01 4:18 ` Alan Modra
2012-05-16 1:55 ` Alan Modra
@ 2012-05-17 2:56 ` David Edelsohn
1 sibling, 0 replies; 9+ messages in thread
From: David Edelsohn @ 2012-05-17 2:56 UTC (permalink / raw)
To: Alan Modra; +Cc: GCC Patches
On Tue, May 1, 2012 at 12:17 AM, Alan Modra <amodra@gmail.com> wrote:
> * config/rs6000/predicates.md (input_operand): Don't match
> constant pool addresses. Remove label_ref, high and plus from
> match_code list. Remove redundant CONSTANT_P test.
> (splat_input_operand): Similarly update match_code list.
> (small_toc_ref): New predicate.
> * config/rs6000/rs6000-protos.h (toc_relative_expr_p): Update prototype.
> * config/rs6000/rs6000.c (tocrel_base, tocrel_offset): Make const.
> (legitimate_constant_pool_address_p): Move TARGET_TOC test and
> register checks to..
> (toc_relative_expr_p): ..here. Add "strict" param. Match new rtl
> generated by create_TOC_reference.
> (rs6000_legitimize_address): Update cerate_TOC_reference call.
> (rs6000_delegitimize_address): Handle new rtl for toc refs.
> (rs6000_cannot_force_const_mem, rs6000_find_base_term): Likewise.
> (use_toc_relative_ref): New function, split out from..
> (rs6000_emit_move): ..here. Remove redundant tests. Update
> create_TOC_reference calls.
> (rs6000_legitimize_reload_address): Formatting. Handle splitting
> of medium/large model toc addresses. Use use_toc_relative_ref.
> (print_operand): Formatting, style. Adjust for toc changes.
> (print_operand_address): Likewise.
> (rs6000_output_addr_const_extra): Likewise.
> (create_TOC_reference): Put TOC_REGISTER in UNSPEC_TOCREL rather
> than a PLUS. Use this formulation for both high and low part
> of -mcmodel=medium/large toc reference too. Before reload,
> always use the small model formulation.
> * config/rs6000/rs6000.md (tls_gd, tls_gd_high): Similarly avoid
> a PLUS in high part of addresses here.
> (tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
> (tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.
> (largetoc_high, largetoc_low): Move earlier. Cope when no
> base reg available.
> (largetoc_high_plus): New insn.
> (movsi_internal1, movsi_internal1_single, movsf_softfloat,
> movdi_mfpgpr, movdi_internal64): Don't handle 'R' constraint here..
> (tocref): ..instead do so here, new insn and split.
Okay.
But please add a comment explaining toc_relative_expr_p(), especially
the meaning of the new strict argument.
And please wait for bootstrap to be unbroken on PPC64.
Thanks, David
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-05-17 2:56 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-27 7:55 rs6000 toc reference rtl again Alan Modra
2012-04-03 17:18 ` David Edelsohn
2012-04-03 18:49 ` Richard Sandiford
2012-04-04 1:04 ` Alan Modra
2012-04-04 9:25 ` Richard Sandiford
2012-04-04 11:14 ` Alan Modra
2012-05-01 4:18 ` Alan Modra
2012-05-16 1:55 ` Alan Modra
2012-05-17 2:56 ` David Edelsohn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).