diff options
author | Jessica Paquette <jpaquette@apple.com> | 2021-01-27 12:09:05 -0800 |
---|---|---|
committer | Jessica Paquette <jpaquette@apple.com> | 2021-01-28 13:58:37 -0800 |
commit | 24261729a49feb4cf0376c6f9326374ab28ec0a5 (patch) | |
tree | 909ff492ccaac70b5d3bc012da6863891c74b64b /llvm/lib/CodeGen/MachineVerifier.cpp | |
parent | ac70a53653d45d0dc6cf50c65b7215d5b7bb8c19 (diff) | |
download | llvm-24261729a49feb4cf0376c6f9326374ab28ec0a5.zip llvm-24261729a49feb4cf0376c6f9326374ab28ec0a5.tar.gz llvm-24261729a49feb4cf0376c6f9326374ab28ec0a5.tar.bz2 |
[GlobalISel] Add G_ASSERT_ZEXT
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.)
This allows us to skip over hints in the legalizer etc. These can then later
be selected like COPY instructions or removed.
Differential Revision: https://reviews.llvm.org/D95564
Diffstat (limited to 'llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineVerifier.cpp | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index 0f6d9b8..2691dd8 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -941,6 +941,41 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { // Verify properties of various specific instruction types switch (MI->getOpcode()) { + case TargetOpcode::G_ASSERT_ZEXT: { + if (!MI->getOperand(2).isImm()) { + report("G_ASSERT_ZEXT expects an immediate operand #2", MI); + break; + } + + Register Dst = MI->getOperand(0).getReg(); + Register Src = MI->getOperand(1).getReg(); + LLT DstTy = MRI->getType(Dst); + LLT SrcTy = MRI->getType(Src); + verifyVectorElementMatch(DstTy, SrcTy, MI); + int64_t Imm = MI->getOperand(2).getImm(); + if (Imm <= 0) { + report("G_ASSERT_ZEXT size must be >= 1", MI); + break; + } + + if (Imm >= SrcTy.getScalarSizeInBits()) { + report("G_ASSERT_ZEXT size must be less than source bit width", MI); + break; + } + + if (MRI->getRegBankOrNull(Src) != MRI->getRegBankOrNull(Dst)) { + report("G_ASSERT_ZEXT source and destination register banks must match", + MI); + break; + } + + if (MRI->getRegClassOrNull(Src) != MRI->getRegClassOrNull(Dst)) + report("G_ASSERT_ZEXT source and destination register classes must match", + MI); + + break; + } + case TargetOpcode::G_CONSTANT: case TargetOpcode::G_FCONSTANT: { LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); @@ -1594,7 +1629,8 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { } } - if (isPreISelGenericOpcode(MCID.getOpcode())) { + unsigned Opc = MCID.getOpcode(); + if (isPreISelGenericOpcode(Opc) || isPreISelGenericOptimizationHint(Opc)) { verifyPreISelGenericInstruction(MI); return; } |