diff mbox

[PATCH/MIPS] Add a delegitimize target hook for MIPS

Message ID E3980B5A0D7C9243AC3486B369A614301875900E@BY2PRD0710MB377.namprd07.prod.outlook.com
State New
Headers show

Commit Message

Andrew Pinski July 21, 2012, 7:25 p.m. UTC
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.

Comments

Richard Sandiford July 22, 2012, 5:23 p.m. UTC | #1
"Pinski, Andrew" <Andrew.Pinski@caviumnetworks.com> writes:
> This patch implements a simple mips_delegitimize_address for this and
> some related cases.

The problem is that these:

> +/* 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)).  */

aren't trustworthy on their own.  The CONSTs are just fragments of
addresses, and while the whole expression would typically reference
A(+CONST_INT), it might instead reference A(+CONST_INT)+SOMETHING,
with the SOMETHING typically being added before the final low part.
We can't tell from looking at the CONST alone whether there's a
non-constant offset or not.

I think this is similar to:

  /* MEMs without MEM_OFFSETs may have been offset, so we can't just
     use their base addresses as equivalent.  */

in the default hook.

Richard
diff mbox

Patch

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