This fixes up match.pd patterns using can_vec_perm_const_p on
existing permutations to indicate whether we are before or
after vector lowering.  For this to be correct we have to use
the new vec_perm_indices CTOR taking the actual permuted inputs
so can_vec_perm_const_p can also handle the vec_shl/vec_shr
expansion path.

Bootstrapped and tested on x86_64-unknown-linux-gnu and aarch64-linux.

        PR middle-end/125875
        * match.pd: When checking for !can_vec_perm_const_p also
        allow variable permutes and use the vec_perm_indices CTOR
        with the original tree operands.

        * gcc.dg/torture/pr125875.c: New testcase.
---
 gcc/match.pd                            | 52 ++++++++++---------------
 gcc/testsuite/gcc.dg/torture/pr125875.c | 29 ++++++++++++++
 2 files changed, 50 insertions(+), 31 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr125875.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 8c410c2f3b3..615ce9b1963 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -11702,19 +11702,15 @@ and,
      machine_mode result_mode = TYPE_MODE (type);
      machine_mode op_mode = TYPE_MODE (TREE_TYPE (@2));
      int nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
-     vec_perm_builder builder0;
-     vec_perm_builder builder1;
-     vec_perm_builder builder2 (nelts, nelts, 1);
+     vec_perm_indices sel0, sel1;
    }
-   (if (tree_to_vec_perm_builder (&builder0, @4)
-       && tree_to_vec_perm_builder (&builder1, @5)
+   (if (tree_to_vec_perm_indices (&sel0, @2, @3, @4)
+       && tree_to_vec_perm_indices (&sel1, @0, @0, @5)
        && TYPE_SIZE (TREE_TYPE (TREE_TYPE (@0)))
           == TYPE_SIZE (TREE_TYPE (TREE_TYPE (@1))))
     (with
      {
-       vec_perm_indices sel0 (builder0, 2, nelts);
-       vec_perm_indices sel1 (builder1, 2, nelts);
-
+       vec_perm_builder builder2 (nelts, nelts, 1);
        for (int i = 0; i < nelts; i++)
         builder2.quick_push (sel0[sel1[i].to_constant ()]);
 
@@ -11728,9 +11724,9 @@ and,
          number of VEC_PERM_EXPRs that can't be handled.  */
        if (can_vec_perm_const_p (result_mode, op_mode, sel2, false)
           || (single_use (@0)
-              ? (!can_vec_perm_const_p (result_mode, op_mode, sel0, false)
-                 || !can_vec_perm_const_p (result_mode, op_mode, sel1, false))
-              : !can_vec_perm_const_p (result_mode, op_mode, sel1, false)))
+              ? (!can_vec_perm_const_p (result_mode, op_mode, sel0, true)
+                 || !can_vec_perm_const_p (result_mode, op_mode, sel1, true))
+              : !can_vec_perm_const_p (result_mode, op_mode, sel1, true)))
         op0 = vec_perm_indices_to_tree (TREE_TYPE (@5), sel2);
      }
      (if (op0)
@@ -11752,18 +11748,15 @@ and,
      machine_mode result_mode = TYPE_MODE (type);
      machine_mode op_mode = TYPE_MODE (TREE_TYPE (@1));
      int nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
-     vec_perm_builder builder0;
-     vec_perm_builder builder1;
-     vec_perm_builder builder2 (nelts, nelts, 2);
+     vec_perm_indices sel0, sel1;
    }
-   (if (tree_to_vec_perm_builder (&builder0, @3)
-       && tree_to_vec_perm_builder (&builder1, @4))
+   (if (tree_to_vec_perm_indices (&sel0, @1, @2, @3)
+        && tree_to_vec_perm_indices (&sel1, @5, @0, @4))
     (with
      {
-       vec_perm_indices sel0 (builder0, 2, nelts);
-       vec_perm_indices sel1 (builder1, 2, nelts);
        bool use_1 = false, use_2 = false;
 
+       vec_perm_builder builder2 (nelts, nelts, 2);
        for (int i = 0; i < nelts; i++)
          {
           if (known_lt ((poly_uint64)sel1[i], sel1.nelts_per_input ()))
@@ -11795,9 +11788,9 @@ and,
            number of VEC_PERM_EXPRs that can't be handled.  */
         if (can_vec_perm_const_p (result_mode, op_mode, sel2, false)
             || (single_use (@0)
-                ? (!can_vec_perm_const_p (result_mode, op_mode, sel0, false)
-                   || !can_vec_perm_const_p (result_mode, op_mode, sel1, 
false))
-                : !can_vec_perm_const_p (result_mode, op_mode, sel1, false)))
+                ? (!can_vec_perm_const_p (result_mode, op_mode, sel0, true)
+                   || !can_vec_perm_const_p (result_mode, op_mode, sel1, true))
+                : !can_vec_perm_const_p (result_mode, op_mode, sel1, true)))
           op0 = vec_perm_indices_to_tree (TREE_TYPE (@4), sel2);
        }
        (if (op0)
@@ -11817,18 +11810,15 @@ and,
      machine_mode result_mode = TYPE_MODE (type);
      machine_mode op_mode = TYPE_MODE (TREE_TYPE (@1));
      int nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
-     vec_perm_builder builder0;
-     vec_perm_builder builder1;
-     vec_perm_builder builder2 (nelts, nelts, 2);
+     vec_perm_indices sel0, sel1;
    }
-   (if (tree_to_vec_perm_builder (&builder0, @3)
-       && tree_to_vec_perm_builder (&builder1, @4))
+   (if (tree_to_vec_perm_indices (&sel0, @1, @2, @3)
+        && tree_to_vec_perm_indices (&sel1, @0, @5, @4))
     (with
      {
-       vec_perm_indices sel0 (builder0, 2, nelts);
-       vec_perm_indices sel1 (builder1, 2, nelts);
        bool use_1 = false, use_2 = false;
 
+       vec_perm_builder builder2 (nelts, nelts, 2);
        for (int i = 0; i < nelts; i++)
          {
           if (known_ge ((poly_uint64)sel1[i], sel1.nelts_per_input ()))
@@ -11859,9 +11849,9 @@ and,
            number of VEC_PERM_EXPRs that can't be handled.  */
         if (can_vec_perm_const_p (result_mode, op_mode, sel2, false)
             || (single_use (@0)
-                ? (!can_vec_perm_const_p (result_mode, op_mode, sel0, false)
-                   || !can_vec_perm_const_p (result_mode, op_mode, sel1, 
false))
-                : !can_vec_perm_const_p (result_mode, op_mode, sel1, false)))
+                ? (!can_vec_perm_const_p (result_mode, op_mode, sel0, true)
+                   || !can_vec_perm_const_p (result_mode, op_mode, sel1, true))
+                : !can_vec_perm_const_p (result_mode, op_mode, sel1, true)))
           op0 = vec_perm_indices_to_tree (TREE_TYPE (@4), sel2);
        }
        (if (op0)
diff --git a/gcc/testsuite/gcc.dg/torture/pr125875.c 
b/gcc/testsuite/gcc.dg/torture/pr125875.c
new file mode 100644
index 00000000000..0cccb190c73
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr125875.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+#include <stdint.h>
+typedef int16_t v4i16 __attribute__((vector_size(8)));
+v4i16 g7, g19;
+int64_t g16;
+_Bool f16_a0_c3, f16_a0_ob6;
+void f16_a0()
+{
+    int32_t ov10;
+    uint64_t __ov_tmp_g16 = __builtin_sub_overflow(0, 0, &__ov_tmp_g16);
+    g16 = __ov_tmp_g16;
+lbl_b1:
+    __builtin_mul_overflow(g16, g16, &ov10);
+    switch (ov10)
+    case 33:
+        goto lbl_sw_def57;
+lbl_sw_def15:
+    if (f16_a0_c3) goto lbl_b1;
+    g7 = __builtin_shufflevector(g7, g7, 4, 3, 4, 5);
+    f16_a0_ob6 = f16_a0;
+    g19 = g19 <= g19;
+lbl_bf43:
+    g19 = ~g19;
+    g7 = __builtin_shufflevector(g7, g19, 6, 7, 0, 1);
+lbl_sw_def57:
+    if (f16_a0_ob6) goto lbl_sw_def15;
+    goto lbl_bf43;
+}
-- 
2.51.0

Reply via email to