diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h index 7a5e29bc7b138..2e3807a2dfffd 100644 --- a/llvm/include/llvm/CodeGen/SDPatternMatch.h +++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h @@ -729,6 +729,11 @@ inline BinaryOpc_match m_Xor(const LHS &L, const RHS &R) { return BinaryOpc_match(ISD::XOR, L, R); } +template +inline auto m_BitwiseLogic(const LHS &L, const RHS &R) { + return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R)); +} + template inline BinaryOpc_match m_SMin(const LHS &L, const RHS &R) { return BinaryOpc_match(ISD::SMIN, L, R); diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 00c6f90e1c864..9ca3ba41c6f13 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10553,29 +10553,20 @@ static SDValue foldBitOrderCrossLogicOp(SDNode *N, SelectionDAG &DAG) { SDValue N0 = N->getOperand(0); EVT VT = N->getValueType(0); SDLoc DL(N); - if (ISD::isBitwiseLogicOp(N0.getOpcode()) && N0.hasOneUse()) { - SDValue OldLHS = N0.getOperand(0); - SDValue OldRHS = N0.getOperand(1); - - // If both operands are bswap/bitreverse, ignore the multiuse - // Otherwise need to ensure logic_op and bswap/bitreverse(x) have one use. - if (OldLHS.getOpcode() == Opcode && OldRHS.getOpcode() == Opcode) { - return DAG.getNode(N0.getOpcode(), DL, VT, OldLHS.getOperand(0), - OldRHS.getOperand(0)); - } + SDValue X, Y; - if (OldLHS.getOpcode() == Opcode && OldLHS.hasOneUse()) { - SDValue NewBitReorder = DAG.getNode(Opcode, DL, VT, OldRHS); - return DAG.getNode(N0.getOpcode(), DL, VT, OldLHS.getOperand(0), - NewBitReorder); - } + // If both operands are bswap/bitreverse, ignore the multiuse + if (sd_match(N0, m_OneUse(m_BitwiseLogic(m_UnaryOp(Opcode, m_Value(X)), + m_UnaryOp(Opcode, m_Value(Y)))))) + return DAG.getNode(N0.getOpcode(), DL, VT, X, Y); - if (OldRHS.getOpcode() == Opcode && OldRHS.hasOneUse()) { - SDValue NewBitReorder = DAG.getNode(Opcode, DL, VT, OldLHS); - return DAG.getNode(N0.getOpcode(), DL, VT, NewBitReorder, - OldRHS.getOperand(0)); - } + // Otherwise need to ensure logic_op and bswap/bitreverse(x) have one use. + if (sd_match(N0, m_OneUse(m_BitwiseLogic( + m_OneUse(m_UnaryOp(Opcode, m_Value(X))), m_Value(Y))))) { + SDValue NewBitReorder = DAG.getNode(Opcode, DL, VT, Y); + return DAG.getNode(N0.getOpcode(), DL, VT, X, NewBitReorder); } + return SDValue(); } diff --git a/llvm/test/CodeGen/ARM/combine-bswap.ll b/llvm/test/CodeGen/ARM/combine-bswap.ll index 16a1d79de28ad..e9436fa24db26 100644 --- a/llvm/test/CodeGen/ARM/combine-bswap.ll +++ b/llvm/test/CodeGen/ARM/combine-bswap.ll @@ -23,7 +23,7 @@ define i64 @bs_or_rhs_bs64(i64 %a, i64 %b) #0 { ; CHECK-NEXT: rev r1, r1 ; CHECK-NEXT: rev r0, r0 ; CHECK-NEXT: orrs r2, r1 -; CHECK-NEXT: orr.w r1, r0, r3 +; CHECK-NEXT: orr.w r1, r3, r0 ; CHECK-NEXT: mov r0, r2 ; CHECK-NEXT: bx lr %1 = tail call i64 @llvm.bswap.i64(i64 %b) diff --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp index df35a8678e0a4..67a0d948dcace 100644 --- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp +++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp @@ -302,13 +302,18 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) { EXPECT_TRUE( sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_SpecificVT(Float32VT), m_SpecificVT(Float32VT)))); + EXPECT_FALSE(sd_match(Add, m_BitwiseLogic(m_Value(), m_Value()))); + EXPECT_FALSE(sd_match(Sub, m_BitwiseLogic(m_Value(), m_Value()))); EXPECT_TRUE(sd_match(And, m_c_BinOp(ISD::AND, m_Value(), m_Value()))); EXPECT_TRUE(sd_match(And, m_And(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(And, m_BitwiseLogic(m_Value(), m_Value()))); EXPECT_TRUE(sd_match(Xor, m_c_BinOp(ISD::XOR, m_Value(), m_Value()))); EXPECT_TRUE(sd_match(Xor, m_Xor(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Xor, m_BitwiseLogic(m_Value(), m_Value()))); EXPECT_TRUE(sd_match(Or, m_c_BinOp(ISD::OR, m_Value(), m_Value()))); EXPECT_TRUE(sd_match(Or, m_Or(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Or, m_BitwiseLogic(m_Value(), m_Value()))); EXPECT_FALSE(sd_match(Or, m_DisjointOr(m_Value(), m_Value()))); EXPECT_TRUE(sd_match(DisOr, m_Or(m_Value(), m_Value())));