From 3484da4bce0e92583c789241c50f34a25842e0ca Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 15 Dec 2004 12:03:23 -0800 Subject: [PATCH] re PR target/19010 (sse and mmx parameter passing broken) 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 | 16 +++++++++++ gcc/config/i386/i386.c | 63 ++++++++++++++++++++++++++++++++++------- gcc/config/i386/i386.h | 8 ++---- gcc/config/i386/i386.md | 17 ++++++----- 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6da3a6a9dfe9..2d64e510f8e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2004-12-15 Richard Henderson + + 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 PR c++/17972 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 8ef04b291cae..ecd8f073f5fc 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 1472669cda30..455a8c3a83bb 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b3a575383416..ee2fbfc49232 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -18423,7 +18423,8 @@ (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} @@ -18448,7 +18449,8 @@ (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) { @@ -18486,9 +18488,10 @@ (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) { @@ -18782,7 +18785,7 @@ (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; @@ -18863,7 +18866,7 @@ (define_insn "*pushv4si" [(set (match_operand:V4SI 0 "push_operand" "=<") (match_operand:V4SI 1 "register_operand" "x"))] - "TARGET_SSE2" + "TARGET_SSE" "#") (define_insn "*pushv2si" -- 2.47.2