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