2 ms·
> On a quick reread, I see a complaint that's entirely due to how > ARM represents indexed load operations, which has absolutely > nothing to do with the vector
by brucehoult 5y ago
> On a quick reread, I see a complaint that's entirely due to how
> ARM represents indexed load operations, which has absolutely
> nothing to do with the vector ISA whatsoever.
Not exactly true.
If you can use fancy addressing modes in your vector loads and stores and you have a fixed length 32 bit opcode (as both Aarch64 and RISC-V do[1]) then specifying an index register and how much to shift it by is taking up an extra 7 bits of your opcode (5 for register number, 2 for shift amount) vs an instruction that just specifies a base pointer register.
That means one instruction is taking up the opcode space that could otherwise be used by 128 different instructions instead.
That means either your vector ISA has fewer instructions and capabilities than it otherwise could have, or else it is taking up a lot more of the overall opcode space.
loop:
LD1D z1.d, p0/z, [x1, x3, LSL #3] // load x
LD1D z0.d, p0/z, [x2, x3, LSL #3] // load y
FMLA z0.d, p0/m, z1.d, z2.d
ST1D z0.d, p0, [x2, x3, LSL #3]
INCD x3 // i
WHILELT p0.d, x3, x0 // i, n
B.ANY loop
Yeah, it's a little more code (4 bytes in RISC-V) to increment x1 and x2 by 8 using extra instructions but 1) that FMLA almost certainly takes 3 or 4 clock cycles, giving you plenty of spare cycles to execute the adds even on a single-issue machine, and 2) vectorized loops are likely to take up so little of your overall application that it makes no difference.
There's an argument to be made that it's worth the opcode space for scaled indexed addressing for integer loads and stores. Reasonable people may differ. But the case for FP and Vector loads and stores is pretty much non-existent.
It's not just a matter of "Ohhh .. that instruction looks so scary"
[1] RISC-V has 16 bit opcodes for very simple and common instructions, but the Vector ISA is entirely 32 bit opcodes.