aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-12-15 09:41:58 -0800
committerRichard Henderson <rth@gcc.gnu.org>2004-12-15 09:41:58 -0800
commitdcbca208a35a734fb1098661ae4681f23b197cb9 (patch)
treeda5e44fa449ec06fe9f6570598b4737ab7cd9145 /gcc/config
parent4586c5575b07cf7264179b939197f653774d71f0 (diff)
downloadgcc-dcbca208a35a734fb1098661ae4681f23b197cb9.zip
gcc-dcbca208a35a734fb1098661ae4681f23b197cb9.tar.gz
gcc-dcbca208a35a734fb1098661ae4681f23b197cb9.tar.bz2
re PR target/19010 (sse and mmx parameter passing broken)
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
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c87
-rw-r--r--gcc/config/i386/i386.h8
2 files changed, 67 insertions, 28 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8819ba8..6ecf8a4 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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.
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index a16f308..9063d85 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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)