summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordpatel <dpatel@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-28 00:13:12 +0000
committerdpatel <dpatel@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-28 00:13:12 +0000
commit6b7acc28494ae8de5616895bd43ff652b08db4ef (patch)
treed499fabff1893bbf2a9b76b6065afdd79d7c845b
parent01ff45405b5a53582bf0938fecf5d7473bf0f3e1 (diff)
downloadppe42-gcc-6b7acc28494ae8de5616895bd43ff652b08db4ef.tar.gz
ppe42-gcc-6b7acc28494ae8de5616895bd43ff652b08db4ef.zip
* expr.c (expand_expr_real_1): Handle VEC_COND_EXPR.
* genopinit.c (optabs): New entry for vcond_gen_code and vcondu_gen_code. * optabs.c (vcond_gen_code, vcondu_gen_code): New optabs. (get_rtx_code): New function. (vector_compare_rtx): New function. (init_optabs): Initialize vcond_gen_code and vcondu_gen_code. (expand_vec_cond_expr_p): New function. (expand_vec_cond_expr): New function. (get_vcond_icode): New function. * optabs.h (expand_vec_cond_expr, expand_vec_cond_expr_p): New externs. (vcond_gen_code, vcondu_gen_code): Same. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@88209 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/expr.c4
-rw-r--r--gcc/genopinit.c4
-rw-r--r--gcc/optabs.c179
-rw-r--r--gcc/optabs.h12
5 files changed, 212 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b3c3a529003..f392069de66 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2004-09-27 Devang Patel <dpatel@apple.com>
+
+ * expr.c (expand_expr_real_1): Handle VEC_COND_EXPR.
+ * genopinit.c (optabs): New entry for vcond_gen_code and
+ vcondu_gen_code.
+ * optabs.c (vcond_gen_code, vcondu_gen_code): New optabs.
+ (get_rtx_code): New function.
+ (vector_compare_rtx): New function.
+ (init_optabs): Initialize vcond_gen_code and vcondu_gen_code.
+ (expand_vec_cond_expr_p): New function.
+ (expand_vec_cond_expr): New function.
+ (get_vcond_icode): New function.
+ * optabs.h (expand_vec_cond_expr, expand_vec_cond_expr_p): New externs.
+ (vcond_gen_code, vcondu_gen_code): Same.
+
2004-09-27 Kelley Cook <kcook@gcc.gnu.org>
* Makefile.in (STAGESTUFF): Split into ...
@@ -45,7 +60,6 @@
* tree-pretty-print.c (dump_generic_node): Print VEC_COND_EXPR.
(print_call_name): Do not print VEC_COND_EXPR.
-
2004-09-27 Devang Patel <dpatel@apple.com>
diff --git a/gcc/expr.c b/gcc/expr.c
index 96cab626f7b..ff8355bc738 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8053,6 +8053,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
OK_DEFER_POP;
return temp;
+ case VEC_COND_EXPR:
+ target = expand_vec_cond_expr (exp, target);
+ return target;
+
case MODIFY_EXPR:
{
/* If lhs is complex, expand calls in rhs before computing it.
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 0d39f67ef75..8c6c8feb292 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -171,7 +171,9 @@ static const char * const optabs[] =
"vec_extract_optab->handlers[$A].insn_code = CODE_FOR_$(vec_extract$a$)",
"vec_init_optab->handlers[$A].insn_code = CODE_FOR_$(vec_init$a$)",
"vec_realign_store_optab->handlers[$A].insn_code = CODE_FOR_$(vec_realign_store_$a$)",
- "vec_realign_load_optab->handlers[$A].insn_code = CODE_FOR_$(vec_realign_load_$a$)" };
+ "vec_realign_load_optab->handlers[$A].insn_code = CODE_FOR_$(vec_realign_load_$a$)",
+ "vcond_gen_code[$A] = CODE_FOR_$(vcond$a$)",
+ "vcondu_gen_code[$A] = CODE_FOR_$(vcondu$a$)" };
static void gen_insn (rtx);
diff --git a/gcc/optabs.c b/gcc/optabs.c
index abb69700a04..8354f7878fc 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -84,6 +84,12 @@ enum insn_code setcc_gen_code[NUM_RTX_CODE];
enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
#endif
+/* Indexed by the machine mode, gives the insn code for vector conditional
+ operation. */
+
+enum insn_code vcond_gen_code[NUM_MACHINE_MODES];
+enum insn_code vcondu_gen_code[NUM_MACHINE_MODES];
+
/* The insn generating function can not take an rtx_code argument.
TRAP_RTX is used as an rtx argument. Its code is replaced with
the code to be used in the trap insn and all other fields are ignored. */
@@ -116,6 +122,8 @@ static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *,
enum machine_mode *, int *);
static rtx widen_clz (enum machine_mode, rtx, rtx);
static rtx expand_parity (enum machine_mode, rtx, rtx);
+static enum rtx_code get_rtx_code (enum tree_code, bool);
+static rtx vector_compare_rtx (tree, bool, enum insn_code);
#ifndef HAVE_conditional_trap
#define HAVE_conditional_trap 0
@@ -2982,7 +2990,6 @@ can_compare_p (enum rtx_code code, enum machine_mode mode,
if (purpose == ccp_store_flag
&& cstore_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
return 1;
-
mode = GET_MODE_WIDER_MODE (mode);
}
while (mode != VOIDmode);
@@ -4649,6 +4656,12 @@ init_optabs (void)
movcc_gen_code[i] = CODE_FOR_nothing;
#endif
+ for (i = 0; i < NUM_MACHINE_MODES; i++)
+ {
+ vcond_gen_code[i] = CODE_FOR_nothing;
+ vcondu_gen_code[i] = CODE_FOR_nothing;
+ }
+
add_optab = init_optab (PLUS);
addv_optab = init_optabv (PLUS);
sub_optab = init_optab (MINUS);
@@ -4992,4 +5005,168 @@ gen_cond_trap (enum rtx_code code ATTRIBUTE_UNUSED, rtx op1,
return insn;
}
+/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
+ or unsigned operation code. */
+
+static enum rtx_code
+get_rtx_code (enum tree_code tcode, bool unsignedp)
+{
+ enum rtx_code code;
+ switch (tcode)
+ {
+ case EQ_EXPR:
+ code = EQ;
+ break;
+ case NE_EXPR:
+ code = NE;
+ break;
+ case LT_EXPR:
+ code = unsignedp ? LTU : LT;
+ break;
+ case LE_EXPR:
+ code = unsignedp ? LEU : LE;
+ break;
+ case GT_EXPR:
+ code = unsignedp ? GTU : GT;
+ break;
+ case GE_EXPR:
+ code = unsignedp ? GEU : GE;
+ break;
+
+ case UNORDERED_EXPR:
+ code = UNORDERED;
+ break;
+ case ORDERED_EXPR:
+ code = ORDERED;
+ break;
+ case UNLT_EXPR:
+ code = UNLT;
+ break;
+ case UNLE_EXPR:
+ code = UNLE;
+ break;
+ case UNGT_EXPR:
+ code = UNGT;
+ break;
+ case UNGE_EXPR:
+ code = UNGE;
+ break;
+ case UNEQ_EXPR:
+ code = UNEQ;
+ break;
+ case LTGT_EXPR:
+ code = LTGT;
+ break;
+
+ default:
+ abort ();
+ }
+ return code;
+}
+
+/* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
+ unsigned operators. Do not generate compare instruction. */
+
+static rtx
+vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
+{
+ enum rtx_code rcode;
+ tree t_op0, t_op1;
+ rtx rtx_op0, rtx_op1;
+
+ if (TREE_CODE_CLASS (TREE_CODE (cond)) != '<')
+ {
+ /* This is unlikely. While generating VEC_COND_EXPR,
+ auto vectorizer ensures that condition is a relational
+ operation. */
+ abort ();
+ }
+ else
+ {
+ rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
+ t_op0 = TREE_OPERAND (cond, 0);
+ t_op1 = TREE_OPERAND (cond, 1);
+ }
+
+ /* Expand operands. */
+ rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)), 1);
+ rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)), 1);
+
+ if (!(*insn_data[icode].operand[4].predicate) (rtx_op0, GET_MODE (rtx_op0))
+ && GET_MODE (rtx_op0) != VOIDmode)
+ rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
+
+ if (!(*insn_data[icode].operand[5].predicate) (rtx_op1, GET_MODE (rtx_op1))
+ && GET_MODE (rtx_op1) != VOIDmode)
+ rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
+
+ return gen_rtx_fmt_ee (rcode, VOIDmode, rtx_op0, rtx_op1);
+}
+
+/* Return insn code for VEC_COND_EXPR EXPR. */
+
+static inline enum insn_code
+get_vcond_icode (tree expr, enum machine_mode mode)
+{
+ enum insn_code icode = CODE_FOR_nothing;
+
+ if (TYPE_UNSIGNED (TREE_TYPE (expr)))
+ icode = vcondu_gen_code[mode];
+ else
+ icode = vcond_gen_code[mode];
+ return icode;
+}
+
+/* Return TRUE iff, appropriate vector insns are available
+ for vector cond expr expr in VMODE mode. */
+
+bool
+expand_vec_cond_expr_p (tree expr, enum machine_mode vmode)
+{
+ if (get_vcond_icode (expr, vmode) == CODE_FOR_nothing)
+ return false;
+ return true;
+}
+
+/* Generate insns for VEC_COND_EXPR. */
+
+rtx
+expand_vec_cond_expr (tree vec_cond_expr, rtx target)
+{
+ enum insn_code icode;
+ rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (vec_cond_expr));
+ bool unsignedp = TYPE_UNSIGNED (TREE_TYPE (vec_cond_expr));
+
+ icode = get_vcond_icode (vec_cond_expr, mode);
+ if (icode == CODE_FOR_nothing)
+ return 0;
+
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ /* Get comparision rtx. First expand both cond expr operands. */
+ comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
+ unsignedp, icode);
+ cc_op0 = XEXP (comparison, 0);
+ cc_op1 = XEXP (comparison, 1);
+ /* Expand both operands and force them in reg, if required. */
+ rtx_op1 = expand_expr (TREE_OPERAND (vec_cond_expr, 1),
+ NULL_RTX, VOIDmode, 1);
+ if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode)
+ && mode != VOIDmode)
+ rtx_op1 = force_reg (mode, rtx_op1);
+
+ rtx_op2 = expand_expr (TREE_OPERAND (vec_cond_expr, 2),
+ NULL_RTX, VOIDmode, 1);
+ if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode)
+ && mode != VOIDmode)
+ rtx_op2 = force_reg (mode, rtx_op2);
+
+ /* Emit instruction! */
+ emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
+ comparison, cc_op0, cc_op1));
+
+ return target;
+}
#include "gt-optabs.h"
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 8e895f203c5..68be8d35e7f 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -398,6 +398,12 @@ extern enum insn_code setcc_gen_code[NUM_RTX_CODE];
extern enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
#endif
+/* Indexed by the machine mode, gives the insn code for vector conditional
+ operation. */
+
+extern enum insn_code vcond_gen_code[NUM_MACHINE_MODES];
+extern enum insn_code vcondu_gen_code[NUM_MACHINE_MODES];
+
/* This array records the insn_code of insns to perform block moves. */
extern enum insn_code movmem_optab[NUM_MACHINE_MODES];
@@ -498,4 +504,10 @@ extern void expand_float (rtx, rtx, int);
/* Generate code for a FIX_EXPR. */
extern void expand_fix (rtx, rtx, int);
+/* Return tree if target supports vector operatiosn for COND_EXPR. */
+bool expand_vec_cond_expr_p (tree, enum machine_mode);
+
+/* Generate code for VEC_COND_EXPR. */
+extern rtx expand_vec_cond_expr (tree, rtx);
+
#endif /* GCC_OPTABS_H */
OpenPOWER on IntegriCloud