diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/tree-vect-patterns.c | 42 |
2 files changed, 45 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index afc18a8..e273614 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,12 @@ 2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> + Alan Hayward <alan.hayward@arm.com> + David Sherwood <david.sherwood@arm.com> + + * tree-vect-patterns.c (vect_recog_mask_conversion_pattern): When + handling COND_EXPRs with boolean comparisons, try to find a better + basis for the mask type than the boolean itself. + +2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> * doc/rtl.texi (MAX_BITSIZE_MODE_ANY_MODE): Describe how the default is calculated and how it can be overridden. diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 50ddc0a..5124c11 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -3968,15 +3968,43 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in, return NULL; } else if (COMPARISON_CLASS_P (rhs1)) - rhs1_type = TREE_TYPE (TREE_OPERAND (rhs1, 0)); + { + /* Check whether we're comparing scalar booleans and (if so) + whether a better mask type exists than the mask associated + with boolean-sized elements. This avoids unnecessary packs + and unpacks if the booleans are set from comparisons of + wider types. E.g. in: + + int x1, x2, x3, x4, y1, y1; + ... + bool b1 = (x1 == x2); + bool b2 = (x3 == x4); + ... = b1 == b2 ? y1 : y2; + + it is better for b1 and b2 to use the mask type associated + with int elements rather bool (byte) elements. */ + rhs1_type = search_type_for_mask (TREE_OPERAND (rhs1, 0), vinfo); + if (!rhs1_type) + rhs1_type = TREE_TYPE (TREE_OPERAND (rhs1, 0)); + } else return NULL; vectype2 = get_mask_type_for_scalar_type (rhs1_type); - if (!vectype1 || !vectype2 - || known_eq (TYPE_VECTOR_SUBPARTS (vectype1), - TYPE_VECTOR_SUBPARTS (vectype2))) + if (!vectype1 || !vectype2) + return NULL; + + /* Continue if a conversion is needed. Also continue if we have + a comparison whose vector type would normally be different from + VECTYPE2 when considered in isolation. In that case we'll + replace the comparison with an SSA name (so that we can record + its vector type) and behave as though the comparison was an SSA + name from the outset. */ + if (known_eq (TYPE_VECTOR_SUBPARTS (vectype1), + TYPE_VECTOR_SUBPARTS (vectype2)) + && (TREE_CODE (rhs1) == SSA_NAME + || rhs1_type == TREE_TYPE (TREE_OPERAND (rhs1, 0)))) return NULL; /* If rhs1 is invariant and we can promote it leave the COND_EXPR @@ -4020,7 +4048,11 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in, append_pattern_def_seq (stmt_vinfo, pattern_stmt); } - tmp = build_mask_conversion (rhs1, vectype1, stmt_vinfo, vinfo); + if (maybe_ne (TYPE_VECTOR_SUBPARTS (vectype1), + TYPE_VECTOR_SUBPARTS (vectype2))) + tmp = build_mask_conversion (rhs1, vectype1, stmt_vinfo, vinfo); + else + tmp = rhs1; lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL); pattern_stmt = gimple_build_assign (lhs, COND_EXPR, tmp, |