[power7-meissner] Fix spec2006 calculix build error; Move more -mdebug=addr support to separate functions

Michael Meissner meissner@linux.vnet.ibm.com
Sat May 30 00:07:00 GMT 2009


This checkin makes Spec2006 build again for -O3 -fpeel-loops -funroll-loops
-mcpu=power7.  I'm not entirely happy with the fix, as I think the real fix is
to find the place that is rewriting the address in reload and teach it not to
do the substitution inside of a const.

The patch also continues on my last checkin to move the -mdebug=addr output to
a separate function, and make the address support infrastructure closer to the
original code, so that it is easier to compare what the differences are.  I
added more checks to make sure we don't allow invalid addresses for Altivec/VSX
modes that only support reg+reg addressing.

The spec code references static memory.  This is an invalid address for VSX, so
it pushes the address to a separate register, and then creates a TOC entry for
the address.  The address has the note:

	(reg_equal (const:DI (plus:DI (symbol_ref:DI) (const_int))))

to represent where it actually points to, which is expected.  However, inside
of IRA/reload, because (reg+int) addressing is not allowed, this gets changed
to move the int to a register and then to (reg+reg).  However, it also changes
the note to:

	(reg_equal (const:DI (plus:DI (symbol_ref:DI) (reg:DI))))

which is illegal having a register inside of the const.  I fixed this inside of
r6000_emit_move to recognize this, and convert it back to loading the
symbol_ref and then doing the add separately.

-- 
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com
-------------- next part --------------
2009-05-29  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-protos.h
	(rs6000_legitimize_reload_address): Delete, in favor of calling
	function through a pointer.
	(rs6000_mode_dependent_address): Ditto.
	(rs6000_legitimize_reload_address_ptr): Pointer to function, so
	that the -mdebug=address support is not done automatically, and
	the code is closer to the original mainline code.
	(rs6000_mode_dependent_address_ptr): Ditto.

	* config/rs6000/rs6000.c (rs6000_legitimize_reload_address_ptr):
	New pointer for switching to the debug version if -mdebug=addr.
	(rs6000_mode_dependent_address_ptr): Ditto.
	(rs6000_legitimize_reload_address): Move debug stuff to separate
	function.  Make static.  Make closer to the original mainline
	code.
	(rs6000_mode_dependent_address): Ditto.
	(rs6000_debug_legitimize_reload_address): Move debug code here.
	Print more information in the debug code.
	(rs6000_mode_dependent_address): Ditto.
	(rs6000_override_options): Override legitimize reload address and
	mode dependent adress pointers if -mdebug=addr.
	(reg_offset_addressing_ok_p): New function to return true if the
	mode allows reg + integer addresses.
	(rs6000_legitimate_offset_address_p): Move code to say whether a
	mode supports reg+int addressing to reg_offset_addressing_ok_p and
	call it.
	(rs6000_legitimize_address): Test early whether a mode only
	supports reg+reg addressing.  Handle reg+0 addressing which seems
	to fall through.
	(rs6000_legitimate_address_p): Add more checks for modes that only
	can do reg+reg addressing.
	(rs6000_emit_move): Deal with (const (plus (symbol_ref) (reg)))
	addresses that are generated upstream, and convert them into
	loading the SYMBOL_REF from the TOC, and adding the register.
	(rs6000_secondary_memory_needed_rtx): Modify debug output to be
	consistant where the newlines are put out.  Add more debug
	output.
	(rs6000_secondary_reload_inner): Ditto.
	(rs6000_preferred_reload_class): Ditto.
	(create_TOC_reference): Add -mdebug=addr output.
	(output_toc): Add assert to make sure what we think is a CONST_INT
	is indeed a CONST_INT.

	* config/rs6000/rs6000.h (LEGITIMIZE_RELOAD_ADDRESS): Call
	function through a pointer to add -mdebug=addr support.
	(GO_IF_MODE_DEPENDENT_ADDRESS): Ditto.

Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 147959)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -116,10 +116,10 @@ extern rtx create_TOC_reference (rtx);
 extern void rs6000_split_multireg_move (rtx, rtx);
 extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
 extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode);
-extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
-					     int, int, int, int *);
+extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode,
+						    int, int, int, int *);
 extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx, int);
