On Wed, 16 Sep 2026, liuhongt wrote:
> update in v2:
> > I think this can happen for non-BitInt INTEGER_TYPE as well, so
> > the checks should be done for all INTEGRAL_TYPE_P
> Yes, for _Bool it's storage size is not equal to type_precision.
> changed.
>
> Bootstrapped and regtested on x86_64-pc-linu-gnu{-m32,}.
> Ok for trunk(and backport to GCC16)?
>
> cond_expr_convert_p used TYPE_SIZE to compare the selected operands.
> This could build a COND_EXPR with integral arms of different precision
> and ICE in range analysis.
>
> Require equal precision for integral arms. When either arm is a
> _BitInt, also require the COND_EXPR type to have mode precision. Reject
> padded _BitInt comparison operands as well.
Sorry for getting back to this only so late.
> PR tree-optimization/127382
>
> gcc/ChangeLog:
>
> * match.pd (cond_expr_convert_p): Require equal precision for integral
> arms. Reject unsupported padded _BitInt operands.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/bitint-143.c: Test mismatched selected-arm precisions.
> * gcc.dg/bitint-144.c: Test a padded _BitInt comparison operand.
> * gcc.target/i386/pr127382.c: Test a mode-precision _BitInt arm.
> ---
> gcc/match.pd | 20 +++++++++++++++++++
> 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, 84 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..9bdd8d5e447 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -13140,6 +13140,17 @@ 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, so integral types must have
> + equal precision. If either is a _BitInt, @2 must also have mode
> + precision. */
> + && (!INTEGRAL_TYPE_P (TREE_TYPE (@2))
> + || (TYPE_PRECISION (TREE_TYPE (@2))
> + == TYPE_PRECISION (TREE_TYPE (@3))))
> + && (!(BITINT_TYPE_P (TREE_TYPE (@2)) || BITINT_TYPE_P (TREE_TYPE
> (@3)))
> + || type_has_mode_precision_p (TREE_TYPE (@2)))
The whole point of this was to validate @2 and @3 are compatible,
the vect pattern supports a sign difference, so I'd rewrite
&& ((INTEGRAL_TYPE_P (TREE_TYPE (@2))
&& INTEGRAL_TYPE_P (TREE_TYPE (@3)))
|| (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@2))
&& types_match (TREE_TYPE (@2), TREE_TYPE (@3))))
to
&& ((INTEGRAL_TYPE_P (TREE_TYPE (@2)
&& tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@3)))
|| (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@2))
&& types_match (TREE_TYPE (@2), TREE_TYPE (@3))))
there shouldn't be any special thing wrt BIT_INT_TYPE again.
> /* 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 +13171,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))
I don't think this fixes anything given the present
&& types_match (TREE_TYPE (@2), TREE_TYPE (@3))
check.
> && single_use (@4)
> && single_use (@5))))
>
> @@ -13174,6 +13188,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 +13204,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 +13221,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)))
Why would a BITINT_TYPE_P be special here? ISTR the PR was about
a mismatch on the COND true/false arm type, not for an issue with
the comparison -- we do not seem to use match[0] at all, but it is
to guide whether the transform is applicable (though for AVX512
basing that on the comparison operand width is dubious).
That said, this and the previous two hunks seem unnecessary.
> && 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
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)