public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* [cft] subreg validation round 2
@ 2004-11-17 18:58 Richard Henderson
  2004-11-17 19:20 ` Bob Wilson
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Richard Henderson @ 2004-11-17 18:58 UTC (permalink / raw)
  To: gcc

This passes on i686, alpha, ia64, powerpc linux, and sparc-solaris.
Given Ulrich's previous testing, it *ought* to pass on s390.  Any
other takers before I check it in and have to pick up pieces after
the fact?


r~



Index: caller-save.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/caller-save.c,v
retrieving revision 1.69
diff -u -p -r1.69 caller-save.c
--- caller-save.c	4 Nov 2004 08:40:56 -0000	1.69
+++ caller-save.c	15 Nov 2004 20:38:43 -0000
@@ -500,8 +500,7 @@ mark_set_regs (rtx reg, rtx setter ATTRI
       rtx inner = SUBREG_REG (reg);
       if (!REG_P (inner) || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
 	return;
-
-      regno = subreg_hard_regno (reg, 1);
+      regno = subreg_regno (reg);
     }
   else if (REG_P (reg)
 	   && REGNO (reg) < FIRST_PSEUDO_REGISTER)
Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.460
diff -u -p -r1.460 combine.c
--- combine.c	22 Oct 2004 17:05:03 -0000	1.460
+++ combine.c	15 Nov 2004 20:38:43 -0000
@@ -9308,16 +9308,18 @@ recog_for_combine (rtx *pnewpat, rtx ins
    An insn containing that will not be recognized.  */
 
 static rtx
-gen_lowpart_for_combine (enum machine_mode mode, rtx x)
+gen_lowpart_for_combine (enum machine_mode omode, rtx x)
 {
+  enum machine_mode imode = GET_MODE (x);
+  unsigned int osize = GET_MODE_SIZE (omode);
+  unsigned int isize = GET_MODE_SIZE (imode);
   rtx result;
 
-  if (GET_MODE (x) == mode)
+  if (omode == imode)
     return x;
 
-  /* Return identity if this is a CONST or symbolic
-     reference.  */
-  if (mode == Pmode
+  /* Return identity if this is a CONST or symbolic reference.  */
+  if (omode == Pmode
       && (GET_CODE (x) == CONST
 	  || GET_CODE (x) == SYMBOL_REF
 	  || GET_CODE (x) == LABEL_REF))
@@ -9325,13 +9327,12 @@ gen_lowpart_for_combine (enum machine_mo
 
   /* We can only support MODE being wider than a word if X is a
      constant integer or has a mode the same size.  */
-
-  if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
-      && ! ((GET_MODE (x) == VOIDmode
+  if (GET_MODE_SIZE (omode) > UNITS_PER_WORD
+      && ! ((imode == VOIDmode
 	     && (GET_CODE (x) == CONST_INT
 		 || GET_CODE (x) == CONST_DOUBLE))
-	    || GET_MODE_SIZE (GET_MODE (x)) == GET_MODE_SIZE (mode)))
-    return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
+	    || isize == osize))
+    goto fail;
 
   /* X might be a paradoxical (subreg (mem)).  In that case, gen_lowpart
      won't know what to do.  So we will strip off the SUBREG here and
@@ -9339,11 +9340,12 @@ gen_lowpart_for_combine (enum machine_mo
   if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x)))
     {
       x = SUBREG_REG (x);
-      if (GET_MODE (x) == mode)
+      if (GET_MODE (x) == omode)
 	return x;
     }
 
-  result = gen_lowpart_common (mode, x);
+  result = gen_lowpart_common (omode, x);
+
 #ifdef CANNOT_CHANGE_MODE_CLASS
   if (result != 0 && GET_CODE (result) == SUBREG)
     record_subregs_of_mode (result);
@@ -9359,33 +9361,28 @@ gen_lowpart_for_combine (enum machine_mo
       /* Refuse to work on a volatile memory ref or one with a mode-dependent
 	 address.  */
       if (MEM_VOLATILE_P (x) || mode_dependent_address_p (XEXP (x, 0)))
-	return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
+	goto fail;
 
       /* If we want to refer to something bigger than the original memref,
 	 generate a paradoxical subreg instead.  That will force a reload
 	 of the original memref X.  */
-      if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
-	return gen_rtx_SUBREG (mode, x, 0);
+      if (isize < osize)
+	return gen_rtx_SUBREG (omode, x, 0);
 
       if (WORDS_BIG_ENDIAN)
-	offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
-		  - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
+	offset = MAX (isize, UNITS_PER_WORD) - MAX (osize, UNITS_PER_WORD);
 
+      /* Adjust the address so that the address-after-the-data is unchanged. */
       if (BYTES_BIG_ENDIAN)
-	{
-	  /* Adjust the address so that the address-after-the-data is
-	     unchanged.  */
-	  offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
-		     - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
-	}
+	offset -= MIN (UNITS_PER_WORD, osize) - MIN (UNITS_PER_WORD, isize);
 
-      return adjust_address_nv (x, mode, offset);
+      return adjust_address_nv (x, omode, offset);
     }
 
   /* If X is a comparison operator, rewrite it in a new mode.  This
      probably won't match, but may allow further simplifications.  */
   else if (COMPARISON_P (x))
-    return gen_rtx_fmt_ee (GET_CODE (x), mode, XEXP (x, 0), XEXP (x, 1));
+    return gen_rtx_fmt_ee (GET_CODE (x), omode, XEXP (x, 0), XEXP (x, 1));
 
   /* If we couldn't simplify X any other way, just enclose it in a
      SUBREG.  Normally, this SUBREG won't match, but some patterns may
@@ -9394,21 +9391,22 @@ gen_lowpart_for_combine (enum machine_mo
     {
       int offset = 0;
       rtx res;
-      enum machine_mode sub_mode = GET_MODE (x);
 
-      offset = subreg_lowpart_offset (mode, sub_mode);
-      if (sub_mode == VOIDmode)
+      offset = subreg_lowpart_offset (omode, imode);
+      if (imode == VOIDmode)
 	{
-	  sub_mode = int_mode_for_mode (mode);
-	  x = gen_lowpart_common (sub_mode, x);
-	  if (x == 0)
-	    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
+	  imode = int_mode_for_mode (omode);
+	  x = gen_lowpart_common (imode, x);
+	  if (x == NULL)
+	    goto fail;
 	}
-      res = simplify_gen_subreg (mode, x, sub_mode, offset);
+      res = simplify_gen_subreg (omode, x, imode, offset);
       if (res)
 	return res;
-      return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
     }
+
+ fail:
+  return gen_rtx_CLOBBER (imode, const0_rtx);
 }
 \f
 /* These routines make binary and unary operations by first seeing if they
Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.322
diff -u -p -r1.322 cse.c
--- cse.c	13 Nov 2004 17:11:02 -0000	1.322
+++ cse.c	15 Nov 2004 20:38:43 -0000
@@ -4327,6 +4327,18 @@ record_jump_equiv (rtx insn, int taken)
   record_jump_cond (code, mode, op0, op1, reversed_nonequality);
 }
 
+/* Yet another form of subreg creation.  In this case, we want something in
+   MODE, and we should assume OP has MODE iff it is naturally modeless.  */
+
+static rtx
+record_jump_cond_subreg (enum machine_mode mode, rtx op)
+{
+  enum machine_mode op_mode = GET_MODE (op);
+  if (op_mode == mode || op_mode == VOIDmode)
+    return op;
+  return lowpart_subreg (mode, op, op_mode);
+}
+
 /* We know that comparison CODE applied to OP0 and OP1 in MODE is true.
    REVERSED_NONEQUALITY is nonzero if CODE had to be swapped.
    Make any useful entries we can with that information.  Called from
@@ -4351,11 +4363,10 @@ record_jump_cond (enum rtx_code code, en
 	  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
-      rtx tem = gen_lowpart (inner_mode, op1);
-
-      record_jump_cond (code, mode, SUBREG_REG (op0),
-			tem ? tem : gen_rtx_SUBREG (inner_mode, op1, 0),
-			reversed_nonequality);
+      rtx tem = record_jump_cond_subreg (inner_mode, op1);
+      if (tem)
+	record_jump_cond (code, mode, SUBREG_REG (op0), tem,
+			  reversed_nonequality);
     }
 
   if (code == EQ && GET_CODE (op1) == SUBREG
@@ -4363,11 +4374,10 @@ record_jump_cond (enum rtx_code code, en
 	  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
-      rtx tem = gen_lowpart (inner_mode, op0);
-
-      record_jump_cond (code, mode, SUBREG_REG (op1),
-			tem ? tem : gen_rtx_SUBREG (inner_mode, op0, 0),
-			reversed_nonequality);
+      rtx tem = record_jump_cond_subreg (inner_mode, op0);
+      if (tem)
+	record_jump_cond (code, mode, SUBREG_REG (op1), tem,
+			  reversed_nonequality);
     }
 
   /* Similarly, if this is an NE comparison, and either is a SUBREG
@@ -4383,11 +4393,10 @@ record_jump_cond (enum rtx_code code, en
 	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
-      rtx tem = gen_lowpart (inner_mode, op1);
-
-      record_jump_cond (code, mode, SUBREG_REG (op0),
-			tem ? tem : gen_rtx_SUBREG (inner_mode, op1, 0),
-			reversed_nonequality);
+      rtx tem = record_jump_cond_subreg (inner_mode, op1);
+      if (tem)
+	record_jump_cond (code, mode, SUBREG_REG (op0), tem,
+			  reversed_nonequality);
     }
 
   if (code == NE && GET_CODE (op1) == SUBREG
@@ -4396,11 +4405,10 @@ record_jump_cond (enum rtx_code code, en
 	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
-      rtx tem = gen_lowpart (inner_mode, op0);
-
-      record_jump_cond (code, mode, SUBREG_REG (op1),
-			tem ? tem : gen_rtx_SUBREG (inner_mode, op0, 0),
-			reversed_nonequality);
+      rtx tem = record_jump_cond_subreg (inner_mode, op0);
+      if (tem)
+	record_jump_cond (code, mode, SUBREG_REG (op1), tem,
+			  reversed_nonequality);
     }
 
   /* Hash both operands.  */
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.424
diff -u -p -r1.424 emit-rtl.c
--- emit-rtl.c	14 Nov 2004 12:55:15 -0000	1.424
+++ emit-rtl.c	15 Nov 2004 20:38:43 -0000
@@ -607,20 +607,98 @@ gen_const_mem (enum machine_mode mode, r
   return mem;
 }
 
+/* We want to create (subreg:OMODE (obj:IMODE) OFFSET).  Return true if
+   this construct would be valid, and false otherwise.  */
+
+bool
+validate_subreg (enum machine_mode omode, enum machine_mode imode,
+		 rtx reg, unsigned int offset)
+{
+  unsigned int isize = GET_MODE_SIZE (imode);
+  unsigned int osize = GET_MODE_SIZE (omode);
+
+  /* All subregs must be aligned.  */
+  if (offset % osize != 0)
+    return false;
+
+  /* The subreg offset cannot be outside the inner object.  */
+  if (offset >= isize)
+    return false;
+
+  /* ??? This should not be here.  Temporarily continue to allow word_mode
+     subregs of anything.  The most common offender is (subreg:SI (reg:DF)).
+     Generally, backends are doing something sketchy but it'll take time to
+     fix them all.  */
+  if (omode == word_mode)
+    ;
+  /* ??? Similarly, e.g. with (subreg:DF (reg:TI)).  Though store_bit_field
+     is the culprit here, and not the backends.  */
+  else if (osize >= UNITS_PER_WORD && isize >= osize)
+    ;
+  /* Allow component subregs of complex and vector.  Though given the below
+     extraction rules, it's not always clear what that means.  */
+  else if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode))
+	   && GET_MODE_INNER (imode) == omode)
+    ;
+  /* ??? x86 sse code makes heavy use of *paradoxical* vector subregs,
+     i.e. (subreg:V4SF (reg:SF) 0).  This surely isn't the cleanest way to
+     represent this.  It's questionable if this ought to be represented at
+     all -- why can't this all be hidden in post-reload splitters that make
+     arbitrarily mode changes to the registers themselves.  */
+  else if (VECTOR_MODE_P (omode) && GET_MODE_INNER (omode) == imode)
+    ;
+  /* Subregs involving floating point modes are not allowed to
+     change size.  Therefore (subreg:DI (reg:DF) 0) is fine, but
+     (subreg:SI (reg:DF) 0) isn't.  */
+  else if (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode))
+    {
+      if (isize != osize)
+	return false;
+    }
+
+  /* Paradoxical subregs must have offset zero.  */
+  if (osize > isize)
+    return offset == 0;
+
+  /* This is a normal subreg.  Verify that the offset is representable.  */
+
+  /* For hard registers, we already have most of these rules collected in
+     subreg_offset_representable_p.  */
+  if (reg && REG_P (reg) && HARD_REGISTER_P (reg))
+    {
+      unsigned int regno = REGNO (reg);
+
+#ifdef CANNOT_CHANGE_MODE_CLASS
+      if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode))
+	  && GET_MODE_INNER (imode) == omode)
+	;
+      else if (REG_CANNOT_CHANGE_MODE_P (regno, imode, omode))
+	return false;
+#endif
+
+      return subreg_offset_representable_p (regno, imode, offset, omode);
+    }
+
+  /* For pseudo registers, we want most of the same checks.  Namely:
+     If the register no larger than a word, the subreg must be lowpart.
+     If the register is larger than a word, the subreg must be the lowpart
+     of a subword.  A subreg does *not* perform arbitrary bit extraction.
+     Given that we've already checked mode/offset alignment, we only have
+     to check subword subregs here.  */
+  if (osize < UNITS_PER_WORD)
+    {
+      enum machine_mode wmode = isize > UNITS_PER_WORD ? word_mode : imode;
+      unsigned int low_off = subreg_lowpart_offset (omode, wmode);
+      if (offset % UNITS_PER_WORD != low_off)
+	return false;
+    }
+  return true;
+}
+
 rtx
 gen_rtx_SUBREG (enum machine_mode mode, rtx reg, int offset)
 {
-  /* This is the most common failure type.
-     Catch it early so we can see who does it.  */
-  gcc_assert (!(offset % GET_MODE_SIZE (mode)));
-
-  /* This check isn't usable right now because combine will
-     throw arbitrary crap like a CALL into a SUBREG in
-     gen_lowpart_for_combine so we must just eat it.  */
-#if 0
-  /* Check for this too.  */
-  gcc_assert (offset < GET_MODE_SIZE (GET_MODE (reg)));
-#endif
+  gcc_assert (validate_subreg (mode, GET_MODE (reg), reg, offset));
   return gen_rtx_raw_SUBREG (mode, reg, offset);
 }
 
@@ -1018,34 +1096,6 @@ maybe_set_first_label_num (rtx x)
     first_label_num = CODE_LABEL_NUMBER (x);
 }
 \f
-/* Return the final regno of X, which is a SUBREG of a hard
-   register.  */
-int
-subreg_hard_regno (rtx x, int check_mode)
-{
-  enum machine_mode mode = GET_MODE (x);
-  unsigned int byte_offset, base_regno, final_regno;
-  rtx reg = SUBREG_REG (x);
-
-  /* This is where we attempt to catch illegal subregs
-     created by the compiler.  */
-  gcc_assert (GET_CODE (x) == SUBREG && REG_P (reg));
-  base_regno = REGNO (reg);
-  gcc_assert (base_regno < FIRST_PSEUDO_REGISTER);
-  gcc_assert (!check_mode || HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)));
-#ifdef ENABLE_CHECKING
-  gcc_assert (subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
-					     SUBREG_BYTE (x), mode));
-#endif
-  /* Catch non-congruent offsets too.  */
-  byte_offset = SUBREG_BYTE (x);
-  gcc_assert (!(byte_offset % GET_MODE_SIZE (mode)));
-
-  final_regno = subreg_regno (x);
-
-  return final_regno;
-}
-
 /* Return a value representing some low-order bits of X, where the number
    of low-order bits is given by MODE.  Note that no conversion is done
    between floating-point and fixed-point values, rather, the bit
Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.205
diff -u -p -r1.205 expmed.c
--- expmed.c	13 Nov 2004 22:10:47 -0000	1.205
+++ expmed.c	15 Nov 2004 20:38:43 -0000
@@ -1233,22 +1233,16 @@ extract_bit_field (rtx str_rtx, unsigned
     {
       if (mode1 != GET_MODE (op0))
 	{
-	  if (GET_CODE (op0) == SUBREG)
+	  if (MEM_P (op0))
+	    op0 = adjust_address (op0, mode1, offset);
+	  else
 	    {
-	      if (GET_MODE (SUBREG_REG (op0)) == mode1
-		  || GET_MODE_CLASS (mode1) == MODE_INT
-		  || GET_MODE_CLASS (mode1) == MODE_PARTIAL_INT)
-		op0 = SUBREG_REG (op0);
-	      else
-		/* Else we've got some float mode source being extracted into
-		   a different float mode destination -- this combination of
-		   subregs results in Severe Tire Damage.  */
+	      rtx sub = simplify_gen_subreg (mode1, op0, GET_MODE (op0),
+					     byte_offset);
+	      if (sub == NULL)
 		goto no_subreg_mode_swap;
+	      op0 = sub;
 	    }
-	  if (REG_P (op0))
-	    op0 = gen_rtx_SUBREG (mode1, op0, byte_offset);
-	  else
-	    op0 = adjust_address (op0, mode1, offset);
 	}
       if (mode1 != mode)
 	return convert_to_mode (tmode, op0, unsignedp);
@@ -1628,19 +1622,41 @@ extract_bit_field (rtx str_rtx, unsigned
     return spec_target;
   if (GET_MODE (target) != tmode && GET_MODE (target) != mode)
     {
-      /* If the target mode is floating-point, first convert to the
-	 integer mode of that size and then access it as a floating-point
-	 value via a SUBREG.  */
-      if (GET_MODE_CLASS (tmode) != MODE_INT
-	  && GET_MODE_CLASS (tmode) != MODE_PARTIAL_INT)
+      /* If the target mode is complex, then extract the two scalar elements
+	 from the value now.  Creating (subreg:SC (reg:DI) 0), as we would do
+	 with the clause below, will cause gen_realpart or gen_imagpart to
+	 fail, since those functions must return lvalues.  */
+      if (COMPLEX_MODE_P (tmode))
 	{
+	  rtx realpart, imagpart;
+	  enum machine_mode itmode = GET_MODE_INNER (tmode);
+
 	  target = convert_to_mode (mode_for_size (GET_MODE_BITSIZE (tmode),
 						   MODE_INT, 0),
 				    target, unsignedp);
+
+	  realpart = extract_bit_field (target, GET_MODE_BITSIZE (itmode), 0,
+					unsignedp, NULL, itmode, itmode);
+	  imagpart = extract_bit_field (target, GET_MODE_BITSIZE (itmode),
+					GET_MODE_BITSIZE (itmode), unsignedp,
+					NULL, itmode, itmode);
+
+	  return gen_rtx_CONCAT (tmode, realpart, imagpart);
+	}
+
+      /* If the target mode is not a scalar integral, first convert to the
+	 integer mode of that size and then access it as a floating-point
+	 value via a SUBREG.  */
+      if (!SCALAR_INT_MODE_P (tmode))
+	{
+	  enum machine_mode smode
+	    = mode_for_size (GET_MODE_BITSIZE (tmode), MODE_INT, 0);
+	  target = convert_to_mode (smode, target, unsignedp);
+	  target = force_reg (smode, target);
 	  return gen_lowpart (tmode, target);
 	}
-      else
-	return convert_to_mode (tmode, target, unsignedp);
+
+      return convert_to_mode (tmode, target, unsignedp);
     }
   return target;
 }
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.741
diff -u -p -r1.741 expr.c
--- expr.c	14 Nov 2004 13:05:19 -0000	1.741
+++ expr.c	15 Nov 2004 20:38:43 -0000
@@ -2647,7 +2647,6 @@ emit_move_insn_1 (rtx x, rtx y)
 {
   enum machine_mode mode = GET_MODE (x);
   enum machine_mode submode;
-  enum mode_class class = GET_MODE_CLASS (mode);
 
   gcc_assert ((unsigned int) mode < (unsigned int) MAX_MACHINE_MODE);
 
@@ -2656,20 +2655,21 @@ emit_move_insn_1 (rtx x, rtx y)
       emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
 
   /* Expand complex moves by moving real part and imag part, if possible.  */
-  else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
+  else if (COMPLEX_MODE_P (mode)
 	   && BLKmode != (submode = GET_MODE_INNER (mode))
 	   && (mov_optab->handlers[(int) submode].insn_code
 	       != CODE_FOR_nothing))
     {
+      unsigned int modesize = GET_MODE_SIZE (mode);
+      unsigned int submodesize = GET_MODE_SIZE (submode);
+
       /* Don't split destination if it is a stack push.  */
-      int stack = push_operand (x, GET_MODE (x));
+      int stack = push_operand (x, mode);
 
 #ifdef PUSH_ROUNDING
       /* In case we output to the stack, but the size is smaller than the
 	 machine can push exactly, we need to use move instructions.  */
-      if (stack
-	  && (PUSH_ROUNDING (GET_MODE_SIZE (submode))
-	      != GET_MODE_SIZE (submode)))
+      if (stack && PUSH_ROUNDING (submodesize) != submodesize)
 	{
 	  rtx temp;
 	  HOST_WIDE_INT offset1, offset2;
@@ -2683,9 +2683,7 @@ emit_move_insn_1 (rtx x, rtx y)
 			       add_optab,
 #endif
 			       stack_pointer_rtx,
-			       GEN_INT
-				 (PUSH_ROUNDING
-				  (GET_MODE_SIZE (GET_MODE (x)))),
+			       GEN_INT (PUSH_ROUNDING (modesize)),
 			       stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
 
 	  if (temp != stack_pointer_rtx)
@@ -2693,11 +2691,10 @@ emit_move_insn_1 (rtx x, rtx y)
 
 #ifdef STACK_GROWS_DOWNWARD
 	  offset1 = 0;
-	  offset2 = GET_MODE_SIZE (submode);
+	  offset2 = submodesize;
 #else
-	  offset1 = -PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)));
-	  offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
-		     + GET_MODE_SIZE (submode));
+	  offset1 = -PUSH_ROUNDING (modesize);
+	  offset2 = -PUSH_ROUNDING (modesize) + submodesize;
 #endif
 
 	  emit_move_insn (change_address (x, submode,
@@ -2748,42 +2745,32 @@ emit_move_insn_1 (rtx x, rtx y)
 	     memory and reload.  FIXME, we should see about using extract and
 	     insert on integer registers, but complex short and complex char
 	     variables should be rarely used.  */
-	  if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
-	      && (reload_in_progress | reload_completed) == 0)
+	  if ((reload_in_progress | reload_completed) == 0
+	      && (!validate_subreg (submode, mode, NULL, submodesize)
+		  || !validate_subreg (submode, mode, NULL, 0)))
 	    {
-	      int packed_dest_p
-		= (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
-	      int packed_src_p
-		= (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
-
-	      if (packed_dest_p || packed_src_p)
+	      if (REG_P (x) || REG_P (y))
 		{
-		  enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
-					       ? MODE_FLOAT : MODE_INT);
-
+		  rtx mem, cmem;
 		  enum machine_mode reg_mode
-		    = mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
+		    = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 1);
+
+		  gcc_assert (reg_mode != BLKmode);
+
+		  mem = assign_stack_temp (reg_mode, modesize, 0);
+		  cmem = adjust_address (mem, mode, 0);
 
-		  if (reg_mode != BLKmode)
+		  if (REG_P (x))
+		    {
+		      rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
+		      emit_move_insn_1 (cmem, y);
+		      return emit_move_insn_1 (sreg, mem);
+		    }
+		  else
 		    {
-		      rtx mem = assign_stack_temp (reg_mode,
-						   GET_MODE_SIZE (mode), 0);
-		      rtx cmem = adjust_address (mem, mode, 0);
-
-		      if (packed_dest_p)
-			{
-			  rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
-
-			  emit_move_insn_1 (cmem, y);
-			  return emit_move_insn_1 (sreg, mem);
-			}
-		      else
-			{
-			  rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
-
-			  emit_move_insn_1 (mem, sreg);
-			  return emit_move_insn_1 (x, cmem);
-			}
+		      rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
+		      emit_move_insn_1 (mem, sreg);
+		      return emit_move_insn_1 (x, cmem);
 		    }
 		}
 	    }
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.342
diff -u -p -r1.342 final.c
--- final.c	9 Nov 2004 10:12:15 -0000	1.342
+++ final.c	15 Nov 2004 20:38:43 -0000
@@ -2636,8 +2636,7 @@ alter_subreg (rtx *xp)
       else
 	{
 	  /* Simplify_subreg can't handle some REG cases, but we have to.  */
-	  unsigned int regno = subreg_hard_regno (x, 1);
-	  
+	  unsigned int regno = subreg_regno (x);
 	  gcc_assert (REG_P (y));
 	  *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, SUBREG_BYTE (x));
 	}
Index: local-alloc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/local-alloc.c,v
retrieving revision 1.141
diff -u -p -r1.141 local-alloc.c
--- local-alloc.c	4 Nov 2004 08:41:04 -0000	1.141
+++ local-alloc.c	15 Nov 2004 20:38:43 -0000
@@ -2012,7 +2012,7 @@ reg_is_born (rtx reg, int birth)
     {
       regno = REGNO (SUBREG_REG (reg));
       if (regno < FIRST_PSEUDO_REGISTER)
-	regno = subreg_hard_regno (reg, 1);
+	regno = subreg_regno (reg);
     }
   else
     regno = REGNO (reg);
Index: regmove.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regmove.c,v
retrieving revision 1.164
diff -u -p -r1.164 regmove.c
--- regmove.c	9 Oct 2004 19:19:24 -0000	1.164
+++ regmove.c	15 Nov 2004 20:38:43 -0000
@@ -1150,10 +1150,8 @@ regmove_optimize (rtx f, int nregs, FILE
 		  && GET_MODE_SIZE (GET_MODE (dst))
 		     >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dst))))
 		{
-		  src_subreg
-		    = gen_rtx_SUBREG (GET_MODE (SUBREG_REG (dst)),
-				      src, SUBREG_BYTE (dst));
 		  dst = SUBREG_REG (dst);
+		  src_subreg = gen_lowpart (GET_MODE (dst), src);
 		}
 	      if (!REG_P (dst)
 		  || REGNO (dst) < FIRST_PSEUDO_REGISTER)
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.524
diff -u -p -r1.524 rtl.h
--- rtl.h	14 Nov 2004 12:55:15 -0000	1.524
+++ rtl.h	15 Nov 2004 20:38:43 -0000
@@ -1353,7 +1353,6 @@ extern rtx emit_copy_of_insn_after (rtx,
 extern void set_reg_attrs_from_mem (rtx, rtx);
 extern void set_mem_attrs_from_reg (rtx, rtx);
 extern void set_reg_attrs_for_parm (rtx, rtx);
-extern void set_reg_pointer_align (rtx, unsigned int);
 extern int mem_expr_equal_p (tree, tree);
 
 /* In rtl.c */
@@ -1377,7 +1376,6 @@ extern rtvec gen_rtvec_v (int, rtx *);
 extern rtx gen_reg_rtx (enum machine_mode);
 extern rtx gen_rtx_REG_offset (rtx, enum machine_mode, unsigned int, int);
 extern rtx gen_label_rtx (void);
-extern int subreg_hard_regno (rtx, int);
 extern rtx gen_lowpart_common (enum machine_mode, rtx);
 
 /* In cse.c */
@@ -1969,6 +1967,8 @@ extern rtx delete_insn_and_edges (rtx);
 extern void delete_insn_chain_and_edges (rtx, rtx);
 extern rtx gen_lowpart_SUBREG (enum machine_mode, rtx);
 extern rtx gen_const_mem (enum machine_mode, rtx);
+extern bool validate_subreg (enum machine_mode, enum machine_mode,
+			     rtx, unsigned int);
 
 /* In combine.c */
 extern int combine_instructions (rtx, unsigned int);
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.207
diff -u -p -r1.207 simplify-rtx.c
--- simplify-rtx.c	28 Oct 2004 12:47:21 -0000	1.207
+++ simplify-rtx.c	15 Nov 2004 20:38:43 -0000
@@ -3641,12 +3641,14 @@ simplify_subreg (enum machine_mode outer
 	}
 
       /* Recurse for further possible simplifications.  */
-      newx = simplify_subreg (outermode, SUBREG_REG (op),
-			     GET_MODE (SUBREG_REG (op)),
-			     final_offset);
+      newx = simplify_subreg (outermode, SUBREG_REG (op), innermostmode,
+			      final_offset);
       if (newx)
 	return newx;
-      return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+      if (validate_subreg (outermode, innermostmode,
+			   SUBREG_REG (op), final_offset))
+        return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+      return NULL_RTX;
     }
 
   /* SUBREG of a hard register => just change the register number
@@ -3674,14 +3676,15 @@ simplify_subreg (enum machine_mode outer
       && subreg_offset_representable_p (REGNO (op), innermode,
 					byte, outermode))
     {
-      rtx tem = gen_rtx_SUBREG (outermode, op, byte);
-      int final_regno = subreg_hard_regno (tem, 0);
+      unsigned int regno = REGNO (op);
+      unsigned int final_regno
+	= regno + subreg_regno_offset (regno, innermode, byte, outermode);
 
       /* ??? We do allow it if the current REG is not valid for
 	 its mode.  This is a kludge to work around how float/complex
 	 arguments are passed on 32-bit SPARC and should be fixed.  */
       if (HARD_REGNO_MODE_OK (final_regno, outermode)
-	  || ! HARD_REGNO_MODE_OK (REGNO (op), innermode))
+	  || ! HARD_REGNO_MODE_OK (regno, innermode))
 	{
 	  rtx x = gen_rtx_REG_offset (op, outermode, final_regno, byte);
 
@@ -3723,9 +3726,9 @@ simplify_subreg (enum machine_mode outer
       res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
       if (res)
 	return res;
-      /* We can at least simplify it by referring directly to the
-	 relevant part.  */
-      return gen_rtx_SUBREG (outermode, part, final_offset);
+      if (validate_subreg (outermode, GET_MODE (part), part, final_offset))
+        return gen_rtx_SUBREG (outermode, part, final_offset);
+      return NULL_RTX;
     }
 
   /* Optimize SUBREG truncations of zero and sign extended values.  */
@@ -3773,17 +3776,6 @@ simplify_gen_subreg (enum machine_mode o
 		     enum machine_mode innermode, unsigned int byte)
 {
   rtx newx;
-  /* Little bit of sanity checking.  */
-  gcc_assert (innermode != VOIDmode);
-  gcc_assert (outermode != VOIDmode);
-  gcc_assert (innermode != BLKmode);
-  gcc_assert (outermode != BLKmode);
-
-  gcc_assert (GET_MODE (op) == innermode
-	      || GET_MODE (op) == VOIDmode);
-
-  gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0);
-  gcc_assert (byte < GET_MODE_SIZE (innermode));
 
   newx = simplify_subreg (outermode, op, innermode, byte);
   if (newx)
@@ -3793,8 +3785,12 @@ simplify_gen_subreg (enum machine_mode o
       || (REG_P (op) && REGNO (op) < FIRST_PSEUDO_REGISTER))
     return NULL_RTX;
 
-  return gen_rtx_SUBREG (outermode, op, byte);
+  if (validate_subreg (outermode, innermode, op, byte))
+    return gen_rtx_SUBREG (outermode, op, byte);
+
+  return NULL_RTX;
 }
+
 /* Simplify X, an rtx expression.
 
    Return the simplified expression or NULL if no simplifications

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 18:58 [cft] subreg validation round 2 Richard Henderson
@ 2004-11-17 19:20 ` Bob Wilson
  2004-11-17 19:58   ` Richard Henderson
  2004-11-17 22:32   ` Janis Johnson
  2004-11-17 19:46 ` Eric Botcazou
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 19+ messages in thread
From: Bob Wilson @ 2004-11-17 19:20 UTC (permalink / raw)
  To: rth; +Cc: gcc

Richard Henderson wrote:
> This passes on i686, alpha, ia64, powerpc linux, and sparc-solaris.
> Given Ulrich's previous testing, it *ought* to pass on s390.  Any
> other takers before I check it in and have to pick up pieces after
> the fact?

I just finished testing the previous version of the patch for Xtensa, and I 
didn't see any regressions.  I'll try this version, too.

But speaking of picking up pieces after the fact....

Your change to assign_parm_setup_block() on 2004-11-13 is causing/exposing a 
problem for Xtensa targets.  Specifically, this piece:

*************** assign_parm_setup_block (tree parm, stru
*** 2648,2654 ****
   	    {
   	      rtx tem, x;
   	      int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
! 	      rtx reg = gen_rtx_REG (word_mode, REGNO (data->entry_parm));

   	      x = expand_shift (LSHIFT_EXPR, word_mode, reg,
   				build_int_cst (NULL_TREE, by),
--- 2663,2669 ----
   	    {
   	      rtx tem, x;
   	      int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
! 	      rtx reg = gen_lowpart (word_mode, entry_parm);

   	      x = expand_shift (LSHIFT_EXPR, word_mode, reg,
   				build_int_cst (NULL_TREE, by),

The Xtensa FUNCTION_ARG macro is returning a BLKmode REG for a 3-byte struct 
argument.  This used to be converted to an SImode REG, but now it gets passed to 
gen_lowpart, which barfs on the BLKmode argument.

Is this my bug?  If so, should I change FUNCTION_ARG code to avoid returning a 
BLKmode reg?  Should I wrap the REG in a PARALLEL?  Something else?

My apologies if this has already been discussed -- I haven't kept up with recent 
changes very well.

Thanks,
--Bob

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 18:58 [cft] subreg validation round 2 Richard Henderson
  2004-11-17 19:20 ` Bob Wilson
