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