fix target/20342 and 20447

Richard Henderson rth@redhat.com
Tue Apr 5 23:02:00 GMT 2005


These two prs are closely related.  Indeed, fixing only the initial
failure of 20342 produced exactly the same ice as 20447.

The output_operand ice is fixed by the print_operand and split_to_parts
changes.

The spill failure problem was caused by us taking both V2SImode and
HImode subregs of a pseudo, and there not being any register class 
that could handle both of those modes.  Fixed by allowing MMX modes
in the general registers.  Given how often these quantities are 
cast to DImode, it seems like this will come up moderately often.

The modes_tiable_p change is needed since we've changed the set of
registers in which these modes are valid.

Tested on i686 and x86_64 linux.


r~


        * config/i386/i386.c (print_operand): Handle vector zeros.
        (ix86_split_to_parts): Handle CONST_VECTOR.
        (ix86_hard_regno_mode_ok): Allow MMX modes in general regs.
        (ix86_modes_tieable_p): Use ix86_hard_regno_mode_ok to decide
        what modes to tie for MMX and SSE registers.
        * config/i386/i386.h (MMX_REG_MODE_P): Remove.
        * config/i386/i386.md: Extend move 0 -> xor peephole to apply
        to vector modes as well.
        * config/i386/predicates.md (const0_operand): Handle VOIDmode
        properly as an input mode.

Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.804
diff -u -p -d -r1.804 i386.c
--- config/i386/i386.c	5 Apr 2005 20:20:29 -0000	1.804
+++ config/i386/i386.c	5 Apr 2005 22:47:09 -0000
@@ -6773,6 +6773,17 @@ print_operand (FILE *file, rtx x, int co
 
   else
     {
+      /* We have patterns that allow zero sets of memory, for instance.
+	 In 64-bit mode, we should probably support all 8-byte vectors,
+	 since we can in fact encode that into an immediate.  */
+      if (GET_CODE (x) == CONST_VECTOR)
+	{
+	  if (x == CONST0_RTX (GET_MODE (x)))
+	    x = const0_rtx;
+	  else
+	    abort ();
+	}
+
       if (code != 'P')
 	{
 	  if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
@@ -10350,8 +10361,18 @@ ix86_split_to_parts (rtx operand, rtx *p
       operand = copy_rtx (operand);
       PUT_MODE (operand, Pmode);
       parts[0] = parts[1] = parts[2] = operand;
+      return size;
     }
-  else if (!TARGET_64BIT)
+
+  if (GET_CODE (operand) == CONST_VECTOR)
+    {
+      enum machine_mode imode = int_mode_for_mode (mode);
+      operand = simplify_subreg (imode, operand, mode, 0);
+      gcc_assert (operand != NULL);
+      mode = imode;
+    }
+
+  if (!TARGET_64BIT)
     {
       if (mode == DImode)
 	split_di (&operand, 1, &parts[0], &parts[1]);
@@ -15111,15 +15132,30 @@ ix86_hard_regno_mode_ok (int regno, enum
       return (VALID_MMX_REG_MODE (mode)
 	      || VALID_MMX_REG_MODE_3DNOW (mode));
     }
-  /* We handle both integer and floats in the general purpose registers.
-     In future we should be able to handle vector modes as well.  */
-  if (!VALID_INT_MODE_P (mode) && !VALID_FP_MODE_P (mode))
-    return 0;
-  /* Take care for QImode values - they can be in non-QI regs, but then
-     they do cause partial register stalls.  */
-  if (regno < 4 || mode != QImode || TARGET_64BIT)
+
+  if (mode == QImode)
+    {
+      /* Take care for QImode values - they can be in non-QI regs,
+	 but then they do cause partial register stalls.  */
+      if (regno < 4 || TARGET_64BIT)
+	return 1;
+      if (!TARGET_PARTIAL_REG_STALL)
+	return 1;
+      return reload_in_progress || reload_completed;
+    }
+  /* We handle both integer and floats in the general purpose registers.  */
+  else if (VALID_INT_MODE_P (mode))
     return 1;
-  return reload_in_progress || reload_completed || !TARGET_PARTIAL_REG_STALL;
+  else if (VALID_FP_MODE_P (mode))
+    return 1;
+  /* Lots of MMX code casts 8 byte vector modes to DImode.  If we then go
+     on to use that value in smaller contexts, this can easily force a 
+     pseudo to be allocated to GENERAL_REGS.  Since this is no worse than
+     supporting DImode, allow it.  */
+  else if (VALID_MMX_REG_MODE_3DNOW (mode) || VALID_MMX_REG_MODE (mode))
+    return 1;
+
+  return 0;
 }
 
 /* A subroutine of ix86_modes_tieable_p.  Return true if MODE is a 
@@ -15172,12 +15208,14 @@ ix86_modes_tieable_p (enum machine_mode 
 
   /* If MODE2 is only appropriate for an SSE register, then tie with 
      any other mode acceptable to SSE registers.  */
-  if (SSE_REG_MODE_P (mode2))
+  if (GET_MODE_SIZE (mode2) >= 8
+      && ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode2))
     return ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode1);
 
   /* If MODE2 is appropriate for an MMX (or SSE) register, then tie
      with any other mode acceptable to MMX registers.  */
-  if (MMX_REG_MODE_P (mode2))
+  if (GET_MODE_SIZE (mode2) == 8
+      && ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode2))
     return ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode1);
 
   return false;
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.425
diff -u -p -d -r1.425 i386.h
--- config/i386/i386.h	5 Apr 2005 20:20:33 -0000	1.425
+++ config/i386/i386.h	5 Apr 2005 22:47:09 -0000
@@ -1109,11 +1109,6 @@ do {									\
    || (MODE) == V8HImode || (MODE) == V2DFmode || (MODE) == V2DImode	\
    || (MODE) == V4SFmode || (MODE) == V4SImode)
 
