aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@gcc.gnu.org>2002-06-18 01:35:47 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2002-06-18 01:35:47 +0000
commitcb2a532e9fe754ec238fe679a131e1fd1c8c340e (patch)
tree73deecdababef51a80958fcc5dee4038fb6bac71 /gcc/optabs.c
parent147d5f6f769614edda4de1f400fc603496da5170 (diff)
downloadgcc-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.c133
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)