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.

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 ?


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

Reply via email to