On 17/07/2026 17:07, Robin Dapp wrote:
This is intended to be an enabling technology for my real project, in which I
want to transform scalar operations into vector operations in the backend,
and the special casing for memory accesses was getting out of hand. By
expressing (unmasked) vector operations identically to the scalar equivalent
I can simplify things greatly, and the other compiler passes can do (some of)
their special MEM handling as they normally would.

Could you sketch what you want to achieve?  I'm just trying to get an idea of
what the "option space" is.  Like, could you do your transform at gimple level?
If that were possible, things could maybe just stay opaque at RTL level?

It's essentially vectorization in the backend, for code with specific attributes. I definitely do not want to do it at gimple level because that would have the exact same problems that the existing vectorizer has.

For example, in most cases I can simply transform

  (set (reg:SI) (plus:SI (reg:SI) (const_int)))

into

  (set (reg:V64SI) (plus:V64SI (reg:V64SI) (const_vector:V64SI)))

which makes total sense and Just Works on AMD GCN for almost all instructions.

So, I want to do the same thing for a MEM:

  (set (reg:SI) (mem:SI (reg:DI)))

becomes

  (set (reg:V64SI) (mem:V64SI (reg:V64DI)))

except that the MEM is not valid because the address "isn't valid". There's no reason it shouldn't work on the architecture -- the two RTL patterns here will emit the *exact same* assembler code (obviously I set the execution mask differently) -- it's just an old assumption built into the compiler.

I considered just leaving the scalar representation for everything, but the register allocator needs to know when to allocate vector registers, and when not (for example, a vec_duplicate looks like a move, except that the source and destination registers are different classes), and stack spills still need the extra space, so that would have required a lot of different cludges.

Maybe related: I have been starting with "native" vector masking for RTL via a
"vec_predicate" and I wonder if your requirements could influence the design of
predicated movs, loads, and stores.  But that's a separate topic.


It might be that a "vec_predicate" would be better than "vec_merge"? But if the register allocator can pull the MEM out of context then we didn't gain anything for the specific issues I discussed in the gcc@ thread.


Andrew

Reply via email to