diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index c1d38419992b1..637a46c508c1f 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -16544,12 +16544,23 @@ static SDValue expandMulToShlAddShlAdd(SDNode *N, SelectionDAG &DAG, break; } - // 2/4/8 * 3/5/9 + 1 -> (shXadd (shYadd X, X), X) int ShX; if (int ShY = isShifted359(MulAmt - 1, ShX)) { assert(ShX != 0 && "MulAmt=4,6,10 handled before"); + // 2/4/8 * 3/5/9 + 1 -> (shXadd (shYadd X, X), X) if (ShX <= 3) return getShlAddShlAdd(N, DAG, ShX, ShY, /*AddX=*/true, Shift); + // 2^N * 3/5/9 + 1 -> (add (shYadd (shl X, N), (shl X, N)), X) + if (Shift == 0) { + SDLoc DL(N); + EVT VT = N->getValueType(0); + SDValue X = N->getOperand(0); + SDValue Shl = + DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ShX, DL, VT)); + SDValue ShlAdd = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, Shl, + DAG.getTargetConstant(ShY, DL, VT), Shl); + return DAG.getNode(ISD::ADD, DL, VT, ShlAdd, X); + } } return SDValue(); } @@ -16610,7 +16621,7 @@ static SDValue expandMul(SDNode *N, SelectionDAG &DAG, DAG.getTargetConstant(Shift, DL, VT), Shift1); } - // TODO: 2^(C1>3) * 3,5,9 +/- 1 + // TODO: 2^(C1>3) * 3/5/9 - 1 // 2^n + 2/4/8 + 1 -> (add (shl X, C1), (shXadd X, X)) if (MulAmt > 2 && isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) { diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index e56c7b41d43ce..156599fb72877 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -944,6 +944,58 @@ define i64 @addmul146(i64 %a, i64 %b) { ret i64 %d } +define i64 @mul49(i64 %a) { +; RV64I-LABEL: mul49: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 49 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: mul49: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 4 +; RV64ZBA-NEXT: sh1add a1, a1, a1 +; RV64ZBA-NEXT: add a0, a1, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: mul49: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: slli a1, a0, 4 +; RV64XANDESPERF-NEXT: nds.lea.h a1, a1, a1 +; RV64XANDESPERF-NEXT: add a0, a1, a0 +; RV64XANDESPERF-NEXT: ret + %c = mul i64 %a, 49 + ret i64 %c +} + +define i64 @zext_mul49(i32 signext %a) { +; RV64I-LABEL: zext_mul49: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 49 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: mulhu a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: zext_mul49: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli.uw a1, a0, 4 +; RV64ZBA-NEXT: sh1add a1, a1, a1 +; RV64ZBA-NEXT: add.uw a0, a0, a1 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: zext_mul49: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: slli a1, a0, 32 +; RV64XANDESPERF-NEXT: srli a1, a1, 28 +; RV64XANDESPERF-NEXT: nds.lea.h a1, a1, a1 +; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, a1, a0 +; RV64XANDESPERF-NEXT: ret + %b = zext i32 %a to i64 + %c = mul i64 %b, 49 + ret i64 %c +} + define i64 @mul50(i64 %a) { ; RV64I-LABEL: mul50: ; RV64I: # %bb.0: @@ -1044,6 +1096,54 @@ define i64 @addmul100(i64 %a, i64 %b) { ret i64 %d } +define i64 @mul145(i64 %a) { +; RV64I-LABEL: mul145: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 145 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: mul145: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 4 +; RV64ZBA-NEXT: sh3add a1, a1, a1 +; RV64ZBA-NEXT: add a0, a1, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: mul145: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: slli a1, a0, 4 +; RV64XANDESPERF-NEXT: nds.lea.d a1, a1, a1 +; RV64XANDESPERF-NEXT: add a0, a1, a0 +; RV64XANDESPERF-NEXT: ret + %c = mul i64 %a, 145 + ret i64 %c +} + +define i64 @mul161(i64 %a) { +; RV64I-LABEL: mul161: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 161 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: mul161: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 5 +; RV64ZBA-NEXT: sh2add a1, a1, a1 +; RV64ZBA-NEXT: add a0, a1, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: mul161: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: slli a1, a0, 5 +; RV64XANDESPERF-NEXT: nds.lea.w a1, a1, a1 +; RV64XANDESPERF-NEXT: add a0, a1, a0 +; RV64XANDESPERF-NEXT: ret + %c = mul i64 %a, 161 + ret i64 %c +} + define i64 @mul162(i64 %a) { ; RV64I-LABEL: mul162: ; RV64I: # %bb.0: