Index: tree-vectorizer.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-vectorizer.c,v retrieving revision 2.8 diff -Idpatel.pbxuser -c -3 -p -r2.8 tree-vectorizer.c *** tree-vectorizer.c 10 Sep 2004 10:44:47 -0000 2.8 --- tree-vectorizer.c 16 Sep 2004 00:12:18 -0000 *************** static bool vectorizable_load (tree, blo *** 165,175 **** --- 165,177 ---- static bool vectorizable_store (tree, block_stmt_iterator *, tree *); static bool vectorizable_operation (tree, block_stmt_iterator *, tree *); static bool vectorizable_assignment (tree, block_stmt_iterator *, tree *); + static bool vectorizable_select (tree, block_stmt_iterator *, tree *); static void vect_align_data_ref (tree); static void vect_enhance_data_refs_alignment (loop_vec_info); /* Utility functions for the analyses. */ static bool vect_is_simple_use (tree , struct loop *, tree *); + static bool vect_is_simple_cond (tree, struct loop *); static bool exist_non_indexing_operands_for_use_p (tree, tree); static bool vect_is_simple_iv_evolution (unsigned, tree, tree *, tree *, bool); static void vect_mark_relevant (varray_type, tree); *************** vectorizable_load (tree stmt, block_stmt *** 1313,1318 **** --- 1315,1414 ---- } + /* vectorizable_select. + + Check if STMT is conditional modify expression that can be vectorized. + If VEC_STMT is also passed, vectorize the STMT: create a vectorized + stmt using VEC_COND_EXPR to replace it, put it in VEC_STMT, and insert it + at BSI. + + Return FALSE if not a vectorizable STMT, TRUE otherwise. */ + + static bool + vectorizable_select (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) + { + tree scalar_dest = NULL_TREE; + tree vec_dest = NULL_TREE; + tree op = NULL_TREE; + tree cond_expr, then_clause, else_clause; + stmt_vec_info stmt_info = vinfo_for_stmt (stmt); + tree vectype = STMT_VINFO_VECTYPE (stmt_info); + tree vec_cond_lhs, vec_cond_rhs, vec_then_clause, vec_else_clause; + tree vec_compare, vec_cond_expr; + tree new_temp; + struct loop *loop = STMT_VINFO_LOOP (stmt_info); + enum machine_mode vec_mode; + + if (TREE_CODE (stmt) != MODIFY_EXPR) + return false; + + op = TREE_OPERAND (stmt, 1); + + if (TREE_CODE (op) != COND_EXPR) + return false; + + cond_expr = TREE_OPERAND (op, 0); + then_clause = TREE_OPERAND (op, 1); + else_clause = TREE_OPERAND (op, 2); + + if (!vect_is_simple_cond (cond_expr, loop)) + return false; + + if (TREE_CODE (then_clause) == SSA_NAME) + { + tree then_def_stmt = SSA_NAME_DEF_STMT (then_clause); + if (!vect_is_simple_use (then_clause, loop, &then_def_stmt)) + return false; + } + else if (TREE_CODE (then_clause) != INTEGER_CST + && TREE_CODE (then_clause) != REAL_CST) + return false; + + if (TREE_CODE (else_clause) == SSA_NAME) + { + tree else_def_stmt = SSA_NAME_DEF_STMT (else_clause); + if (!vect_is_simple_use (else_clause, loop, &else_def_stmt)) + return false; + } + else if (TREE_CODE (else_clause) != INTEGER_CST + && TREE_CODE (else_clause) != REAL_CST) + return false; + + + vec_mode = TYPE_MODE (vectype); + + if (!vec_stmt) + { + STMT_VINFO_TYPE (stmt_info) = select_vec_info_type; + return expand_vec_cond_expr_p (op, vec_mode); + } + + /* Transform */ + + /* Handle def. */ + scalar_dest = TREE_OPERAND (stmt, 0); + vec_dest = vect_create_destination_var (scalar_dest, vectype); + + /* Handle cond expr. */ + vec_cond_lhs = vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt); + vec_cond_rhs = vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt); + vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt); + vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt); + + /* Arguments are ready. create the new vector stmt. */ + vec_compare = build2 (TREE_CODE (cond_expr), vectype, + vec_cond_lhs, vec_cond_rhs); + vec_cond_expr = build (VEC_COND_EXPR, vectype, + vec_compare, vec_then_clause, vec_else_clause); + + *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, vec_cond_expr); + new_temp = make_ssa_name (vec_dest, *vec_stmt); + TREE_OPERAND (*vec_stmt, 0) = new_temp; + vect_finish_stmt_generation (stmt, *vec_stmt, bsi); + + return true; + } + /* Function vect_transform_stmt. Create a vectorized stmt to replace STMT, and insert it at BSI. */ *************** vect_transform_stmt (tree stmt, block_st *** 1347,1352 **** --- 1443,1454 ---- gcc_assert (done); is_store = true; break; + + case select_vec_info_type: + if (!vectorizable_select (stmt, bsi, &vec_stmt)) + abort (); + break; + default: if (vect_debug_details (NULL)) fprintf (dump_file, "stmt not supported."); *************** vect_transform_loop (loop_vec_info loop_ *** 1515,1520 **** --- 1617,1662 ---- fprintf (dump_file, "LOOP VECTORIZED."); } + /* FUnction vect_is_simple_cond. + + Input: + LOOP - the loop that is being vectorized. + COND - Condition that is checked for simple use. + + Returns whether a COND can be vectorized. Checkes whether + condition operands are supportable using vec_is_simple_use. */ + + static bool + vect_is_simple_cond (tree cond, struct loop *loop) + { + tree lhs, rhs; + + if (TREE_CODE_CLASS (TREE_CODE (cond)) != '<') + return false; + + lhs = TREE_OPERAND (cond, 0); + rhs = TREE_OPERAND (cond, 1); + + if (TREE_CODE (lhs) == SSA_NAME) + { + tree lhs_def_stmt = SSA_NAME_DEF_STMT (lhs); + if (!vect_is_simple_use (lhs, loop, &lhs_def_stmt)) + return false; + } + else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST) + return false; + + if (TREE_CODE (rhs) == SSA_NAME) + { + tree rhs_def_stmt = SSA_NAME_DEF_STMT (rhs); + if (!vect_is_simple_use (rhs, loop, &rhs_def_stmt)) + return false; + } + else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST) + return false; + + return true; + } /* Function vect_is_simple_use. *************** vect_analyze_operations (loop_vec_info l *** 1686,1692 **** ok = (vectorizable_operation (stmt, NULL, NULL) || vectorizable_assignment (stmt, NULL, NULL) || vectorizable_load (stmt, NULL, NULL) ! || vectorizable_store (stmt, NULL, NULL)); if (!ok) { --- 1828,1835 ---- ok = (vectorizable_operation (stmt, NULL, NULL) || vectorizable_assignment (stmt, NULL, NULL) || vectorizable_load (stmt, NULL, NULL) ! || vectorizable_store (stmt, NULL, NULL) ! || vectorizable_select (stmt, NULL, NULL)); if (!ok) { Index: tree-vectorizer.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-vectorizer.h,v retrieving revision 2.3 diff -Idpatel.pbxuser -c -3 -p -r2.3 tree-vectorizer.h *** tree-vectorizer.h 10 Sep 2004 10:44:48 -0000 2.3 --- tree-vectorizer.h 16 Sep 2004 00:12:18 -0000 *************** enum stmt_vec_info_type { *** 42,48 **** load_vec_info_type, store_vec_info_type, op_vec_info_type, ! assignment_vec_info_type }; typedef struct _stmt_vec_info { --- 42,49 ---- load_vec_info_type, store_vec_info_type, op_vec_info_type, ! assignment_vec_info_type, ! select_vec_info_type }; typedef struct _stmt_vec_info { /* { dg-do run } */ /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */ /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */ #include #include #define N 16 #define MAX 42 extern void abort(void); int main () { int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11}; int i, j; for (i = 0; i < 16; i++) { /* j = A[i];*/ A[i] = ( A[i] >= MAX ? MAX : 0); } /* check results: */ for (i = 0; i < N; i++) { if (A[i] > MAX) abort (); } return 0; } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */