Index: llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -39,6 +39,20 @@ return SP; } +template struct OneNonDBGUse_match { + SubPatternT SubPat; + OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {} + + bool match(const MachineRegisterInfo &MRI, Register Reg) { + return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg); + } +}; + +template +inline OneNonDBGUse_match m_OneNonDBGUse(const SubPat &SP) { + return SP; +} + struct ConstantMatch { int64_t &CR; ConstantMatch(int64_t &C) : CR(C) {} Index: llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp =================================================================== --- llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp +++ llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp @@ -392,13 +392,24 @@ LLT s64 = LLT::scalar(64); auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); - // Make multiple uses of this add. + Register Reg = MIBAdd.getReg(0); + + // Only one use of Reg. B.buildCast(LLT::pointer(0, 32), MIBAdd); + EXPECT_TRUE(mi_match(Reg, *MRI, m_OneUse(m_GAdd(m_Reg(), m_Reg())))); + EXPECT_TRUE(mi_match(Reg, *MRI, m_OneNonDBGUse(m_GAdd(m_Reg(), m_Reg())))); + + // Add multiple debug uses of Reg. + B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg})->getOperand(0).setIsDebug(); + B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg})->getOperand(0).setIsDebug(); + + EXPECT_FALSE(mi_match(Reg, *MRI, m_OneUse(m_GAdd(m_Reg(), m_Reg())))); + EXPECT_TRUE(mi_match(Reg, *MRI, m_OneNonDBGUse(m_GAdd(m_Reg(), m_Reg())))); + + // Multiple non-debug uses of Reg. B.buildCast(LLT::pointer(1, 32), MIBAdd); - bool match = mi_match(MIBAdd.getReg(0), *MRI, m_GAdd(m_Reg(), m_Reg())); - EXPECT_TRUE(match); - match = mi_match(MIBAdd.getReg(0), *MRI, m_OneUse(m_GAdd(m_Reg(), m_Reg()))); - EXPECT_FALSE(match); + EXPECT_FALSE(mi_match(Reg, *MRI, m_OneUse(m_GAdd(m_Reg(), m_Reg())))); + EXPECT_FALSE(mi_match(Reg, *MRI, m_OneNonDBGUse(m_GAdd(m_Reg(), m_Reg())))); } TEST_F(AArch64GISelMITest, MatchSpecificConstant) {