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 <ja...@redhat.com> > > 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 <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)