Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2269,6 +2269,11 @@ .addReg(DestReg) .addReg(SrcReg) .addReg(RISCV::X0)); + } else if (Inst.Opc == RISCV::SH1ADD || Inst.Opc == RISCV::SH2ADD || + Inst.Opc == RISCV::SH3ADD) { + emitToStreamer( + Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addReg( + SrcReg)); } else { emitToStreamer( Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm( Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -182,6 +182,32 @@ } } + // Try to generate (SH*ADD r, r), in which r is an int32. The total cost is + // at most 3 instructions. + if (Res.size() > 3 && ActiveFeatures[RISCV::FeatureStdExtZba]) { + assert(ActiveFeatures[RISCV::Feature64Bit] && + "Expected RV32 to only need 2 instructions"); + int64_t Div = 0; + unsigned Opc = 0; + // Select the opcode and divisor. + if ((Val % 3) == 0 && isInt<32>(Val / 3)) { + Div = 3; + Opc = RISCV::SH1ADD; + } else if ((Val % 5) == 0 && isInt<32>(Val / 5)) { + Div = 5; + Opc = RISCV::SH2ADD; + } else if ((Val % 9) == 0 && isInt<32>(Val / 9)) { + Div = 9; + Opc = RISCV::SH3ADD; + } + // Build the new isntruction sequence. + if (Div > 0) { + Res.clear(); + generateInstSeqImpl(Val / Div, ActiveFeatures, Res); + Res.push_back(RISCVMatInt::Inst(Opc, 0)); + } + } + return Res; } Index: llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -140,6 +140,9 @@ else if (Inst.Opc == RISCV::ADDUW) Result = CurDAG->getMachineNode(RISCV::ADDUW, DL, XLenVT, SrcReg, CurDAG->getRegister(RISCV::X0, XLenVT)); + else if (Inst.Opc == RISCV::SH1ADD || Inst.Opc == RISCV::SH2ADD || + Inst.Opc == RISCV::SH3ADD) + Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SrcReg); else Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SDImm); Index: llvm/lib/Target/RISCV/RISCVInstrInfo.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -458,6 +458,12 @@ .addReg(SrcReg, RegState::Kill) .addReg(RISCV::X0) .setMIFlag(Flag); + } else if (Inst.Opc == RISCV::SH1ADD || Inst.Opc == RISCV::SH2ADD || + Inst.Opc == RISCV::SH3ADD) { + BuildMI(MBB, MBBI, DL, get(Inst.Opc), Result) + .addReg(SrcReg, RegState::Kill) + .addReg(SrcReg, RegState::Kill) + .setMIFlag(Flag); } else { BuildMI(MBB, MBBI, DL, get(Inst.Opc), Result) .addReg(SrcReg, RegState::Kill) Index: llvm/test/CodeGen/RISCV/imm.ll =================================================================== --- llvm/test/CodeGen/RISCV/imm.ll +++ llvm/test/CodeGen/RISCV/imm.ll @@ -522,10 +522,9 @@ ; ; RV64IB-LABEL: imm_5372288229: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a0, 160 -; RV64IB-NEXT: addiw a0, a0, 437 -; RV64IB-NEXT: slli a0, a0, 13 -; RV64IB-NEXT: addi a0, a0, -795 +; RV64IB-NEXT: lui a0, 437198 +; RV64IB-NEXT: addiw a0, a0, -265 +; RV64IB-NEXT: sh1add a0, a0, a0 ; RV64IB-NEXT: ret ret i64 5372288229 } @@ -540,10 +539,9 @@ ; ; RV64IB-LABEL: imm_neg_5372288229: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a0, 1048416 -; RV64IB-NEXT: addiw a0, a0, -437 -; RV64IB-NEXT: slli a0, a0, 13 -; RV64IB-NEXT: addi a0, a0, 795 +; RV64IB-NEXT: lui a0, 611378 +; RV64IB-NEXT: addiw a0, a0, 265 +; RV64IB-NEXT: sh1add a0, a0, a0 ; RV64IB-NEXT: ret ret i64 -5372288229 } @@ -558,10 +556,9 @@ ; ; RV64IB-LABEL: imm_8953813715: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a0, 267 -; RV64IB-NEXT: addiw a0, a0, -637 -; RV64IB-NEXT: slli a0, a0, 13 -; RV64IB-NEXT: addi a0, a0, -1325 +; RV64IB-NEXT: lui a0, 437198 +; RV64IB-NEXT: addiw a0, a0, -265 +; RV64IB-NEXT: sh2add a0, a0, a0 ; RV64IB-NEXT: ret ret i64 8953813715 } @@ -576,10 +573,9 @@ ; ; RV64IB-LABEL: imm_neg_8953813715: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a0, 1048309 -; RV64IB-NEXT: addiw a0, a0, 637 -; RV64IB-NEXT: slli a0, a0, 13 -; RV64IB-NEXT: addi a0, a0, 1325 +; RV64IB-NEXT: lui a0, 611378 +; RV64IB-NEXT: addiw a0, a0, 265 +; RV64IB-NEXT: sh2add a0, a0, a0 ; RV64IB-NEXT: ret ret i64 -8953813715 } @@ -594,10 +590,9 @@ ; ; RV64IB-LABEL: imm_16116864687: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a0, 961 -; RV64IB-NEXT: addiw a0, a0, -1475 -; RV64IB-NEXT: slli a0, a0, 12 -; RV64IB-NEXT: addi a0, a0, 1711 +; RV64IB-NEXT: lui a0, 437198 +; RV64IB-NEXT: addiw a0, a0, -265 +; RV64IB-NEXT: sh3add a0, a0, a0 ; RV64IB-NEXT: ret ret i64 16116864687 } @@ -612,10 +607,9 @@ ; ; RV64IB-LABEL: imm_neg_16116864687: ; RV64IB: # %bb.0: -; RV64IB-NEXT: lui a0, 1047615 -; RV64IB-NEXT: addiw a0, a0, 1475 -; RV64IB-NEXT: slli a0, a0, 12 -; RV64IB-NEXT: addi a0, a0, -1711 +; RV64IB-NEXT: lui a0, 611378 +; RV64IB-NEXT: addiw a0, a0, 265 +; RV64IB-NEXT: sh3add a0, a0, a0 ; RV64IB-NEXT: ret ret i64 -16116864687 }