This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

rs6000 toc reference rtl again


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}")
 
 ;; 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]