@ 2004-11-17 19:46 ` Eric Botcazou
  2004-11-19 21:50   ` Richard Henderson
  2004-11-18 23:43 ` Kaz Kojima
  2004-11-19  0:08 ` Janis Johnson
  3 siblings, 1 reply; 19+ messages in thread
From: Eric Botcazou @ 2004-11-17 19:46 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc

> This passes on i686, alpha, ia64, powerpc linux, and sparc-solaris.
> Given Ulrich's previous testing, it *ought* to pass on s390.  Any
> other takers before I check it in and have to pick up pieces after
> the fact?

How did you address the problem with SPARC splitters?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 19:20 ` Bob Wilson
@ 2004-11-17 19:58   ` Richard Henderson
  2004-11-18  1:06     ` Alan Modra
  2004-11-18 16:23     ` Richard Sandiford
  2004-11-17 22:32   ` Janis Johnson
  1 sibling, 2 replies; 19+ messages in thread
From: Richard Henderson @ 2004-11-17 19:58 UTC (permalink / raw)
  To: Bob Wilson; +Cc: gcc

On Wed, Nov 17, 2004 at 11:18:41AM -0800, Bob Wilson wrote:
> Is this my bug?

Yes.  BLKmode REGs are illegal.

> If so, should I change FUNCTION_ARG code to avoid 
> returning a BLKmode reg?  Should I wrap the REG in a PARALLEL?

Presumably you didn't just return the SImode reg in the first place
because you want the three bytes in the high part of the register?
Then, yes, a PARALLEL should do.


r~

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 19:20 ` Bob Wilson
  2004-11-17 19:58   ` Richard Henderson
@ 2004-11-17 22:32   ` Janis Johnson
  2004-11-17 23:05     ` Andrew Pinski
  2004-11-18 11:40     ` Alan Modra
  1 sibling, 2 replies; 19+ messages in thread
