On Tue, 7 Jul 2026, Zhongyao Chen wrote:

> On Fri, Jul 3, 2026 at 7:58 PM Richard Biener <[email protected]> wrote:
> >
> > Ah, OK.  So the issue is that without swapping we can build
> > the operand from scalars because we "late" fail here, but
> > after swapping we fail early during vect_build_slp_tree_1
> > and in that case we never build the operand from scalars.
> > Instead we now build the swapped parent operand from scalars.
> >
> > It seems that we might instead want change the original patch
> > so that we preserve the build from scalars when we build
> > operand zero but, if we could have swapped and the just
> > built child is external (aka built from scalars), we make
> > sure matches[] is still correctly populated so we can
> > try vect_build_slp_tree_1 on the swapped stmt set to see
> > if we'd wreck and only when not discard the extern promoted
> > child and try with swapping?
> >
> > That would basically implement the original change in a different,
> > more local way.
> >
> > Richard.

Sorry for the delay responding ...

> I tried the "preserve the build from scalars" direction, but it gets a
> bit complicated since I have to keep/restore the failed child state.
> 
> So I tried another way, which close to your earlier patch.
> 
> probe the swapped stmts with vect_build_slp_tree_1,
> if that fails again, then skip swap and allow child external directly.
> 
> Does this look OK ?

Hmm, so this probes ahead that we can likely successfully build
the swapped operand zero.

Of course the first vect_build_slp_tree_1 is redundant (we'll
do it again during vect_build_slp_tree before swapping).

So what I had in mind was sth like (just a quick sketch, not even
compile tested):

diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index ff11b392305..c1d82a8907e 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -3018,17 +3018,22 @@ out:
            }
        }
 
-      old_swap_distance = least_upthread_swappable_op_distance;
-      if (can_swap_nonmatching)
-       least_upthread_swappable_op_distance = 1;
-      else if (least_upthread_swappable_op_distance != -1U)
-       least_upthread_swappable_op_distance++;
       child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts,
                                   &this_max_nunits,
                                   matches, limit,
                                   &this_tree_size, bst_map);
-      least_upthread_swappable_op_distance = old_swap_distance;
-      if (child != NULL)
+
+      slp_tree saved_child = NULL;
+      if (child
+         && is_a <bb_vec_info> (vinfo)
+         && SLP_TREE_DEF_TYPE (child) == vect_external_def
+         && oprnd_info->first_dt != vect_external_def
+         && oprnd_info->first_dt != vect_constant_def
+         && can_swap_nonmatching)
+       /* Check if matches[] from above is still populated correctly.
+          I think it is.  */
+       saved_child = child;
+      else if (child != NULL)
        {
          oprnd_info->def_stmts = vNULL;
          children.safe_push (child);
@@ -3094,6 +3099,14 @@ out:
              children.safe_push (child);
              continue;
            }
+         if (saved_child)
+           {
+             /* Now un-swap stmts.  matches[] should be still available
+                from above.  Important so we get operand 1 back.  */
+             oprnd_info->def_stmts = vNULL;
+             children.safe_push (saved_child);
+             continue;
+           }
        }
 fail:
 



> diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
> index 2250f6f74a1..b60c53cd5d2 100644
> --- a/gcc/tree-vect-slp.cc
> +++ b/gcc/tree-vect-slp.cc
> @@ -3013,6 +3013,51 @@ out:
>               if (j != 0 && !stmt_can_swap[j])
>                 can_swap_nonmatching = false;
>             }
> +
> +         if (can_swap_nonmatching)
> +           {
> +             /* Keep the delayed swap retry only if the swapped immediate
> +                operand-zero node still matches at this level.  */
> +             unsigned char *probe_swap = XALLOCAVEC (unsigned char,
> group_size);
> +             bool *probe_matches = XALLOCAVEC (bool, group_size);
> +             bool probe_two_operators = false;
> +             tree probe_vectype = NULL_TREE;
> +             poly_uint64 probe_max_nunits = this_max_nunits;
> +             bool op0_matches
> +               = vect_build_slp_tree_1 (vinfo, probe_swap,
> +                                        oprnds_info[0]->def_stmts,
> +                                        group_size, &probe_max_nunits,
> +                                        probe_matches, &probe_two_operators,
> +                                        &probe_vectype);
> +             if (!op0_matches && !probe_matches[0])
> +               can_swap_nonmatching = false;
> +
> +             if (can_swap_nonmatching)
> +               {
> +                 vec<stmt_vec_info> probe_stmts = vNULL;
> +                 probe_stmts.create (group_size);
> +                 for (j = 0; j < group_size; ++j)
> +                   {
> +                     bool swap_lane
> +                       = (op0_matches
> +                          ? j != 0
> +                          : !probe_matches[j]);
> +                     probe_stmts.quick_push (swap_lane
> +                                             ? oprnds_info[1]->def_stmts[j]
> +                                             : oprnds_info[0]->def_stmts[j]);
> +                   }
> +
> +                 probe_two_operators = false;
> +                 probe_vectype = NULL_TREE;
> +                 probe_max_nunits = this_max_nunits;
> +                 if (!vect_build_slp_tree_1 (vinfo, probe_swap,
> +                                             probe_stmts, group_size,
> +                                             &probe_max_nunits, 
> probe_matches,
> +                                             &probe_two_operators,
> &probe_vectype))
> +                   can_swap_nonmatching = false;
> +                 probe_stmts.release ();
> +               }
> +           }
>         }
> 
>        old_swap_distance = least_upthread_swappable_op_distance;
> 
> 
> 
> --
> Regards,
> Zhongyao
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald; (HRB 36809, AG Nuernberg)

Reply via email to