On Wed, 27 Mar 2024, Jakub Jelinek wrote:
> Hi!
>
> The following patch attempts to fix the (view_convert (convert@0 @1))
> optimization. If TREE_TYPE (@0) is a _BitInt type with padding bits
> and @0 has the same precision as @1 and it has a different sign
> and _BitInt with padding bits are extended on the target (x86 doesn't,
> aarch64 doesn't, but arm plans to do that), then optimizing it to
> just (view_convert @1) is wrong, the padding bits wouldn't be what
> it should be.
> E.g. bitint-64.c test with -O2 has
> _5 = (unsigned _BitInt(5)) _4;
> _7 = (unsigned _BitInt(5)) e.0_1;
> _8 = _5 + _7;
> _9 = (_BitInt(5)) _8;
> _10 = VIEW_CONVERT_EXPR<unsigned char>(_9);
> and forwprop1 changes that to just
> _5 = (unsigned _BitInt(5)) _4;
> _7 = (unsigned _BitInt(5)) e.0_1;
> _8 = _5 + _7;
> _10 = VIEW_CONVERT_EXPR<unsigned char>(_8);
> The former makes the padding bits well defined (at least on arm in
> the future), while the latter has those bits zero extended.
So I think the existing rule, when extended to
|| (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE
(@1))
&& TYPE_UNSIGNED (TREE_TYPE (@1))
assumes padding is extended according to the signedness. But the
original
&& (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE
(@1))
rule has the padding undefined. I think that's inconsistent at least.
I'll note that we do not constrain 'type' so the V_C_E could
re-interpret the integer (with or without padding) as floating-point.
Given the previous
/* For integral conversions with the same precision or pointer
conversions use a NOP_EXPR instead. */
(simplify
(view_convert @0)
should match first we should only ever see non-integer/pointer here
or cases where the V_C_E looks at padding. IMO we should change
this to
&& ((TYPE_PRECISION (TREE_TYPE (@0)) >= TYPE_PRECISION (TREE_TYPE
(@1))
&& TYPE_SIGN (TREE_TYPE (@0)) == TYPE_SIGN (TREE_TYPE (@1))))
|| (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE
(@1))
&& TYPE_UNSIGNED (TREE_TYPE (@1))))
? Having this inconsistent treatment of padding is bad.
In your case the precision is equal so this should fix it, right?
Not sure if it's worth adding a INTEGERAL_TYPE_P (type) case with
TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@1)), see the
previous pattern.
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2024-03-26 Jakub Jelinek <[email protected]>
>
> PR tree-optimization/114469
> * match.pd ((view_convert (convert@0 @1))): Don't optimize if
> TREE_TYPE (@0) is a BITINT_TYPE with padding bits which are supposed
> to be extended by the ABI.
>
> --- gcc/match.pd.jj 2024-03-15 11:04:24.672914747 +0100
> +++ gcc/match.pd 2024-03-26 15:49:44.177864509 +0100
> @@ -4699,13 +4699,38 @@ (define_operator_list SYNC_FETCH_AND_AND
> zero-extend while keeping the same size (for bool-to-char). */
> (simplify
> (view_convert (convert@0 @1))
> - (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
> - && (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE
> (@1)))
> - && TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1))
> - && (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1))
> - || (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@1))
> - && TYPE_UNSIGNED (TREE_TYPE (@1)))))
> - (view_convert @1)))
> + (with { tree type0 = TREE_TYPE (@0);
> + tree type1 = TREE_TYPE (@1);
> + bool ok = false;
> + if ((INTEGRAL_TYPE_P (type0) || POINTER_TYPE_P (type0))
> + && (INTEGRAL_TYPE_P (type1) || POINTER_TYPE_P (type1))
> + && TYPE_SIZE (type0) == TYPE_SIZE (type1))
> + {
> + if (TYPE_PRECISION (type0) == TYPE_PRECISION (type1))
> + {
> + if (TREE_CODE (type0) != BITINT_TYPE)
> + ok = true;
> + else
> + {
> + /* Avoid optimizing this if type0 is a _BitInt
> + type with padding bits which are supposed to be
> + extended. */
> + struct bitint_info info;
> + targetm.c.bitint_type_info (TYPE_PRECISION (type0),
> + &info);
> + if (!info.extended)
> + ok = true;
> + else
> + ok = (TYPE_PRECISION (type0)
> + == tree_to_uhwi (TYPE_SIZE (type0)));
> + }
> + }
> + else if (TYPE_PRECISION (type0) > TYPE_PRECISION (type1)
> + && TYPE_UNSIGNED (type1))
> + ok = true;
> + } }
> + (if (ok)
> + (view_convert @1))))
>
> /* Simplify a view-converted empty or single-element constructor. */
> (simplify
>
> Jakub
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)