cond_expr_convert_p used TYPE_SIZE to compare the selected operands.
For _BitInt this could build a COND_EXPR with arms of different
precision and ICE in range analysis.
Require equal precision for _BitInt arms. Reject padded comparison
operands and padded inputs to conditional conversions.
Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
Ok for trunk?
gcc/ChangeLog:
PR tree-optimization/127382
* match.pd (cond_expr_convert_p): Check _BitInt precision and reject
unsupported padded operands.
gcc/testsuite/ChangeLog:
* gcc.dg/bitint-143.c: New test.
* gcc.dg/bitint-144.c: Ditto.
* gcc.target/i386/pr127382.c: Ditto.
---
gcc/match.pd | 18 +++++++++++++++++
gcc/testsuite/gcc.dg/bitint-143.c | 20 +++++++++++++++++++
gcc/testsuite/gcc.dg/bitint-144.c | 19 ++++++++++++++++++
gcc/testsuite/gcc.target/i386/pr127382.c | 25 ++++++++++++++++++++++++
4 files changed, 82 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/bitint-143.c
create mode 100644 gcc/testsuite/gcc.dg/bitint-144.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr127382.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 4059ed787f0..2e0077706c8 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -13140,6 +13140,15 @@ and,
TYPE_SIZE (TREE_TYPE (@2)))
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (@0)),
TYPE_SIZE (TREE_TYPE (@3)))
+ /* Vector comparisons cannot ignore padding bits. */
+ && (!BITINT_TYPE_P (TREE_TYPE (@0))
+ || type_has_mode_precision_p (TREE_TYPE (@0)))
+ /* @2 and @3 become the COND_EXPR arms. If either is a _BitInt,
+ require equal precision and require @2 to have mode precision. */
+ && (!(BITINT_TYPE_P (TREE_TYPE (@2)) || BITINT_TYPE_P (TREE_TYPE (@3)))
+ || (TYPE_PRECISION (TREE_TYPE (@2))
+ == TYPE_PRECISION (TREE_TYPE (@3))
+ && type_has_mode_precision_p (TREE_TYPE (@2))))
/* For vect_recog_cond_expr_convert_pattern, @2 and @3 can differ in
signess when convert is truncation, but not ok for extension since
it's sign_extend vs zero_extend. */
@@ -13160,6 +13169,9 @@ and,
&& !operand_equal_p (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (@0)))
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (@0)),
TYPE_SIZE (TREE_TYPE (@2)))
+ && (!BITINT_TYPE_P (TREE_TYPE (@0))
+ || type_has_mode_precision_p (TREE_TYPE (@0)))
+ && type_has_mode_precision_p (TREE_TYPE (@2))
&& single_use (@4)
&& single_use (@5))))
@@ -13174,6 +13186,8 @@ and,
TYPE_SIZE (TREE_TYPE (@0)))
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (@0)),
TYPE_SIZE (TREE_TYPE (@2)))
+ && (!BITINT_TYPE_P (TREE_TYPE (@0))
+ || type_has_mode_precision_p (TREE_TYPE (@0)))
&& single_use (@4)
&& single_use (@5))))
@@ -13188,6 +13202,8 @@ and,
TYPE_SIZE (TREE_TYPE (@0)))
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (@0)),
TYPE_SIZE (TREE_TYPE (@3)))
+ && (!BITINT_TYPE_P (TREE_TYPE (@0))
+ || type_has_mode_precision_p (TREE_TYPE (@0)))
&& single_use (@5)
&& (flag_unsafe_math_optimizations
|| exact_real_truncate (TYPE_MODE (TREE_TYPE (@3)),
@@ -13203,6 +13219,8 @@ and,
&& !operand_equal_p (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (@0)))
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (@0)),
TYPE_SIZE (TREE_TYPE (@2)))
+ && (!BITINT_TYPE_P (TREE_TYPE (@0))
+ || type_has_mode_precision_p (TREE_TYPE (@0)))
&& single_use (@4)
&& (flag_unsafe_math_optimizations
|| exact_real_truncate (TYPE_MODE (TREE_TYPE (@2)),
diff --git a/gcc/testsuite/gcc.dg/bitint-143.c
b/gcc/testsuite/gcc.dg/bitint-143.c
new file mode 100644
index 00000000000..c461974d323
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-143.c
@@ -0,0 +1,20 @@
+/* PR tree-optimization/127382 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O2" } */
+
+#if __BITINT_MAXWIDTH__ >= 65
+_BitInt(7) m0[8];
+unsigned _BitInt(17) g1;
+_BitInt(7) p0;
+
+void
+foo (int s0)
+{
+ p0 = g1;
+ for (unsigned i = 0; i < 7; i++)
+ {
+ _BitInt(65) tt = -(_BitInt(65)) (s0 ? i : g1);
+ m0[i & 7] = tt / 10;
+ }
+}
+#endif
diff --git a/gcc/testsuite/gcc.dg/bitint-144.c
b/gcc/testsuite/gcc.dg/bitint-144.c
new file mode 100644
index 00000000000..555ac75dc21
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-144.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/127382 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O3" } */
+
+/* This used to ICE during vectorization. */
+
+#if __BITINT_MAXWIDTH__ >= 17
+_BitInt(17) g[256];
+unsigned int a[256];
+int b[256];
+short d[256];
+
+void
+foo (void)
+{
+ for (int i = 0; i < 256; i++)
+ d[i] = g[i] < 5wb ? (short) a[i] : (short) b[i];
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/pr127382.c
b/gcc/testsuite/gcc.target/i386/pr127382.c
new file mode 100644
index 00000000000..edf2ebf688f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127382.c
@@ -0,0 +1,25 @@
+/* PR tree-optimization/127382 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-march=x86-64-v4 -O3 -fdump-tree-vect-details" } */
+
+/* A bit-precise type whose precision fills its container is as good as the
+ plain integer type of the same width, so cond_expr_convert_p has to keep
+ matching it, no mask packing. */
+
+/* { dg-final { scan-tree-dump "vect_recog_cond_expr_convert_pattern" "vect" {
target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "kshift" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "kunpck" { target { ! ia32 } } } } */
+
+#if __BITINT_MAXWIDTH__ >= 32
+_BitInt(32) a[256];
+int b[256];
+short d[256];
+float c[256];
+
+void
+foo (void)
+{
+ for (int i = 0; i < 256; i++)
+ d[i] = c[i] < 1.0f ? (short) a[i] : (short) b[i];
+}
+#endif
--
2.34.1