-/* Return true for modes passed in MMX registers.  */
-#define MMX_REG_MODE_P(MODE) \
- ((MODE) == V8QImode || (MODE) == V4HImode || (MODE) == V2SImode	\
-   || (MODE) == V2SFmode)
-
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.  */
 
 #define HARD_REGNO_MODE_OK(REGNO, MODE)	\
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.624
diff -u -p -d -r1.624 i386.md
--- config/i386/i386.md	5 Apr 2005 05:23:14 -0000	1.624
+++ config/i386/i386.md	5 Apr 2005 22:47:13 -0000
@@ -18659,18 +18659,16 @@
 ;; Attempt to always use XOR for zeroing registers.
 (define_peephole2
   [(set (match_operand 0 "register_operand" "")
-	(const_int 0))]
-  "(GET_MODE (operands[0]) == QImode
-    || GET_MODE (operands[0]) == HImode
-    || GET_MODE (operands[0]) == SImode
-    || (GET_MODE (operands[0]) == DImode && TARGET_64BIT))
+	(match_operand 1 "const0_operand" ""))]
+  "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
    && (! TARGET_USE_MOV0 || optimize_size)
    && GENERAL_REG_P (operands[0])
    && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (const_int 0))
 	      (clobber (reg:CC FLAGS_REG))])]
-  "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode,
-			      operands[0]);")
+{
+  operands[0] = gen_lowpart (word_mode, operands[0]);
+})
 
 (define_peephole2
   [(set (strict_low_part (match_operand 0 "register_operand" ""))
Index: config/i386/predicates.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/predicates.md,v
retrieving revision 1.16
diff -u -p -d -r1.16 predicates.md
--- config/i386/predicates.md	23 Jan 2005 15:05:45 -0000	1.16
+++ config/i386/predicates.md	5 Apr 2005 22:47:13 -0000
@@ -499,8 +499,12 @@
 
 ;; Match exactly zero.
 (define_predicate "const0_operand"
-  (and (match_code "const_int,const_double,const_vector")
-       (match_test "op == CONST0_RTX (mode)")))
+  (match_code "const_int,const_double,const_vector")
+{
+  if (mode == VOIDmode)
+    mode = GET_MODE (op);
+  return op == CONST0_RTX (mode);
+})
 
 ;; Match exactly one.
 (define_predicate "const1_operand"



More information about the Gcc-patches mailing list