Just like the `REP STOS` instruction, this removes a fairly nasty bit of
code generation from our dispatcher. This instruction behaves like a
memcpy/memmove when not dealing with the faulting behaviour around the
instruction.
With a microbench things improves this instruction's throughput by 3.5%
to 25.5% depending on operating size.
There is a TODO for implementing this instruction with ARM's future MOPS
instructions which will accelerate this implementation further.
Now that our register types are strongly typed and don't implicitly convert
across one another, we can get rid of the templating on some member
functions, turning them into normal member functions.
We can collapse the array into a shift, and the others can just use 8 as
the starting value to be shifted instead of multiplying by 8.
Aside from the array change, everything else is likely already constant
folded, but it does make things a little more straightforward
x86's REP STOS instruction is a memset (with element size!) with the
ability to choose a direction of execution.
Additionally it has a feature where if it faults part-way through the
copy, an application can catch the fault and continue afterwards to know
how many bytes got copied.
RCX is the counter which decrements for each element, and RDI is the
memory pointer. On fault these will reflect the last location that was
attempted to be written. FEX doesn't support this behaviour which makes
our lives easier.
Without supporting that feature, this turns in to a directional memset
by element size. Let's remove all the multiple blocks and just emit a
single IR operation to improve performance of the JIT.
Our generated code here was terrible, the IR was terrible, multiblock is
always slow with RA. Just a general overall improvement.
With profiling pressure-vessel this change deletes the hottest block that
appeared in the trace. This instruction is very commonly used for
memsetting a region to zero so it should be quite fast.
We can also optimize REP MOVS in the future with a Memcpy IR operation
in a similar fashion.
Additionally in the future these can be optimized to use ARM's new MOPS
instructions since the most common case is memset by byte. Which is when
we should expose the "Fast REP STOS" CPUID bit. Both setp/setm/sete and
cpyfp/cpyfm/cpyfe match `REP STOS` and `REP MOVS` respectively.
This operation directly matches what the x86 STOS instruction does
without supporting its faulting behaviour.
STOS faulting behaviour is that RCX and RDI get updated to the last word
written. Which is something that FEX hasn't ever supported.