Skip to content

Commit a74f825

Browse files
authored
[MIPatternMatch] Add m_DeferredReg/Type (#121218)
This pattern does the same thing as m_SpecificReg/Type except the value it matches against origniated from an earlier pattern in the same mi_match expression. This patch also changes how commutative patterns are handled: in order to support m_DefferedReg/Type, we always have to run the LHS-pattern before the RHS one.
1 parent c7d2370 commit a74f825

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

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

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,36 @@ inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
372372
inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
373373
inline operand_type_match m_Pred() { return operand_type_match(); }
374374

375+
template <typename BindTy> struct deferred_helper {
376+
static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
377+
return VR == V;
378+
}
379+
};
380+
381+
template <> struct deferred_helper<LLT> {
382+
static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
383+
return VT == MRI.getType(R);
384+
}
385+
};
386+
387+
template <typename Class> struct deferred_ty {
388+
Class &VR;
389+
390+
deferred_ty(Class &V) : VR(V) {}
391+
392+
template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
393+
return deferred_helper<Class>::match(MRI, VR, V);
394+
}
395+
};
396+
397+
/// Similar to m_SpecificReg/Type, but the specific value to match originated
398+
/// from an earlier sub-pattern in the same mi_match expression. For example,
399+
/// we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
400+
/// because `X` is not initialized at the time it's passed to `m_SpecificReg`.
401+
/// Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
402+
inline deferred_ty<Register> m_DeferredReg(Register &R) { return R; }
403+
inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
404+
375405
struct ImplicitDefMatch {
376406
bool match(const MachineRegisterInfo &MRI, Register Reg) {
377407
MachineInstr *TmpMI;
@@ -401,8 +431,13 @@ struct BinaryOp_match {
401431
if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
402432
return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
403433
R.match(MRI, TmpMI->getOperand(2).getReg())) ||
404-
(Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
405-
L.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())));
406441
}
407442
}
408443
return false;
@@ -426,8 +461,13 @@ struct BinaryOpc_match {
426461
TmpMI->getNumOperands() == 3) {
427462
return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
428463
R.match(MRI, TmpMI->getOperand(2).getReg())) ||
429-
(Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
430-
L.match(MRI, TmpMI->getOperand(2).getReg())));
464+
// NOTE: When trying the alternative operand ordering
465+
// with a commutative operation, it is imperative to always run
466+
// the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
467+
// (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as
468+
// expected.
469+
(Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
470+
R.match(MRI, TmpMI->getOperand(1).getReg())));
431471
}
432472
}
433473
return false;
@@ -674,6 +714,10 @@ struct CompareOp_match {
674714
Register RHS = TmpMI->getOperand(3).getReg();
675715
if (L.match(MRI, LHS) && R.match(MRI, RHS))
676716
return true;
717+
// NOTE: When trying the alternative operand ordering
718+
// with a commutative operation, it is imperative to always run
719+
// 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.
677721
if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
678722
P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
679723
return true;

llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,36 @@ TEST_F(AArch64GISelMITest, MatchSpecificReg) {
920920
EXPECT_TRUE(mi_match(Add.getReg(0), *MRI, m_GAdd(m_SpecificReg(Reg), m_Reg())));
921921
}
922922

923+
TEST_F(AArch64GISelMITest, DeferredMatching) {
924+
setUp();
925+
if (!TM)
926+
GTEST_SKIP();
927+
auto s64 = LLT::scalar(64);
928+
auto s32 = LLT::scalar(32);
929+
930+
auto Cst1 = B.buildConstant(s64, 42);
931+
auto Cst2 = B.buildConstant(s64, 314);
932+
auto Add = B.buildAdd(s64, Cst1, Cst2);
933+
auto Sub = B.buildSub(s64, Add, Cst1);
934+
935+
auto TruncAdd = B.buildTrunc(s32, Add);
936+
auto TruncSub = B.buildTrunc(s32, Sub);
937+
auto NarrowAdd = B.buildAdd(s32, TruncAdd, TruncSub);
938+
939+
Register X;
940+
EXPECT_TRUE(mi_match(Sub.getReg(0), *MRI,
941+
m_GSub(m_GAdd(m_Reg(X), m_Reg()), m_DeferredReg(X))));
942+
LLT Ty;
943+
EXPECT_TRUE(
944+
mi_match(NarrowAdd.getReg(0), *MRI,
945+
m_GAdd(m_GTrunc(m_Type(Ty)), m_GTrunc(m_DeferredType(Ty)))));
946+
947+
// Test commutative.
948+
auto Add2 = B.buildAdd(s64, Sub, Cst1);
949+
EXPECT_TRUE(mi_match(Add2.getReg(0), *MRI,
950+
m_GAdd(m_Reg(X), m_GSub(m_Reg(), m_DeferredReg(X)))));
951+
}
952+
923953
} // namespace
924954

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

0 commit comments

Comments
 (0)