aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineVerifier.cpp
diff options
context:
space:
mode:
authorJessica Paquette <jpaquette@apple.com>2021-01-27 12:09:05 -0800
committerJessica Paquette <jpaquette@apple.com>2021-01-28 13:58:37 -0800
commit24261729a49feb4cf0376c6f9326374ab28ec0a5 (patch)
tree909ff492ccaac70b5d3bc012da6863891c74b64b /llvm/lib/CodeGen/MachineVerifier.cpp
parentac70a53653d45d0dc6cf50c65b7215d5b7bb8c19 (diff)
downloadllvm-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.cpp38
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;
}