-extern bool rs6000_mode_dependent_address (rtx);
+extern bool (*rs6000_mode_dependent_address_ptr) (rtx);
 extern rtx rs6000_find_base_term (rtx);
 extern bool rs6000_offsettable_memref_p (rtx);
 extern rtx rs6000_return_addr (int, rtx);
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 147959)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -805,6 +805,7 @@ static void rs6000_emit_allocate_stack (
 static unsigned rs6000_hash_constant (rtx);
 static unsigned toc_hash_function (const void *);
 static int toc_hash_eq (const void *, const void *);
+static bool reg_offset_addressing_ok_p (enum machine_mode);
 static bool constant_pool_expr_p (rtx);
 static bool legitimate_small_data_p (enum machine_mode, rtx);
 static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
@@ -1018,6 +1019,21 @@ static rtx rs6000_emit_vector_compare (e
 				       enum machine_mode);
 static tree rs6000_stack_protect_fail (void);
 
+static rtx rs6000_legitimize_reload_address (rtx, enum machine_mode, int, int,
+					     int, int *);
+
+static rtx rs6000_debug_legitimize_reload_address (rtx, enum machine_mode, int,
+						   int, int, int *);
+
+rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode, int, int,
+					     int, int *)
+  = rs6000_legitimize_reload_address;
+
+static bool rs6000_mode_dependent_address (rtx);
+static bool rs6000_debug_mode_dependent_address (rtx);
+bool (*rs6000_mode_dependent_address_ptr) (rtx)
+  = rs6000_mode_dependent_address;
+
 static enum reg_class rs6000_secondary_reload_class (enum reg_class,
 						     enum machine_mode, rtx);
 static enum reg_class rs6000_debug_secondary_reload_class (enum reg_class,
@@ -2294,6 +2310,10 @@ rs6000_override_options (const char *def
 	    = rs6000_debug_cannot_change_mode_class;
 	  rs6000_preferred_reload_class_ptr
 	    = rs6000_debug_preferred_reload_class;
+	  rs6000_legitimize_reload_address_ptr
+	    = rs6000_debug_legitimize_reload_address;
+	  rs6000_mode_dependent_address_ptr
+	    = rs6000_debug_mode_dependent_address;
 	}
     }
 
@@ -4332,6 +4352,38 @@ gpr_or_gpr_p (rtx op0, rtx op1)
 /* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address_p.  */
 
 static bool
