On Wed, 13 Dec 2023, Jakub Jelinek wrote: > Hi! > > The following testcase ICEs, because a PHI argument from latch edge > uses a SSA_NAME set only in a conditionally executed block inside of the > loop. > This happens when we have some outer cast which lowers its operand several > times, under some condition with variable index, under different condition > with some constant index, otherwise something else, and then there is > an inner cast from non-_BitInt integer (or small/middle one). Such cast > in certain conditions is emitted by initializing some SSA_NAMEs in the > initialization statements before loops (say for casts from <= limb size > precision by computing a SSA_NAME for the first limb and then extension > of it for the later limbs) and uses the prepare_data_in_out function > to create a PHI node. Such function is passed the value (constant or > SSA_NAME) to use in the PHI argument from the pre-header edge, but for > the latch edge it always created a new SSA_NAME and then caller emitted > in the following 3 spots an extra assignment to set that SSA_NAME to > whatever value we want from the latch edge. In all these 3 cases > the argument from the latch edge is known already before the loop though, > either constant or SSA_NAME computed in pre-header as well. > But the need to emit an assignment combined with the handle_operand done > in a conditional basic block results in the SSA verification failure. > > The following patch fixes it by extending the prpare_data_in_out method, > so that when the latch edge argument is known before (constant or computed > in pre-header), we can just use it directly and avoid the extra assignment > that would normally be hopefully optimized away later to what we now emit > directly. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Richard. > 2023-12-13 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/112940 > * gimple-lower-bitint.cc (struct bitint_large_huge): Add another > argument to prepare_data_in_out method defaulted to NULL_TREE. > (bitint_large_huge::handle_operand): Pass another argument to > prepare_data_in_out instead of emitting an assignment to set it. > (bitint_large_huge::prepare_data_in_out): Add VAL_OUT argument. > If non-NULL, use it as PHI argument instead of creating a new > SSA_NAME. > (bitint_large_huge::handle_cast): Pass rext as another argument > to 2 prepare_data_in_out calls instead of emitting assignments > to set them. > > * gcc.dg/bitint-53.c: New test. > > --- gcc/gimple-lower-bitint.cc.jj 2023-12-08 09:03:06.644475539 +0100 > +++ gcc/gimple-lower-bitint.cc 2023-12-12 18:31:24.440394239 +0100 > @@ -405,7 +405,7 @@ struct bitint_large_huge > profile_probability, profile_probability, > edge &, edge &, edge &); > tree handle_operand (tree, tree); > - tree prepare_data_in_out (tree, tree, tree *); > + tree prepare_data_in_out (tree, tree, tree *, tree = NULL_TREE); > tree add_cast (tree, tree); > tree handle_plus_minus (tree_code, tree, tree, tree); > tree handle_lshift (tree, tree, tree); > @@ -872,11 +872,8 @@ bitint_large_huge::handle_operand (tree > gcc_assert (m_first); > m_data.pop (); > m_data.pop (); > - prepare_data_in_out (fold_convert (m_limb_type, op), idx, &out); > - g = gimple_build_assign (m_data[m_data_cnt + 1], > - build_int_cst (m_limb_type, ext)); > - insert_before (g); > - m_data[m_data_cnt + 1] = gimple_assign_rhs1 (g); > + prepare_data_in_out (fold_convert (m_limb_type, op), idx, &out, > + build_int_cst (m_limb_type, ext)); > } > else if (min_prec > prec - rem - 2 * limb_prec) > { > @@ -1008,10 +1005,13 @@ bitint_large_huge::handle_operand (tree > > /* Helper method, add a PHI node with VAL from preheader edge if > inside of a loop and m_first. Keep state in a pair of m_data > - elements. */ > + elements. If VAL_OUT is non-NULL, use that as PHI argument from > + the latch edge, otherwise create a new SSA_NAME for it and let > + caller initialize it. */ > > tree > -bitint_large_huge::prepare_data_in_out (tree val, tree idx, tree *data_out) > +bitint_large_huge::prepare_data_in_out (tree val, tree idx, tree *data_out, > + tree val_out) > { > if (!m_first) > { > @@ -1034,7 +1034,7 @@ bitint_large_huge::prepare_data_in_out ( > if (e1 == e2) > e2 = EDGE_PRED (m_bb, 1); > add_phi_arg (phi, val, e1, UNKNOWN_LOCATION); > - tree out = make_ssa_name (TREE_TYPE (val)); > + tree out = val_out ? val_out : make_ssa_name (TREE_TYPE (val)); > add_phi_arg (phi, out, e2, UNKNOWN_LOCATION); > m_data.safe_push (in); > m_data.safe_push (out); > @@ -1541,14 +1541,10 @@ bitint_large_huge::handle_cast (tree lhs > if (m_first) > { > tree out1, out2; > - prepare_data_in_out (r1, idx, &out1); > - g = gimple_build_assign (m_data[m_data_cnt + 1], rext); > - insert_before (g); > + prepare_data_in_out (r1, idx, &out1, rext); > if (TYPE_PRECISION (rhs_type) > limb_prec) > { > - prepare_data_in_out (r2, idx, &out2); > - g = gimple_build_assign (m_data[m_data_cnt + 3], rext); > - insert_before (g); > + prepare_data_in_out (r2, idx, &out2, rext); > m_data.pop (); > t = m_data.pop (); > m_data[m_data_cnt + 1] = t; > --- gcc/testsuite/gcc.dg/bitint-53.c.jj 2023-12-12 18:28:16.203949817 > +0100 > +++ gcc/testsuite/gcc.dg/bitint-53.c 2023-12-12 18:27:47.307342133 +0100 > @@ -0,0 +1,17 @@ > +/* PR tree-optimization/112940 */ > +/* { dg-do compile { target bitint } } */ > +/* { dg-options "-std=c23 -O2" } */ > + > +#if __BITINT_MAXWIDTH__ >= 1025 > +_BitInt (1025) b; > +#endif > + > +void > +foo (long x) > +{ > +#if __BITINT_MAXWIDTH__ >= 1025 > + b += (unsigned _BitInt (255)) x; > +#else > + (void) x; > +#endif > +} > > 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)