diff options
author | Aldy Hernandez <aldyh@gcc.gnu.org> | 2002-06-18 01:35:47 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2002-06-18 01:35:47 +0000 |
commit | cb2a532e9fe754ec238fe679a131e1fd1c8c340e (patch) | |
tree | 73deecdababef51a80958fcc5dee4038fb6bac71 /gcc/optabs.c | |
parent | 147d5f6f769614edda4de1f400fc603496da5170 (diff) | |
download | gcc-cb2a532e9fe754ec238fe679a131e1fd1c8c340e.zip gcc-cb2a532e9fe754ec238fe679a131e1fd1c8c340e.tar.gz gcc-cb2a532e9fe754ec238fe679a131e1fd1c8c340e.tar.bz2 |
simd-1.c: New.
2002-06-16 Aldy Hernandez <aldyh@redhat.com>
* gcc.c-torture/execute/simd-1.c: New.
* gcc.dg/simd-1.c: New.
* doc/extend.texi (Vector Extensions): Document that we can
specify simd types not specifically supported by the hardware.
Document that simd types can be used as function arguments.
Document that signness does make a difference in SIMD types.
Misc cleanups and revisions to the "vector extensions" section.
* simplify-rtx.c (simplify_subreg): Simplify subregs of vector
constants.
* expr.c (vector_mode_valid_p): New.
* expr.h: Add vector_mode_valid_p.
* defaults.h (VECTOR_MODE_SUPPORTED_P): Set default.
* emit-rtl.c (immed_double_const): Do not abort on vectors.
* c-common.c (type_for_mode): Always build vector nodes regardless
of VECTOR_MODE_SUPPORTED_P.
(handle_mode_attribute): Error if we can't emulate a nonexisting
vector mode.
(handle_vector_size_attribute): Same.
* optabs.c (expand_binop): Open-code vector operations.
(expand_unop): Open-code vector unops.
(expand_vector_binop): New.
(expand_vector_unop): New.
* c-typeck.c (build_binary_op): Allow vectors in binops.
Allow vectors in conditional operatiors.
(build_unary_op): Allow vectors in unary minus.
* config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Conditionalize on
TARGET_ALTIVEC.
From-SVN: r54727
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r-- | gcc/optabs.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index 88cdf2f..61990e3 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -120,6 +120,11 @@ static void emit_cmp_and_jump_insn_1 PARAMS ((rtx, rtx, enum machine_mode, enum rtx_code, int, rtx)); static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *, enum machine_mode *, int *)); +static rtx expand_vector_binop PARAMS ((enum machine_mode, optab, + rtx, rtx, rtx, int, + enum optab_methods)); +static rtx expand_vector_unop PARAMS ((enum machine_mode, optab, rtx, rtx, + int)); /* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to the result of operation CODE applied to OP0 (and OP1 if it is a binary @@ -1531,6 +1536,12 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) delete_insns_since (last); } + /* Open-code the vector operations if we have no hardware support + for them. */ + if (class == MODE_VECTOR_INT || class == MODE_VECTOR_FLOAT) + return expand_vector_binop (mode, binoptab, op0, op1, target, + unsignedp, methods); + /* We need to open-code the complex type operations: '+, -, * and /' */ /* At this point we allow operations between two similar complex @@ -1900,6 +1911,125 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) delete_insns_since (entry_last); return 0; } + +/* Like expand_binop, but for open-coding vectors binops. */ + +static rtx +expand_vector_binop (mode, binoptab, op0, op1, target, unsignedp, methods) + enum machine_mode mode; + optab binoptab; + rtx op0, op1; + rtx target; + int unsignedp; + enum optab_methods methods; +{ + enum machine_mode submode; + int elts, i; + rtx t, a, b, res, seq; + enum mode_class class; + + class = GET_MODE_CLASS (mode); + + submode = GET_MODE_INNER (mode); + elts = GET_MODE_NUNITS (mode); + + if (!target) + target = gen_reg_rtx (mode); + + start_sequence (); + + /* FIXME: Optimally, we should try to do this in narrower vector + modes if available. E.g. When trying V8SI, try V4SI, else + V2SI, else decay into SI. */ + + switch (binoptab->code) + { + case PLUS: + case MINUS: + case MULT: + case DIV: + for (i = 0; i < elts; ++i) + { + t = simplify_gen_subreg (submode, target, mode, + i * UNITS_PER_WORD); + a = simplify_gen_subreg (submode, op0, mode, + i * UNITS_PER_WORD); + b = simplify_gen_subreg (submode, op1, mode, + i * UNITS_PER_WORD); + + if (binoptab->code == DIV) + { + if (class == MODE_VECTOR_FLOAT) + res = expand_binop (submode, binoptab, a, b, t, + unsignedp, methods); + else + res = expand_divmod (0, TRUNC_DIV_EXPR, submode, + a, b, t, unsignedp); + } + else + res = expand_binop (submode, binoptab, a, b, t, + unsignedp, methods); + + if (res == 0) + break; + + emit_move_insn (t, res); + } + break; + + default: + abort (); + } + + seq = get_insns (); + end_sequence (); + emit_insn (seq); + + return target; +} + +/* Like expand_unop but for open-coding vector unops. */ + +static rtx +expand_vector_unop (mode, unoptab, op0, target, unsignedp) + enum machine_mode mode; + optab unoptab; + rtx op0; + rtx target; + int unsignedp; +{ + enum machine_mode submode; + int elts, i; + rtx t, a, res, seq; + + submode = GET_MODE_INNER (mode); + elts = GET_MODE_NUNITS (mode); + + if (!target) + target = gen_reg_rtx (mode); + + start_sequence (); + + /* FIXME: Optimally, we should try to do this in narrower vector + modes if available. E.g. When trying V8SI, try V4SI, else + V2SI, else decay into SI. */ + + for (i = 0; i < elts; ++i) + { + t = simplify_gen_subreg (submode, target, mode, i * UNITS_PER_WORD); + a = simplify_gen_subreg (submode, op0, mode, i * UNITS_PER_WORD); + + res = expand_unop (submode, unoptab, a, t, unsignedp); + + emit_move_insn (t, res); + } + + seq = get_insns (); + end_sequence (); + emit_insn (seq); + + return target; +} /* Expand a binary operator which has both signed and unsigned forms. UOPTAB is the optab for unsigned operations, and SOPTAB is for @@ -2324,6 +2454,9 @@ expand_unop (mode, unoptab, op0, target, unsignedp) return target; } + if (class == MODE_VECTOR_FLOAT || class == MODE_VECTOR_INT) + return expand_vector_unop (mode, unoptab, op0, target, unsignedp); + /* It can't be done in this mode. Can we do it in a wider mode? */ if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) |