diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h --- a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -68,8 +68,13 @@ return SpecificConstantMatch(RequestedValue); } -/// Matches an integer 0. +///{ +/// Convenience matchers for specific integer values. inline SpecificConstantMatch m_ZeroInt() { return SpecificConstantMatch(0); } +inline SpecificConstantMatch m_AllOnesInt() { + return SpecificConstantMatch(-1); +} +///} // TODO: Rework this for different kinds of MachineOperand. // Currently assumes the Src for a match is a register. @@ -451,6 +456,14 @@ return m_GSub(m_ZeroInt(), Src); } +/// Matches a register not-ed by a G_XOR. +/// G_XOR %not_reg, -1 +template +inline BinaryOp_match +m_Not(const SrcTy &&Src) { + return m_GXor(Src, m_AllOnesInt()); +} + } // namespace GMIPatternMatch } // namespace llvm diff --git a/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp b/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp --- a/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp @@ -426,6 +426,17 @@ EXPECT_FALSE(mi_match(FortyTwo.getReg(0), *MRI, m_ZeroInt())); } +TEST_F(AArch64GISelMITest, MatchAllOnesInt) { + setUp(); + if (!TM) + return; + auto AllOnes = B.buildConstant(LLT::scalar(64), -1); + EXPECT_TRUE(mi_match(AllOnes.getReg(0), *MRI, m_AllOnesInt())); + + auto FortyTwo = B.buildConstant(LLT::scalar(64), 42); + EXPECT_FALSE(mi_match(FortyTwo.getReg(0), *MRI, m_AllOnesInt())); +} + TEST_F(AArch64GISelMITest, MatchNeg) { setUp(); if (!TM) @@ -457,6 +468,39 @@ EXPECT_TRUE(mi_match(AddInst.getReg(2), *MRI, m_Neg(m_Reg(NegatedReg)))); EXPECT_EQ(NegatedReg, Copies[0]); } + +TEST_F(AArch64GISelMITest, MatchNot) { + setUp(); + if (!TM) + return; + + LLT s64 = LLT::scalar(64); + auto AllOnes = B.buildConstant(LLT::scalar(64), -1); + auto NotInst1 = B.buildXor(s64, Copies[0], AllOnes); + Register NotReg; + + // Match: G_XOR %NotReg, -1 + EXPECT_TRUE(mi_match(NotInst1.getReg(0), *MRI, m_Not(m_Reg(NotReg)))); + EXPECT_EQ(NotReg, Copies[0]); + + // Match: G_XOR -1, %NotReg + auto NotInst2 = B.buildXor(s64, AllOnes, Copies[1]); + EXPECT_TRUE(mi_match(NotInst2.getReg(0), *MRI, m_Not(m_Reg(NotReg)))); + EXPECT_EQ(NotReg, Copies[1]); + + // Don't match: G_XOR %NotReg, 42 + auto FortyTwo = B.buildConstant(LLT::scalar(64), 42); + auto WrongCst = B.buildXor(s64, Copies[0], FortyTwo); + EXPECT_FALSE(mi_match(WrongCst.getReg(0), *MRI, m_Not(m_Reg(NotReg)))); + + // Complex testcase. + // %xor = G_XOR %NotReg, -1 + // %add = G_ADD %x, %xor + auto AddInst = B.buildAdd(s64, Copies[1], NotInst1); + NotReg = Register(); + EXPECT_TRUE(mi_match(AddInst.getReg(2), *MRI, m_Not(m_Reg(NotReg)))); + EXPECT_EQ(NotReg, Copies[0]); +} } // namespace int main(int argc, char **argv) {