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:
parent
55040e7a24
commit
7ce67fbe42
@ -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>
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
179
gcc/optabs.c
179
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"
|
||||
|
12
gcc/optabs.h
12
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user