[llvm] [GISel][AArch64] Allow PatLeafs to be imported in GISel which were previously causing warnings (PR #140935)
via llvm-commits
llvm-commits at lists.llvm.org
Fri May 30 08:44:23 PDT 2025
https://github.com/jyli0116 updated https://github.com/llvm/llvm-project/pull/140935
>From 741e3cf47f04a4d838c49a545922bc098a6951f9 Mon Sep 17 00:00:00 2001
From: Yu Li <yu.li at arm.com>
Date: Wed, 21 May 2025 15:07:54 +0000
Subject: [PATCH] [GISel][AArch64] Allow PatLeafs to be imported in GISel which
were previously causing warnings
---
.../CodeGen/GlobalISel/GIMatchTableExecutor.h | 12 +
.../GlobalISel/GIMatchTableExecutorImpl.h | 20 +
.../include/llvm/Target/TargetSelectionDAG.td | 1 +
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 16 +-
.../GISel/AArch64InstructionSelector.cpp | 34 +
.../CodeGen/AArch64/aarch64-mull-masks.ll | 612 ++++++------------
.../AArch64/arm64-extract-insert-varidx.ll | 2 +-
llvm/test/CodeGen/AArch64/arm64-rev.ll | 62 +-
llvm/test/CodeGen/AArch64/insertextract.ll | 4 +-
.../GlobalISelEmitter/GlobalISelEmitter.td | 10 +
.../TableGen/GlobalISelEmitter/HwModes.td | 1 +
.../TableGen/Common/CodeGenDAGPatterns.cpp | 11 +
.../TableGen/Common/CodeGenDAGPatterns.h | 5 +
.../GlobalISel/GlobalISelMatchTable.cpp | 14 +
.../Common/GlobalISel/GlobalISelMatchTable.h | 21 +
.../GlobalISelMatchTableExecutorEmitter.cpp | 4 +
.../GlobalISelMatchTableExecutorEmitter.h | 24 +
.../TableGen/GlobalISelCombinerEmitter.cpp | 7 +
llvm/utils/TableGen/GlobalISelEmitter.cpp | 32 +-
19 files changed, 429 insertions(+), 463 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
index 6a7c0edbf2ce0..0b904915b9614 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
@@ -160,6 +160,12 @@ enum {
/// - Pred(2) - The predicate to test
GIM_CheckImmOperandPredicate,
+ /// Check a register predicate on the specified instruction.
+ /// - InsnID(ULEB128) - Instruction ID
+ /// - OpIdx(ULEB128) - Operand index
+ /// - Pred(2) - The predicate to test
+ GIM_CheckRegOperandPredicate,
+
/// Check a memory operation has the specified atomic ordering.
/// - InsnID(ULEB128) - Instruction ID
/// - Ordering(ULEB128) - The AtomicOrdering value
@@ -706,6 +712,12 @@ class GIMatchTableExecutor {
"Subclasses must override this with a tablegen-erated function");
}
+ virtual bool testMOPredicate_MO(unsigned, const MachineOperand &,
+ const MatcherState &State) const {
+ llvm_unreachable(
+ "Subclasses must override this with a tablegen-erated function");
+ }
+
virtual bool testSimplePredicate(unsigned) const {
llvm_unreachable("Subclass does not implement testSimplePredicate!");
}
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index 6c4f03649149e..58d64671307d4 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -410,6 +410,26 @@ bool GIMatchTableExecutor::executeMatchTable(
return false;
break;
}
+ case GIM_CheckRegOperandPredicate: {
+ uint64_t InsnID = readULEB();
+ uint64_t OpIdx = readULEB();
+ uint16_t Predicate = readU16();
+ DEBUG_WITH_TYPE(TgtExecutor::getName(),
+ dbgs()
+ << CurrentIdx << ": GIM_CheckRegOperandPredicate(MIs["
+ << InsnID << "]->getOperand(" << OpIdx
+ << "), Predicate=" << Predicate << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ assert(State.MIs[InsnID]->getOperand(OpIdx).isReg() &&
+ "Expected register operand");
+ assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+
+ if (!testMOPredicate_MO(Predicate, MO, State))
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ break;
+ }
case GIM_CheckIsBuildVectorAllOnes:
case GIM_CheckIsBuildVectorAllZeros: {
uint64_t InsnID = readULEB();
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index 406baa4f5fdaa..933132d62866f 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -959,6 +959,7 @@ class PatFrags<dag ops, list<dag> frags, code pred = [{}],
list<dag> Fragments = frags;
code PredicateCode = pred;
code GISelPredicateCode = [{}];
+ code GISelRegPredicateCode = [{}];
code ImmediateCode = [{}];
SDNodeXForm OperandTransform = xform;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 22ecf99b12de6..2aadc4ae062e1 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -685,23 +685,31 @@ defm trunc_masked_scatter_i32 : masked_gather_scatter<trunc_masked_scatter_i32>;
def top16Zero: PatLeaf<(i32 GPR32:$src), [{
return Op.getValueType() == MVT::i32 &&
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(32, 16));
- }]>;
+ }]> {
+ let GISelRegPredicateCode = [{return isTop16Zero(MO); }];
+}
// top32Zero - answer true if the upper 32 bits of $src are 0, false otherwise
def top32Zero: PatLeaf<(i64 GPR64:$src), [{
return Op.getValueType() == MVT::i64 &&
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(64, 32));
- }]>;
+ }]> {
+ let GISelRegPredicateCode = [{ return isTop32Zero(MO); }];
+}
// topbitsallzero - Return true if all bits except the lowest bit are known zero
def topbitsallzero32: PatLeaf<(i32 GPR32:$src), [{
return Op.getValueType() == MVT::i32 &&
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(32, 31));
- }]>;
+ }]> {
+ let GISelRegPredicateCode = [{ return isTopBitsAllZero32(MO); }];
+}
def topbitsallzero64: PatLeaf<(i64 GPR64:$src), [{
return Op.getValueType() == MVT::i64 &&
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(64, 63));
- }]>;
+ }]> {
+ let GISelRegPredicateCode = [{ return isTopBitsAllZero64(MO); }];
+}
// Node definitions.
def AArch64CB : SDNode<"AArch64ISD::CB", SDT_AArch64cb, [SDNPHasChain]>;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index e0c693bff3c0a..e1e2c533a9f3b 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -22,6 +22,7 @@
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
+#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
@@ -510,6 +511,16 @@ class AArch64InstructionSelector : public InstructionSelector {
/// Return true if \p MI is a load or store of \p NumBytes bytes.
bool isLoadStoreOfNumBytes(const MachineInstr &MI, unsigned NumBytes) const;
+ /// Return true if top 16 bits of register are zero.
+ bool isTop16Zero(const MachineOperand &MO) const;
+
+ /// Return true if top 32 bits of register are zero.
+ bool isTop32Zero(const MachineOperand &MO) const;
+
+ /// Return true if all bits of register except the lowest bit are known zero.
+ bool isTopBitsAllZero32(const MachineOperand &MO) const;
+ bool isTopBitsAllZero64(const MachineOperand &MO) const;
+
/// Returns true if \p MI is guaranteed to have the high-half of a 64-bit
/// register zeroed out. In other words, the result of MI has been explicitly
/// zero extended.
@@ -7985,6 +7996,29 @@ bool AArch64InstructionSelector::isLoadStoreOfNumBytes(
return (*MI.memoperands_begin())->getSize() == NumBytes;
}
+bool AArch64InstructionSelector::isTop16Zero(const MachineOperand &MO) const {
+ Register Reg = MO.getReg();
+ return VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(32, 16));
+}
+
+// bool isTop32Zero(const MachineOperand &MO) const;
+bool AArch64InstructionSelector::isTop32Zero(const MachineOperand &MO) const {
+ Register Reg = MO.getReg();
+ return VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(64, 32));
+}
+
+bool AArch64InstructionSelector::isTopBitsAllZero32(
+ const MachineOperand &MO) const {
+ Register Reg = MO.getReg();
+ return VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(32, 31));
+}
+
+bool AArch64InstructionSelector::isTopBitsAllZero64(
+ const MachineOperand &MO) const {
+ Register Reg = MO.getReg();
+ return VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(64, 63));
+}
+
bool AArch64InstructionSelector::isDef32(const MachineInstr &MI) const {
const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
if (MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() != 32)
diff --git a/llvm/test/CodeGen/AArch64/aarch64-mull-masks.ll b/llvm/test/CodeGen/AArch64/aarch64-mull-masks.ll
index 8de1fc5762c15..bf73aeb855c09 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-mull-masks.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-mull-masks.ll
@@ -1291,21 +1291,13 @@ entry:
}
define i64 @umull_ldrb_h(ptr %x0, i16 %x1) {
-; CHECK-SD-LABEL: umull_ldrb_h:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umull x0, w8, w9
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldrb_h:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: mul x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldrb_h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umull x0, w8, w9
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1315,21 +1307,13 @@ entry:
}
define i64 @umull_ldrb_h_commuted(ptr %x0, i16 %x1) {
-; CHECK-SD-LABEL: umull_ldrb_h_commuted:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umull x0, w9, w8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldrb_h_commuted:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: mul x0, x9, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldrb_h_commuted:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umull x0, w9, w8
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1339,18 +1323,11 @@ entry:
}
define i64 @umull_ldrh_w(ptr %x0, i32 %x1) {
-; CHECK-SD-LABEL: umull_ldrh_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrh w8, [x0]
-; CHECK-SD-NEXT: umull x0, w8, w1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldrh_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrh w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: mul x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldrh_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrh w8, [x0]
+; CHECK-NEXT: umull x0, w8, w1
+; CHECK-NEXT: ret
entry:
%ext64 = load i16, ptr %x0
%zext = zext i16 %ext64 to i64
@@ -1360,21 +1337,13 @@ entry:
}
define i64 @umull_ldr_b(ptr %x0, i8 %x1) {
-; CHECK-SD-LABEL: umull_ldr_b:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xff
-; CHECK-SD-NEXT: umull x0, w8, w9
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldr_b:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xff
-; CHECK-GI-NEXT: mul x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldr_b:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xff
+; CHECK-NEXT: umull x0, w8, w9
+; CHECK-NEXT: ret
entry:
%ext64 = load i32, ptr %x0
%zext = zext i32 %ext64 to i64
@@ -1384,18 +1353,11 @@ entry:
}
define i64 @umull_ldr2_w(ptr %x0, i32 %x1) {
-; CHECK-SD-LABEL: umull_ldr2_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umull x0, w8, w1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldr2_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: mul x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldr2_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umull x0, w8, w1
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1405,19 +1367,12 @@ entry:
}
define i64 @umull_ldr2_ldr2(ptr %x0, ptr %x1) {
-; CHECK-SD-LABEL: umull_ldr2_ldr2:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: ldr w9, [x1]
-; CHECK-SD-NEXT: umull x0, w8, w9
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldr2_ldr2:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: ldr w9, [x1]
-; CHECK-GI-NEXT: mul x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldr2_ldr2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: ldr w9, [x1]
+; CHECK-NEXT: umull x0, w8, w9
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1428,18 +1383,11 @@ entry:
}
define i64 @umull_ldr2_d(ptr %x0, i64 %x1) {
-; CHECK-SD-LABEL: umull_ldr2_d:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umull x0, w8, w1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldr2_d:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: mul x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldr2_d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umull x0, w8, w1
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1449,21 +1397,13 @@ entry:
}
define i64 @umaddl_ldrb_h(ptr %x0, i16 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umaddl_ldrb_h:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umaddl x0, w8, w9, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_ldrb_h:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: madd x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_ldrb_h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umaddl x0, w8, w9, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1474,21 +1414,13 @@ entry:
}
define i64 @umaddl_ldrb_h_commuted(ptr %x0, i16 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umaddl_ldrb_h_commuted:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umaddl x0, w9, w8, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_ldrb_h_commuted:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: madd x0, x9, x8, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_ldrb_h_commuted:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umaddl x0, w9, w8, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1499,18 +1431,11 @@ entry:
}
define i64 @umaddl_ldrh_w(ptr %x0, i32 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umaddl_ldrh_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrh w8, [x0]
-; CHECK-SD-NEXT: umaddl x0, w8, w1, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_ldrh_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrh w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: madd x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_ldrh_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrh w8, [x0]
+; CHECK-NEXT: umaddl x0, w8, w1, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i16, ptr %x0
%zext = zext i16 %ext64 to i64
@@ -1521,21 +1446,13 @@ entry:
}
define i64 @umaddl_ldr_b(ptr %x0, i8 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umaddl_ldr_b:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xff
-; CHECK-SD-NEXT: umaddl x0, w8, w9, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_ldr_b:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xff
-; CHECK-GI-NEXT: madd x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_ldr_b:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xff
+; CHECK-NEXT: umaddl x0, w8, w9, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i32, ptr %x0
%zext = zext i32 %ext64 to i64
@@ -1546,18 +1463,11 @@ entry:
}
define i64 @umaddl_ldr2_w(ptr %x0, i32 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umaddl_ldr2_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umaddl x0, w8, w1, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_ldr2_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: madd x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_ldr2_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umaddl x0, w8, w1, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1568,19 +1478,12 @@ entry:
}
define i64 @umaddl_ldr2_ldr2(ptr %x0, ptr %x1, i64 %x2) {
-; CHECK-SD-LABEL: umaddl_ldr2_ldr2:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: ldr w9, [x1]
-; CHECK-SD-NEXT: umaddl x0, w8, w9, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_ldr2_ldr2:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: ldr w9, [x1]
-; CHECK-GI-NEXT: madd x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_ldr2_ldr2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: ldr w9, [x1]
+; CHECK-NEXT: umaddl x0, w8, w9, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1592,18 +1495,11 @@ entry:
}
define i64 @umaddl_ldr2_d(ptr %x0, i64 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umaddl_ldr2_d:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umaddl x0, w8, w1, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_ldr2_d:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: madd x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_ldr2_d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umaddl x0, w8, w1, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1614,21 +1510,13 @@ entry:
}
define i64 @umnegl_ldrb_h(ptr %x0, i16 %x1) {
-; CHECK-SD-LABEL: umnegl_ldrb_h:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umnegl x0, w8, w9
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umnegl_ldrb_h:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: mneg x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umnegl_ldrb_h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umnegl x0, w8, w9
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1639,21 +1527,13 @@ entry:
}
define i64 @umnegl_ldrb_h_commuted(ptr %x0, i16 %x1) {
-; CHECK-SD-LABEL: umnegl_ldrb_h_commuted:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umnegl x0, w9, w8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umnegl_ldrb_h_commuted:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: mneg x0, x9, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umnegl_ldrb_h_commuted:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umnegl x0, w9, w8
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1664,18 +1544,11 @@ entry:
}
define i64 @umnegl_ldrh_w(ptr %x0, i32 %x1) {
-; CHECK-SD-LABEL: umnegl_ldrh_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrh w8, [x0]
-; CHECK-SD-NEXT: umnegl x0, w8, w1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umnegl_ldrh_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrh w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: mneg x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umnegl_ldrh_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrh w8, [x0]
+; CHECK-NEXT: umnegl x0, w8, w1
+; CHECK-NEXT: ret
entry:
%ext64 = load i16, ptr %x0
%zext = zext i16 %ext64 to i64
@@ -1686,21 +1559,13 @@ entry:
}
define i64 @umnegl_ldr_b(ptr %x0, i8 %x1) {
-; CHECK-SD-LABEL: umnegl_ldr_b:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xff
-; CHECK-SD-NEXT: umnegl x0, w8, w9
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umnegl_ldr_b:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xff
-; CHECK-GI-NEXT: mneg x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umnegl_ldr_b:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xff
+; CHECK-NEXT: umnegl x0, w8, w9
+; CHECK-NEXT: ret
entry:
%ext64 = load i32, ptr %x0
%zext = zext i32 %ext64 to i64
@@ -1711,18 +1576,11 @@ entry:
}
define i64 @umnegl_ldr2_w(ptr %x0, i32 %x1) {
-; CHECK-SD-LABEL: umnegl_ldr2_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umnegl x0, w8, w1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umnegl_ldr2_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: mneg x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umnegl_ldr2_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umnegl x0, w8, w1
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1733,19 +1591,12 @@ entry:
}
define i64 @umnegl_ldr2_ldr2(ptr %x0, ptr %x1) {
-; CHECK-SD-LABEL: umnegl_ldr2_ldr2:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: ldr w9, [x1]
-; CHECK-SD-NEXT: umnegl x0, w8, w9
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umnegl_ldr2_ldr2:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: ldr w9, [x1]
-; CHECK-GI-NEXT: mneg x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umnegl_ldr2_ldr2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: ldr w9, [x1]
+; CHECK-NEXT: umnegl x0, w8, w9
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1757,18 +1608,11 @@ entry:
}
define i64 @umnegl_ldr2_d(ptr %x0, i64 %x1) {
-; CHECK-SD-LABEL: umnegl_ldr2_d:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umnegl x0, w8, w1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umnegl_ldr2_d:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: mneg x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umnegl_ldr2_d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umnegl x0, w8, w1
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1779,21 +1623,13 @@ entry:
}
define i64 @umsubl_ldrb_h(ptr %x0, i16 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umsubl_ldrb_h:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umsubl x0, w8, w9, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umsubl_ldrb_h:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: msub x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umsubl_ldrb_h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umsubl x0, w8, w9, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1804,21 +1640,13 @@ entry:
}
define i64 @umsubl_ldrb_h_commuted(ptr %x0, i16 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umsubl_ldrb_h_commuted:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrb w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xffff
-; CHECK-SD-NEXT: umsubl x0, w9, w8, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umsubl_ldrb_h_commuted:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrb w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xffff
-; CHECK-GI-NEXT: msub x0, x9, x8, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umsubl_ldrb_h_commuted:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrb w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xffff
+; CHECK-NEXT: umsubl x0, w9, w8, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i8, ptr %x0
%zext = zext i8 %ext64 to i64
@@ -1829,18 +1657,11 @@ entry:
}
define i64 @umsubl_ldrh_w(ptr %x0, i32 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umsubl_ldrh_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldrh w8, [x0]
-; CHECK-SD-NEXT: umsubl x0, w8, w1, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umsubl_ldrh_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldrh w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: msub x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umsubl_ldrh_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldrh w8, [x0]
+; CHECK-NEXT: umsubl x0, w8, w1, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i16, ptr %x0
%zext = zext i16 %ext64 to i64
@@ -1851,21 +1672,13 @@ entry:
}
define i64 @umsubl_ldr_b(ptr %x0, i8 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umsubl_ldr_b:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-SD-NEXT: and x9, x1, #0xff
-; CHECK-SD-NEXT: umsubl x0, w8, w9, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umsubl_ldr_b:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
-; CHECK-GI-NEXT: and x9, x1, #0xff
-; CHECK-GI-NEXT: msub x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umsubl_ldr_b:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
+; CHECK-NEXT: and x9, x1, #0xff
+; CHECK-NEXT: umsubl x0, w8, w9, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i32, ptr %x0
%zext = zext i32 %ext64 to i64
@@ -1876,18 +1689,11 @@ entry:
}
define i64 @umsubl_ldr2_w(ptr %x0, i32 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umsubl_ldr2_w:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umsubl x0, w8, w1, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umsubl_ldr2_w:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: msub x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umsubl_ldr2_w:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umsubl x0, w8, w1, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1898,19 +1704,12 @@ entry:
}
define i64 @umsubl_ldr2_ldr2(ptr %x0, ptr %x1, i64 %x2) {
-; CHECK-SD-LABEL: umsubl_ldr2_ldr2:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: ldr w9, [x1]
-; CHECK-SD-NEXT: umsubl x0, w8, w9, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umsubl_ldr2_ldr2:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: ldr w9, [x1]
-; CHECK-GI-NEXT: msub x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umsubl_ldr2_ldr2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: ldr w9, [x1]
+; CHECK-NEXT: umsubl x0, w8, w9, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1922,18 +1721,11 @@ entry:
}
define i64 @umsubl_ldr2_d(ptr %x0, i64 %x1, i64 %x2) {
-; CHECK-SD-LABEL: umsubl_ldr2_d:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr w8, [x0]
-; CHECK-SD-NEXT: umsubl x0, w8, w1, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umsubl_ldr2_d:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr w8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: msub x0, x8, x9, x2
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umsubl_ldr2_d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr w8, [x0]
+; CHECK-NEXT: umsubl x0, w8, w1, x2
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 4294967295
@@ -1944,20 +1736,12 @@ entry:
}
define i64 @umull_ldr2_w_cc1(ptr %x0, i32 %x1) {
-; CHECK-SD-LABEL: umull_ldr2_w_cc1:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ldr x8, [x0]
-; CHECK-SD-NEXT: and x8, x8, #0x7fffffff
-; CHECK-SD-NEXT: umull x0, w8, w1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_ldr2_w_cc1:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldr x8, [x0]
-; CHECK-GI-NEXT: mov w9, w1
-; CHECK-GI-NEXT: and x8, x8, #0x7fffffff
-; CHECK-GI-NEXT: mul x0, x8, x9
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_ldr2_w_cc1:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr x8, [x0]
+; CHECK-NEXT: and x8, x8, #0x7fffffff
+; CHECK-NEXT: umull x0, w8, w1
+; CHECK-NEXT: ret
entry:
%ext64 = load i64, ptr %x0
%and = and i64 %ext64, 2147483647
@@ -1998,18 +1782,11 @@ entry:
}
define i64 @umull_and_lshr(i64 %x) {
-; CHECK-SD-LABEL: umull_and_lshr:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: lsr x8, x0, #32
-; CHECK-SD-NEXT: umull x0, w0, w8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umull_and_lshr:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: lsr x8, x0, #32
-; CHECK-GI-NEXT: mov w9, w0
-; CHECK-GI-NEXT: mul x0, x9, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umull_and_lshr:
+; CHECK: // %bb.0:
+; CHECK-NEXT: lsr x8, x0, #32
+; CHECK-NEXT: umull x0, w0, w8
+; CHECK-NEXT: ret
%lo = and i64 %x, u0xffffffff
%hi = lshr i64 %x, 32
%mul = mul i64 %lo, %hi
@@ -2028,18 +1805,11 @@ define i64 @umull_and_and(i64 %x, i64 %y) {
}
define i64 @umaddl_and_lshr(i64 %x, i64 %a) {
-; CHECK-SD-LABEL: umaddl_and_lshr:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: lsr x8, x0, #32
-; CHECK-SD-NEXT: umaddl x0, w0, w8, x1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_and_lshr:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: lsr x8, x0, #32
-; CHECK-GI-NEXT: mov w9, w0
-; CHECK-GI-NEXT: madd x0, x9, x8, x1
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_and_lshr:
+; CHECK: // %bb.0:
+; CHECK-NEXT: lsr x8, x0, #32
+; CHECK-NEXT: umaddl x0, w0, w8, x1
+; CHECK-NEXT: ret
%lo = and i64 %x, u0xffffffff
%hi = lshr i64 %x, 32
%mul = mul i64 %lo, %hi
@@ -2048,16 +1818,10 @@ define i64 @umaddl_and_lshr(i64 %x, i64 %a) {
}
define i64 @umaddl_and_and(i64 %x, i64 %y, i64 %a) {
-; CHECK-SD-LABEL: umaddl_and_and:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: umaddl x0, w0, w1, x2
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umaddl_and_and:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: umull x8, w0, w1
-; CHECK-GI-NEXT: add x0, x2, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umaddl_and_and:
+; CHECK: // %bb.0:
+; CHECK-NEXT: umaddl x0, w0, w1, x2
+; CHECK-NEXT: ret
%lo = and i64 %x, u0xffffffff
%hi = and i64 %y, u0xffffffff
%mul = mul i64 %lo, %hi
diff --git a/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll b/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll
index 0f085566b0d8d..69b30108ed534 100644
--- a/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll
@@ -174,7 +174,7 @@ define <2 x i16> @test_varidx_extract_v4s16(<4 x i16> %x, i32 %idx) {
; CHECK-GISEL-NEXT: and x9, x9, #0x3
; CHECK-GISEL-NEXT: // kill: def $d0 killed $d0 def $q0
; CHECK-GISEL-NEXT: str d0, [sp, #8]
-; CHECK-GISEL-NEXT: madd x8, x9, x8, x10
+; CHECK-GISEL-NEXT: umaddl x8, w9, w8, x10
; CHECK-GISEL-NEXT: umov w9, v0.h[1]
; CHECK-GISEL-NEXT: ld1 { v0.h }[0], [x8]
; CHECK-GISEL-NEXT: mov v0.s[1], w9
diff --git a/llvm/test/CodeGen/AArch64/arm64-rev.ll b/llvm/test/CodeGen/AArch64/arm64-rev.ll
index 6bdd5f998a3b9..84557b441853a 100644
--- a/llvm/test/CodeGen/AArch64/arm64-rev.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-rev.ll
@@ -34,8 +34,7 @@ define i32 @test_rev_w_srl16(i16 %a) {
; CHECK-GI-LABEL: test_rev_w_srl16:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: and w8, w0, #0xffff
-; CHECK-GI-NEXT: rev w8, w8
-; CHECK-GI-NEXT: lsr w0, w8, #16
+; CHECK-GI-NEXT: rev16 w0, w8
; CHECK-GI-NEXT: ret
entry:
%0 = zext i16 %a to i32
@@ -45,12 +44,18 @@ entry:
}
define i32 @test_rev_w_srl16_load(ptr %a) {
-; CHECK-LABEL: test_rev_w_srl16_load:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ldrh w8, [x0]
-; CHECK-NEXT: rev w8, w8
-; CHECK-NEXT: lsr w0, w8, #16
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_rev_w_srl16_load:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ldrh w8, [x0]
+; CHECK-SD-NEXT: rev w8, w8
+; CHECK-SD-NEXT: lsr w0, w8, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_rev_w_srl16_load:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: ldrh w8, [x0]
+; CHECK-GI-NEXT: rev16 w0, w8
+; CHECK-GI-NEXT: ret
entry:
%0 = load i16, ptr %a
%1 = zext i16 %0 to i32
@@ -71,8 +76,7 @@ define i32 @test_rev_w_srl16_add(i8 %a, i8 %b) {
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: and w8, w1, #0xff
; CHECK-GI-NEXT: add w8, w8, w0, uxtb
-; CHECK-GI-NEXT: rev w8, w8
-; CHECK-GI-NEXT: lsr w0, w8, #16
+; CHECK-GI-NEXT: rev16 w0, w8
; CHECK-GI-NEXT: ret
entry:
%0 = zext i8 %a to i32
@@ -96,8 +100,7 @@ define i64 @test_rev_x_srl32(i32 %a) {
; CHECK-GI-LABEL: test_rev_x_srl32:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: mov w8, w0
-; CHECK-GI-NEXT: rev x8, x8
-; CHECK-GI-NEXT: lsr x0, x8, #32
+; CHECK-GI-NEXT: rev32 x0, x8
; CHECK-GI-NEXT: ret
entry:
%0 = zext i32 %a to i64
@@ -107,12 +110,18 @@ entry:
}
define i64 @test_rev_x_srl32_load(ptr %a) {
-; CHECK-LABEL: test_rev_x_srl32_load:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ldr w8, [x0]
-; CHECK-NEXT: rev x8, x8
-; CHECK-NEXT: lsr x0, x8, #32
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_rev_x_srl32_load:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ldr w8, [x0]
+; CHECK-SD-NEXT: rev x8, x8
+; CHECK-SD-NEXT: lsr x0, x8, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_rev_x_srl32_load:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: ldr w8, [x0]
+; CHECK-GI-NEXT: rev32 x0, x8
+; CHECK-GI-NEXT: ret
entry:
%0 = load i32, ptr %a
%1 = zext i32 %0 to i64
@@ -122,18 +131,11 @@ entry:
}
define i64 @test_rev_x_srl32_shift(i64 %a) {
-; CHECK-SD-LABEL: test_rev_x_srl32_shift:
-; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: ubfx x8, x0, #2, #29
-; CHECK-SD-NEXT: rev32 x0, x8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: test_rev_x_srl32_shift:
-; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ubfx x8, x0, #2, #29
-; CHECK-GI-NEXT: rev x8, x8
-; CHECK-GI-NEXT: lsr x0, x8, #32
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: test_rev_x_srl32_shift:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ubfx x8, x0, #2, #29
+; CHECK-NEXT: rev32 x0, x8
+; CHECK-NEXT: ret
entry:
%0 = shl i64 %a, 33
%1 = lshr i64 %0, 35
diff --git a/llvm/test/CodeGen/AArch64/insertextract.ll b/llvm/test/CodeGen/AArch64/insertextract.ll
index aa4f31fb5f53e..50de99c756a58 100644
--- a/llvm/test/CodeGen/AArch64/insertextract.ll
+++ b/llvm/test/CodeGen/AArch64/insertextract.ll
@@ -630,7 +630,7 @@ define <8 x i8> @insert_v8i8_c(<8 x i8> %a, i8 %b, i32 %c) {
; CHECK-GI-NEXT: mov w8, #1 // =0x1
; CHECK-GI-NEXT: str d0, [sp, #8]
; CHECK-GI-NEXT: and x9, x9, #0x7
-; CHECK-GI-NEXT: mul x8, x9, x8
+; CHECK-GI-NEXT: umull x8, w9, w8
; CHECK-GI-NEXT: add x9, sp, #8
; CHECK-GI-NEXT: strb w0, [x9, x8]
; CHECK-GI-NEXT: ldr d0, [sp, #8]
@@ -682,7 +682,7 @@ define <16 x i8> @insert_v16i8_c(<16 x i8> %a, i8 %b, i32 %c) {
; CHECK-GI-NEXT: mov w8, #1 // =0x1
; CHECK-GI-NEXT: str q0, [sp]
; CHECK-GI-NEXT: and x9, x9, #0xf
-; CHECK-GI-NEXT: mul x8, x9, x8
+; CHECK-GI-NEXT: umull x8, w9, w8
; CHECK-GI-NEXT: mov x9, sp
; CHECK-GI-NEXT: strb w0, [x9, x8]
; CHECK-GI-NEXT: ldr q0, [sp], #16
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index 570adbb632616..0f61b75d3e2ee 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -82,6 +82,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// CHECK-NEXT: bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat &Imm) const override;
// CHECK-NEXT: const uint8_t *getMatchTable() const override;
// CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override;
+// CHECK-NEXT: bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand &MO, const MatcherState &State) const override;
// CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override;
// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override;
// CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL
@@ -157,6 +158,15 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// CHECK-NEXT: GICXXPred_MI_Predicate_frag = GICXXPred_Invalid + 1,
// CHECK-NEXT: };
+// CHECK-LABEL: // PatFrag predicates.
+// CHECK-NEXT: bool MyTargetInstructionSelector::testMOPredicate_MO(unsigned PredicateID, const MachineOperand & MO, const MatcherState &State) const {
+// CHECK-NEXT: const auto &Operands = State.RecordedOperands;
+// CHECK-NEXT: (void)Operands;
+// CHECK-NEXT: llvm_unreachable("Unknown predicate");
+// CHECK-NEXT: return false;
+// CHECK-NEXT: }
+
+
// CHECK-LABEL: // PatFrag predicates.
// CHECK-NEXT: enum {
// CHECK-NEXT: GICXXPred_I64_Predicate_cimm8 = GICXXPred_Invalid + 1,
diff --git a/llvm/test/TableGen/GlobalISelEmitter/HwModes.td b/llvm/test/TableGen/GlobalISelEmitter/HwModes.td
index 510368516739d..f112577e4c3c4 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/HwModes.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/HwModes.td
@@ -54,6 +54,7 @@ class I<dag OOps, dag IOps, list<dag> Pat>
// CHECK-NEXT: bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat &Imm) const override;
// CHECK-NEXT: const uint8_t *getMatchTable() const override;
// CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override;
+// CHECK-NEXT: bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand &MO, const MatcherState &State) const override;
// CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override;
// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override;
// CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index 3029604adcc36..fd4c563e0bfde 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -1297,6 +1297,17 @@ std::string TreePredicateFn::getGISelPredicateCode() const {
PatFragRec->getRecord()->getValueAsString("GISelPredicateCode"));
}
+bool TreePredicateFn::hasGISelRegPredicateCode() const {
+ return !PatFragRec->getRecord()
+ ->getValueAsString("GISelRegPredicateCode")
+ .empty();
+}
+
+std::string TreePredicateFn::getGISelRegPredicateCode() const {
+ return std::string(
+ PatFragRec->getRecord()->getValueAsString("GISelRegPredicateCode"));
+}
+
StringRef TreePredicateFn::getImmType() const {
if (immCodeUsesAPInt())
return "const APInt &";
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h
index 725414f8f68d9..581313f1d5d54 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h
@@ -590,6 +590,11 @@ class TreePredicateFn {
bool hasGISelPredicateCode() const;
std::string getGISelPredicateCode() const;
+ // If true, indicates that GlobalISel-based C++ code was supplied for checking
+ // register operands.
+ bool hasGISelRegPredicateCode() const;
+ std::string getGISelRegPredicateCode() const;
+
private:
bool hasPredCode() const;
bool hasImmCode() const;
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 2cb357927250f..fbf892e6c708e 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -33,6 +33,8 @@ Error failUnsupported(const Twine &Reason) {
std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) {
if (Predicate.hasGISelPredicateCode())
return "GICXXPred_MI_" + Predicate.getFnName();
+ else if (Predicate.hasGISelRegPredicateCode())
+ return "GICXXPred_MO_" + Predicate.getFnName();
return "GICXXPred_" + Predicate.getImmTypeIdentifier().str() + "_" +
Predicate.getFnName();
}
@@ -1326,6 +1328,18 @@ void OperandImmPredicateMatcher::emitPredicateOpcodes(MatchTable &Table,
<< MatchTable::LineBreak;
}
+//===- OperandRegPredicateMatcher -----------------------------------------===//
+
+void OperandRegPredicateMatcher::emitPredicateOpcodes(MatchTable &Table,
+ RuleMatcher &Rule) const {
+ Table << MatchTable::Opcode("GIM_CheckRegOperandPredicate")
+ << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
+ << MatchTable::Comment("MO") << MatchTable::ULEB128Value(OpIdx)
+ << MatchTable::Comment("Predicate")
+ << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate))
+ << MatchTable::LineBreak;
+}
+
//===- OperandMatcher -----------------------------------------------------===//
std::string OperandMatcher::getOperandExpr(unsigned InsnVarID) const {
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h
index 9f17882cdae4f..1bed3ebfaee83 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h
@@ -824,6 +824,7 @@ class PredicateMatcher {
IPM_OneUse,
IPM_GenericPredicate,
IPM_MIFlags,
+ OPM_RegPredicate,
OPM_SameOperand,
OPM_ComplexPattern,
OPM_IntrinsicID,
@@ -1255,6 +1256,26 @@ class OperandImmPredicateMatcher : public OperandPredicateMatcher {
RuleMatcher &Rule) const override;
};
+/// Generates code to check that this operand is a register whose value meets
+/// the predicate.
+class OperandRegPredicateMatcher : public OperandPredicateMatcher {
+protected:
+ TreePredicateFn Predicate;
+
+public:
+ OperandRegPredicateMatcher(unsigned InsnVarID, unsigned OpIdx,
+ const TreePredicateFn &Predicate)
+ : OperandPredicateMatcher(OPM_RegPredicate, InsnVarID, OpIdx),
+ Predicate(Predicate) {}
+
+ static bool classof(const PredicateMatcher *P) {
+ return P->getKind() == OPM_RegPredicate;
+ }
+
+ void emitPredicateOpcodes(MatchTable &Table,
+ RuleMatcher &Rule) const override;
+};
+
/// Generates code to check that a set of predicates match for a particular
/// operand.
class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> {
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
index ffab2fdedc5a1..b68d5773f647e 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
@@ -182,6 +182,7 @@ void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl(
emitSubtargetFeatureBitsetImpl(OS, Rules);
emitComplexPredicates(OS, ComplexOperandMatchers);
emitMIPredicateFns(OS);
+ emitRegPredicateFns(OS);
emitI64ImmPredicateFns(OS);
emitAPFloatImmPredicateFns(OS);
emitAPIntImmPredicateFns(OS);
@@ -234,6 +235,9 @@ void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl(
<< " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI"
", const MatcherState &State) "
"const override;\n"
+ << " bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand "
+ "&MO, const MatcherState &State) "
+ "const override;\n"
<< " bool testSimplePredicate(unsigned PredicateID) const override;\n"
<< " bool runCustomAction(unsigned FnID, const MatcherState &State, "
"NewMIVector &OutMIs) "
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h
index 862f1e83c169f..b625fffb03833 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h
@@ -143,6 +143,26 @@ class GlobalISelMatchTableExecutorEmitter {
AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment);
}
+ /// Emits `testMOPredicate_MO`.
+ /// @tparam PredicateObject An object representing a predicate to emit.
+ /// @param OS Output stream.
+ /// @param AdditionalDecls Additional C++ variable declarations.
+ /// @param Predicates Predicates to emit.
+ /// @param GetPredEnumName Returns an enum name for a given predicate.
+ /// @param GetPredCode Returns the C++ code of a given predicate.
+ /// @param Comment Optional comment for the enum declaration.
+ template <typename PredicateObject>
+ void emitRegPredicateFnsImpl(
+ raw_ostream &OS, StringRef AdditionalDecls,
+ ArrayRef<PredicateObject> Predicates,
+ std::function<StringRef(PredicateObject)> GetPredEnumName,
+ std::function<StringRef(PredicateObject)> GetPredCode,
+ StringRef Comment = "") {
+ return emitCxxPredicateFns(
+ OS, "MO", "const MachineOperand &", "MO", ", const MatcherState &State",
+ AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment);
+ }
+
/// Helper function to emit the following executor functions:
/// * testImmPredicate_I64 (TypeIdentifier=I64)
/// * testImmPredicate_APInt (TypeIdentifier=APInt)
@@ -189,6 +209,10 @@ class GlobalISelMatchTableExecutorEmitter {
/// Note: `emitMIPredicateFnsImpl` can be used to do most of the work.
virtual void emitMIPredicateFns(raw_ostream &OS) = 0;
+ /// Emit the `testRegPredicate` function
+ /// Note `emitRegPredicateFnsImpl` can be used to do most of the work.
+ virtual void emitRegPredicateFns(raw_ostream &OS) = 0;
+
/// Emit the `testImmPredicate_I64` function.
/// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0;
diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
index 090e6bb37c3aa..5d5e72a2931ce 100644
--- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
@@ -2414,6 +2414,7 @@ class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter {
void emitAdditionalImpl(raw_ostream &OS) override;
void emitMIPredicateFns(raw_ostream &OS) override;
+ void emitRegPredicateFns(raw_ostream &OS) override;
void emitI64ImmPredicateFns(raw_ostream &OS) override;
void emitAPFloatImmPredicateFns(raw_ostream &OS) override;
void emitAPIntImmPredicateFns(raw_ostream &OS) override;
@@ -2581,6 +2582,12 @@ void GICombinerEmitter::emitMIPredicateFns(raw_ostream &OS) {
[](const CXXPredicateCode *C) -> StringRef { return C->Code; });
}
+void GICombinerEmitter::emitRegPredicateFns(raw_ostream &OS) {
+ // Unused, but still needs to be called.
+ emitRegPredicateFnsImpl<unsigned>(
+ OS, "", {}, [](unsigned) { return ""; }, [](unsigned) { return ""; });
+}
+
void GICombinerEmitter::emitI64ImmPredicateFns(raw_ostream &OS) {
// Unused, but still needs to be called.
emitImmPredicateFnsImpl<unsigned>(
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index edaf5299efc39..9f0e5cf641a31 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -321,6 +321,7 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
void emitAdditionalImpl(raw_ostream &OS) override;
void emitMIPredicateFns(raw_ostream &OS) override;
+ void emitRegPredicateFns(raw_ostream &OS) override;
void emitI64ImmPredicateFns(raw_ostream &OS) override;
void emitAPFloatImmPredicateFns(raw_ostream &OS) override;
void emitAPIntImmPredicateFns(raw_ostream &OS) override;
@@ -1110,8 +1111,18 @@ Error GlobalISelEmitter::importChildMatcher(
return Error::success();
}
- if (SrcChild.hasAnyPredicate())
- return failedImport("Src pattern child has unsupported predicate");
+ if (SrcChild.hasAnyPredicate()) {
+ for (const TreePredicateCall &Call : SrcChild.getPredicateCalls()) {
+ const TreePredicateFn &Predicate = Call.Fn;
+
+ if (!Predicate.hasGISelRegPredicateCode()) {
+ return failedImport("Src pattern child has unsupported predicate");
+ } else {
+ OM.addPredicate<OperandRegPredicateMatcher>(Predicate);
+ }
+ }
+ return Error::success();
+ }
// Check for constant immediates.
if (auto *ChildInt = dyn_cast<IntInit>(SrcChild.getLeafValue())) {
@@ -2291,6 +2302,23 @@ void GlobalISelEmitter::emitMIPredicateFns(raw_ostream &OS) {
"PatFrag predicates.");
}
+void GlobalISelEmitter::emitRegPredicateFns(raw_ostream &OS) {
+ std::vector<const Record *> MatchedRecords;
+ llvm::copy_if(AllPatFrags, std::back_inserter(MatchedRecords),
+ [](const Record *R) {
+ return !R->getValueAsString("GISelRegPredicateCode").empty();
+ });
+ emitRegPredicateFnsImpl<const Record *>(
+ OS,
+ " const auto &Operands = State.RecordedOperands;\n"
+ " (void)Operands;",
+ ArrayRef<const Record *>(MatchedRecords), &getPatFragPredicateEnumName,
+ [](const Record *R) {
+ return R->getValueAsString("GISelRegPredicateCode");
+ },
+ "PatFrag predicates.");
+}
+
void GlobalISelEmitter::emitI64ImmPredicateFns(raw_ostream &OS) {
std::vector<const Record *> MatchedRecords;
llvm::copy_if(AllPatFrags, std::back_inserter(MatchedRecords),
More information about the llvm-commits
mailing list