diff options
author | Eric Botcazou <ebotcazou@libertysurf.fr> | 2004-11-06 18:06:05 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2004-11-06 17:06:05 +0000 |
commit | 45261626da8e061958c44be098de4c38cca60acf (patch) | |
tree | e467f18493f5713b5223d86ab110b758c6dc221e | |
parent | 8d43449beeca514721c7bc676fe7b5879810ca42 (diff) | |
download | gcc-45261626da8e061958c44be098de4c38cca60acf.zip gcc-45261626da8e061958c44be098de4c38cca60acf.tar.gz gcc-45261626da8e061958c44be098de4c38cca60acf.tar.bz2 |
sparc.c (scan_record_type): Handle vector types.
* config/sparc/sparc.c (scan_record_type): Handle vector types.
(function_arg_slotno): Handle vector types specially.
(function_arg_record_value_1): Split fields with vector type and
BLKmode into their subparts.
(function_arg_record_value_2): Likewise. Be prepared to handle
more than 2 registers per field.
(function_arg_union_value): Increment regno inside the loop.
(function_arg_vector_value): New function.
(function_arg): Use it to split fields with vector type and
BLKmode into their subparts and build a PARALLEL. Treat
other vector types like floats.
(function_value): Likewise.
(sparc_pass_by_reference): Handle vector types.
(sparc_return_in_memory): Likewise.
From-SVN: r90179
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 287 |
2 files changed, 232 insertions, 72 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c9429d1..138c140 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2004-11-06 Eric Botcazou <ebotcazou@libertysurf.fr> + + * config/sparc/sparc.c (scan_record_type): Handle vector types. + (function_arg_slotno): Handle vector types specially. + (function_arg_record_value_1): Split fields with vector type and + BLKmode into their subparts. + (function_arg_record_value_2): Likewise. Be prepared to handle + more than 2 registers per field. + (function_arg_union_value): Increment regno inside the loop. + (function_arg_vector_value): New function. + (function_arg): Use it to split fields with vector type and + BLKmode into their subparts and build a PARALLEL. Treat + other vector types like floats. + (function_value): Likewise. + (sparc_pass_by_reference): Handle vector types. + (sparc_return_in_memory): Likewise. + 2004-11-06 Kazu Hirata <kazu@cs.umass.edu> * tree-cfg.c (find_taken_edge_cond_expr): Remove an "if" diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 3371db9..d44ab95 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -4928,8 +4928,7 @@ output_sibcall (rtx insn, rtx call_operand) _Complex double 16 memory FP reg. _Complex long double 32 memory FP reg. - vector float <=32 memory FP reg. - vector float >32 memory memory + vector float any memory memory aggregate any memory memory @@ -4974,8 +4973,8 @@ implemented by the Sun compiler. Note #2: integral vector types follow the scalar floating-point types conventions to match what is implemented by the Sun VIS SDK. -Note #3: floating-point vector types follow the complex floating-point -types conventions. */ +Note #3: floating-point vector types follow the aggregate types +conventions. */ /* Maximum number of int regs for args. */ @@ -5037,7 +5036,9 @@ scan_record_type (tree type, int *intregs_p, int *fpregs_p, int *packed_p) { if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE) scan_record_type (TREE_TYPE (field), intregs_p, fpregs_p, 0); - else if (FLOAT_TYPE_P (TREE_TYPE (field)) && TARGET_FPU) + else if ((FLOAT_TYPE_P (TREE_TYPE (field)) + || TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE) + && TARGET_FPU) *fpregs_p = 1; else *intregs_p = 1; @@ -5072,6 +5073,7 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode, ? SPARC_INCOMING_INT_ARG_FIRST : SPARC_OUTGOING_INT_ARG_FIRST); int slotno = cum->words; + enum mode_class mclass; int regno; *ppadding = 0; @@ -5091,12 +5093,37 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode, && (slotno & 1) != 0) slotno++, *ppadding = 1; - switch (GET_MODE_CLASS (mode)) + mclass = GET_MODE_CLASS (mode); + if (type && TREE_CODE (type) == VECTOR_TYPE) + { + /* Vector types deserve special treatment because they are + polymorphic wrt their mode, depending upon whether VIS + instructions are enabled. */ + if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) + { + /* The SPARC port defines no floating-point vector modes. */ + if (mode != BLKmode) + abort (); + } + else + { + /* Integral vector types should either have a vector + mode or an integral mode, because we are guaranteed + by pass_by_reference that their size is not greater + than 16 bytes and TImode is 16-byte wide. */ + if (mode == BLKmode) + abort (); + + /* Vector integers are handled like floats according to + the Sun VIS SDK. */ + mclass = MODE_FLOAT; + } + } + + switch (mclass) { case MODE_FLOAT: case MODE_COMPLEX_FLOAT: - case MODE_VECTOR_INT: - case MODE_VECTOR_FLOAT: if (TARGET_ARCH64 && TARGET_FPU && named) { if (slotno >= SPARC_FP_ARG_MAX) @@ -5132,18 +5159,21 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode, && (slotno & 1) != 0) slotno++, *ppadding = 1; - if (TARGET_ARCH32 || (type && TREE_CODE (type) == UNION_TYPE)) + if (TARGET_ARCH32 || !type || (TREE_CODE (type) == UNION_TYPE)) { if (slotno >= SPARC_INT_ARG_MAX) return -1; regno = regbase + slotno; } - else /* TARGET_ARCH64 && type && TREE_CODE (type) == RECORD_TYPE */ + else /* TARGET_ARCH64 && type */ { int intregs_p = 0, fpregs_p = 0, packed_p = 0; /* First see what kinds of registers we would need. */ - scan_record_type (type, &intregs_p, &fpregs_p, &packed_p); + if (TREE_CODE (type) == VECTOR_TYPE) + fpregs_p = 1; + else + scan_record_type (type, &intregs_p, &fpregs_p, &packed_p); /* The ABI obviously doesn't specify how packed structures are passed. These are defined to be passed in int regs @@ -5274,8 +5304,12 @@ function_arg_record_value_1 (tree type, HOST_WIDE_INT startbitpos, /* There's no need to check this_slotno < SPARC_FP_ARG MAX. If it wasn't true we wouldn't be here. */ - parms->nregs += 1; - if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE) + if (TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE + && DECL_MODE (field) == BLKmode) + parms->nregs += TYPE_VECTOR_SUBPARTS (TREE_TYPE (field)); + else if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE) + parms->nregs += 2; + else parms->nregs += 1; } else @@ -5389,34 +5423,41 @@ function_arg_record_value_2 (tree type, HOST_WIDE_INT startbitpos, && ! packed_p) { int this_slotno = parms->slotno + bitpos / BITS_PER_WORD; - int regno; + int regno, nregs, pos; enum machine_mode mode = DECL_MODE (field); rtx reg; function_arg_record_value_3 (bitpos, parms); - switch (mode) - { - case SCmode: mode = SFmode; break; - case DCmode: mode = DFmode; break; - case TCmode: mode = TFmode; break; - default: break; + + if (TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE + && mode == BLKmode) + { + mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field))); + nregs = TYPE_VECTOR_SUBPARTS (TREE_TYPE (field)); } + else if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE) + { + mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field))); + nregs = 2; + } + else + nregs = 1; + regno = SPARC_FP_ARG_FIRST + this_slotno * 2; if (GET_MODE_SIZE (mode) <= 4 && (bitpos & 32) != 0) regno++; reg = gen_rtx_REG (mode, regno); + pos = bitpos / BITS_PER_UNIT; XVECEXP (parms->ret, 0, parms->stack + parms->nregs) - = gen_rtx_EXPR_LIST (VOIDmode, reg, - GEN_INT (bitpos / BITS_PER_UNIT)); + = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (pos)); parms->nregs += 1; - if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE) + while (--nregs > 0) { regno += GET_MODE_SIZE (mode) / 4; reg = gen_rtx_REG (mode, regno); + pos += GET_MODE_SIZE (mode); XVECEXP (parms->ret, 0, parms->stack + parms->nregs) - = gen_rtx_EXPR_LIST (VOIDmode, reg, - GEN_INT ((bitpos + GET_MODE_BITSIZE (mode)) - / BITS_PER_UNIT)); + = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (pos)); parms->nregs += 1; } } @@ -5547,14 +5588,47 @@ function_arg_union_value (int size, enum machine_mode mode, int regno) int nwords = ROUND_ADVANCE (size), i; rtx regs; - /* Unions are passed left-justified. */ regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords)); for (i = 0; i < nwords; i++) - XVECEXP (regs, 0, i) - = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_REG (word_mode, regno + i), - GEN_INT (UNITS_PER_WORD * i)); + { + /* Unions are passed left-justified. */ + XVECEXP (regs, 0, i) + = gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_REG (word_mode, regno), + GEN_INT (UNITS_PER_WORD * i)); + regno++; + } + + return regs; +} + +/* Used by function_arg and function_value to implement the conventions + for passing and returning large (BLKmode) vectors. + Return an expression valid as a return value for the two macros + FUNCTION_ARG and FUNCTION_VALUE. + + SIZE is the size in bytes of the vector. + BASE_MODE is the argument's base machine mode. + REGNO is the FP hard register the vector will be passed in. */ + +static rtx +function_arg_vector_value (int size, enum machine_mode base_mode, int regno) +{ + unsigned short base_mode_size = GET_MODE_SIZE (base_mode); + int nregs = size / base_mode_size, i; + rtx regs; + + regs = gen_rtx_PARALLEL (BLKmode, rtvec_alloc (nregs)); + + for (i = 0; i < nregs; i++) + { + XVECEXP (regs, 0, i) + = gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_REG (base_mode, regno), + GEN_INT (base_mode_size * i)); + regno += base_mode_size / 4; + } return regs; } @@ -5582,6 +5656,7 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode, ? SPARC_INCOMING_INT_ARG_FIRST : SPARC_OUTGOING_INT_ARG_FIRST); int slotno, regno, padding; + enum mode_class mclass = GET_MODE_CLASS (mode); rtx reg; slotno = function_arg_slotno (cum, mode, type, named, incoming_p, @@ -5615,14 +5690,29 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode, return function_arg_union_value (size, mode, regno); } + else if (type && TREE_CODE (type) == VECTOR_TYPE) + { + /* Vector types deserve special treatment because they are + polymorphic wrt their mode, depending upon whether VIS + instructions are enabled. */ + HOST_WIDE_INT size = int_size_in_bytes (type); + + if (size > 16) + abort (); /* shouldn't get here */ + + if (mode == BLKmode) + return function_arg_vector_value (size, + TYPE_MODE (TREE_TYPE (type)), + SPARC_FP_ARG_FIRST + 2*slotno); + else + mclass = MODE_FLOAT; + } + /* v9 fp args in reg slots beyond the int reg slots get passed in regs but also have the slot allocated for them. If no prototype is in scope fp values in register slots get passed in two places, either fp regs and int regs or fp regs and memory. */ - else if ((GET_MODE_CLASS (mode) == MODE_FLOAT - || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT - || GET_MODE_CLASS (mode) == MODE_VECTOR_INT - || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) && SPARC_FP_REG_P (regno)) { reg = gen_rtx_REG (mode, regno); @@ -5760,11 +5850,8 @@ function_arg_partial_nregs (const struct sparc_args *cum, return 0; } -/* Return true if the argument should be passed by reference. - !v9: The SPARC ABI stipulates passing struct arguments (of any size) and - quad-precision floats by invisible reference. - v9: Aggregates greater than 16 bytes are passed by reference. - For Pascal, also pass arrays by reference. */ +/* Handle the TARGET_PASS_BY_REFERENCE target hook. + Specify whether to pass the argument by reference. */ static bool sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, @@ -5773,23 +5860,48 @@ sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, { if (TARGET_ARCH32) { - return ((type && AGGREGATE_TYPE_P (type)) - /* Extended ABI (as implemented by the Sun compiler) says - that all complex floats are passed in memory. */ + /* Original SPARC 32-bit ABI says that structures and unions, + and quad-precision floats are passed by reference. For Pascal, + also pass arrays by reference. All other base types are passed + in registers. + + Extended ABI (as implemented by the Sun compiler) says that all + complex floats are passed by reference. Pass complex integers + in registers up to 8 bytes. More generally, enforce the 2-word + cap for passing arguments in registers. + + Vector ABI (as implemented by the Sun VIS SDK) says that vector + integers are passed like floats of the same size, that is in + registers up to 8 bytes. Pass all vector floats by reference + like structure and unions. */ + return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type))) || mode == SCmode - /* Enforce the 2-word cap for passing arguments in registers. - This affects CDImode, TFmode, DCmode, TCmode and large - vector modes. */ - || GET_MODE_SIZE (mode) > 8); + /* Catch CDImode, TFmode, DCmode and TCmode. */ + || GET_MODE_SIZE (mode) > 8 + || (type + && TREE_CODE (type) == VECTOR_TYPE + && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8)); } else { + /* Original SPARC 64-bit ABI says that structures and unions + smaller than 16 bytes are passed in registers, as well as + all other base types. For Pascal, pass arrays by reference. + + Extended ABI (as implemented by the Sun compiler) says that + complex floats are passed in registers up to 16 bytes. Pass + all complex integers in registers up to 16 bytes. More generally, + enforce the 2-word cap for passing arguments in registers. + + Vector ABI (as implemented by the Sun VIS SDK) says that vector + integers are passed like floats of the same size, that is in + registers (up to 16 bytes). Pass all vector floats like structure + and unions. */ return ((type && TREE_CODE (type) == ARRAY_TYPE) || (type - && AGGREGATE_TYPE_P (type) + && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE) && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16) - /* Enforce the 2-word cap for passing arguments in registers. - This affects CTImode, TCmode and large vector modes. */ + /* Catch CTImode and TCmode. */ || GET_MODE_SIZE (mode) > 16); } } @@ -5861,30 +5973,40 @@ static bool sparc_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) { if (TARGET_ARCH32) - /* Original SPARC 32-bit ABI says that quad-precision floats - and all structures are returned in memory. Extended ABI - (as implemented by the Sun compiler) says that all complex - floats are returned in registers (8 FP registers at most - for '_Complex long double'). Return all complex integers - in registers (4 at most for '_Complex long long'). */ + /* Original SPARC 32-bit ABI says that structures and unions, + and quad-precision floats are returned in memory. All other + base types are returned in registers. + + Extended ABI (as implemented by the Sun compiler) says that + all complex floats are returned in registers (8 FP registers + at most for '_Complex long double'). Return all complex integers + in registers (4 at most for '_Complex long long'). + + Vector ABI (as implemented by the Sun VIS SDK) says that vector + integers are returned like floats of the same size, that is in + registers up to 8 bytes and in memory otherwise. Return all + vector floats in memory like structure and unions; note that + they always have BLKmode like the latter. */ return (TYPE_MODE (type) == BLKmode || TYPE_MODE (type) == TFmode - /* Integral vector types follow the scalar FP types conventions. */ - || (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_INT - && GET_MODE_SIZE (TYPE_MODE (type)) > 8) - /* FP vector types follow the complex FP types conventions. */ - || (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_FLOAT - && GET_MODE_SIZE (TYPE_MODE (type)) > 32)); + || (TREE_CODE (type) == VECTOR_TYPE + && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8)); else /* Original SPARC 64-bit ABI says that structures and unions - smaller than 32 bytes are returned in registers. Extended - ABI (as implemented by the Sun compiler) says that all complex - floats are returned in registers (8 FP registers at most - for '_Complex long double'). Return all complex integers - in registers (4 at most for '_Complex TItype'). */ + smaller than 32 bytes are returned in registers, as well as + all other base types. + + Extended ABI (as implemented by the Sun compiler) says that all + complex floats are returned in registers (8 FP registers at most + for '_Complex long double'). Return all complex integers in + registers (4 at most for '_Complex TItype'). + + Vector ABI (as implemented by the Sun VIS SDK) says that vector + integers are returned like floats of the same size, that is in + registers. Return all vector floats like structure and unions; + note that they always have BLKmode like the latter. */ return ((TYPE_MODE (type) == BLKmode - && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 32) - || GET_MODE_SIZE (TYPE_MODE (type)) > 32); + && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 32)); } /* Handle the TARGET_STRUCT_VALUE target hook. @@ -5917,9 +6039,27 @@ function_value (tree type, enum machine_mode mode, int incoming_p) int regbase = (incoming_p ? SPARC_OUTGOING_INT_ARG_FIRST : SPARC_INCOMING_INT_ARG_FIRST); + enum mode_class mclass = GET_MODE_CLASS (mode); int regno; - if (TARGET_ARCH64 && type) + if (type && TREE_CODE (type) == VECTOR_TYPE) + { + /* Vector types deserve special treatment because they are + polymorphic wrt their mode, depending upon whether VIS + instructions are enabled. */ + HOST_WIDE_INT size = int_size_in_bytes (type); + + if ((TARGET_ARCH32 && size > 8) || (TARGET_ARCH64 && size > 32)) + abort (); /* shouldn't get here */ + + if (mode == BLKmode) + return function_arg_vector_value (size, + TYPE_MODE (TREE_TYPE (type)), + SPARC_FP_ARG_FIRST); + else + mclass = MODE_FLOAT; + } + else if (type && TARGET_ARCH64) { if (TREE_CODE (type) == RECORD_TYPE) { @@ -5962,13 +6102,16 @@ function_value (tree type, enum machine_mode mode, int incoming_p) for unions in that case. */ if (mode == BLKmode) return function_arg_union_value (bytes, mode, regbase); + else + mclass = MODE_INT; } - else if (GET_MODE_CLASS (mode) == MODE_INT + else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD) mode = word_mode; } - if (TARGET_FPU && (FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode))) + if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) + && TARGET_FPU) regno = SPARC_FP_ARG_FIRST; else regno = regbase; |