This removes odd things from being a valid RHS and transitions the two easy cases from single to ternary RHS. There are now two codes left that should IMHO move over to ternary, COND_EXPR and VEC_COND_EXPR. I'll tackle them separately.
Bootstrapped and tested on x86_64-unknown-linux-gnu, testing in progress. I plan to commit this tomorrow if there are no complaints. Richard. 2011-03-21 Richard Guenther <rguent...@suse.de> * gimple.c (gimple_rhs_class_table): POLYNOMIAL_CHREC is not a valid RHS. Make DOT_PROD_EXPR and REALIGN_LOAD_EXPR ternary. * tree-cfg.c (verify_gimple_assign_ternary): Allow DOT_PROD_EXPR and REALIGN_LOAD_EXPR. (verify_gimple_assign_single): Do not allow POLYNOMIAL_CHREC, DOT_PROD_EXPR or REALIGN_LOAD_EXPR. * expr.c (expand_expr_real_1): Move REALIGN_LOAD_EXPR and DOT_PROD_EXPR case ... (expand_expr_real_2): ... here. * gimple-pretty-print.c (dump_ternary_rhs): Handle DOT_PROD_EXPR and REALIGN_LOAD_EXPR. * tree-data-ref.c (split_constant_offset): Bail out for all CHRECs. * tree-vect-loop.c (vect_model_reduction_cost): Handle ternaries. (vect_create_epilog_for_reduction): Likewise. (vectorizable_reduction): Likewise. * tree-vect-patterns.c (vect_recog_dot_prod_pattern): Adjust. * tree-vect-stmts.c (vectorizable_load): Likewise. Index: gcc/gimple.c =================================================================== *** gcc/gimple.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/gimple.c 2011-03-21 17:21:21.000000000 +0100 *************** get_gimple_rhs_num_ops (enum tree_code c *** 2514,2519 **** --- 2514,2521 ---- : (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \ : ((SYM) == WIDEN_MULT_PLUS_EXPR \ || (SYM) == WIDEN_MULT_MINUS_EXPR \ + || (SYM) == DOT_PROD_EXPR \ + || (SYM) == REALIGN_LOAD_EXPR \ || (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS \ : ((SYM) == COND_EXPR \ || (SYM) == CONSTRUCTOR \ *************** get_gimple_rhs_num_ops (enum tree_code c *** 2522,2531 **** || (SYM) == ADDR_EXPR \ || (SYM) == WITH_SIZE_EXPR \ || (SYM) == SSA_NAME \ ! || (SYM) == POLYNOMIAL_CHREC \ ! || (SYM) == DOT_PROD_EXPR \ ! || (SYM) == VEC_COND_EXPR \ ! || (SYM) == REALIGN_LOAD_EXPR) ? GIMPLE_SINGLE_RHS \ : GIMPLE_INVALID_RHS), #define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS, --- 2524,2530 ---- || (SYM) == ADDR_EXPR \ || (SYM) == WITH_SIZE_EXPR \ || (SYM) == SSA_NAME \ ! || (SYM) == VEC_COND_EXPR) ? GIMPLE_SINGLE_RHS \ : GIMPLE_INVALID_RHS), #define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS, Index: gcc/tree-cfg.c =================================================================== *** gcc/tree-cfg.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/tree-cfg.c 2011-03-21 17:21:38.000000000 +0100 *************** verify_gimple_assign_ternary (gimple stm *** 3742,3747 **** --- 3742,3752 ---- } break; + case DOT_PROD_EXPR: + case REALIGN_LOAD_EXPR: + /* FIXME. */ + return false; + default: gcc_unreachable (); } *************** verify_gimple_assign_single (gimple stmt *** 3872,3881 **** case OBJ_TYPE_REF: case ASSERT_EXPR: case WITH_SIZE_EXPR: - case POLYNOMIAL_CHREC: - case DOT_PROD_EXPR: case VEC_COND_EXPR: - case REALIGN_LOAD_EXPR: /* FIXME. */ return res; --- 3877,3883 ---- Index: gcc/expr.c =================================================================== *** gcc/expr.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/expr.c 2011-03-21 16:37:18.000000000 +0100 *************** expand_expr_real_2 (sepops ops, rtx targ *** 8259,8264 **** --- 8259,8294 ---- mode = TYPE_MODE (TREE_TYPE (treeop0)); goto binop; + case DOT_PROD_EXPR: + { + tree oprnd0 = treeop0; + tree oprnd1 = treeop1; + tree oprnd2 = treeop2; + rtx op2; + + expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); + op2 = expand_normal (oprnd2); + target = expand_widen_pattern_expr (ops, op0, op1, op2, + target, unsignedp); + return target; + } + + case REALIGN_LOAD_EXPR: + { + tree oprnd0 = treeop0; + tree oprnd1 = treeop1; + tree oprnd2 = treeop2; + rtx op2; + + this_optab = optab_for_tree_code (code, type, optab_default); + expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); + op2 = expand_normal (oprnd2); + temp = expand_ternary_op (mode, this_optab, op0, op1, op2, + target, unsignedp); + gcc_assert (temp); + return temp; + } + default: gcc_unreachable (); } *************** expand_expr_real_1 (tree exp, rtx target *** 8288,8294 **** int unsignedp; enum machine_mode mode; enum tree_code code = TREE_CODE (exp); - optab this_optab; rtx subtarget, original_target; int ignore; tree context; --- 8318,8323 ---- *************** expand_expr_real_1 (tree exp, rtx target *** 9697,9732 **** return expand_expr_real (treeop0, original_target, tmode, modifier, alt_rtl); - case REALIGN_LOAD_EXPR: - { - tree oprnd0 = treeop0; - tree oprnd1 = treeop1; - tree oprnd2 = treeop2; - rtx op2; - - this_optab = optab_for_tree_code (code, type, optab_default); - expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); - op2 = expand_normal (oprnd2); - temp = expand_ternary_op (mode, this_optab, op0, op1, op2, - target, unsignedp); - gcc_assert (temp); - return temp; - } - - case DOT_PROD_EXPR: - { - tree oprnd0 = treeop0; - tree oprnd1 = treeop1; - tree oprnd2 = treeop2; - rtx op2; - - expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); - op2 = expand_normal (oprnd2); - target = expand_widen_pattern_expr (&ops, op0, op1, op2, - target, unsignedp); - return target; - } - case COMPOUND_LITERAL_EXPR: { /* Initialize the anonymous variable declared in the compound --- 9726,9731 ---- Index: gcc/gimple-pretty-print.c =================================================================== *** gcc/gimple-pretty-print.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/gimple-pretty-print.c 2011-03-21 16:37:18.000000000 +0100 *************** dump_ternary_rhs (pretty_printer *buffer *** 408,413 **** --- 408,433 ---- dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false); break; + case DOT_PROD_EXPR: + pp_string (buffer, "DOT_PROD_EXPR <"); + dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false); + pp_string (buffer, ", "); + dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false); + pp_string (buffer, ", "); + dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false); + pp_string (buffer, ">"); + break; + + case REALIGN_LOAD_EXPR: + pp_string (buffer, "REALIGN_LOAD <"); + dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false); + pp_string (buffer, ", "); + dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false); + pp_string (buffer, ", "); + dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false); + pp_string (buffer, ">"); + break; + default: gcc_unreachable (); } Index: gcc/tree-data-ref.c =================================================================== *** gcc/tree-data-ref.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/tree-data-ref.c 2011-03-21 16:37:18.000000000 +0100 *************** split_constant_offset (tree exp, tree *v *** 686,692 **** *off = ssize_int (0); STRIP_NOPS (exp); ! if (automatically_generated_chrec_p (exp)) return; otype = TREE_TYPE (exp); --- 686,692 ---- *off = ssize_int (0); STRIP_NOPS (exp); ! if (tree_is_chrec (exp)) return; otype = TREE_TYPE (exp); Index: gcc/tree-vect-loop.c =================================================================== *** gcc/tree-vect-loop.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/tree-vect-loop.c 2011-03-21 16:37:18.000000000 +0100 *************** vect_model_reduction_cost (stmt_vec_info *** 2498,2503 **** --- 2498,2506 ---- case GIMPLE_BINARY_RHS: reduction_op = gimple_assign_rhs2 (stmt); break; + case GIMPLE_TERNARY_RHS: + reduction_op = gimple_assign_rhs3 (stmt); + break; default: gcc_unreachable (); } *************** vect_create_epilog_for_reduction (VEC (t *** 3191,3197 **** { case GIMPLE_SINGLE_RHS: gcc_assert (TREE_OPERAND_LENGTH (gimple_assign_rhs1 (stmt)) ! == ternary_op); reduction_op = TREE_OPERAND (gimple_assign_rhs1 (stmt), reduc_index); break; case GIMPLE_UNARY_RHS: --- 3194,3200 ---- { case GIMPLE_SINGLE_RHS: gcc_assert (TREE_OPERAND_LENGTH (gimple_assign_rhs1 (stmt)) ! == ternary_op); reduction_op = TREE_OPERAND (gimple_assign_rhs1 (stmt), reduc_index); break; case GIMPLE_UNARY_RHS: *************** vect_create_epilog_for_reduction (VEC (t *** 3201,3206 **** --- 3204,3212 ---- reduction_op = reduc_index ? gimple_assign_rhs2 (stmt) : gimple_assign_rhs1 (stmt); break; + case GIMPLE_TERNARY_RHS: + reduction_op = gimple_op (stmt, reduc_index + 1); + break; default: gcc_unreachable (); } *************** vectorizable_reduction (gimple stmt, gim *** 4026,4031 **** --- 4032,4046 ---- ops[1] = gimple_assign_rhs2 (stmt); break; + case GIMPLE_TERNARY_RHS: + code = gimple_assign_rhs_code (stmt); + op_type = TREE_CODE_LENGTH (code); + gcc_assert (op_type == ternary_op); + ops[0] = gimple_assign_rhs1 (stmt); + ops[1] = gimple_assign_rhs2 (stmt); + ops[2] = gimple_assign_rhs3 (stmt); + break; + case GIMPLE_UNARY_RHS: return false; Index: gcc/tree-vect-patterns.c =================================================================== *** gcc/tree-vect-patterns.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/tree-vect-patterns.c 2011-03-21 16:37:29.000000000 +0100 *************** vect_recog_dot_prod_pattern (gimple last *** 179,185 **** tree prod_type; loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_info); ! tree var, rhs; if (!is_gimple_assign (last_stmt)) return NULL; --- 179,185 ---- tree prod_type; loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_info); ! tree var; if (!is_gimple_assign (last_stmt)) return NULL; *************** vect_recog_dot_prod_pattern (gimple last *** 311,318 **** /* Pattern detected. Create a stmt to be used to replace the pattern: */ var = vect_recog_temp_ssa_var (type, NULL); ! rhs = build3 (DOT_PROD_EXPR, type, oprnd00, oprnd01, oprnd1), ! pattern_stmt = gimple_build_assign (var, rhs); if (vect_print_dump_info (REPORT_DETAILS)) { --- 311,318 ---- /* Pattern detected. Create a stmt to be used to replace the pattern: */ var = vect_recog_temp_ssa_var (type, NULL); ! pattern_stmt = gimple_build_assign_with_ops3 (DOT_PROD_EXPR, var, ! oprnd00, oprnd01, oprnd1); if (vect_print_dump_info (REPORT_DETAILS)) { Index: gcc/tree-vect-stmts.c =================================================================== *** gcc/tree-vect-stmts.c.orig 2011-03-21 16:28:59.000000000 +0100 --- gcc/tree-vect-stmts.c 2011-03-21 16:37:18.000000000 +0100 *************** vectorizable_load (gimple stmt, gimple_s *** 4236,4250 **** if (alignment_support_scheme == dr_explicit_realign_optimized || alignment_support_scheme == dr_explicit_realign) { - tree tmp; - lsq = gimple_assign_lhs (new_stmt); if (!realignment_token) realignment_token = dataref_ptr; vec_dest = vect_create_destination_var (scalar_dest, vectype); ! tmp = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq, ! realignment_token); ! new_stmt = gimple_build_assign (vec_dest, tmp); new_temp = make_ssa_name (vec_dest, new_stmt); gimple_assign_set_lhs (new_stmt, new_temp); vect_finish_stmt_generation (stmt, new_stmt, gsi); --- 4236,4248 ---- if (alignment_support_scheme == dr_explicit_realign_optimized || alignment_support_scheme == dr_explicit_realign) { lsq = gimple_assign_lhs (new_stmt); if (!realignment_token) realignment_token = dataref_ptr; vec_dest = vect_create_destination_var (scalar_dest, vectype); ! new_stmt ! = gimple_build_assign_with_ops3 (REALIGN_LOAD_EXPR, vec_dest, ! msq, lsq, realignment_token); new_temp = make_ssa_name (vec_dest, new_stmt); gimple_assign_set_lhs (new_stmt, new_temp); vect_finish_stmt_generation (stmt, new_stmt, gsi);