diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 9d90eb0a65218..cb20959e9dcc8 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -9150,10 +9150,22 @@ static SDValue lowerSelectToBinOp(SDNode *N, SelectionDAG &DAG, DAG.getNode(ISD::ADD, DL, VT, CondV, DAG.getAllOnesConstant(DL, VT)); return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(FalseV)); } - // (select c, y, 0) -> -c & y - if (isNullConstant(FalseV) && (!HasCZero || isSimm12Constant(TrueV))) { - SDValue Neg = DAG.getNegative(CondV, DL, VT); - return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV)); + if (isNullConstant(FalseV)) { + // (select c, (1 << ShAmount) + 1, 0) -> (c << ShAmount) + c + if (auto *TrueC = dyn_cast(TrueV)) { + uint64_t TrueM1 = TrueC->getZExtValue() - 1; + if (isPowerOf2_64(TrueM1)) { + unsigned ShAmount = Log2_64(TrueM1); + if (Subtarget.hasShlAdd(ShAmount)) + return DAG.getNode(RISCVISD::SHL_ADD, DL, VT, CondV, + DAG.getConstant(ShAmount, DL, VT), CondV); + } + } + // (select c, y, 0) -> -c & y + if (!HasCZero || isSimm12Constant(TrueV)) { + SDValue Neg = DAG.getNegative(CondV, DL, VT); + return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV)); + } } } diff --git a/llvm/test/CodeGen/RISCV/rv32zba.ll b/llvm/test/CodeGen/RISCV/rv32zba.ll index ab099103b4216..0d490682d1ff3 100644 --- a/llvm/test/CodeGen/RISCV/rv32zba.ll +++ b/llvm/test/CodeGen/RISCV/rv32zba.ll @@ -1136,3 +1136,132 @@ define i32 @mul_neg8(i32 %a) { %c = mul i32 %a, -8 ret i32 %c } + +define i32 @select3i32(i1 zeroext %x) { +; RV32I-LABEL: select3i32: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 3 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select3i32: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh1add a0, a0, a0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select3i32: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.h a0, a0, a0 +; RV32XANDESPERF-NEXT: ret + %select = select i1 %x, i32 3, i32 0 + ret i32 %select +} + +define i32 @select5i32(i1 zeroext %x) { +; RV32I-LABEL: select5i32: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 5 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select5i32: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh2add a0, a0, a0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select5i32: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.w a0, a0, a0 +; RV32XANDESPERF-NEXT: ret + %select = select i1 %x, i32 5, i32 0 + ret i32 %select +} + +define i32 @select9i32(i1 zeroext %x) { +; RV32I-LABEL: select9i32: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 9 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select9i32: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh3add a0, a0, a0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select9i32: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.d a0, a0, a0 +; RV32XANDESPERF-NEXT: ret + %select = select i1 %x, i32 9, i32 0 + ret i32 %select +} + +define i64 @select3i64(i1 zeroext %x) { +; RV32I-LABEL: select3i64: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 3 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select3i64: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh1add a0, a0, a0 +; RV32ZBA-NEXT: li a1, 0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select3i64: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.h a0, a0, a0 +; RV32XANDESPERF-NEXT: li a1, 0 +; RV32XANDESPERF-NEXT: ret + %select = select i1 %x, i64 3, i64 0 + ret i64 %select +} + +define i64 @select5i64(i1 zeroext %x) { +; RV32I-LABEL: select5i64: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 5 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select5i64: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh2add a0, a0, a0 +; RV32ZBA-NEXT: li a1, 0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select5i64: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.w a0, a0, a0 +; RV32XANDESPERF-NEXT: li a1, 0 +; RV32XANDESPERF-NEXT: ret + %select = select i1 %x, i64 5, i64 0 + ret i64 %select +} + +define i64 @select9i64(i1 zeroext %x) { +; RV32I-LABEL: select9i64: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 9 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select9i64: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh3add a0, a0, a0 +; RV32ZBA-NEXT: li a1, 0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select9i64: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.d a0, a0, a0 +; RV32XANDESPERF-NEXT: li a1, 0 +; RV32XANDESPERF-NEXT: ret + %select = select i1 %x, i64 9, i64 0 + ret i64 %select +} diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index b46f7cc440b7a..95f9f7116fe68 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -4576,3 +4576,63 @@ define i64 @append_32ones(i64 %x) { %o = or i64 %s, 4294967295 ret i64 %o } + +define i32 @select3(i1 zeroext %x) { +; RV64I-LABEL: select3: +; RV64I: # %bb.0: +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: andi a0, a0, 3 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: select3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: select3: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: nds.lea.h a0, a0, a0 +; RV64XANDESPERF-NEXT: ret + %select = select i1 %x, i32 3, i32 0 + ret i32 %select +} + +define i32 @select5(i1 zeroext %x) { +; RV64I-LABEL: select5: +; RV64I: # %bb.0: +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: andi a0, a0, 5 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: select5: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh2add a0, a0, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: select5: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: nds.lea.w a0, a0, a0 +; RV64XANDESPERF-NEXT: ret + %select = select i1 %x, i32 5, i32 0 + ret i32 %select +} + +define i32 @select9(i1 zeroext %x) { +; RV64I-LABEL: select9: +; RV64I: # %bb.0: +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: andi a0, a0, 9 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: select9: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh3add a0, a0, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: select9: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: nds.lea.d a0, a0, a0 +; RV64XANDESPERF-NEXT: ret + %select = select i1 %x, i32 9, i32 0 + ret i32 %select +} diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll index ec83fd7a28f32..918468bdf03d3 100644 --- a/llvm/test/CodeGen/RISCV/xqciac.ll +++ b/llvm/test/CodeGen/RISCV/xqciac.ll @@ -599,3 +599,23 @@ define i32 @add_shl_moreOneUse_4(i32 %x) { %add = add i32 %mul, %or ret i32 %add } + +define i32 @select65(i1 zeroext %x) { +; RV32IM-LABEL: select65: +; RV32IM: # %bb.0: +; RV32IM-NEXT: neg a0, a0 +; RV32IM-NEXT: andi a0, a0, 65 +; RV32IM-NEXT: ret +; +; RV32IMXQCIAC-LABEL: select65: +; RV32IMXQCIAC: # %bb.0: +; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a0, 6 +; RV32IMXQCIAC-NEXT: ret +; +; RV32IZBAMXQCIAC-LABEL: select65: +; RV32IZBAMXQCIAC: # %bb.0: +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a0, 6 +; RV32IZBAMXQCIAC-NEXT: ret + %select = select i1 %x, i32 65, i32 0 + ret i32 %select +}