Page MenuHomePhabricator

[ARM] Add IR intrinsics for MVE VLD[24] and VST[24].
ClosedPublic

Authored by simon_tatham on Oct 9 2019, 6:01 AM.

Details

Summary

The VST2 and VST4 instructions take two or four vector registers as
input, and store part of each register to memory in an interleaved
pattern. They come in variants indicating which part of each register
they store (VST20 and VST21; VST40 to VST43 inclusive); the intention
is that issuing each of those variants in turn has the combined effect
of loading or storing the whole set of registers to a memory block of
equal size. The corresponding VLD2 and VLD4 instructions load from
memory in the same interleaved format: each one overwrites only part
of its output register set, and again, the idea is that if you use
VLD4{0,1,2,3} or VLD2{0,1} together, you end up having written to the
whole of each register.

I've implemented the stores and loads quite differently. The loads
were easiest to implement as a single intrinsic that expands to all
four VLD4x instructions or both VLD2x, delivering four complete output
registers. (Implementing each individual load as a separate
instruction taking four input registers to partially overwrite is
possible in theory, but pointless, and when I tried it, I found it
would need extra work to get the register allocation not to be
horrible.) Since that intrinsic delivers multiple outputs, it has to
be instruction-selected in custom C++.

But the store instructions are easier to model individually, because
they don't overwrite any register at all and you can write a DAG Isel
pattern in Tablegen for each one.

Hence, my new intrinsic int_arm_mve_vld4q expands to four load
instructions, delivers four full output vectors, and is handled by C++
code, whereas int_arm_mve_vst4q expands to just one store
instruction, takes four input vectors and a constant indicating which
lanes to store, and is handled entirely in Tablegen. (And similarly
for vld2q/vst2q.) This is asymmetric, but it was the easiest way to do
each one.

Diff Detail

Event Timeline

simon_tatham created this revision.Oct 9 2019, 6:01 AM

Looks good. I think we can use this for autovec codegen too (there is a pre-isel pass that allows us to convert load+shuffle combos that the vectorizer produces into these intrinsics). As that is the case it would probably be worth making sure we have lots of test coverage of the different types. (I'm happy enough to do that later if you with, but adding them here sounds more sensible, as this is where they are being introduced).

llvm/lib/Target/ARM/ARMInstrMVE.td
4374

Do we need floating point types?

Added floating-point forms of the interleaving loads. (They just
expand to the same instructions as the correspondingly sized integers,
of course.)

dmgreen accepted this revision.Oct 24 2019, 7:14 AM

Nice one. LGTM

This revision is now accepted and ready to land.Oct 24 2019, 7:14 AM
This revision was automatically updated to reflect the committed changes.