From: Janis Johnson @ 2004-11-17 22:32 UTC (permalink / raw)
  To: Bob Wilson; +Cc: rth, gcc

On Wed, Nov 17, 2004 at 11:18:41AM -0800, Bob Wilson wrote:
> 
> But speaking of picking up pieces after the fact....
> 
> Your change to assign_parm_setup_block() on 2004-11-13 is causing/exposing 
> a problem for Xtensa targets.  Specifically, this piece:
> 
> *************** assign_parm_setup_block (tree parm, stru
> *** 2648,2654 ****
 ...
> 
> The Xtensa FUNCTION_ARG macro is returning a BLKmode REG for a 3-byte 
> struct argument.  This used to be converted to an SImode REG, but now it 
> gets passed to gen_lowpart, which barfs on the BLKmode argument.

That change also causes several new test failures for powerpc64-linux
with -m64, which now ICE in gen_lowpart_common for a BLKmode argument.

Janis

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 22:32   ` Janis Johnson
@ 2004-11-17 23:05     ` Andrew Pinski
  2004-11-18 11:40     ` Alan Modra
  1 sibling, 0 replies; 19+ messages in thread
From: Andrew Pinski @ 2004-11-17 23:05 UTC (permalink / raw)
  To: Janis Johnson; +Cc: Bob Wilson, gcc, rth


On Nov 17, 2004, at 5:31 PM, Janis Johnson wrote:

> That change also causes several new test failures for powerpc64-linux
> with -m64, which now ICE in gen_lowpart_common for a BLKmode argument.

Yes this is because subreg of a register which is BLKmode is invalid
now.
See <http://gcc.gnu.org/ml/gcc/2004-11/msg00573.html> for another
target which did the same thing and how to fix it.

Thanks,
Andrew Pinski

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 19:58   ` Richard Henderson
@ 2004-11-18  1:06     ` Alan Modra
  2004-11-18  2:43       ` Bob Wilson
  2004-11-18 16:23     ` Richard Sandiford
  1 sibling, 1 reply; 19+ messages in thread
From: Alan Modra @ 2004-11-18  1:06 UTC (permalink / raw)
  To: Richard Henderson, Bob Wilson, gcc

On Wed, Nov 17, 2004 at 11:45:53AM -0800, Richard Henderson wrote:
> On Wed, Nov 17, 2004 at 11:18:41AM -0800, Bob Wilson wrote:
> > If so, should I change FUNCTION_ARG code to avoid 
> > returning a BLKmode reg?  Should I wrap the REG in a PARALLEL?
> 
> Presumably you didn't just return the SImode reg in the first place
> because you want the three bytes in the high part of the register?
> Then, yes, a PARALLEL should do.

Or define a suitable BLOCK_REG_PADDING.  At least, that used to work..

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-18  1:06     ` Alan Modra
@ 2004-11-18  2:43       ` Bob Wilson
  0 siblings, 0 replies; 19+ messages in thread
From: Bob Wilson @ 2004-11-18  2:43 UTC (permalink / raw)
  To: Alan Modra; +Cc: Richard Henderson, gcc

Alan Modra wrote:
> On Wed, Nov 17, 2004 at 11:45:53AM -0800, Richard Henderson wrote:
> 
>>On Wed, Nov 17, 2004 at 11:18:41AM -0800, Bob Wilson wrote:
>>
>>>If so, should I change FUNCTION_ARG code to avoid 
>>>returning a BLKmode reg?  Should I wrap the REG in a PARALLEL?
>>
>>Presumably you didn't just return the SImode reg in the first place
>>because you want the three bytes in the high part of the register?
>>Then, yes, a PARALLEL should do.
> 
> 
> Or define a suitable BLOCK_REG_PADDING.  At least, that used to work..

I'm looking into it, but from a quick check of various other ports, I'm 
surprised that more of them aren't breaking.  (Or maybe they are....)  Many of 
the FUNCTION_ARG implementations create a REG with whatever mode is specified as 
an argument to FUNCTION_ARG, which is what the Xtensa code does.  I'm not doing 
anything special here.

The "smaller than a word struct argument" case that causes the ICE is actually 
the easiest to handle.  Ignoring the padding issue, a single SImode REG will 
work.  For a struct bigger than a word, I guess a PARALLEL is required to 
specify each consecutive register separately (at least in the general case where 
there is no mode of the right size).  I can see why it should be that way, but 
it was so much easier to just specify the first register with BLKmode....

Thanks for the suggestions.

--Bob

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 22:32   ` Janis Johnson
  2004-11-17 23:05     ` Andrew Pinski
@ 2004-11-18 11:40     ` Alan Modra
  1 sibling, 0 replies; 19+ messages in thread
From: Alan Modra @ 2004-11-18 11:40 UTC (permalink / raw)
  To: Janis Johnson; +Cc: Bob Wilson, rth, gcc

On Wed, Nov 17, 2004 at 02:31:28PM -0800, Janis Johnson wrote:
> That change also causes several new test failures for powerpc64-linux
> with -m64, which now ICE in gen_lowpart_common for a BLKmode argument.

Fixed like this

	* config/rs6000/rs6000.c (function_arg): Don't return BLKmode regs.

Bootstrapped and regression tested powerpc64-linux.  I also ran the
compat testsuite against my system compiler, and found no problems apart
from a few tests that failed with an ICE on mainline
expand_expr_addr_expr_1, at expr.c:6067
and scalar-by-value-7 failing due to my system compiler doing the wrong
thing..

diff -urp gcc-rth/gcc/config/rs6000/rs6000.c gcc-rth2/gcc/config/rs6000/rs6000.c
--- gcc-rth/gcc/config/rs6000/rs6000.c	2004-11-17 13:59:18.000000000 +1030
+++ gcc-rth2/gcc/config/rs6000/rs6000.c	2004-11-18 10:51:37.796602798 +1030
@@ -5528,6 +5528,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum
 	  if (TARGET_32BIT && TARGET_POWERPC64)
 	    return rs6000_mixed_function_arg (mode, type, align_words);
 
+	  if (mode == BLKmode)
+	    mode = Pmode;
+
 	  return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
 	}
       else

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 19:58   ` Richard Henderson
  2004-11-18  1:06     ` Alan Modra
