Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -8754,6 +8754,11 @@ if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() || (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2()) return true; + // Optimize x*(PowerOf2+[2|4|8]) to (SH[1|2|3]ADD x, (SLLI x, bits)). + if (Subtarget.hasStdExtZba() && + ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() || + (Imm - 8).isPowerOf2())) + return true; // Omit the following optimization if the sub target has the M extension // and the data size >= XLen. if (Subtarget.hasStdExtM() && VT.getSizeInBits() >= Subtarget.getXLen()) @@ -8764,7 +8769,7 @@ APInt ImmS = Imm.ashr(Imm.countTrailingZeros()); if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() || (1 - ImmS).isPowerOf2()) - return true; + return true; } } } Index: llvm/lib/Target/RISCV/RISCVInstrInfoB.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -969,32 +969,39 @@ return !C || !isInt<12>(C->getSExtValue()); }]>; -let Predicates = [HasStdExtZba] in { -def : Pat<(add (shl GPR:$rs1, (XLenVT 1)), non_imm12:$rs2), - (SH1ADD GPR:$rs1, GPR:$rs2)>; -def : Pat<(add (shl GPR:$rs1, (XLenVT 2)), non_imm12:$rs2), - (SH2ADD GPR:$rs1, GPR:$rs2)>; -def : Pat<(add (shl GPR:$rs1, (XLenVT 3)), non_imm12:$rs2), - (SH3ADD GPR:$rs1, GPR:$rs2)>; +def addshl : PatFrag<(ops node:$A, node:$B, node:$C, node:$D), + (add (add (shl node:$A, node:$B), (shl node:$A, node:$C)), + node:$D), [{ + return N->getOperand(0)->getOperand(0)->hasOneUse() && + N->getOperand(0)->getOperand(1)->hasOneUse(); +}]>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 6)), GPR:$rs2), +let Predicates = [HasStdExtZba] in { +def : Pat<(addshl GPR:$rs1, (XLenVT 1), (XLenVT 2), non_imm12:$rs2), (SH1ADD (SH1ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 10)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 1), (XLenVT 3), non_imm12:$rs2), (SH1ADD (SH2ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 18)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 1), (XLenVT 4), non_imm12:$rs2), (SH1ADD (SH3ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 12)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 2), (XLenVT 3), non_imm12:$rs2), (SH2ADD (SH1ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 20)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 2), (XLenVT 4), non_imm12:$rs2), (SH2ADD (SH2ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 36)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 2), (XLenVT 5), non_imm12:$rs2), (SH2ADD (SH3ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 24)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 3), (XLenVT 4), non_imm12:$rs2), (SH3ADD (SH1ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 40)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 3), (XLenVT 5), non_imm12:$rs2), (SH3ADD (SH2ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 72)), GPR:$rs2), +def : Pat<(addshl GPR:$rs1, (XLenVT 3), (XLenVT 6), non_imm12:$rs2), (SH3ADD (SH3ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; + +def : Pat<(add (shl GPR:$rs1, (XLenVT 1)), non_imm12:$rs2), + (SH1ADD GPR:$rs1, GPR:$rs2)>; +def : Pat<(add (shl GPR:$rs1, (XLenVT 2)), non_imm12:$rs2), + (SH2ADD GPR:$rs1, GPR:$rs2)>; +def : Pat<(add (shl GPR:$rs1, (XLenVT 3)), non_imm12:$rs2), + (SH3ADD GPR:$rs1, GPR:$rs2)>; } // Predicates = [HasStdExtZba] let Predicates = [HasStdExtZba, IsRV64] in { Index: llvm/test/CodeGen/RISCV/rv32zba.ll =================================================================== --- llvm/test/CodeGen/RISCV/rv32zba.ll +++ llvm/test/CodeGen/RISCV/rv32zba.ll @@ -372,14 +372,14 @@ ; ; RV32IB-LABEL: mul258: ; RV32IB: # %bb.0: -; RV32IB-NEXT: addi a1, zero, 258 -; RV32IB-NEXT: mul a0, a0, a1 +; RV32IB-NEXT: slli a1, a0, 8 +; RV32IB-NEXT: sh1add a0, a0, a1 ; RV32IB-NEXT: ret ; ; RV32IBA-LABEL: mul258: ; RV32IBA: # %bb.0: -; RV32IBA-NEXT: addi a1, zero, 258 -; RV32IBA-NEXT: mul a0, a0, a1 +; RV32IBA-NEXT: slli a1, a0, 8 +; RV32IBA-NEXT: sh1add a0, a0, a1 ; RV32IBA-NEXT: ret %c = mul i32 %a, 258 ret i32 %c @@ -394,14 +394,14 @@ ; ; RV32IB-LABEL: mul260: ; RV32IB: # %bb.0: -; RV32IB-NEXT: addi a1, zero, 260 -; RV32IB-NEXT: mul a0, a0, a1 +; RV32IB-NEXT: slli a1, a0, 8 +; RV32IB-NEXT: sh2add a0, a0, a1 ; RV32IB-NEXT: ret ; ; RV32IBA-LABEL: mul260: ; RV32IBA: # %bb.0: -; RV32IBA-NEXT: addi a1, zero, 260 -; RV32IBA-NEXT: mul a0, a0, a1 +; RV32IBA-NEXT: slli a1, a0, 8 +; RV32IBA-NEXT: sh2add a0, a0, a1 ; RV32IBA-NEXT: ret %c = mul i32 %a, 260 ret i32 %c @@ -416,14 +416,14 @@ ; ; RV32IB-LABEL: mul264: ; RV32IB: # %bb.0: -; RV32IB-NEXT: addi a1, zero, 264 -; RV32IB-NEXT: mul a0, a0, a1 +; RV32IB-NEXT: slli a1, a0, 8 +; RV32IB-NEXT: sh3add a0, a0, a1 ; RV32IB-NEXT: ret ; ; RV32IBA-LABEL: mul264: ; RV32IBA: # %bb.0: -; RV32IBA-NEXT: addi a1, zero, 264 -; RV32IBA-NEXT: mul a0, a0, a1 +; RV32IBA-NEXT: slli a1, a0, 8 +; RV32IBA-NEXT: sh3add a0, a0, a1 ; RV32IBA-NEXT: ret %c = mul i32 %a, 264 ret i32 %c Index: llvm/test/CodeGen/RISCV/rv64zba.ll =================================================================== --- llvm/test/CodeGen/RISCV/rv64zba.ll +++ llvm/test/CodeGen/RISCV/rv64zba.ll @@ -830,14 +830,14 @@ ; ; RV64IB-LABEL: mul258: ; RV64IB: # %bb.0: -; RV64IB-NEXT: addi a1, zero, 258 -; RV64IB-NEXT: mul a0, a0, a1 +; RV64IB-NEXT: slli a1, a0, 8 +; RV64IB-NEXT: sh1add a0, a0, a1 ; RV64IB-NEXT: ret ; ; RV64IBA-LABEL: mul258: ; RV64IBA: # %bb.0: -; RV64IBA-NEXT: addi a1, zero, 258 -; RV64IBA-NEXT: mul a0, a0, a1 +; RV64IBA-NEXT: slli a1, a0, 8 +; RV64IBA-NEXT: sh1add a0, a0, a1 ; RV64IBA-NEXT: ret %c = mul i64 %a, 258 ret i64 %c @@ -852,14 +852,14 @@ ; ; RV64IB-LABEL: mul260: ; RV64IB: # %bb.0: -; RV64IB-NEXT: addi a1, zero, 260 -; RV64IB-NEXT: mul a0, a0, a1 +; RV64IB-NEXT: slli a1, a0, 8 +; RV64IB-NEXT: sh2add a0, a0, a1 ; RV64IB-NEXT: ret ; ; RV64IBA-LABEL: mul260: ; RV64IBA: # %bb.0: -; RV64IBA-NEXT: addi a1, zero, 260 -; RV64IBA-NEXT: mul a0, a0, a1 +; RV64IBA-NEXT: slli a1, a0, 8 +; RV64IBA-NEXT: sh2add a0, a0, a1 ; RV64IBA-NEXT: ret %c = mul i64 %a, 260 ret i64 %c @@ -874,14 +874,14 @@ ; ; RV64IB-LABEL: mul264: ; RV64IB: # %bb.0: -; RV64IB-NEXT: addi a1, zero, 264 -; RV64IB-NEXT: mul a0, a0, a1 +; RV64IB-NEXT: slli a1, a0, 8 +; RV64IB-NEXT: sh3add a0, a0, a1 ; RV64IB-NEXT: ret ; ; RV64IBA-LABEL: mul264: ; RV64IBA: # %bb.0: -; RV64IBA-NEXT: addi a1, zero, 264 -; RV64IBA-NEXT: mul a0, a0, a1 +; RV64IBA-NEXT: slli a1, a0, 8 +; RV64IBA-NEXT: sh3add a0, a0, a1 ; RV64IBA-NEXT: ret %c = mul i64 %a, 264 ret i64 %c