+reg_offset_addressing_ok_p (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case V16QImode:
+    case V8HImode:
+    case V4SFmode:
+    case V4SImode:
+    case V2DFmode:
+    case V2DImode:
+      /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid.  */
+      if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
+	return false;
+      break;
+
+    case V4HImode:
+    case V2SImode:
+    case V1DImode:
+    case V2SFmode:
+       /* Paired vector modes.  Only reg+reg addressing is valid.  */
+      if (TARGET_PAIRED_FLOAT)
+        return false;
+      break;
+
+    default:
+      break;
+    }
+
+  return true;
+}
+
+static bool
 constant_pool_expr_p (rtx op)
 {
   rtx base, offset;
@@ -4388,35 +4440,23 @@ rs6000_legitimate_offset_address_p (enum
     return false;
   if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
     return false;
+  if (!reg_offset_addressing_ok_p (mode))
+    return false;
   if (legitimate_constant_pool_address_p (x))
     return true;
   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
     return false;
+  if (!reg_offset_addressing_ok_p (mode))
+    return false;
 
   offset = INTVAL (XEXP (x, 1));
   extra = 0;
   switch (mode)
     {
-    case V16QImode:
-    case V8HImode:
-    case V4SFmode:
-    case V4SImode:
-    case V2DFmode:
-    case V2DImode:
-      /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid and
-	 constant offset zero should not occur due to canonicalization.  */
-      if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
-	return false;
-      break;
-
     case V4HImode:
     case V2SImode:
     case V1DImode:
     case V2SFmode:
-       /* Paired vector modes.  Only reg+reg addressing is valid and
-	  constant offset zero should not occur due to canonicalization.  */
-      if (TARGET_PAIRED_FLOAT)
-        return false;
       /* SPE vector modes.  */
       return SPE_CONST_OFFSET_OK (offset);
 
@@ -4589,23 +4629,27 @@ static rtx
 rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
 			   enum machine_mode mode)
 {
-  if (GET_CODE (x) == SYMBOL_REF)
+  if (!reg_offset_addressing_ok_p (mode))
     {
-      enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
-      if (model != 0)
-	return rs6000_legitimize_tls_address (x, model);
-    }
+      /* In theory we should not be seeing addresses of the form reg+0,
+	 but just in case it is generated, optimize it away.  */
+      if (GET_CODE (x) == PLUS && XEXP (x, 1) == const0_rtx)
+	return force_reg (Pmode, XEXP (x, 0));
 
-  if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
-    {
       /* Make sure both operands are registers.  */
-      if (GET_CODE (x) == PLUS)
+      else if (GET_CODE (x) == PLUS)
 	return gen_rtx_PLUS (Pmode,
 			     force_reg (Pmode, XEXP (x, 0)),
 			     force_reg (Pmode, XEXP (x, 1)));
       else
 	return force_reg (Pmode, x);
     }
+  if (GET_CODE (x) == SYMBOL_REF)
+    {
+      enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
+      if (model != 0)
+	return rs6000_legitimize_tls_address (x, model);
+    }
   if (GET_CODE (x) == PLUS
       && GET_CODE (XEXP (x, 0)) == REG
       && GET_CODE (XEXP (x, 1)) == CONST_INT
@@ -4728,21 +4772,48 @@ rs6000_legitimize_address (rtx x, rtx ol
 static rtx
 rs6000_debug_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
 {
-  rtx ret = rs6000_legitimize_address (x, oldx, mode);
+  rtx ret;
+  rtx insns;
 
-  fprintf (stderr,
-	   "\nrs6000_legitimize_address: mode %s, original addr:\n",
-	   GET_MODE_NAME (mode));
+  start_sequence ();
+  ret = rs6000_legitimize_address (x, oldx, mode);
+  insns = get_insns ();
+  end_sequence ();
 
-  debug_rtx (x);
   if (ret != x)
     {
-      fprintf (stderr, "New addr:\n");
+      fprintf (stderr,
+	       "\nrs6000_legitimize_address: mode %s, old code %s, "
+	       "new code %s, modified\n",
+	       GET_MODE_NAME (mode), GET_RTX_NAME (GET_CODE (x)),
+	       GET_RTX_NAME (GET_CODE (ret)));
+
+      fprintf (stderr, "Original address:\n");
+      debug_rtx (x);
+
+      fprintf (stderr, "oldx:\n");
+      debug_rtx (oldx);
+
+      fprintf (stderr, "New address:\n");
       debug_rtx (ret);
-      fprintf (stderr, "\n");
+
+      if (insns)
+	{
+	  fprintf (stderr, "Insns added:\n");
+	  debug_rtx_list (insns, 20);
+	}
     }
   else
-    fprintf (stderr, "no change to the address\n\n");
+    {
+      fprintf (stderr,
+	       "\nrs6000_legitimize_address: mode %s, code %s, no change:\n",
+	       GET_MODE_NAME (mode), GET_RTX_NAME (GET_CODE (x)));
+
+      debug_rtx (x);
+    }
+
+  if (insns)
+    emit_insn (insns);
 
   return ret;
 }
@@ -5021,13 +5092,12 @@ rs6000_tls_symbol_ref_1 (rtx *x, void *d
    A movsf_low is generated so we wind up with 2 instructions rather than 3.
    The Darwin code is inside #if TARGET_MACHO because only then are the
    machopic_* functions defined.  */
-rtx
+static rtx
 rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
 				  int opnum, int type,
 				  int ind_levels ATTRIBUTE_UNUSED, int *win)
 {
-  rtx orig_x = x;
-  rtx ret = NULL_RTX;
+  bool reg_offset_p = reg_offset_addressing_ok_p (mode);
 
   /* We must recognize output that we have already generated ourselves.  */
   if (GET_CODE (x) == PLUS
@@ -5040,17 +5110,17 @@ rs6000_legitimize_reload_address (rtx x,
 		   BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
 		   opnum, (enum reload_type)type);
       *win = 1;
-      ret = x;
+      return x;
     }
 
 #if TARGET_MACHO
-  else if (DEFAULT_ABI == ABI_DARWIN && flag_pic
-	   && GET_CODE (x) == LO_SUM
-	   && GET_CODE (XEXP (x, 0)) == PLUS
-	   && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
-	   && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
-	   && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
-	   && machopic_operand_p (XEXP (x, 1)))
+  if (DEFAULT_ABI == ABI_DARWIN && flag_pic
+      && GET_CODE (x) == LO_SUM
+      && GET_CODE (XEXP (x, 0)) == PLUS
+      && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
+      && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
+      && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
+      && machopic_operand_p (XEXP (x, 1)))
     {
       /* Result of previous invocation of this function on Darwin
 	 floating point constant.  */
@@ -5058,40 +5128,42 @@ rs6000_legitimize_reload_address (rtx x,
 		   BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
 		   opnum, (enum reload_type)type);
       *win = 1;
-      ret = x;
+      return x;
     }
 #endif
 
   /* Force ld/std non-word aligned offset into base register by wrapping
      in offset 0.  */
-  else if (GET_CODE (x) == PLUS
-	   && GET_CODE (XEXP (x, 0)) == REG
-	   && REGNO (XEXP (x, 0)) < 32
-	   && INT_REG_OK_FOR_BASE_P (XEXP (x, 0), 1)
-	   && GET_CODE (XEXP (x, 1)) == CONST_INT
-	   && (INTVAL (XEXP (x, 1)) & 3) != 0
-	   && VECTOR_MEM_NONE_P (mode)
-	   && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
-	   && TARGET_POWERPC64)
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 0)) == REG
+      && REGNO (XEXP (x, 0)) < 32
+      && INT_REG_OK_FOR_BASE_P (XEXP (x, 0), 1)
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && reg_offset_p
+      && (INTVAL (XEXP (x, 1)) & 3) != 0
+      && VECTOR_MEM_NONE_P (mode)
+      && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
+      && TARGET_POWERPC64)
     {
       x = gen_rtx_PLUS (GET_MODE (x), x, GEN_INT (0));
       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);
       *win = 1;
-      ret = x;
+      return x;
     }
 
-  else if (GET_CODE (x) == PLUS
-	   && GET_CODE (XEXP (x, 0)) == REG
-	   && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
-	   && INT_REG_OK_FOR_BASE_P (XEXP (x, 0), 1)
-	   && GET_CODE (XEXP (x, 1)) == CONST_INT
-	   && !SPE_VECTOR_MODE (mode)
-	   && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-				       || mode == DDmode || mode == TDmode
-				       || mode == DImode))
-	   && VECTOR_MEM_NONE_P (mode))
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 0)) == REG
+      && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
+      && INT_REG_OK_FOR_BASE_P (XEXP (x, 0), 1)
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && reg_offset_p
+      && !SPE_VECTOR_MODE (mode)
+      && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+				  || mode == DDmode || mode == TDmode
+				  || mode == DImode))
+      && VECTOR_MEM_NONE_P (mode))
     {
       HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
       HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
@@ -5102,45 +5174,43 @@ rs6000_legitimize_reload_address (rtx x,
       if (high + low != val)
 	{
 	  *win = 0;
-	  ret = x;
+	  return x;
 	}
-      else
-	{
-	  /* Reload the high part into a base reg; leave the low part
-	     in the mem directly.  */
 
-	  x = gen_rtx_PLUS (GET_MODE (x),
-			    gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
-					  GEN_INT (high)),
-			    GEN_INT (low));
+      /* Reload the high part into a base reg; leave the low part
+	 in the mem directly.  */
 
-	  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);
-	  *win = 1;
-	  return x;
-	}
+      x = gen_rtx_PLUS (GET_MODE (x),
+			gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+				      GEN_INT (high)),
+			GEN_INT (low));
+
+      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);
+      *win = 1;
+      return x;
     }
 
