expr.c (expand_expr_real_1): Handle VEC_COND_EXPR.

* 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.

From-SVN: r88209
This commit is contained in:
Devang Patel 2004-09-27 17:13:12 -07:00 committed by Devang Patel
parent 55040e7a24
commit 7ce67fbe42
5 changed files with 212 additions and 3 deletions

View File

@ -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>

View File

@ -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.

View File

@ -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);

View File

@ -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"

View File

@ -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 */