diff options
Diffstat (limited to 'gcc/tree-complex.c')
-rw-r--r-- | gcc/tree-complex.c | 157 |
1 files changed, 90 insertions, 67 deletions
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 18582c1b20b..98b6c561503 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -632,8 +632,13 @@ tree_vec_extract (block_stmt_iterator *bsi, tree type, { if (bitpos) return gimplify_build3 (bsi, BIT_FIELD_REF, type, t, bitsize, bitpos); - else + + /* Build a conversion; VIEW_CONVERT_EXPR is very expensive unless T will + anyway be stored in memory, so prefer NOP_EXPR. */ + else if (TYPE_MODE (type) == BLKmode) return gimplify_build1 (bsi, VIEW_CONVERT_EXPR, type, t); + else + return gimplify_build1 (bsi, NOP_EXPR, type, t); } static tree @@ -783,7 +788,7 @@ expand_vector_parallel (block_stmt_iterator *bsi, elem_op_func f, tree type, result = f (bsi, compute_type, a, b, NULL_TREE, NULL_TREE, code); } - return build1 (VIEW_CONVERT_EXPR, type, result); + return result; } /* Expand a vector operation to scalars; for integer types we can use @@ -810,6 +815,60 @@ expand_vector_addition (block_stmt_iterator *bsi, a, b, code); } +static tree +expand_vector_operation (block_stmt_iterator *bsi, tree type, tree compute_type, + tree rhs, enum tree_code code) +{ + enum machine_mode compute_mode = TYPE_MODE (compute_type); + + /* If the compute mode is not a vector mode (hence we are not decomposing + a BLKmode vector to smaller, hardware-supported vectors), we may want + to expand the operations in parallel. */ + if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT + && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT) + switch (code) + { + case PLUS_EXPR: + case MINUS_EXPR: + if (!TYPE_TRAP_SIGNED (type)) + return expand_vector_addition (bsi, do_binop, do_plus_minus, type, + TREE_OPERAND (rhs, 0), + TREE_OPERAND (rhs, 1), code); + break; + + case NEGATE_EXPR: + if (!TYPE_TRAP_SIGNED (type)) + return expand_vector_addition (bsi, do_unop, do_negate, type, + TREE_OPERAND (rhs, 0), + NULL_TREE, code); + break; + + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + return expand_vector_parallel (bsi, do_binop, type, + TREE_OPERAND (rhs, 0), + TREE_OPERAND (rhs, 1), code); + + case BIT_NOT_EXPR: + return expand_vector_parallel (bsi, do_unop, type, + TREE_OPERAND (rhs, 0), + NULL_TREE, code); + + default: + break; + } + + if (TREE_CODE_CLASS (code) == tcc_unary) + return expand_vector_piecewise (bsi, do_unop, type, compute_type, + TREE_OPERAND (rhs, 0), + NULL_TREE, code); + else + return expand_vector_piecewise (bsi, do_binop, type, compute_type, + TREE_OPERAND (rhs, 0), + TREE_OPERAND (rhs, 1), code); +} + /* Return a type for the widest vector mode whose components are of mode INNER_MODE, or NULL_TREE if none is found. */ static tree @@ -841,7 +900,7 @@ static void expand_vector_operations_1 (block_stmt_iterator *bsi) { tree stmt = bsi_stmt (*bsi); - tree *p_rhs, rhs, type, compute_type; + tree *p_lhs, *p_rhs, lhs, rhs, type, compute_type; enum tree_code code; enum machine_mode compute_mode; optab op; @@ -856,7 +915,9 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) /* FALLTHRU */ case MODIFY_EXPR: + p_lhs = &TREE_OPERAND (stmt, 0); p_rhs = &TREE_OPERAND (stmt, 1); + lhs = *p_lhs; rhs = *p_rhs; break; @@ -897,86 +958,48 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) compute_type = vector_compute_type; } - compute_mode = TYPE_MODE (compute_type); - /* If we are breaking a BLKmode vector into smaller pieces, type_for_widest_vector_mode has already looked into the optab, so skip these checks. */ if (compute_type == type) { + compute_mode = TYPE_MODE (compute_type); if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT) && op != NULL && op->handlers[compute_mode].insn_code != CODE_FOR_nothing) return; else - { - /* There is no operation in hardware, so fall back to scalars. */ - compute_type = TREE_TYPE (type); - compute_mode = TYPE_MODE (compute_type); - } + /* There is no operation in hardware, so fall back to scalars. */ + compute_type = TREE_TYPE (type); } - /* If the compute mode is not a vector mode (hence we are decomposing - a BLKmode vector to smaller, hardware-supported vectors), we may - want to expand the operations in parallel. */ - if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT - && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT) - switch (code) - { - case PLUS_EXPR: - case MINUS_EXPR: - if (TYPE_TRAP_SIGNED (type)) - break; - - *p_rhs = expand_vector_addition (bsi, do_binop, do_plus_minus, type, - TREE_OPERAND (rhs, 0), - TREE_OPERAND (rhs, 1), code); - mark_stmt_modified (bsi_stmt (*bsi)); - return; - - case NEGATE_EXPR: - if (TYPE_TRAP_SIGNED (type)) - break; - - *p_rhs = expand_vector_addition (bsi, do_unop, do_negate, type, - TREE_OPERAND (rhs, 0), - NULL_TREE, code); - mark_stmt_modified (bsi_stmt (*bsi)); - return; - - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - *p_rhs = expand_vector_parallel (bsi, do_binop, type, - TREE_OPERAND (rhs, 0), - TREE_OPERAND (rhs, 1), code); - mark_stmt_modified (bsi_stmt (*bsi)); - return; - - case BIT_NOT_EXPR: - *p_rhs = expand_vector_parallel (bsi, do_unop, type, - TREE_OPERAND (rhs, 0), - NULL_TREE, code); - mark_stmt_modified (bsi_stmt (*bsi)); - return; - - default: - break; - } - - if (TREE_CODE_CLASS (code) == tcc_unary) - *p_rhs = expand_vector_piecewise (bsi, do_unop, type, compute_type, - TREE_OPERAND (rhs, 0), - NULL_TREE, code); + rhs = expand_vector_operation (bsi, type, compute_type, rhs, code); + if (lang_hooks.types_compatible_p (TREE_TYPE (lhs), TREE_TYPE (rhs))) + *p_rhs = rhs; else - *p_rhs = expand_vector_piecewise (bsi, do_binop, type, compute_type, - TREE_OPERAND (rhs, 0), - TREE_OPERAND (rhs, 1), code); + { + /* Build a conversion; VIEW_CONVERT_EXPR is very expensive unless T will + be stored in memory anyway, so prefer NOP_EXPR. Also, perform the + VIEW_CONVERT_EXPR on the left side of the assignment. */ + if (TYPE_MODE (TREE_TYPE (rhs)) == BLKmode) + *p_lhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), lhs); + else + *p_rhs = gimplify_build1 (bsi, NOP_EXPR, TREE_TYPE (lhs), rhs); + } mark_stmt_modified (bsi_stmt (*bsi)); } +/* Use this to lower vector operations introduced by the vectorizer, + if it may need the bit-twiddling tricks implemented in this file. */ + +static bool +gate_expand_vector_operations (void) +{ + return flag_tree_vectorize != 0; +} + static void expand_vector_operations (void) { @@ -1015,8 +1038,8 @@ tree_lower_operations (void) struct tree_opt_pass pass_lower_vector_ssa = { - "vector", /* name */ - NULL, /* gate */ + "veclower", /* name */ + gate_expand_vector_operations, /* gate */ expand_vector_operations, /* execute */ NULL, /* sub */ NULL, /* next */ |