diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 55c64d566914..089018f362b1 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2269,6 +2269,11 @@ void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value, .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( diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp index a040df34d9ec..ecf11bd986f8 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -250,6 +250,33 @@ InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures) { } } + // Perform optimization with SH*ADD in the Zba extension. + if (Res.size() > 2 && ActiveFeatures[RISCV::FeatureStdExtZba]) { + assert(ActiveFeatures[RISCV::Feature64Bit] && + "Expected RV32 to only need 2 instructions"); + int64_t Div = 0; + unsigned Opc = 0; + RISCVMatInt::InstSeq TmpSeq; + // 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 instruction sequence. + if (Div > 0) { + generateInstSeqImpl(Val / Div, ActiveFeatures, TmpSeq); + TmpSeq.push_back(RISCVMatInt::Inst(Opc, 0)); + if (TmpSeq.size() < Res.size()) + Res = TmpSeq; + } + } + return Res; } diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index ddf17097554a..4ac91e7b63e5 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -140,6 +140,9 @@ static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm, 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); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 9d56c5124172..882ad58fa3db 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -458,6 +458,12 @@ void RISCVInstrInfo::movImm(MachineBasicBlock &MBB, .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) diff --git a/llvm/test/CodeGen/RISCV/imm.ll b/llvm/test/CodeGen/RISCV/imm.ll index b2cfe6c6dea5..4ffd4b3ae47f 100644 --- a/llvm/test/CodeGen/RISCV/imm.ll +++ b/llvm/test/CodeGen/RISCV/imm.ll @@ -959,10 +959,9 @@ define i64 @imm_neg_5372288229() { ; ; RV64IZBA-LABEL: imm_neg_5372288229: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: lui a0, 1048416 -; RV64IZBA-NEXT: addiw a0, a0, -437 -; RV64IZBA-NEXT: slli a0, a0, 13 -; RV64IZBA-NEXT: addi a0, a0, 795 +; RV64IZBA-NEXT: lui a0, 611378 +; RV64IZBA-NEXT: addiw a0, a0, 265 +; RV64IZBA-NEXT: sh1add a0, a0, a0 ; RV64IZBA-NEXT: ret ; ; RV64IZBS-LABEL: imm_neg_5372288229: @@ -992,10 +991,9 @@ define i64 @imm_8953813715() { ; ; RV64IZBA-LABEL: imm_8953813715: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: lui a0, 267 -; RV64IZBA-NEXT: addiw a0, a0, -637 -; RV64IZBA-NEXT: slli a0, a0, 13 -; RV64IZBA-NEXT: addi a0, a0, -1325 +; RV64IZBA-NEXT: lui a0, 437198 +; RV64IZBA-NEXT: addiw a0, a0, -265 +; RV64IZBA-NEXT: sh2add a0, a0, a0 ; RV64IZBA-NEXT: ret ; ; RV64IZBS-LABEL: imm_8953813715: @@ -1025,10 +1023,9 @@ define i64 @imm_neg_8953813715() { ; ; RV64IZBA-LABEL: imm_neg_8953813715: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: lui a0, 1048309 -; RV64IZBA-NEXT: addiw a0, a0, 637 -; RV64IZBA-NEXT: slli a0, a0, 13 -; RV64IZBA-NEXT: addi a0, a0, 1325 +; RV64IZBA-NEXT: lui a0, 611378 +; RV64IZBA-NEXT: addiw a0, a0, 265 +; RV64IZBA-NEXT: sh2add a0, a0, a0 ; RV64IZBA-NEXT: ret ; ; RV64IZBS-LABEL: imm_neg_8953813715: @@ -1058,10 +1055,9 @@ define i64 @imm_16116864687() { ; ; RV64IZBA-LABEL: imm_16116864687: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: lui a0, 961 -; RV64IZBA-NEXT: addiw a0, a0, -1475 -; RV64IZBA-NEXT: slli a0, a0, 12 -; RV64IZBA-NEXT: addi a0, a0, 1711 +; RV64IZBA-NEXT: lui a0, 437198 +; RV64IZBA-NEXT: addiw a0, a0, -265 +; RV64IZBA-NEXT: sh3add a0, a0, a0 ; RV64IZBA-NEXT: ret ; ; RV64IZBS-LABEL: imm_16116864687: @@ -1092,10 +1088,9 @@ define i64 @imm_neg_16116864687() { ; ; RV64IZBA-LABEL: imm_neg_16116864687: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: lui a0, 1047615 -; RV64IZBA-NEXT: addiw a0, a0, 1475 -; RV64IZBA-NEXT: slli a0, a0, 12 -; RV64IZBA-NEXT: addi a0, a0, -1711 +; RV64IZBA-NEXT: lui a0, 611378 +; RV64IZBA-NEXT: addiw a0, a0, 265 +; RV64IZBA-NEXT: sh3add a0, a0, a0 ; RV64IZBA-NEXT: ret ; ; RV64IZBS-LABEL: imm_neg_16116864687: @@ -1447,10 +1442,9 @@ define i64 @imm_neg_2863311530() { ; ; RV64IZBA-LABEL: imm_neg_2863311530: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: lui a0, 1048405 -; RV64IZBA-NEXT: addiw a0, a0, 1365 -; RV64IZBA-NEXT: slli a0, a0, 12 -; RV64IZBA-NEXT: addi a0, a0, 1366 +; RV64IZBA-NEXT: lui a0, 908766 +; RV64IZBA-NEXT: addiw a0, a0, -546 +; RV64IZBA-NEXT: sh2add a0, a0, a0 ; RV64IZBA-NEXT: ret ; ; RV64IZBS-LABEL: imm_neg_2863311530: diff --git a/llvm/test/MC/RISCV/rv64zba-aliases-valid.s b/llvm/test/MC/RISCV/rv64zba-aliases-valid.s index 3cab2f35e2c1..8668796d9b11 100644 --- a/llvm/test/MC/RISCV/rv64zba-aliases-valid.s +++ b/llvm/test/MC/RISCV/rv64zba-aliases-valid.s @@ -46,3 +46,43 @@ li x5, 0xbbbbb0007bb # CHECK-S-OBJ: lui t0, 768955 # CHECK-S-OBJ-NEXT: slli.uw t0, t0, 4 li x5, 0xbbbbb0000 + +# CHECK-S-OBJ-NOALIAS: lui t1, 611378 +# CHECK-S-OBJ-NOALIAS-NEXT: addiw t1, t1, 265 +# CHECK-S-OBJ-NOALIAS-NEXT: sh1add t1, t1, t1 +# CHECK-S-OBJ: lui t1, 611378 +# CHECK-S-OBJ-NEXT: addiw t1, t1, 265 +# CHECK-S-OBJ-NEXT: sh1add t1, t1, t1 +li x6, -5372288229 + +# CHECK-S-OBJ-NOALIAS: lui t1, 437198 +# CHECK-S-OBJ-NOALIAS-NEXT: addiw t1, t1, -265 +# CHECK-S-OBJ-NOALIAS-NEXT: sh2add t1, t1, t1 +# CHECK-S-OBJ: lui t1, 437198 +# CHECK-S-OBJ-NEXT: addiw t1, t1, -265 +# CHECK-S-OBJ-NEXT: sh2add t1, t1, t1 +li x6, 8953813715 + +# CHECK-S-OBJ-NOALIAS: lui t1, 611378 +# CHECK-S-OBJ-NOALIAS-NEXT: addiw t1, t1, 265 +# CHECK-S-OBJ-NOALIAS-NEXT: sh2add t1, t1, t1 +# CHECK-S-OBJ: lui t1, 611378 +# CHECK-S-OBJ-NEXT: addiw t1, t1, 265 +# CHECK-S-OBJ-NEXT: sh2add t1, t1, t1 +li x6, -8953813715 + +# CHECK-S-OBJ-NOALIAS: lui t1, 437198 +# CHECK-S-OBJ-NOALIAS-NEXT: addiw t1, t1, -265 +# CHECK-S-OBJ-NOALIAS-NEXT: sh3add t1, t1, t1 +# CHECK-S-OBJ: lui t1, 437198 +# CHECK-S-OBJ-NEXT: addiw t1, t1, -265 +# CHECK-S-OBJ-NEXT: sh3add t1, t1, t1 +li x6, 16116864687 + +# CHECK-S-OBJ-NOALIAS: lui t1, 611378 +# CHECK-S-OBJ-NOALIAS-NEXT: addiw t1, t1, 265 +# CHECK-S-OBJ-NOALIAS-NEXT: sh3add t1, t1, t1 +# CHECK-S-OBJ: lui t1, 611378 +# CHECK-S-OBJ-NEXT: addiw t1, t1, 265 +# CHECK-S-OBJ-NEXT: sh3add t1, t1, t1 +li x6, -16116864687