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

Reply via email to