From 6b7acc28494ae8de5616895bd43ff652b08db4ef Mon Sep 17 00:00:00 2001 From: dpatel Date: Tue, 28 Sep 2004 00:13:12 +0000 Subject: * 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 --- gcc/optabs.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 1 deletion(-) (limited to 'gcc/optabs.c') 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" -- cgit v1.2.1