-  else if (GET_CODE (x) == SYMBOL_REF
-	   && VECTOR_MEM_NONE_P (mode)
-	   && (!TARGET_SPE || !SPE_VECTOR_MODE (mode))
+  if (GET_CODE (x) == SYMBOL_REF
+      && reg_offset_p
+      && VECTOR_MEM_NONE_P (mode)
+      && !SPE_VECTOR_MODE (mode)
 #if TARGET_MACHO
-	   && DEFAULT_ABI == ABI_DARWIN
-	   && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
+      && DEFAULT_ABI == ABI_DARWIN
+      && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
 #else
-	   && DEFAULT_ABI == ABI_V4
-	   && !flag_pic
+      && DEFAULT_ABI == ABI_V4
+      && !flag_pic
 #endif
-	   /* Don't do this for TFmode or TDmode, since the result isn't
-	      offsettable.  The same goes for DImode without 64-bit gprs and
-	      DFmode and DDmode without fprs.  */
-	   && VECTOR_MEM_NONE_P (mode)
-	   && mode != TFmode
-	   && mode != TDmode
-	   && (mode != DImode || TARGET_POWERPC64)
-	   && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
-	       || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
+      /* Don't do this for TFmode or TDmode, since the result isn't offsettable.
+	 The same goes for DImode without 64-bit gprs and DFmode and DDmode
+	 without fprs.  */
+      && mode != TFmode
+      && mode != TDmode
+      && (mode != DImode || TARGET_POWERPC64)
+      && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
+	  || (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)))
     {
 #if TARGET_MACHO
       if (flag_pic)
@@ -5159,7 +5229,7 @@ rs6000_legitimize_reload_address (rtx x,
 		   BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
 		   opnum, (enum reload_type)type);
       *win = 1;
-      ret = x;
+      return x;
     }
 
   /* Reload an offset address wrapped by an AND that represents the
@@ -5168,54 +5238,55 @@ rs6000_legitimize_reload_address (rtx x,
      force reload to create the address with an AND in a separate
      register, because we can't guarantee an altivec register will
      be used.  */
