This adds a generic opcode which communicates that a type has already been zero-extended from a narrower type.
This is intended to be similar to AssertZext in SelectionDAG.
For example,
%x_was_extended:_(s64) = G_ASSERT_ZEXT %x, 16
Signifies that the top 48 bits of %x are known to be 0.
This is useful in cases like this:
define i1 @zeroext_param(i8 zeroext %x) { %cmp = icmp ult i8 %x, -20 ret i1 %cmp }
In AArch64, %x must use a 32-bit register, which is then truncated to a 8-bit value.
If we know that %x is already zero-ed out in the relevant high bits, we can avoid the truncate.
Currently, in GISel, this looks like this:
_zeroext_param: and w8, w0, #0xff ; We don't actually need this! cmp w8, #236 cset w0, lo ret
While SDAG does not produce the truncation, since it knows that it's unnecessary:
_zeroext_param: cmp w0, #236 cset w0, lo ret
This patch
- Adds G_ASSERT_ZEXT
- Adds MIRBuilder support for it
- Adds MachineVerifier support for it
- Documents it
It also puts G_ASSERT_ZEXT into its own class of "hint instruction." (There should be a G_ASSERT_SEXT in the future, maybe a G_ASSERT_ALIGN as well.)
The reason for doing this rather than making it a pseudo like, say, COPY, is that these *are* pre-ISel generic opcodes. The only difference is
- They should be ignored by the legalizer
- They shouldn't impact register bank selection
- They should select to nothing
It also puts G_ASSERT_ZEXT into its own class of "hint instruction." (There should be a G_ASSERT_SEXT in the future, maybe a G_ASSERT_ALIGN as well.)
Should mention this behaves identically to a COPY