diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -8063,14 +8063,16 @@ // (sub x, (select cond, 0, c)) // -> (select cond, x, (sub x, c)) [AllOnes=0] static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, - SelectionDAG &DAG, bool AllOnes) { + SelectionDAG &DAG, bool AllOnes, + const RISCVSubtarget &Subtarget) { EVT VT = N->getValueType(0); // Skip vectors. if (VT.isVector()) return SDValue(); - if ((Slct.getOpcode() != ISD::SELECT && + if (!Subtarget.hasShortForwardBranchOpt() || + (Slct.getOpcode() != ISD::SELECT && Slct.getOpcode() != RISCVISD::SELECT_CC) || !Slct.hasOneUse()) return SDValue(); @@ -8111,12 +8113,13 @@ // Attempt combineSelectAndUse on each operand of a commutative operator N. static SDValue combineSelectAndUseCommutative(SDNode *N, SelectionDAG &DAG, - bool AllOnes) { + bool AllOnes, + const RISCVSubtarget &Subtarget) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); - if (SDValue Result = combineSelectAndUse(N, N0, N1, DAG, AllOnes)) + if (SDValue Result = combineSelectAndUse(N, N0, N1, DAG, AllOnes, Subtarget)) return Result; - if (SDValue Result = combineSelectAndUse(N, N1, N0, DAG, AllOnes)) + if (SDValue Result = combineSelectAndUse(N, N1, N0, DAG, AllOnes, Subtarget)) return Result; return SDValue(); } @@ -8198,7 +8201,7 @@ return V; // fold (add (select lhs, rhs, cc, 0, y), x) -> // (select lhs, rhs, cc, x, (add x, y)) - return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false); + return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false, Subtarget); } // Try to turn a sub boolean RHS and constant LHS into an addi. @@ -8242,7 +8245,8 @@ return DAG.getNode(ISD::ADD, DL, VT, NewLHS, NewRHS); } -static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG) { +static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { if (SDValue V = combineSubOfBoolean(N, DAG)) return V; @@ -8250,7 +8254,7 @@ // (select lhs, rhs, cc, x, (sub x, y)) SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); - return combineSelectAndUse(N, N1, N0, DAG, /*AllOnes*/ false); + return combineSelectAndUse(N, N1, N0, DAG, /*AllOnes*/ false, Subtarget); } // Apply DeMorgan's law to (and/or (xor X, 1), (xor Y, 1)) if X and Y are 0/1. @@ -8356,7 +8360,7 @@ // fold (and (select lhs, rhs, cc, -1, y), x) -> // (select lhs, rhs, cc, x, (and x, y)) - return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ true); + return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ true, Subtarget); } static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, @@ -8372,10 +8376,11 @@ // fold (or (select cond, 0, y), x) -> // (select cond, x, (or x, y)) - return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false); + return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false, Subtarget); } -static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG) { +static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -8394,7 +8399,7 @@ return V; // fold (xor (select cond, 0, y), x) -> // (select cond, x, (xor x, y)) - return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false); + return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false, Subtarget); } // Replace (seteq (i64 (and X, 0xffffffff)), C1) with @@ -9596,13 +9601,13 @@ case ISD::ADD: return performADDCombine(N, DAG, Subtarget); case ISD::SUB: - return performSUBCombine(N, DAG); + return performSUBCombine(N, DAG, Subtarget); case ISD::AND: return performANDCombine(N, DCI, Subtarget); case ISD::OR: return performORCombine(N, DCI, Subtarget); case ISD::XOR: - return performXORCombine(N, DAG); + return performXORCombine(N, DAG, Subtarget); case ISD::FADD: case ISD::UMAX: case ISD::UMIN: diff --git a/llvm/test/CodeGen/RISCV/select-binop-identity.ll b/llvm/test/CodeGen/RISCV/select-binop-identity.ll --- a/llvm/test/CodeGen/RISCV/select-binop-identity.ll +++ b/llvm/test/CodeGen/RISCV/select-binop-identity.ll @@ -13,20 +13,17 @@ define signext i32 @and_select_all_ones_i32(i1 zeroext %c, i32 signext %x, i32 %y) { ; RV32I-LABEL: and_select_all_ones_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: beqz a0, .LBB0_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: and a2, a2, a1 -; RV32I-NEXT: .LBB0_2: -; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: or a0, a0, a1 +; RV32I-NEXT: and a0, a0, a2 ; RV32I-NEXT: ret ; ; RV64I-LABEL: and_select_all_ones_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: beqz a0, .LBB0_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: and a2, a2, a1 -; RV64I-NEXT: .LBB0_2: -; RV64I-NEXT: sext.w a0, a2 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: and a0, a0, a2 +; RV64I-NEXT: sext.w a0, a0 ; RV64I-NEXT: ret %a = select i1 %c, i32 %x, i32 -1 %b = and i32 %a, %y @@ -36,22 +33,18 @@ define i64 @and_select_all_ones_i64(i1 zeroext %c, i64 %x, i64 %y) { ; RV32I-LABEL: and_select_all_ones_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: bnez a0, .LBB1_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: and a3, a3, a1 -; RV32I-NEXT: and a4, a4, a2 -; RV32I-NEXT: .LBB1_2: -; RV32I-NEXT: mv a0, a3 -; RV32I-NEXT: mv a1, a4 +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: or a2, a0, a2 +; RV32I-NEXT: or a0, a0, a1 +; RV32I-NEXT: and a0, a3, a0 +; RV32I-NEXT: and a1, a4, a2 ; RV32I-NEXT: ret ; ; RV64I-LABEL: and_select_all_ones_i64: ; RV64I: # %bb.0: -; RV64I-NEXT: bnez a0, .LBB1_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: and a2, a2, a1 -; RV64I-NEXT: .LBB1_2: -; RV64I-NEXT: mv a0, a2 +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: and a0, a2, a0 ; RV64I-NEXT: ret %a = select i1 %c, i64 -1, i64 %x %b = and i64 %y, %a @@ -63,14 +56,14 @@ ; RV32I: # %bb.0: ; RV32I-NEXT: neg a0, a0 ; RV32I-NEXT: and a0, a0, a1 -; RV32I-NEXT: or a0, a0, a2 +; RV32I-NEXT: or a0, a2, a0 ; RV32I-NEXT: ret ; ; RV64I-LABEL: or_select_all_zeros_i32: ; RV64I: # %bb.0: ; RV64I-NEXT: neg a0, a0 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: or a0, a0, a2 +; RV64I-NEXT: or a0, a2, a0 ; RV64I-NEXT: ret %a = select i1 %c, i32 %x, i32 0 %b = or i32 %y, %a @@ -80,22 +73,18 @@ define i64 @or_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) { ; RV32I-LABEL: or_select_all_zeros_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: bnez a0, .LBB3_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: or a3, a3, a1 -; RV32I-NEXT: or a4, a4, a2 -; RV32I-NEXT: .LBB3_2: -; RV32I-NEXT: mv a0, a3 -; RV32I-NEXT: mv a1, a4 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: and a2, a0, a2 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: or a0, a0, a3 +; RV32I-NEXT: or a1, a2, a4 ; RV32I-NEXT: ret ; ; RV64I-LABEL: or_select_all_zeros_i64: ; RV64I: # %bb.0: -; RV64I-NEXT: bnez a0, .LBB3_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: or a2, a2, a1 -; RV64I-NEXT: .LBB3_2: -; RV64I-NEXT: mv a0, a2 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: or a0, a0, a2 ; RV64I-NEXT: ret %a = select i1 %c, i64 0, i64 %x %b = or i64 %a, %y @@ -105,20 +94,16 @@ define signext i32 @xor_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32 signext %y) { ; RV32I-LABEL: xor_select_all_zeros_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: bnez a0, .LBB4_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: xor a2, a2, a1 -; RV32I-NEXT: .LBB4_2: -; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: xor a0, a2, a0 ; RV32I-NEXT: ret ; ; RV64I-LABEL: xor_select_all_zeros_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: bnez a0, .LBB4_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: xor a2, a2, a1 -; RV64I-NEXT: .LBB4_2: -; RV64I-NEXT: mv a0, a2 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: xor a0, a2, a0 ; RV64I-NEXT: ret %a = select i1 %c, i32 0, i32 %x %b = xor i32 %y, %a @@ -128,11 +113,11 @@ define i64 @xor_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) { ; RV32I-LABEL: xor_select_all_zeros_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: neg a5, a0 -; RV32I-NEXT: and a0, a5, a1 +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: and a2, a0, a2 +; RV32I-NEXT: and a0, a0, a1 ; RV32I-NEXT: xor a0, a0, a3 -; RV32I-NEXT: and a1, a5, a2 -; RV32I-NEXT: xor a1, a1, a4 +; RV32I-NEXT: xor a1, a2, a4 ; RV32I-NEXT: ret ; ; RV64I-LABEL: xor_select_all_zeros_i64: @@ -149,20 +134,16 @@ define signext i32 @add_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32 signext %y) { ; RV32I-LABEL: add_select_all_zeros_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: bnez a0, .LBB6_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: add a2, a2, a1 -; RV32I-NEXT: .LBB6_2: -; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: add a0, a2, a0 ; RV32I-NEXT: ret ; ; RV64I-LABEL: add_select_all_zeros_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: bnez a0, .LBB6_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: addw a2, a2, a1 -; RV64I-NEXT: .LBB6_2: -; RV64I-NEXT: mv a0, a2 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: addw a0, a2, a0 ; RV64I-NEXT: ret %a = select i1 %c, i32 0, i32 %x %b = add i32 %y, %a @@ -172,25 +153,20 @@ define i64 @add_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) { ; RV32I-LABEL: add_select_all_zeros_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: beqz a0, .LBB7_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: add a2, a4, a2 -; RV32I-NEXT: add a1, a3, a1 -; RV32I-NEXT: sltu a4, a1, a3 -; RV32I-NEXT: add a4, a2, a4 -; RV32I-NEXT: mv a3, a1 -; RV32I-NEXT: .LBB7_2: -; RV32I-NEXT: mv a0, a3 -; RV32I-NEXT: mv a1, a4 +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: and a2, a0, a2 +; RV32I-NEXT: and a1, a0, a1 +; RV32I-NEXT: add a0, a1, a3 +; RV32I-NEXT: sltu a1, a0, a1 +; RV32I-NEXT: add a2, a2, a4 +; RV32I-NEXT: add a1, a2, a1 ; RV32I-NEXT: ret ; ; RV64I-LABEL: add_select_all_zeros_i64: ; RV64I: # %bb.0: -; RV64I-NEXT: beqz a0, .LBB7_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: add a2, a2, a1 -; RV64I-NEXT: .LBB7_2: -; RV64I-NEXT: mv a0, a2 +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: add a0, a0, a2 ; RV64I-NEXT: ret %a = select i1 %c, i64 %x, i64 0 %b = add i64 %a, %y @@ -200,20 +176,16 @@ define signext i32 @sub_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32 signext %y) { ; RV32I-LABEL: sub_select_all_zeros_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: bnez a0, .LBB8_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: sub a2, a2, a1 -; RV32I-NEXT: .LBB8_2: -; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: sub a0, a2, a0 ; RV32I-NEXT: ret ; ; RV64I-LABEL: sub_select_all_zeros_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: bnez a0, .LBB8_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: subw a2, a2, a1 -; RV64I-NEXT: .LBB8_2: -; RV64I-NEXT: mv a0, a2 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: subw a0, a2, a0 ; RV64I-NEXT: ret %a = select i1 %c, i32 0, i32 %x %b = sub i32 %y, %a @@ -223,24 +195,20 @@ define i64 @sub_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) { ; RV32I-LABEL: sub_select_all_zeros_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: beqz a0, .LBB9_2 -; RV32I-NEXT: # %bb.1: -; RV32I-NEXT: sltu a0, a3, a1 +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: and a2, a0, a2 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: sltu a1, a3, a0 ; RV32I-NEXT: sub a4, a4, a2 -; RV32I-NEXT: sub a4, a4, a0 -; RV32I-NEXT: sub a3, a3, a1 -; RV32I-NEXT: .LBB9_2: -; RV32I-NEXT: mv a0, a3 -; RV32I-NEXT: mv a1, a4 +; RV32I-NEXT: sub a1, a4, a1 +; RV32I-NEXT: sub a0, a3, a0 ; RV32I-NEXT: ret ; ; RV64I-LABEL: sub_select_all_zeros_i64: ; RV64I: # %bb.0: -; RV64I-NEXT: beqz a0, .LBB9_2 -; RV64I-NEXT: # %bb.1: -; RV64I-NEXT: sub a2, a2, a1 -; RV64I-NEXT: .LBB9_2: -; RV64I-NEXT: mv a0, a2 +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: sub a0, a2, a0 ; RV64I-NEXT: ret %a = select i1 %c, i64 %x, i64 0 %b = sub i64 %y, %a