@ 2004-11-18 16:23     ` Richard Sandiford
  2004-11-19 21:39       ` Richard Henderson
  1 sibling, 1 reply; 19+ messages in thread
From: Richard Sandiford @ 2004-11-18 16:23 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Bob Wilson, gcc

Richard Henderson <rth@redhat.com> writes:
> On Wed, Nov 17, 2004 at 11:18:41AM -0800, Bob Wilson wrote:
>> Is this my bug?
>
> Yes.  BLKmode REGs are illegal.

I realise that they are in general, but it's fairly clear that,
for example, FUNCTION_VALUE is allowed to return BLKmode REGs.
Routines like hard_function_value have code that specifically
handles such cases.  I'd always thought that FUNCTION_ARG was
in the same boat, and that the argument handling code interpreted
(reg:BLK X) as meaning "as many consecutive registers as necessary,
starting at X".

MIPS's FUNCTION_ARG has returned (reg:BLK reg) for as long as I've
been working on it and it always seems to have been interpreted in
the right way.

Are you saying that FUNCTION_ARG isn't an exception, and that it can
never return a BLKmode REG?  If so, what's the correct mode for, say,
a 33 byte value passed in 5 consecutive 64-bit registers?  I suppose
the answer is probably "there isn't one, use a PARALLEL", but like I
say, returning BLKmode REGs has worked fine until now, so this does
seem like an interface change.

Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 18:58 [cft] subreg validation round 2 Richard Henderson
  2004-11-17 19:20 ` Bob Wilson
  2004-11-17 19:46 ` Eric Botcazou
