From b4e82619bca237b96d0a85da90d4f67c71428f99 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@redhat.com>
Date: Tue, 5 Apr 2005 15:53:08 -0700
Subject: [PATCH] re PR target/20342 (ICE in spill_failure, at reload1.c:1872)

        PR target/20342
        PR target/20447
        * 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.

From-SVN: r97663
---
 gcc/ChangeLog                 | 15 +++++++++
 gcc/config/i386/i386.c        | 60 ++++++++++++++++++++++++++++-------
 gcc/config/i386/i386.h        |  5 ---
 gcc/config/i386/i386.md       | 12 +++----
 gcc/config/i386/predicates.md |  8 +++--
 5 files changed, 75 insertions(+), 25 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 69e4e3d86eca..846d4367a004 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2005-04-05  Richard Henderson  <rth@redhat.com>
+
+	PR target/20342
+	PR target/20447
+	* 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.
+
 2005-04-05  Andrew MacLeod  <amacleod@redhat.com>
 
 	* tree-ssa-operands.c (verify_abort): Use %p for pointers.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 5eeb54867c4a..e762fa751870 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6773,6 +6773,17 @@ print_operand (FILE *file, rtx x, int code)
 
   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 *parts, enum machine_mode mode)
       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 machine_mode mode)
       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;
+  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 reload_in_progress || reload_completed || !TARGET_PARTIAL_REG_STALL;
+
+  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 mode1, enum machine_mode mode2)
 
   /* 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;
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 819b0b2367d7..ffba1d791457 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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)	\
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 6c5962bdec4c..179546924d6a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -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" ""))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 66f25058182d..668c7c061e5f 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -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"
-- 
GitLab