diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 49f9ed5f6e7b6..46372c78263a1 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1357,7 +1357,8 @@ m_NUWAddLike(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches a group of binary opcodes. // -template +template struct BinOpPred_match : Predicate { LHS_t L; RHS_t R; @@ -1366,8 +1367,10 @@ struct BinOpPred_match : Predicate { template bool match(OpTy *V) { if (auto *I = dyn_cast(V)) - return this->isOpType(I->getOpcode()) && L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + return this->isOpType(I->getOpcode()) && + ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || + (Commutable && L.match(I->getOperand(1)) && + R.match(I->getOperand(0)))); return false; } }; @@ -1434,6 +1437,13 @@ m_BitwiseLogic(const LHS &L, const RHS &R) { return BinOpPred_match(L, R); } +/// Matches bitwise logic operations in either order. +template +inline BinOpPred_match +m_c_BitwiseLogic(const LHS &L, const RHS &R) { + return BinOpPred_match(L, R); +} + /// Matches integer division operations. template inline BinOpPred_match m_IDiv(const LHS &L, diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index 533a30bfba45d..a0b873de2d586 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -494,6 +494,45 @@ TEST_F(PatternMatchTest, Unless) { EXPECT_FALSE(m_Unless(m_c_Add(m_Zero(), m_One())).match(X)); } +TEST_F(PatternMatchTest, BitWise) { + Value *Or = IRB.CreateOr(IRB.getInt32(1), IRB.getInt32(0)); + Value *Xor = IRB.CreateXor(IRB.getInt32(1), IRB.getInt32(0)); + Value *And = IRB.CreateXor(IRB.getInt32(1), IRB.getInt32(0)); + Constant *T = IRB.getInt1(true); + Constant *F = IRB.getInt1(false); + Value *Alloca = IRB.CreateAlloca(IRB.getInt1Ty()); + Value *X = IRB.CreateLoad(IRB.getInt1Ty(), Alloca); + Value *Y = IRB.CreateLoad(IRB.getInt1Ty(), Alloca); + Value *LAnd = IRB.CreateSelect(X, Y, F); + Value *LOr = IRB.CreateSelect(X, T, Y); + Value *Add = IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(0)); + + EXPECT_TRUE(m_BitwiseLogic(m_One(), m_Zero()).match(Or)); + EXPECT_TRUE(m_BitwiseLogic(m_One(), m_Zero()).match(Xor)); + EXPECT_TRUE(m_BitwiseLogic(m_One(), m_Zero()).match(And)); + EXPECT_FALSE(m_BitwiseLogic(m_Value(), m_Value()).match(LAnd)); + EXPECT_FALSE(m_BitwiseLogic(m_Value(), m_Value()).match(LOr)); + EXPECT_FALSE(m_BitwiseLogic(m_Value(), m_Value()).match(Add)); + + EXPECT_FALSE(m_BitwiseLogic(m_Zero(), m_One()).match(Or)); + EXPECT_FALSE(m_BitwiseLogic(m_Zero(), m_One()).match(Xor)); + EXPECT_FALSE(m_BitwiseLogic(m_Zero(), m_One()).match(And)); + + EXPECT_TRUE(m_c_BitwiseLogic(m_One(), m_Zero()).match(Or)); + EXPECT_TRUE(m_c_BitwiseLogic(m_One(), m_Zero()).match(Xor)); + EXPECT_TRUE(m_c_BitwiseLogic(m_One(), m_Zero()).match(And)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Value(), m_Value()).match(LAnd)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Value(), m_Value()).match(LOr)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Value(), m_Value()).match(Add)); + + EXPECT_TRUE(m_c_BitwiseLogic(m_Zero(), m_One()).match(Or)); + EXPECT_TRUE(m_c_BitwiseLogic(m_Zero(), m_One()).match(Xor)); + EXPECT_TRUE(m_c_BitwiseLogic(m_Zero(), m_One()).match(And)); + + EXPECT_FALSE(m_c_BitwiseLogic(m_One(), m_One()).match(Or)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Zero(), m_Zero()).match(Xor)); +} + TEST_F(PatternMatchTest, ZExtSExtSelf) { LLVMContext &Ctx = IRB.getContext();