@ 2004-11-18 23:43 ` Kaz Kojima
  2004-11-19  0:08 ` Janis Johnson
  3 siblings, 0 replies; 19+ messages in thread
From: Kaz Kojima @ 2004-11-18 23:43 UTC (permalink / raw)
  To: gcc

Richard Henderson <rth@redhat.com> wrote:
> This passes on i686, alpha, ia64, powerpc linux, and sparc-solaris.
> Given Ulrich's previous testing, it *ought* to pass on s390.  Any
> other takers before I check it in and have to pick up pieces after
> the fact?

FYI, bootstrapped successfully on sh4-unknown-linux-gnu.  The native
regtest hasn't completed yet, though there are no regressions on x86
cross sh4-unknown-linux-gnu.

Regards,
	kaz

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 18:58 [cft] subreg validation round 2 Richard Henderson
                   ` (2 preceding siblings ...)
  2004-11-18 23:43 ` Kaz Kojima
@ 2004-11-19  0:08 ` Janis Johnson
  3 siblings, 0 replies; 19+ messages in thread
From: Janis Johnson @ 2004-11-19  0:08 UTC (permalink / raw)
  To: Richard Henderson, gcc; +Cc: amodra

On Wed, Nov 17, 2004 at 10:40:09AM -0800, Richard Henderson wrote:
> This passes on i686, alpha, ia64, powerpc linux, and sparc-solaris.
> Given Ulrich's previous testing, it *ought* to pass on s390.  Any
> other takers before I check it in and have to pick up pieces after
> the fact?

Together with a patch that Alan Modra sent yesterday, it works on
powerpc64-unknown-linux-gnu with -m32 and -m64.  I only built and tested
C and C++, but that's where I saw problems with earlier versions.

Janis

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-18 16:23     ` Richard Sandiford
@ 2004-11-19 21:39       ` Richard Henderson
  2004-11-22 20:40         ` Richard Henderson
  0 siblings, 1 reply; 19+ messages in thread
From: Richard Henderson @ 2004-11-19 21:39 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: Bob Wilson, gcc

On Thu, Nov 18, 2004 at 01:17:07PM +0000, Richard Sandiford wrote:
> I realise that they are in general, but it's fairly clear that,
> for example, FUNCTION_VALUE is allowed to return BLKmode REGs.
> Routines like hard_function_value have code that specifically
> handles such cases.

I think you have a point.  I'll revert that part of the patch
and fix this a different way.  And update the documentation.


r~

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-17 19:46 ` Eric Botcazou
@ 2004-11-19 21:50   ` Richard Henderson
  2004-11-19 22:43     ` Eric Botcazou
  0 siblings, 1 reply; 19+ messages in thread
From: Richard Henderson @ 2004-11-19 21:50 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc

On Wed, Nov 17, 2004 at 08:21:34PM +0100, Eric Botcazou wrote:
> How did you address the problem with SPARC splitters?


@@ -3674,14 +3676,15 @@ simplify_subreg (enum machine_mode outer
       && subreg_offset_representable_p (REGNO (op), innermode,
 					byte, outermode))
     {
-      rtx tem = gen_rtx_SUBREG (outermode, op, byte);
-      int final_regno = subreg_hard_regno (tem, 0);
+      unsigned int regno = REGNO (op);
+      unsigned int final_regno
+	= regno + subreg_regno_offset (regno, innermode, byte, outermode);
 


r~

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-19 21:50   ` Richard Henderson
@ 2004-11-19 22:43     ` Eric Botcazou
  2004-11-19 22:46       ` Richard Henderson
  0 siblings, 1 reply; 19+ messages in thread
From: Eric Botcazou @ 2004-11-19 22:43 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc

> > How did you address the problem with SPARC splitters?
>
> @@ -3674,14 +3676,15 @@ simplify_subreg (enum machine_mode outer
>        && subreg_offset_representable_p (REGNO (op), innermode,
>  					byte, outermode))
>      {
> -      rtx tem = gen_rtx_SUBREG (outermode, op, byte);
> -      int final_regno = subreg_hard_regno (tem, 0);
> +      unsigned int regno = REGNO (op);
> +      unsigned int final_regno
> +	= regno + subreg_regno_offset (regno, innermode, byte, outermode);

Ouch!  Pretty deeply buried in the subreg handling stuff.

Would you see any advantage in manually building the hard regs within the 
splitters?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-19 22:43     ` Eric Botcazou
@ 2004-11-19 22:46       ` Richard Henderson
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Henderson @ 2004-11-19 22:46 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc

On Fri, Nov 19, 2004 at 11:24:40PM +0100, Eric Botcazou wrote:
> Would you see any advantage in manually building the hard regs within the 
> splitters?

No.  Indeed, it can hurt, since using gen_lowpart helps arrange
for proper debugging information to be generated.  I.e. it updates
the REG_ATTRS information properly.

I'm sure there's lots of backends that could do well to not JUST
call gen_rtx_REG (mode, REGNO (x)).  Using gen_rtx_REG_offset 
instead would be much preferred.


r~

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
  2004-11-19 21:39       ` Richard Henderson
@ 2004-11-22 20:40         ` Richard Henderson
  0 siblings, 0 replies; 19+ messages in thread
From: Richard Henderson @ 2004-11-22 20:40 UTC (permalink / raw)
  To: Richard Sandiford, Bob Wilson, gcc

On Fri, Nov 19, 2004 at 12:22:28PM -0800, Richard Henderson wrote:
> I think you have a point.  I'll revert that part of the patch
> and fix this a different way.  And update the documentation.

I never did find why I made this change.  The only thing I can
think is that I was modifying something nearby and thought "this
obviously cannot be correct."

So I've applied this reversion.


r~


        * function.c (assign_parm_setup_block): Revert 11-13 change to
        forcably re-mode a (possibly BLKmode) hard register.

Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.588
diff -c -p -d -u -r1.588 function.c
--- function.c	14 Nov 2004 06:22:56 -0000	1.588
+++ function.c	22 Nov 2004 18:52:41 -0000
@@ -2663,7 +2663,7 @@ assign_parm_setup_block (struct assign_p
 	    {
 	      rtx tem, x;
 	      int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
-	      rtx reg = gen_lowpart (word_mode, entry_parm);
+	      rtx reg = gen_rtx_REG (word_mode, REGNO (entry_parm));
 
 	      x = expand_shift (LSHIFT_EXPR, word_mode, reg,
 				build_int_cst (NULL_TREE, by),

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
       [not found] <OF12E4E5CC.BDFB0F1C-ON41256F4F.0067F055-41256F4F.00682968@LocalDomain>
@ 2004-11-17 21:42 ` Ulrich Weigand
  0 siblings, 0 replies; 19+ messages in thread
From: Ulrich Weigand @ 2004-11-17 21:42 UTC (permalink / raw)
  To: rth; +Cc: gcc





Ulrich Weigand/Germany/IBM wrote on 11/17/2004 07:57:43 PM:
> I've started testing on s390(x) with the rest of the patch applied.

Testing completed without regression on s390-ibm-linux
and s390x-ibm-linux.

Bye,
Ulrich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [cft] subreg validation round 2
@ 2004-11-17 19:19 Ulrich Weigand
  0 siblings, 0 replies; 19+ messages in thread
From: Ulrich Weigand @ 2004-11-17 19:19 UTC (permalink / raw)
  To: rth; +Cc: gcc





Richard Henderson wrote:

>Index: regmove.c
>===================================================================
>RCS file: /cvs/gcc/gcc/gcc/regmove.c,v
>retrieving revision 1.164
>diff -u -p -r1.164 regmove.c
>--- regmove.c    9 Oct 2004 19:19:24 -0000     1.164
>+++ regmove.c    15 Nov 2004 20:38:43 -0000
>@@ -1150,10 +1150,8 @@ regmove_optimize (rtx f, int nregs, FILE
>             && GET_MODE_SIZE (GET_MODE (dst))
>                >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dst))))
>           {
>-            src_subreg
>-              = gen_rtx_SUBREG (GET_MODE (SUBREG_REG (dst)),
>-                            src, SUBREG_BYTE (dst));
>             dst = SUBREG_REG (dst);
>+            src_subreg = gen_lowpart (GET_MODE (dst), src);
>           }
>           if (!REG_P (dst)
>             || REGNO (dst) < FIRST_PSEUDO_REGISTER)

This hunk fails as I've already checked in the updated version of the fix.

I've started testing on s390(x) with the rest of the patch applied.


Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2004-11-22 18:58 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-17 18:58 [cft] subreg validation round 2 Richard Henderson
2004-11-17 19:20 ` Bob Wilson
2004-11-17 19:58   ` Richard Henderson
2004-11-18  1:06     ` Alan Modra
2004-11-18  2:43       ` Bob Wilson
2004-11-18 16:23     ` Richard Sandiford
2004-11-19 21:39       ` Richard Henderson
2004-11-22 20:40         ` Richard Henderson
2004-11-17 22:32   ` Janis Johnson
2004-11-17 23:05     ` Andrew Pinski
2004-11-18 11:40     ` Alan Modra
2004-11-17 19:46 ` Eric Botcazou
2004-11-19 21:50   ` Richard Henderson
2004-11-19 22:43     ` Eric Botcazou
2004-11-19 22:46       ` Richard Henderson
2004-11-18 23:43 ` Kaz Kojima
2004-11-19  0:08 ` Janis Johnson
2004-11-17 19:19 Ulrich Weigand
     [not found] <OF12E4E5CC.BDFB0F1C-ON41256F4F.0067F055-41256F4F.00682968@LocalDomain>
2004-11-17 21:42 ` Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).