-  else if (VECTOR_MEM_ALTIVEC_P (mode)
-	   && GET_CODE (x) == AND
-	   && GET_CODE (XEXP (x, 0)) == PLUS
-	   && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
-	   && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-	   && GET_CODE (XEXP (x, 1)) == CONST_INT
-	   && INTVAL (XEXP (x, 1)) == -16)
+  if (VECTOR_MEM_ALTIVEC_P (mode)
+      && GET_CODE (x) == AND
+      && GET_CODE (XEXP (x, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && INTVAL (XEXP (x, 1)) == -16)
     {
       x = XEXP (x, 0);
       *win = 1;
-      ret = x;
+      return x;
     }
 
-  else if (TARGET_TOC
-	   && GET_CODE (x) == SYMBOL_REF
-	   && constant_pool_expr_p (x)
-	   && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
+  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))
     {
       x = create_TOC_reference (x);
       *win = 1;
-      ret = x;
+      return x;
     }
+  *win = 0;
+  return x;
+}
 
-  else
-    {
-      *win = 0;
-      ret = x;
-    }
+/* Debug version of rs6000_legitimize_reload_address.  */
+static rtx
+rs6000_debug_legitimize_reload_address (rtx x, enum machine_mode mode,
+					int opnum, int type,
+					int ind_levels, int *win)
+{
+  rtx ret = rs6000_legitimize_reload_address (x, mode, opnum, type,
+					      ind_levels, win);
+  fprintf (stderr,
+	   "\nrs6000_legitimize_reload_address: mode = %s, opnum = %d, "
+	   "type = %d, ind_levels = %d, win = %d, original addr:\n",
+	   GET_MODE_NAME (mode), opnum, type, ind_levels, *win);
+  debug_rtx (x);
 
-  if (TARGET_DEBUG_ADDR)
+  if (x == ret)
+    fprintf (stderr, "Same address returned\n");
+  else if (!ret)
+    fprintf (stderr, "NULL returned\n");
+  else
     {
-      fprintf (stderr,
-	       "\nrs6000_legitimize_reload_address: mode = %s, opnum = %d, "
-	       "type = %d, ind_levels = %d, win = %d, original addr:\n",
-	       GET_MODE_NAME (mode), opnum, type, ind_levels, *win);
-      debug_rtx (orig_x);
-
-      if (orig_x == ret)
-	fprintf (stderr, "Same address returned\n");
-      else if (!ret)
-	fprintf (stderr, "NULL returned\n");
-      else
-	{
-	  fprintf (stderr, "New address:\n");
-	  debug_rtx (ret);
-	}
-
-      fprintf (stderr, "\n");
+      fprintf (stderr, "New address:\n");
+      debug_rtx (ret);
     }
 
   return ret;
@@ -5241,6 +5312,8 @@ rs6000_legitimize_reload_address (rtx x,
 bool
 rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
 {
+  bool reg_offset_p = reg_offset_addressing_ok_p (mode);
+
   /* If this is an unaligned stvx/ldvx type address, discard the outer AND.  */
   if (VECTOR_MEM_ALTIVEC_P (mode)
       && GET_CODE (x) == AND
@@ -5263,12 +5336,13 @@ rs6000_legitimate_address_p (enum machin
       && TARGET_UPDATE
       && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
     return 1;
-  if (legitimate_small_data_p (mode, x))
+  if (reg_offset_p && legitimate_small_data_p (mode, x))
     return 1;
-  if (legitimate_constant_pool_address_p (x))
+  if (reg_offset_p && legitimate_constant_pool_address_p (x))
     return 1;
   /* If not REG_OK_STRICT (before reload) let pass any stack offset.  */
   if (! reg_ok_strict
+      && reg_offset_p
       && GET_CODE (x) == PLUS
       && GET_CODE (XEXP (x, 0)) == REG
       && (XEXP (x, 0) == virtual_stack_vars_rtx
@@ -5314,7 +5388,7 @@ rs6000_legitimate_address_p (enum machin
 	      && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
       && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
     return 1;
-  if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
+  if (reg_offset_p && legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
     return 1;
   return 0;
 }
@@ -5327,12 +5401,13 @@ rs6000_debug_legitimate_address_p (enum 
   bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
   fprintf (stderr,
 	   "\nrs6000_legitimate_address_p: return = %s, mode = %s, "
-	   "strict = %d\n",
+	   "strict = %d, code = %s\n",
 	   ret ? "true" : "false",
 	   GET_MODE_NAME (mode),
-	   reg_ok_strict);
+	   reg_ok_strict,
+	   GET_RTX_NAME (GET_CODE (x)));
   debug_rtx (x);
-  fprintf (stderr, "\n");
+
   return ret;
 }
 
@@ -5340,54 +5415,53 @@ rs6000_debug_legitimate_address_p (enum 
    has an effect that depends on the machine mode it is used for.
 
    On the RS/6000 this is true of all integral offsets (since AltiVec
-   modes don't allow them) or is a pre-increment or decrement.
+   and VSX modes don't allow them) or is a pre-increment or decrement.
 
    ??? Except that due to conceptual problems in offsettable_address_p
    we can't really report the problems of integral offsets.  So leave
    this assuming that the adjustable offset must be valid for the
    sub-words of a TFmode operand, which is what we had before.  */
 
-bool
+static bool
 rs6000_mode_dependent_address (rtx addr)
 {
-  bool ret = false;
-
   switch (GET_CODE (addr))
     {
     case PLUS:
       if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
 	{
 	  unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
-	  ret = (val + 12 + 0x8000 >= 0x10000);
+	  return val + 12 + 0x8000 >= 0x10000;
 	}
       break;
 
     case LO_SUM:
-      ret = true;
-      break;
+      return true;
 
     /* Auto-increment cases are now treated generically in recog.c.  */
     case PRE_MODIFY:
-      ret = (TARGET_UPDATE != 0);
-      break;
+      return TARGET_UPDATE;
 
-      /* AND is only allowed in Altivec loads.  */
+    /* AND is only allowed in Altivec loads.  */
     case AND:
-      ret = true;
-      break;
+      return true;
 
     default:
       break;
     }
 
-  if (TARGET_DEBUG_ADDR)
-    {
-      fprintf (stderr,
-	       "\nrs6000_mode_dependent_address: ret = %s\n",
-	       ret ? "true" : "false");
-      debug_rtx (addr);
-      fprintf (stderr, "\n");
-    }
+  return false;
+}
+
+/* Debug version of rs6000_mode_dependent_address.  */
+static bool
+rs6000_debug_mode_dependent_address (rtx addr)
+{
+  bool ret = rs6000_mode_dependent_address (addr);
+
+  fprintf (stderr, "\nrs6000_mode_dependent_address: ret = %s\n",
+	   ret ? "true" : "false");
+  debug_rtx (addr);
 
   return ret;
 }
@@ -5782,6 +5856,32 @@ rs6000_emit_move (rtx dest, rtx source, 
       return;
     }
 
+  /* Fix up invalid (const (plus (symbol_ref) (reg))) that seems to be created
+     in the secondary_reload phase, which evidently overwrites the CONST_INT
+     with a register.  */
+  if (GET_CODE (source) == CONST && GET_CODE (XEXP (source, 0)) == PLUS
+      && mode == Pmode)
+    {
+      rtx add_op0 = XEXP (XEXP (source, 0), 0);
+      rtx add_op1 = XEXP (XEXP (source, 0), 1);
+
+      if (GET_CODE (add_op0) == SYMBOL_REF && GET_CODE (add_op1) == REG)
+	{
+	  rtx tmp = (can_create_pseudo_p ()) ? gen_reg_rtx (Pmode) : dest;
+
+	  if (TARGET_DEBUG_ADDR)
+	    {
+	      fprintf (stderr, "\nrs6000_emit_move: bad source\n");
+	      debug_rtx (source);
+	    }
+
+	  rs6000_emit_move (tmp, add_op0, Pmode);
+	  emit_insn (gen_rtx_SET (VOIDmode, dest,
+				  gen_rtx_PLUS (Pmode, tmp, add_op1)));
+	  return;
+	}
+    }
+
   if (can_create_pseudo_p () && GET_CODE (operands[0]) == MEM
       && !gpc_reg_operand (operands[1], mode))
     operands[1] = force_reg (mode, operands[1]);
@@ -12600,13 +12700,12 @@ rs6000_secondary_memory_needed_rtx (enum
 
   if (TARGET_DEBUG_ADDR)
     {
-      fprintf (stderr, "rs6000_secondary_memory_needed_rtx, mode %s, rtx:\n",
+      fprintf (stderr, "\nrs6000_secondary_memory_needed_rtx, mode %s, rtx:\n",
 	       GET_MODE_NAME (mode));
       if (!ret)
 	fprintf (stderr, "\tNULL_RTX\n");
       else
 	debug_rtx (ret);
-      fprintf (stderr, "\n");
     }
 
   return ret;
@@ -12787,7 +12886,7 @@ rs6000_secondary_reload (bool in_p,
   if (TARGET_DEBUG_ADDR)
     {
       fprintf (stderr,
-	       "rs6000_secondary_reload, return %s, in_p = %s, rclass = %s, "
+	       "\nrs6000_secondary_reload, return %s, in_p = %s, rclass = %s, "
 	       "mode = %s",
 	       reg_class_names[ret],
 	       in_p ? "true" : "false",
@@ -12804,7 +12903,6 @@ rs6000_secondary_reload (bool in_p,
 	fprintf (stderr, "\n");
 
       debug_rtx (x);
-      fprintf (stderr, "\n");
     }
 
   return ret;
@@ -12829,7 +12927,7 @@ rs6000_secondary_reload_inner (rtx reg, 
 
   if (TARGET_DEBUG_ADDR)
     {
-      fprintf (stderr, "rs6000_secondary_reload_inner, type = %s\n",
+      fprintf (stderr, "\nrs6000_secondary_reload_inner, type = %s\n",
 	       store_p ? "store" : "load");
       fprintf (stderr, "reg:\n");
       debug_rtx (reg);
@@ -12837,7 +12935,6 @@ rs6000_secondary_reload_inner (rtx reg, 
       debug_rtx (mem);
       fprintf (stderr, "scratch:\n");
       debug_rtx (scratch);
-      fprintf (stderr, "\n");
     }
 
   gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
@@ -12877,6 +12974,14 @@ rs6000_secondary_reload_inner (rtx reg, 
 	      && (GET_CODE (addr_op2) != CONST_INT
 		  || !satisfies_constraint_I (addr_op2)))
 	    {
+	      if (TARGET_DEBUG_ADDR)
+		{
+		  fprintf (stderr,
+			   "\nMove plus addr to register %s, mode = %s: ",
+			   rs6000_reg_names[REGNO (scratch)],
+			   GET_MODE_NAME (mode));
+		  debug_rtx (addr_op2);
+		}
 	      rs6000_emit_move (scratch, addr_op2, Pmode);
 	      addr_op2 = scratch;
 	    }
@@ -12893,6 +12998,13 @@ rs6000_secondary_reload_inner (rtx reg, 
       else if (!legitimate_indirect_address_p (addr, false)
 	       && !rs6000_legitimate_offset_address_p (TImode, addr, false))
 	{
+	  if (TARGET_DEBUG_ADDR)
+	    {
+	      fprintf (stderr, "\nMove addr to register %s, mode = %s: ",
+		       rs6000_reg_names[REGNO (scratch_or_premodify)],
+		       GET_MODE_NAME (mode));
+	      debug_rtx (addr);
+	    }
 	  rs6000_emit_move (scratch_or_premodify, addr, Pmode);
 	  addr = scratch_or_premodify;
 	  scratch_or_premodify = scratch;
@@ -12952,6 +13064,12 @@ rs6000_secondary_reload_inner (rtx reg, 
 	  addr_op2 = XEXP (addr, 1);
 	  gcc_assert (REG_P (addr_op1));
 
+	  if (TARGET_DEBUG_ADDR)
+	    {
+	      fprintf (stderr, "\nMove plus addr to register %s, mode = %s: ",
+		       rs6000_reg_names[REGNO (scratch)], GET_MODE_NAME (mode));
+	      debug_rtx (addr_op2);
+	    }
 	  rs6000_emit_move (scratch, addr_op2, Pmode);
 	  emit_insn (gen_rtx_SET (VOIDmode,
 				  scratch_or_premodify,
@@ -12965,6 +13083,14 @@ rs6000_secondary_reload_inner (rtx reg, 
       else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
 	       || GET_CODE (addr) == CONST_INT || REG_P (addr))
 	{
+	  if (TARGET_DEBUG_ADDR)
+	    {
+	      fprintf (stderr, "\nMove addr to register %s, mode = %s: ",
+		       rs6000_reg_names[REGNO (scratch_or_premodify)],
+		       GET_MODE_NAME (mode));
+	      debug_rtx (addr);
+	    }
+
 	  rs6000_emit_move (scratch_or_premodify, addr, Pmode);
 	  addr = scratch_or_premodify;
 	  scratch_or_premodify = scratch;
@@ -13001,6 +13127,13 @@ rs6000_secondary_reload_inner (rtx reg, 
 	  addr = scratch;
 	}
 
+      if (TARGET_DEBUG_ADDR)
+	{
+	  fprintf (stderr, "\nAnd addr to register %s, mode = %s: ",
+		   rs6000_reg_names[REGNO (scratch)], GET_MODE_NAME (mode));
+	  debug_rtx (and_op2);
+	}
+
       and_rtx = gen_rtx_SET (VOIDmode,
 			     scratch,
 			     gen_rtx_AND (Pmode,
@@ -13018,7 +13151,7 @@ rs6000_secondary_reload_inner (rtx reg, 
     {
       mem = change_address (mem, mode, addr);
       if (TARGET_DEBUG_ADDR)
-	fprintf (stderr, "rs6000_secondary_reload_inner, mem adjusted.\n");
+	fprintf (stderr, "\nrs6000_secondary_reload_inner, mem adjusted.\n");
     }
 
   /* Now create the move.  */
@@ -13176,12 +13309,11 @@ rs6000_debug_preferred_reload_class (rtx
   enum reg_class ret = rs6000_preferred_reload_class (x, rclass);
 
   fprintf (stderr,
-	   "rs6000_preferred_reload_class, return %s, rclass = %s, "
+	   "\nrs6000_preferred_reload_class, return %s, rclass = %s, "
 	   "mode = %s, x:\n",
 	   reg_class_names[ret], reg_class_names[rclass],
 	   GET_MODE_NAME (GET_MODE (x)));
   debug_rtx (x);
-  fprintf (stderr, "\n");
 
   return ret;
 }
@@ -13340,12 +13472,11 @@ rs6000_debug_secondary_reload_class (enu
 {
   enum reg_class ret = rs6000_secondary_reload_class (rclass, mode, in);
   fprintf (stderr,
-	   "rs6000_secondary_reload_class, return %s, rclass = %s, "
+	   "\nrs6000_secondary_reload_class, return %s, rclass = %s, "
 	   "mode = %s, input rtx:\n",
 	   reg_class_names[ret], reg_class_names[rclass],
 	   GET_MODE_NAME (mode));
   debug_rtx (in);
-  fprintf (stderr, "\n");
 
   return ret;
 }
@@ -17182,6 +17313,19 @@ uses_TOC (void)
 rtx
 create_TOC_reference (rtx symbol)
 {
+  if (TARGET_DEBUG_ADDR)
+    {
+      if (GET_CODE (symbol) == SYMBOL_REF)
+	fprintf (stderr, "\ncreate_TOC_reference, (symbol_ref %s)\n",
+		 XSTR (symbol, 0));
+      else
+	{
+	  fprintf (stderr, "\ncreate_TOC_reference, code %s:\n",
+		   GET_RTX_NAME (GET_CODE (symbol)));
+	  debug_rtx (symbol);
+	}
+    }
+
   if (!can_create_pseudo_p ())
     df_set_regs_ever_live (TOC_REGISTER, true);
   return gen_rtx_PLUS (Pmode,
@@ -20049,7 +20193,8 @@ output_toc (FILE *file, rtx x, int label
 
   if (GET_CODE (x) == CONST)
     {
-      gcc_assert (GET_CODE (XEXP (x, 0)) == PLUS);
+      gcc_assert (GET_CODE (XEXP (x, 0)) == PLUS
+		  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT);
 
       base = XEXP (XEXP (x, 0), 0);
       offset = INTVAL (XEXP (XEXP (x, 0), 1));
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 147959)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1880,7 +1880,7 @@ typedef struct rs6000_args
 #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)	     \
 do {									     \
   int win;								     \
-  (X) = rs6000_legitimize_reload_address ((X), (MODE), (OPNUM),		     \
+  (X) = rs6000_legitimize_reload_address_ptr ((X), (MODE), (OPNUM),	     \
 			(int)(TYPE), (IND_LEVELS), &win);		     \
   if ( win )								     \
     goto WIN;								     \
@@ -1891,7 +1891,7 @@ do {									     \
 
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)		\
 do {								\
-  if (rs6000_mode_dependent_address (ADDR))			\
+  if (rs6000_mode_dependent_address_ptr (ADDR))			\
     goto LABEL;							\
 } while (0)
 


More information about the Gcc-patches mailing list