Hi,
MIPS does not currently implement a mips_delegitimize_address target hook and
for n64, a RTL is produced which the standard delegitimize cannot handle:
(const:DI (plus:DI (unspec:DI [
(symbol_ref:DI ("s") <var_decl 0x7fe08a5a3140 s>)
] 229)
(const_int 4 [0x4])))
This patch implements a simple mips_delegitimize_address for this and some
related cases.
OK? Bootstrapped and tested on mips64-linux-gnu with no regressions.
Thanks,
Andrew Pinski
ChangeLog:
* config/mips/mips.c (mips_delegitimize_address): New function.
(TARGET_DELEGITIMIZE_ADDRESS): Define.
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c (revision 189746)
+++ tree-pretty-print.c (working copy)
@@ -855,6 +855,7 @@ dump_generic_node (pretty_printer *buffe
&& TREE_TYPE (TREE_OPERAND (node, 0)) != NULL_TREE
/* Same pointer types, but ignoring POINTER_TYPE vs.
REFERENCE_TYPE. */
+ && TREE_TYPE (TREE_OPERAND (node, 0))
&& (TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 0)))
== TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 1))))
&& (TYPE_MODE (TREE_TYPE (TREE_OPERAND (node, 0)))
@@ -1218,6 +1219,7 @@ dump_generic_node (pretty_printer *buffe
|| (TREE_CODE (op0) == MEM_REF
&& TREE_CODE (TREE_OPERAND (op0, 0)) != ADDR_EXPR
&& integer_zerop (TREE_OPERAND (op0, 1))
+ && TREE_TYPE (TREE_OPERAND (op0, 0))
/* Dump the types of INTEGER_CSTs explicitly, for we
can't infer them and MEM_ATTR caching will share
MEM_REFs with differently-typed op0s. */
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c (revision 189746)
+++ config/mips/mips.c (working copy)
@@ -2991,6 +2991,75 @@ mips_legitimize_address (rtx x, rtx oldx
return x;
}
+/* In the name of slightly smaller debug output, and to cater to
+ general assembler lossage, recognize various UNSPEC sequences
+ and turn them back into a direct symbol reference. */
+
+static rtx
+mips_delegitimize_address (rtx orig_x)
+{
+ orig_x = delegitimize_mem_from_attrs (orig_x);
+
+ /* Turn (PLUS:DI (XX)
+ (CONST:DI (UNSPEC:DI [(A)] SYMBOL_64_LOW)))
+ into A. */
+ /* Turn (PLUS:DI (XX)
+ (CONST:DI (PLUS:DI (UNSPEC:DI [(A)] SYMBOL_64_LOW)
(const_int)))
+ into (PLUS:DI A (const_int)). */
+ /* Turn (PLUS:DI (ASHIFT:DI (CONST:DI (UNSPEC:DI [(A)] SYMBOL_64_HIGH)) (32)
)
+ (XX))
+ into A. */
+ /* Turn (PLUS:DI (ASHIFT:DI (CONST:DI (PLUS:DI (UNSPEC:DI [(A)]
SYMBOL_64_HIGH)
+ (const_int))) (32))
+ (XX))
+ into (PLUS:DI A (const_int)). */
+ if (GET_CODE (orig_x) == PLUS)
+ {
+ rtx addon = NULL_RTX;
+ rtx inconst1 = XEXP (orig_x, 1);
+ enum mips_symbol_type type = SYMBOL_64_LOW;
+
+ /* Strip the possible LO_SUM.*/
+ if (GET_CODE (inconst1) == LO_SUM)
+ inconst1 = XEXP (inconst1, 1);
+
+ /* If we don't have a const on the right hand side, see if
+ we have a shift of a const. */
+ if (GET_CODE (inconst1) != CONST
+ && GET_CODE (XEXP (orig_x, 0)) == ASHIFT
+ && XEXP (XEXP (orig_x, 0), 1) == GEN_INT (32))
+ {
+ inconst1 = XEXP (XEXP (orig_x, 0), 0);
+
+ if (GET_CODE (inconst1) == LO_SUM)
+ inconst1 = XEXP (inconst1, 1);
+ type = SYMBOL_64_HIGH;
+ }
+
+ if (GET_CODE (inconst1) != CONST)
+ return orig_x;
+
+ inconst1 = XEXP (inconst1, 0);
+
+ if (GET_CODE (inconst1) == PLUS
+ && CONST_INT_P (XEXP (inconst1, 1)))
+ {
+ addon = XEXP (inconst1, 1);
+ inconst1 = XEXP (inconst1, 0);
+ }
+ if (GET_CODE (inconst1) == UNSPEC
+ && XINT (inconst1, 1) == UNSPEC_ADDRESS_FIRST + type)
+ {
+ rtx symbol = XVECEXP (inconst1, 0, 0);
+ if (addon != NULL_RTX)
+ symbol = simplify_gen_binary (PLUS, GET_MODE (symbol), symbol,
addon);
+ return symbol;
+ }
+ }
+
+ return orig_x;
+}
+
/* Load VALUE into DEST. TEMP is as for mips_force_temporary. */
void
@@ -17447,6 +17516,9 @@ mips_expand_vec_minmax (rtx target, rtx
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS mips_legitimize_address
+#undef TARGET_DELEGITIMIZE_ADDRESS
+#define TARGET_DELEGITIMIZE_ADDRESS mips_delegitimize_address
+
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE