Skip to content

Commit 9bac1b6

Browse files
authored
[GlobalISel] Add and use a m_GAddLike pattern matcher. NFC (#125435)
This adds a Flags parameter to the BinaryOp_match, allowing it to detect different flags like Disjoint. A m_GDisjointOr is added to detect Or's with disjoint flags, and G_AddLike is then either a m_GADD or m_GDisjointOr. The rest is trying to allow matching `const MachineInstr&`, as opposed to non-const references.
1 parent c88352d commit 9bac1b6

File tree

3 files changed

+74
-16
lines changed

3 files changed

+74
-16
lines changed

llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ template <typename Pattern>
3333
return P.match(MRI, &MI);
3434
}
3535

36+
template <typename Pattern>
37+
[[nodiscard]] bool mi_match(const MachineInstr &MI,
38+
const MachineRegisterInfo &MRI, Pattern &&P) {
39+
return P.match(MRI, &MI);
40+
}
41+
3642
// TODO: Extend for N use.
3743
template <typename SubPatternT> struct OneUse_match {
3844
SubPatternT SubPat;
@@ -337,6 +343,19 @@ template <> struct bind_helper<MachineInstr *> {
337343
}
338344
};
339345

346+
template <> struct bind_helper<const MachineInstr *> {
347+
static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
348+
Register Reg) {
349+
MI = MRI.getVRegDef(Reg);
350+
return MI;
351+
}
352+
static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
353+
const MachineInstr *Inst) {
354+
MI = Inst;
355+
return MI;
356+
}
357+
};
358+
340359
template <> struct bind_helper<LLT> {
341360
static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
342361
Ty = MRI.getType(Reg);
@@ -368,6 +387,9 @@ template <typename Class> struct bind_ty {
368387

369388
inline bind_ty<Register> m_Reg(Register &R) { return R; }
370389
inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
390+
inline bind_ty<const MachineInstr *> m_MInstr(const MachineInstr *&MI) {
391+
return MI;
392+
}
371393
inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
372394
inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
373395
inline operand_type_match m_Pred() { return operand_type_match(); }
@@ -418,26 +440,28 @@ inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
418440

419441
// General helper for all the binary generic MI such as G_ADD/G_SUB etc
420442
template <typename LHS_P, typename RHS_P, unsigned Opcode,
421-
bool Commutable = false>
443+
bool Commutable = false, unsigned Flags = MachineInstr::NoFlags>
422444
struct BinaryOp_match {
423445
LHS_P L;
424446
RHS_P R;
425447

426448
BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
427449
template <typename OpTy>
428450
bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
429-
MachineInstr *TmpMI;
451+
const MachineInstr *TmpMI;
430452
if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
431453
if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
432-
return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
433-
R.match(MRI, TmpMI->getOperand(2).getReg())) ||
434-
// NOTE: When trying the alternative operand ordering
435-
// with a commutative operation, it is imperative to always run
436-
// the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
437-
// (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as
438-
// expected.
439-
(Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
440-
R.match(MRI, TmpMI->getOperand(1).getReg())));
454+
if ((!L.match(MRI, TmpMI->getOperand(1).getReg()) ||
455+
!R.match(MRI, TmpMI->getOperand(2).getReg())) &&
456+
// NOTE: When trying the alternative operand ordering
457+
// with a commutative operation, it is imperative to always run
458+
// the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
459+
// (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
460+
// expected.
461+
(!Commutable || !L.match(MRI, TmpMI->getOperand(2).getReg()) ||
462+
!R.match(MRI, TmpMI->getOperand(1).getReg())))
463+
return false;
464+
return (TmpMI->getFlags() & Flags) == Flags;
441465
}
442466
}
443467
return false;
@@ -464,7 +488,7 @@ struct BinaryOpc_match {
464488
// NOTE: When trying the alternative operand ordering
465489
// with a commutative operation, it is imperative to always run
466490
// the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
467-
// (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as
491+
// (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
468492
// expected.
469493
(Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
470494
R.match(MRI, TmpMI->getOperand(1).getReg())));
@@ -559,6 +583,19 @@ inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true> m_GOr(const LHS &L,
559583
return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true>(L, R);
560584
}
561585

586+
template <typename LHS, typename RHS>
587+
inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
588+
MachineInstr::Disjoint>
589+
m_GDisjointOr(const LHS &L, const RHS &R) {
590+
return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
591+
MachineInstr::Disjoint>(L, R);
592+
}
593+
594+
template <typename LHS, typename RHS>
595+
inline auto m_GAddLike(const LHS &L, const RHS &R) {
596+
return m_any_of(m_GAdd(L, R), m_GDisjointOr(L, R));
597+
}
598+
562599
template <typename LHS, typename RHS>
563600
inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SHL, false>
564601
m_GShl(const LHS &L, const RHS &R) {
@@ -717,7 +754,7 @@ struct CompareOp_match {
717754
// NOTE: When trying the alternative operand ordering
718755
// with a commutative operation, it is imperative to always run
719756
// the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
720-
// (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as expected.
757+
// (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
721758
if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
722759
P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
723760
return true;

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,9 +1030,7 @@ def add_and_or_is_add : PatFrags<(ops node:$lhs, node:$rhs),
10301030
return CurDAG->isADDLike(SDValue(N,0));
10311031
}]> {
10321032
let GISelPredicateCode = [{
1033-
return MI.getOpcode() == TargetOpcode::G_ADD ||
1034-
(MI.getOpcode() == TargetOpcode::G_OR &&
1035-
MI.getFlag(MachineInstr::MIFlag::Disjoint));
1033+
return mi_match(MI, MRI, m_GAddLike(m_Reg(), m_Reg()));
10361034
}];
10371035
}
10381036

llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,29 @@ TEST_F(AArch64GISelMITest, DeferredMatching) {
950950
m_GAdd(m_Reg(X), m_GSub(m_Reg(), m_DeferredReg(X)))));
951951
}
952952

953+
TEST_F(AArch64GISelMITest, AddLike) {
954+
setUp();
955+
if (!TM)
956+
GTEST_SKIP();
957+
auto s64 = LLT::scalar(64);
958+
959+
auto Cst1 = B.buildConstant(s64, 42);
960+
auto Cst2 = B.buildConstant(s64, 314);
961+
962+
auto Or1 = B.buildOr(s64, Cst1, Cst2, MachineInstr::Disjoint);
963+
auto Or2 = B.buildOr(s64, Cst1, Cst2);
964+
auto Add = B.buildAdd(s64, Cst1, Cst2);
965+
auto Sub = B.buildSub(s64, Cst1, Cst2);
966+
967+
EXPECT_TRUE(mi_match(Or1.getReg(0), *MRI, m_GDisjointOr(m_Reg(), m_Reg())));
968+
EXPECT_FALSE(mi_match(Or2.getReg(0), *MRI, m_GDisjointOr(m_Reg(), m_Reg())));
969+
970+
EXPECT_TRUE(mi_match(Add.getReg(0), *MRI, m_GAddLike(m_Reg(), m_Reg())));
971+
EXPECT_FALSE(mi_match(Sub.getReg(0), *MRI, m_GAddLike(m_Reg(), m_Reg())));
972+
EXPECT_TRUE(mi_match(Or1.getReg(0), *MRI, m_GAddLike(m_Reg(), m_Reg())));
973+
EXPECT_FALSE(mi_match(Or2.getReg(0), *MRI, m_GAddLike(m_Reg(), m_Reg())));
974+
}
975+
953976
} // namespace
954977

955978
int main(int argc, char **argv) {

0 commit comments

Comments
 (0)