diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -6119,11 +6119,16 @@ if (SDValue V = foldLogicOfSetCCs(true, N0, N1, DL)) return V; + // Canonicalize: + // and(x, srl) -> and(srl, x) + if (N1.getOpcode() == ISD::SRL) + std::swap(N0, N1); + // TODO: Rewrite this to return a new 'AND' instead of using CombineTo. - if (N0.getOpcode() == ISD::ADD && N1.getOpcode() == ISD::SRL && - VT.getSizeInBits() <= 64 && N0->hasOneUse()) { - if (ConstantSDNode *ADDI = dyn_cast(N0.getOperand(1))) { - if (ConstantSDNode *SRLI = dyn_cast(N1.getOperand(1))) { + if (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::ADD && + VT.getSizeInBits() <= 64 && N1->hasOneUse()) { + if (ConstantSDNode *ADDI = dyn_cast(N1.getOperand(1))) { + if (ConstantSDNode *SRLI = dyn_cast(N0.getOperand(1))) { // Look for (and (add x, c1), (lshr y, c2)). If C1 wasn't a legal // immediate for an add, but it is legal if its top c2 bits are set, // transform the ADD so the immediate doesn't need to be materialized @@ -6134,14 +6139,14 @@ !TLI.isLegalAddImmediate(ADDC.getSExtValue())) { APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), SRLC.getZExtValue()); - if (DAG.MaskedValueIsZero(N0.getOperand(1), Mask)) { + if (DAG.MaskedValueIsZero(N1.getOperand(1), Mask)) { ADDC |= Mask; if (TLI.isLegalAddImmediate(ADDC.getSExtValue())) { - SDLoc DL0(N0); + SDLoc DL0(N1); SDValue NewAdd = DAG.getNode(ISD::ADD, DL0, VT, - N0.getOperand(0), DAG.getConstant(ADDC, DL, VT)); - CombineTo(N0.getNode(), NewAdd); + N1.getOperand(0), DAG.getConstant(ADDC, DL, VT)); + CombineTo(N1.getNode(), NewAdd); // Return N so it doesn't get rechecked! return SDValue(N, 0); } diff --git a/llvm/test/CodeGen/RISCV/and-add-lsr.ll b/llvm/test/CodeGen/RISCV/and-add-lsr.ll --- a/llvm/test/CodeGen/RISCV/and-add-lsr.ll +++ b/llvm/test/CodeGen/RISCV/and-add-lsr.ll @@ -7,18 +7,14 @@ define i32 @and_add_lsr(i32 %x, i32 %y) { ; RV32I-LABEL: and_add_lsr: ; RV32I: # %bb.0: -; RV32I-NEXT: lui a2, 1 -; RV32I-NEXT: addi a2, a2, -1 -; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: addi a0, a0, -1 ; RV32I-NEXT: srli a1, a1, 20 ; RV32I-NEXT: and a0, a1, a0 ; RV32I-NEXT: ret ; ; RV64I-LABEL: and_add_lsr: ; RV64I: # %bb.0: -; RV64I-NEXT: lui a2, 1 -; RV64I-NEXT: addiw a2, a2, -1 -; RV64I-NEXT: addw a0, a0, a2 +; RV64I-NEXT: addiw a0, a0, -1 ; RV64I-NEXT: srliw a1, a1, 20 ; RV64I-NEXT: and a0, a1, a0 ; RV64I-NEXT: ret