]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/19010 (sse and mmx parameter passing broken)
authorRichard Henderson <rth@redhat.com>
Wed, 15 Dec 2004 20:03:23 +0000 (12:03 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 15 Dec 2004 20:03:23 +0000 (12:03 -0800)
        PR target/19010
        * config/i386/i386.c (gen_reg_or_parallel): New.
        (function_arg): Use it.
        (ix86_hard_regno_mode_ok): Test SSE1 and SSE2 separately,
        MMX and 3DNOW separately.
        (ix86_rtx_costs): Simplify FLOAT_EXTEND case.
        * config/i386/i386.h (VALID_SSE2_REG_MODE): Move SSE2 cases from ...
        (VALID_SSE_REG_MODE): ... here.
        * config/i386/i386.md (movv4sf_internal): Validate one MEM.
        (movv4si_internal): Likewise.
        (movv2di_internal): Likewise.  Enable for SSE2 only.
        (movv2di): Enable for SSE2 only.
        (pushv4si): Enable for SSE1.

From-SVN: r92215

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index 6da3a6a9dfe99ec5409932614f3e780373863024..2d64e510f8e3de5a48aa3f38a49cdc520770dd52 100644 (file)
@@ -1,3 +1,19 @@
+2004-12-15  Richard Henderson  <rth@redhat.com>
+
+        PR target/19010
+        * config/i386/i386.c (gen_reg_or_parallel): New.
+        (function_arg): Use it.
+        (ix86_hard_regno_mode_ok): Test SSE1 and SSE2 separately,
+        MMX and 3DNOW separately.
+        (ix86_rtx_costs): Simplify FLOAT_EXTEND case.
+        * config/i386/i386.h (VALID_SSE2_REG_MODE): Move SSE2 cases from ...
+        (VALID_SSE_REG_MODE): ... here.
+       * config/i386/i386.md (movv4sf_internal): Validate one MEM.
+       (movv4si_internal): Likewise.
+       (movv2di_internal): Likewise.  Enable for SSE2 only.
+       (movv2di): Enable for SSE2 only.
+       (pushv4si): Enable for SSE1.
+
 2004-12-15  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR c++/17972
index 8ef04b291caeccffb6828fdb69bf1599b06c2976..ecd8f073f5fc5db9030d49c0cd218a0f0bb1d474 100644 (file)
@@ -2536,6 +2536,34 @@ function_arg_advance (CUMULATIVE_ARGS *cum,      /* current arg information */
   return;
 }
 
+/* A subroutine of function_arg.  We want to pass a parameter whose nominal
+   type is MODE in REGNO.  We try to minimize ABI variation, so MODE may not
+   actually be valid for REGNO with the current ISA.  In this case, ALT_MODE
+   is used instead.  It must be the same size as MODE, and must be known to
+   be valid for REGNO.  Finally, ORIG_MODE is the original mode of the 
+   parameter, as seen by the type system.  This may be different from MODE
+   when we're mucking with things minimizing ABI variations.
+
+   Returns a REG or a PARALLEL as appropriate.  */
+
+static rtx
+gen_reg_or_parallel (enum machine_mode mode, enum machine_mode alt_mode,
+                    enum machine_mode orig_mode, unsigned int regno)
+{
+  rtx tmp;
+
+  if (HARD_REGNO_MODE_OK (regno, mode))
+    tmp = gen_rtx_REG (mode, regno);
+  else
+    {
+      tmp = gen_rtx_REG (alt_mode, regno);
+      tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
+      tmp = gen_rtx_PARALLEL (orig_mode, gen_rtvec (1, tmp));
+    }
+
+  return tmp;
+}
+
 /* Define where to put the arguments to a function.
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
@@ -2550,12 +2578,11 @@ function_arg_advance (CUMULATIVE_ARGS *cum,     /* current arg information */
     (otherwise it is an extra parameter matching an ellipsis).  */
 
 rtx
-function_arg (CUMULATIVE_ARGS *cum,    /* current arg information */
-             enum machine_mode mode,   /* current arg mode */
-             tree type,        /* type of the argument or 0 if lib support */
-             int named)        /* != 0 for normal args, == 0 for ...  args */
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode orig_mode,
+             tree type, int named)
 {
-  rtx ret   = NULL_RTX;
+  enum machine_mode mode = orig_mode;
+  rtx ret = NULL_RTX;
   int bytes =
     (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
@@ -2628,7 +2655,8 @@ function_arg (CUMULATIVE_ARGS *cum,       /* current arg information */
                         "changes the ABI");
              }
            if (cum->sse_nregs)
-             ret = gen_rtx_REG (mode, cum->sse_regno + FIRST_SSE_REG);
+             ret = gen_reg_or_parallel (mode, TImode, orig_mode,
+                                        cum->sse_regno + FIRST_SSE_REG);
          }
        break;
       case V8QImode:
@@ -2644,7 +2672,8 @@ function_arg (CUMULATIVE_ARGS *cum,       /* current arg information */
                         "changes the ABI");
              }
            if (cum->mmx_nregs)
-             ret = gen_rtx_REG (mode, cum->mmx_regno + FIRST_MMX_REG);
+             ret = gen_reg_or_parallel (mode, DImode, orig_mode,
+                                        cum->mmx_regno + FIRST_MMX_REG);
          }
        break;
       }
@@ -14897,10 +14926,20 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
   if (FP_REGNO_P (regno))
     return VALID_FP_MODE_P (mode);
   if (SSE_REGNO_P (regno))
-    return (TARGET_SSE ? VALID_SSE_REG_MODE (mode) : 0);
+    {
+      if (TARGET_SSE2 && VALID_SSE2_REG_MODE (mode))
+       return 1;
+      if (TARGET_SSE && VALID_SSE_REG_MODE (mode))
+       return 1;
+      return 0;
+    }
   if (MMX_REGNO_P (regno))
-    return (TARGET_MMX
-           ? VALID_MMX_REG_MODE (mode) || VALID_MMX_REG_MODE_3DNOW (mode) : 0);
+    {
+      if (TARGET_3DNOW && VALID_MMX_REG_MODE_3DNOW (mode))
+       return 1;
+      if (TARGET_MMX && VALID_MMX_REG_MODE (mode))
+       return 1;
+    }
   /* 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))
@@ -15236,7 +15275,9 @@ ix86_rtx_costs (rtx x, int code, int outer_code, int *total)
       return false;
 
     case FLOAT_EXTEND:
-      if (!TARGET_SSE_MATH || !VALID_SSE_REG_MODE (mode))
+      if (!TARGET_SSE_MATH
+         || mode == XFmode
+         || (mode == DFmode && !TARGET_SSE2))
        *total = 0;
       return false;
 
index 1472669cda3056ac6632e937f3da6572dd4dbf61..455a8c3a83bb012b48288abc8ca289fb670926f9 100644 (file)
@@ -1063,14 +1063,12 @@ do {                                                                    \
 
 #define VALID_SSE2_REG_MODE(MODE) \
     ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode    \
-     || (MODE) == V2DImode)
+     || (MODE) == V2DImode || (MODE) == DFmode                         \
+     || VALID_MMX_REG_MODE (MODE))
 
 #define VALID_SSE_REG_MODE(MODE)                                       \
     ((MODE) == TImode || (MODE) == V4SFmode || (MODE) == V4SImode      \
-     || (MODE) == SFmode || (MODE) == TFmode                           \
-     /* Always accept SSE2 modes so that xmmintrin.h compiles.  */     \
-     || VALID_SSE2_REG_MODE (MODE)                                     \
-     || (TARGET_SSE2 && ((MODE) == DFmode || VALID_MMX_REG_MODE (MODE))))
+     || (MODE) == SFmode || (MODE) == TFmode)
 
 #define VALID_MMX_REG_MODE_3DNOW(MODE) \
     ((MODE) == V2SFmode || (MODE) == SFmode)
index b3a575383416e058e36bafb23cb173d646d951be..ee2fbfc492323098fa28dc6e5cc36ecd314447e0 100644 (file)
 (define_insn "movv4sf_internal"
   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
        (match_operand:V4SF 1 "vector_move_operand" "C,xm,x"))]
-  "TARGET_SSE"
+  "TARGET_SSE
+   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
   "@
     xorps\t%0, %0
     movaps\t{%1, %0|%0, %1}
 (define_insn "movv4si_internal"
   [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,x,m")
        (match_operand:V4SI 1 "vector_move_operand" "C,xm,x"))]
-  "TARGET_SSE"
+  "TARGET_SSE
+   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
 {
   switch (which_alternative)
     {
               (const_string "TI")))])
 
 (define_insn "movv2di_internal"
-  [(set (match_operand:V2DI 0 "nonimmediate_operand" "=x,x,m")
-       (match_operand:V2DI 1 "vector_move_operand" "C,xm,x"))]
-  "TARGET_SSE"
+  [(set (match_operand:V2DI 0 "nonimmediate_operand" "=Y,Y,m")
+       (match_operand:V2DI 1 "vector_move_operand" "C,Ym,Y"))]
+  "TARGET_SSE2
+   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
 {
   switch (which_alternative)
     {
 (define_expand "movv2di"
   [(set (match_operand:V2DI 0 "nonimmediate_operand" "")
        (match_operand:V2DI 1 "nonimmediate_operand" ""))]
-  "TARGET_SSE"
+  "TARGET_SSE2"
 {
   ix86_expand_vector_move (V2DImode, operands);
   DONE;
 (define_insn "*pushv4si"
   [(set (match_operand:V4SI 0 "push_operand" "=<")
        (match_operand:V4SI 1 "register_operand" "x"))]
-  "TARGET_SSE2"
+  "TARGET_SSE"
   "#")
 
 (define_insn "*pushv2si"