I was reading the SVE whitepaper from ARM and came across something that struck me as odd (in a non-SVE example):
mov x8, xzr
I didn't know what this xzr
register was, so I looked it up and found some content from ARM stating that it was, in many contexts, synonymous with zero.
So it looks like x8
is being initialised to zero, which makes sense because it's executed just before a loop where x8
is used as the loop counter.
What I don't understand is, why wasn't the literal 0
used instead of xzr
? For example:
mov x8, 0
To summarise, my question is: why might one use the xzr
register instead of the literal 0
here?
I think the mov x8, xzr
vs mov x8, #0
comparison is something of a red herring.
As @old_timer's answer shows, there is no encoding gain to be made, and quite likely (although admittedly I haven't checked) little or no pipeline performance gain.
What xzr
gives us, however - in addition to a dummy register as per @InfinitelyManic's answer - is access to a zero-valued operand without having to load and occupy a real register. This has the dual benefit of one less instruction, and one more register available to hold 'real' data.
I think this is an important characteristic that the original 'some content from ARM' referred to in the OP neglects to point out.
That's what I mean by mov x8, xzr
vs mov x8, #0
being a red herring. If we're zeroing x8
with the intention of then modifying it, then using xzr
or #0
is pretty arbitrary (although I'd tend to favour #0
as the more obvious). But if we're zeroing x8
purely in order to supply a zero operand to a subsequent instruction, then we'd be better off using - where permitted - xzr
instead of x8
as the operand in that instruction, and not zeroing x8
at all.