Re: [PATCH][RFC] Remove max_nunits, choose VF independent of externs/constants
Richard Biener <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 20 Aug 2026, Richard Sandiford wrote: > Bit rusty on this stuff, so only really replying for the final comment, > but FWIW: > > Richard Biener <[email protected]> writes: > > The following decides on the VF based on assigned SLP_TREE_VECTYPE > > rather than on the tracked max_nunits in the SLP graph which also > > factors in external and constant nodes. Those get their vector > > type assigned in vectorizable_* via vect_maybe_update_slp_op_vectype > > and there's freedom to vectorizable_* to pick a suitable one. > > > > Specifically conversions of externs/constants can cause a higher > > than necessary VF which would be a missed optimization. > > Agree that ignoring externs and constants sounds good. > > > Changing the VF as outlined will run into both vect_prologue_cost_for_slp > > and vect_create_constant_vectors ICEing when computing > > vect_get_num_copies since that asserts it can exact_div the > > number of lanes as in the unrolled loop by the number of lanes in the > > (out of loop) vector type. But vectorizable_* can opt to just > > use the lowpart of such vectors but require it in full due to target > > constraints. So this RFC patch introduces vect_get_num_copies_ > > which performs a ceil_div instead (I think we can change the global > > copy to do that). This shifts the ICE to vectorizable_conversion > > which is mightly confused by "too large" vector types. IMO rather > > than picking a vector type randomly when not already assigned, it > > should chose it based on target constraints. Or, even better, > > emit the conversion in scalar. But I expect similar issues to > > appear in multi-operand widening/narrowing operations. > > > > The fundamental issue is that we eventually break the same-size > > constraint for loop vectorization here (which we want!), and some > > vectorizable_* are not prepared. > > Not sure what you mean by the same-size constraint. For SVE we already > use mixed sizes for loop vectorisation, both for related operations > (extend/truncate) and unrelated operations (e.g. separate double and > int accumulations in the same loop). > > But yeah, the fact that we might want to use a vector with unused lanes > makes it sound like the relationship will eventually be too complicated > to do on the fly in vect_update_slp_vf_for_node. Is the idea to > calculate the maximum VF that would still only require a single vector > for at least one datatype? If lanes are deliberately being left unused, > that might not always be the best starting point. Sometimes it might > be better to use the maximum VF that requires only a single vector > for all datatypes. > > Increasing the VF can be done via unrolling, with target input. > But it seems harder to decrease the VF if it starts out too large. Yes, this should at most deacrease the VF. I'd also still want to move to iterate the VF rather than the vector mode, but this requires more work still. > I don't think that for SVE it would be useful to use a repeating > pattern of "used lanes for one vector iteration followed by unused > lanes for that vector iteration" for variable-length vectors. > For simple power-of-2 relationships, we'd be better off doing what we do > now and using unpacked vectors. For other combinations, the predicates > might in practice be too hard to set up. So for externs/constants (which this is about), a target might not have a mode for say V4QImode vectors when VF==4 but it might have V8QImode and the operation to vectorize given for example another input of V4SImode can happily use the V8QImode input, just consuming the first 4 lanes like there's often _hi/_lo variants. > > On x86_64 I see the following (unsure if related): > > > > FAIL: gcc.target/i386/pr108938-3.c scan-assembler-times bswap[\\t ]+ 3 > > > > Otherwise bootstrapped/tested on x86_64-unknown-linux-gnu and > > aarch64-linux-gnu. > > > > I suspect coverage for constant/extern operands isn't great, of course > > and the vectorizable_conversion hack needs to be properly fixed. > > Plus, I wonder when can_div_away_from_zero_p can possibly fail ... > > Do you mean in general? can_div_away_from_zero_p can fail for many cases. > For example, (16 + 8x) / (4 + 4x) is 4 for x==0, 3 for x==1, 2⅔ for x==2, > etc. > > So we can only assert that can_div_away_from_zero_p succeeds if there is > something about the values that guarantees success (usually because > something weeded out other cases earlier, or because the inputs were > constructed to have a particular relationship). > > In terms of more realistic examples: poly_ints are used to represent > frame offsets and sizes. It isn't possible to represent all given > frame offsets as a whole number of VLA vectors plus a residue, > even if the offset is aligned to the minimum vector size. I see. I have placed actual verification of can_div_away_from_zero_p where we used to (not) verify that we can code generate constants and externs. I'll post a finished series once the final testing bits come in. Thanks, Richard.