]> gcc.gnu.org Git - gcc.git/commitdiff
re PR target/19010 (sse and mmx parameter passing broken)
authorRichard Henderson <rth@redhat.com>
Wed, 15 Dec 2004 17:41:58 +0000 (09:41 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 15 Dec 2004 17:41:58 +0000 (09:41 -0800)
        PR target/19010
        * config/i386/i386.c (ix86_must_pass_in_stack): Don't return true
        for TImode vectors.
        (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.
        (ix86_vector_mode_supported_p): Test SSE1 and SSE2 separately.
        * config/i386/i386.h (VALID_SSE2_REG_MODE): Move SSE2 cases from ...
        (VALID_SSE_REG_MODE): ... here.

        * gcc.target/i386/i386.exp: New harness.
        * gcc.target/i386/vect-args.c: New.

From-SVN: r92205

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/i386.exp [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/vect-args.c [new file with mode: 0644]

index 7c981a64ecf453b5a56119d39296f0f45bcf52d7..5f618627d887e7c4129dba96e7013f3a80ae5a53 100644 (file)
@@ -1,3 +1,17 @@
+2004-12-15  Richard Henderson  <rth@redhat.com>
+
+       PR target/19010
+       * config/i386/i386.c (ix86_must_pass_in_stack): Don't return true
+       for TImode vectors.
+       (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.
+       (ix86_vector_mode_supported_p): Test SSE1 and SSE2 separately.
+       * config/i386/i386.h (VALID_SSE2_REG_MODE): Move SSE2 cases from ...
+       (VALID_SSE_REG_MODE): ... here.
+
 2004-12-15  David Edelsohn  <edelsohn@gnu.org>
 
        * xcoffout.c (xcoffout_declare_function): Change strncpy to memcpy.
index 8819ba84bb0b6fa599a435fc4440c3c986ffb968..6ecf8a417c562cb2bc8082e924946a1b103c311a 100644 (file)
@@ -1943,7 +1943,12 @@ ix86_must_pass_in_stack (enum machine_mode mode, tree type)
 {
   if (must_pass_in_stack_var_size_or_pad (mode, type))
     return true;
-  return (!TARGET_64BIT && type && mode == TImode);
+
+  /* For 32-bit, we want TImode aggregates to go on the stack.  But watch out!
+     The layout_type routine is crafty and tries to trick us into passing
+     currently unsupported vector types on the stack by using TImode.  */
+  return (!TARGET_64BIT && mode == TImode
+         && type && TREE_CODE (type) != VECTOR_TYPE);
 }
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
@@ -2640,6 +2645,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.
@@ -2654,12 +2687,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;
@@ -2755,7 +2787,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:
@@ -2771,7 +2804,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;
       }
@@ -13991,10 +14025,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))
@@ -14372,7 +14416,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;
 
@@ -15164,20 +15210,15 @@ ix86_expand_vector_init (rtx target, rtx vals)
 static bool
 ix86_vector_mode_supported_p (enum machine_mode mode)
 {
-  if (TARGET_SSE
-      && VALID_SSE_REG_MODE (mode))
+  if (TARGET_SSE && VALID_SSE_REG_MODE (mode))
     return true;
-
-  else if (TARGET_MMX
-          && VALID_MMX_REG_MODE (mode))
+  if (TARGET_SSE2 && VALID_SSE2_REG_MODE (mode))
     return true;
-
-  else if (TARGET_3DNOW
-          && VALID_MMX_REG_MODE_3DNOW (mode))
+  if (TARGET_MMX && VALID_MMX_REG_MODE (mode))
     return true;
-
-  else
-    return false;
+  if (TARGET_3DNOW && VALID_MMX_REG_MODE_3DNOW (mode))
+    return true;
+  return false;
 }
 
 /* Worker function for TARGET_MD_ASM_CLOBBERS.
index a16f3084268938dfed5237de0a3b00aac9f89b6f..9063d85b1a7c640160ab6768ecaeaf09ef4cefe5 100644 (file)
@@ -1075,14 +1075,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 bfbe58fe084ebe264574ce10439ee1da0fe3772d..449213da5ac58028179de2b40e7553b9a9db28e5 100644 (file)
@@ -1,3 +1,8 @@
+2004-12-15  Richard Henderson  <rth@redhat.com>
+
+       * gcc.target/i386/i386.exp: New harness.
+       * gcc.target/i386/vect-args.c: New.
+
 2004-12-15  David Edelsohn  <edelsohn@gnu.org>
 
        * gcc.dg/20040813-1.c: Skip for *-*-aix*.
diff --git a/gcc/testsuite/gcc.target/i386/i386.exp b/gcc/testsuite/gcc.target/i386/i386.exp
new file mode 100644 (file)
index 0000000..4b92d4a
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright (C) 1997, 2004 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a SPARC target.
+if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then {
+  return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+    set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Special case compilation of vect-args.c so we don't have to
+# replicate it 10 times.
+foreach type { "" -mmmx -m3dnow -msse -msse2 } {
+  foreach level { "" -O } {
+    set flags "$type $level"
+    verbose -log "Testing vect-args, $flags" 1
+    dg-test $srcdir/$subdir/vect-args.c $flags ""
+  }
+}
+
+# Everything else.
+set tests [lsort [find $srcdir/$subdir *.\[cS\]]]
+set tests [prune $tests $srcdir/$subdir/vect-args.c]
+
+# Main loop.
+dg-runtest $tests "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/i386/vect-args.c b/gcc/testsuite/gcc.target/i386/vect-args.c
new file mode 100644 (file)
index 0000000..94b602d
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-w" } */
+
+/* SSE1 and SSE2 modes.  */
+typedef unsigned char V16QImode __attribute__((vector_size(16)));
+typedef unsigned short V8HImode __attribute__((vector_size(16)));
+typedef unsigned int V4SImode __attribute__((vector_size(16)));
+typedef unsigned long long V2DImode __attribute__((vector_size(16)));
+typedef float V4SFmode __attribute__((vector_size(16)));
+typedef double V2DFmode __attribute__((vector_size(16)));
+
+/* MMX and 3DNOW modes.  */
+typedef unsigned char V8QImode __attribute__((vector_size(8)));
+typedef unsigned short V4HImode __attribute__((vector_size(8)));
+typedef unsigned int V2SImode __attribute__((vector_size(8)));
+typedef float V2SFmode __attribute__((vector_size(8)));
+
+/* Test argument loading and unloading of each.  */
+#define TEST(TYPE)                                     \
+extern TYPE data_##TYPE;                               \
+void r_##TYPE (TYPE x) { data_##TYPE = x; }            \
+void s_##TYPE (void) { r_##TYPE (data_##TYPE); }
+
+TEST(V16QImode)
+TEST(V8HImode)
+TEST(V4SImode)
+TEST(V2DImode)
+TEST(V4SFmode)
+TEST(V2DFmode)
+TEST(V8QImode)
+TEST(V4HImode)
+TEST(V2SImode)
+TEST(V2SFmode)
This page took 0.10903 seconds and 5 git commands to generate.