]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add boolean pattern for bitwise ops
authorRichard Biener <rguenther@suse.de>
Tue, 7 Oct 2025 13:38:57 +0000 (15:38 +0200)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 8 Oct 2025 11:39:05 +0000 (13:39 +0200)
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.

gcc/testsuite/gcc.dg/vect/vect-bool-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-bool-cmp-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-bool-cmp-4.c [new file with mode: 0644]
gcc/tree-vect-patterns.cc

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 (file)
index 0000000..88db018
--- /dev/null
@@ -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 (file)
index 0000000..4d96af6
--- /dev/null
@@ -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 (file)
index 0000000..162f228
--- /dev/null
@@ -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" } } */
index 8b4f9840181e82e44aa60a41dcfe179e08f8291d..5581f44a6a8455fce7eb012559b19b50a779add0 100644 (file)
@@ -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