https://gcc.gnu.org/g:055c6cc038ef6bba311eee2abdafaadb532ddd5b
commit r16-4296-g055c6cc038ef6bba311eee2abdafaadb532ddd5b Author: Richard Biener <[email protected]> Date: Tue Oct 7 15:38:57 2025 +0200 Add boolean pattern for bitwise ops As we consider bitwise operations possible mask operations we have to consider the case of only one operand arriving as mask. The following compensates for this by creating mask from the other operand and insert possibly required mask conversions. PR tree-optimization/110223 PR tree-optimization/122128 * tree-vect-patterns.cc (vect_recog_bool_pattern): Add compensation for mixed mask/data bitwise operations. * gcc.dg/vect/vect-bool-2.c: New testcase. * gcc.dg/vect/vect-bool-cmp-3.c: Likewise. * gcc.dg/vect/vect-bool-cmp-4.c: Likewise. Diff: --- gcc/testsuite/gcc.dg/vect/vect-bool-2.c | 17 ++++++++ gcc/testsuite/gcc.dg/vect/vect-bool-cmp-3.c | 14 +++++++ gcc/testsuite/gcc.dg/vect/vect-bool-cmp-4.c | 14 +++++++ gcc/tree-vect-patterns.cc | 62 +++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+) diff --git a/gcc/testsuite/gcc.dg/vect/vect-bool-2.c b/gcc/testsuite/gcc.dg/vect/vect-bool-2.c new file mode 100644 index 000000000000..88db018a4f51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-bool-2.c @@ -0,0 +1,17 @@ +/* PR122128 */ +/* { dg-do compile } */ + +_Bool a[1024]; +signed char b[1024]; + +void foo () +{ + for (int i = 0; i < 1024; ++i) + { + bool x = a[i]; + bool y = b[i] < 17; + a[i] = x & y; + } +} + +/* { dg-final { scan-tree-dump "optimized: loop vectorized" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-3.c b/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-3.c new file mode 100644 index 000000000000..4d96af65e928 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-3.c @@ -0,0 +1,14 @@ +/* PR110223 */ +/* { dg-do compile } */ + +_Bool k[1024]; +_Bool res[1024]; + +int main () +{ + int i; + for (i = 0; i < 1024; i++) + res[i] = k[i] != (i == 0); +} + +/* { dg-final { scan-tree-dump "optimized: loop vectorized" "vect" { target vect_unpack } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-4.c b/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-4.c new file mode 100644 index 000000000000..162f22835daa --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-4.c @@ -0,0 +1,14 @@ +/* PR110223 */ +/* { dg-do compile } */ + +_Bool k[1024]; +_Bool res[1024]; + +int main () +{ + char i; + for (i = 0; i < 64; i++) + res[i] = k[i] != (i == 0); +} + +/* { dg-final { scan-tree-dump "optimized: loop vectorized" "vect" } } */ diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 8b4f9840181e..5581f44a6a84 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -5754,6 +5754,68 @@ vect_recog_bool_pattern (vec_info *vinfo, *type_out = vectype; vect_pattern_detected ("vect_recog_bool_pattern", last_stmt); + return pattern_stmt; + } + else if (rhs_code == BIT_XOR_EXPR + || rhs_code == BIT_AND_EXPR + || rhs_code == BIT_IOR_EXPR) + { + tree lhs_type = integer_type_for_mask (lhs, vinfo); + if (!lhs_type) + return NULL; + vectype = get_mask_type_for_scalar_type (vinfo, lhs_type); + if (!vectype) + return NULL; + tree rhs2 = gimple_assign_rhs2 (last_stmt); + tree rhs1_type = integer_type_for_mask (var, vinfo); + tree rhs2_type = integer_type_for_mask (rhs2, vinfo); + if (rhs1_type && rhs2_type) + return NULL; + /* When one input is a mask and the other is not create a pattern + stmt sequence that creates a mask for the non-mask input and + convert it to one suitable for the output mask used. */ + if (rhs1_type && !rhs2_type) + { + tree rhs1_vectype = get_mask_type_for_scalar_type (vinfo, rhs1_type); + if (!rhs1_vectype) + return NULL; + tree rhs2_vectype = get_vectype_for_scalar_type (vinfo, + TREE_TYPE (rhs2)); + if (!rhs2_vectype) + return NULL; + tree new_vectype = truth_type_for (rhs2_vectype); + tree tem = vect_recog_temp_ssa_var (TREE_TYPE (new_vectype), NULL); + pattern_stmt = gimple_build_assign (tem, NE_EXPR, rhs2, + build_zero_cst + (TREE_TYPE (rhs2))); + append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, + new_vectype, TREE_TYPE (new_vectype)); + rhs2 = vect_convert_mask_for_vectype (tem, rhs1_vectype, + stmt_vinfo, vinfo); + } + else if (!rhs1_type && rhs2_type) + { + tree rhs2_vectype = get_mask_type_for_scalar_type (vinfo, rhs2_type); + if (!rhs2_vectype) + return NULL; + tree rhs1_vectype = get_vectype_for_scalar_type (vinfo, + TREE_TYPE (var)); + if (!rhs1_vectype) + return NULL; + tree new_vectype = truth_type_for (rhs1_vectype); + tree tem = vect_recog_temp_ssa_var (TREE_TYPE (new_vectype), NULL); + pattern_stmt = gimple_build_assign (tem, NE_EXPR, var, + build_zero_cst + (TREE_TYPE (var))); + append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, + new_vectype, TREE_TYPE (new_vectype)); + var = vect_convert_mask_for_vectype (tem, rhs2_vectype, + stmt_vinfo, vinfo); + } + lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL); + pattern_stmt = gimple_build_assign (lhs, rhs_code, var, rhs2); + vect_pattern_detected ("vect_recog_bool_pattern", last_stmt); + *type_out = vectype; return pattern_stmt; } else if (rhs_code == SSA_NAME
