diff options
Diffstat (limited to 'llvm/lib/Target/RISCV')
| -rw-r--r-- | llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 82 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVFeatures.td | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 18 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 19 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfo.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoD.td | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoF.td | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 31 | 
13 files changed, 148 insertions, 34 deletions
| diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index 8198173..282cf5d 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -92,6 +92,10 @@ private:    void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,                   MachineIRBuilder &MIB) const;    bool selectUnmergeValues(MachineInstr &MI, MachineIRBuilder &MIB) const; +  void addVectorLoadStoreOperands(MachineInstr &I, +                                  SmallVectorImpl<SrcOp> &SrcOps, +                                  unsigned &CurOp, bool IsMasked, +                                  bool IsStrided) const;    bool selectIntrinsicWithSideEffects(MachineInstr &I,                                        MachineIRBuilder &MIB) const; @@ -716,6 +720,26 @@ static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {    return GenericOpc;  } +void RISCVInstructionSelector::addVectorLoadStoreOperands( +    MachineInstr &I, SmallVectorImpl<SrcOp> &SrcOps, unsigned &CurOp, +    bool IsMasked, bool IsStrided) const { +  // Base Pointer +  auto PtrReg = I.getOperand(CurOp++).getReg(); +  SrcOps.push_back(PtrReg); + +  // Stride +  if (IsStrided) { +    auto StrideReg = I.getOperand(CurOp++).getReg(); +    SrcOps.push_back(StrideReg); +  } + +  // Mask +  if (IsMasked) { +    auto MaskReg = I.getOperand(CurOp++).getReg(); +    SrcOps.push_back(MaskReg); +  } +} +  bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(      MachineInstr &I, MachineIRBuilder &MIB) const {    // Find the intrinsic ID. @@ -752,21 +776,7 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(        SrcOps.push_back(Register(RISCV::NoRegister));      } -    // Base Pointer -    auto PtrReg = I.getOperand(CurOp++).getReg(); -    SrcOps.push_back(PtrReg); - -    // Stride -    if (IsStrided) { -      auto StrideReg = I.getOperand(CurOp++).getReg(); -      SrcOps.push_back(StrideReg); -    } - -    // Mask -    if (IsMasked) { -      auto MaskReg = I.getOperand(CurOp++).getReg(); -      SrcOps.push_back(MaskReg); -    } +    addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);      RISCVVType::VLMUL LMUL = RISCVTargetLowering::getLMUL(getMVTForLLT(VT));      const RISCV::VLEPseudo *P = @@ -795,6 +805,48 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(      I.eraseFromParent();      return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);    } +  case Intrinsic::riscv_vsm: +  case Intrinsic::riscv_vse: +  case Intrinsic::riscv_vse_mask: +  case Intrinsic::riscv_vsse: +  case Intrinsic::riscv_vsse_mask: { +    bool IsMasked = IntrinID == Intrinsic::riscv_vse_mask || +                    IntrinID == Intrinsic::riscv_vsse_mask; +    bool IsStrided = IntrinID == Intrinsic::riscv_vsse || +                     IntrinID == Intrinsic::riscv_vsse_mask; +    LLT VT = MRI->getType(I.getOperand(1).getReg()); +    unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits()); + +    // Sources +    unsigned CurOp = 1; +    SmallVector<SrcOp, 4> SrcOps; // Source registers. + +    // Store value +    auto PassthruReg = I.getOperand(CurOp++).getReg(); +    SrcOps.push_back(PassthruReg); + +    addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided); + +    RISCVVType::VLMUL LMUL = RISCVTargetLowering::getLMUL(getMVTForLLT(VT)); +    const RISCV::VSEPseudo *P = RISCV::getVSEPseudo( +        IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL)); + +    auto PseudoMI = MIB.buildInstr(P->Pseudo, {}, SrcOps); + +    // Select VL +    auto VLOpFn = renderVLOp(I.getOperand(CurOp++)); +    for (auto &RenderFn : *VLOpFn) +      RenderFn(PseudoMI); + +    // SEW +    PseudoMI.addImm(Log2SEW); + +    // Memref +    PseudoMI.cloneMemRefs(I); + +    I.eraseFromParent(); +    return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI); +  }    }  } diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp index 4105618..526675a 100644 --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -127,6 +127,10 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,    case RISCV::PseudoCCAND:    case RISCV::PseudoCCOR:    case RISCV::PseudoCCXOR: +  case RISCV::PseudoCCMAX: +  case RISCV::PseudoCCMAXU: +  case RISCV::PseudoCCMIN: +  case RISCV::PseudoCCMINU:    case RISCV::PseudoCCADDW:    case RISCV::PseudoCCSUBW:    case RISCV::PseudoCCSLL: @@ -217,6 +221,7 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,          .addImm(0);    } else {      unsigned NewOpc; +    // clang-format off      switch (MI.getOpcode()) {      default:        llvm_unreachable("Unexpected opcode!"); @@ -228,6 +233,10 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,      case RISCV::PseudoCCAND:   NewOpc = RISCV::AND;   break;      case RISCV::PseudoCCOR:    NewOpc = RISCV::OR;    break;      case RISCV::PseudoCCXOR:   NewOpc = RISCV::XOR;   break; +    case RISCV::PseudoCCMAX:   NewOpc = RISCV::MAX;   break; +    case RISCV::PseudoCCMIN:   NewOpc = RISCV::MIN;   break; +    case RISCV::PseudoCCMAXU:  NewOpc = RISCV::MAXU;  break; +    case RISCV::PseudoCCMINU:  NewOpc = RISCV::MINU;  break;      case RISCV::PseudoCCADDI:  NewOpc = RISCV::ADDI;  break;      case RISCV::PseudoCCSLLI:  NewOpc = RISCV::SLLI;  break;      case RISCV::PseudoCCSRLI:  NewOpc = RISCV::SRLI;  break; @@ -250,6 +259,7 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,      case RISCV::PseudoCCNDS_BFOS: NewOpc = RISCV::NDS_BFOS; break;      case RISCV::PseudoCCNDS_BFOZ: NewOpc = RISCV::NDS_BFOZ; break;      } +    // clang-format on      if (NewOpc == RISCV::NDS_BFOZ || NewOpc == RISCV::NDS_BFOS) {        BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg) diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index b4556f6..cfee6ab 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -1851,6 +1851,11 @@ def TuneShortForwardBranchOpt  def HasShortForwardBranchOpt : Predicate<"Subtarget->hasShortForwardBranchOpt()">;  def NoShortForwardBranchOpt : Predicate<"!Subtarget->hasShortForwardBranchOpt()">; +def TuneShortForwardBranchIMinMax +    : SubtargetFeature<"short-forward-branch-i-minmax", "HasShortForwardBranchIMinMax", +                       "true", "Enable short forward branch optimization for min,max instructions in Zbb", +                       [TuneShortForwardBranchOpt]>; +  // Some subtargets require a S2V transfer buffer to move scalars into vectors.  // FIXME: Forming .vx/.vf/.wx/.wf can reduce register pressure.  def TuneNoSinkSplatOperands diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 9a6afa1..b25a054 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -3995,6 +3995,7 @@ bool RISCVDAGToDAGISel::hasAllNBitUsers(SDNode *Node, unsigned Bits,      case RISCV::CTZW:      case RISCV::CPOPW:      case RISCV::SLLI_UW: +    case RISCV::ABSW:      case RISCV::FMV_W_X:      case RISCV::FCVT_H_W:      case RISCV::FCVT_H_W_INX: diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 1c930ac..c6a8b84 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -433,6 +433,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,    if (Subtarget.hasStdExtP() ||        (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {      setOperationAction(ISD::ABS, XLenVT, Legal); +    if (Subtarget.is64Bit()) +      setOperationAction(ISD::ABS, MVT::i32, Custom);    } else if (Subtarget.hasShortForwardBranchOpt()) {      // We can use PseudoCCSUB to implement ABS.      setOperationAction(ISD::ABS, XLenVT, Legal); @@ -14816,8 +14818,16 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,      assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&             "Unexpected custom legalisation"); +    if (Subtarget.hasStdExtP()) { +      SDValue Src = +          DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0)); +      SDValue Abs = DAG.getNode(RISCVISD::ABSW, DL, MVT::i64, Src); +      Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Abs)); +      return; +    } +      if (Subtarget.hasStdExtZbb()) { -      // Emit a special ABSW node that will be expanded to NEGW+MAX at isel. +      // Emit a special node that will be expanded to NEGW+MAX at isel.        // This allows us to remember that the result is sign extended. Expanding        // to NEGW+MAX here requires a Freeze which breaks ComputeNumSignBits.        SDValue Src = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, @@ -19784,7 +19794,9 @@ legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index,      // LLVM's legalization take care of the splitting.      // FIXME: LLVM can't split VP_GATHER or VP_SCATTER yet.      Index = DAG.getNode(ISD::SIGN_EXTEND, DL, -                        IndexVT.changeVectorElementType(XLenVT), Index); +                        EVT::getVectorVT(*DAG.getContext(), XLenVT, +                                         IndexVT.getVectorElementCount()), +                        Index);    }    IndexType = ISD::UNSIGNED_SCALED;    return true; @@ -20290,6 +20302,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,      break;    } +  case RISCVISD::ABSW:    case RISCVISD::CLZW:    case RISCVISD::CTZW: {      // Only the lower 32 bits of the first operand are read @@ -21862,6 +21875,7 @@ unsigned RISCVTargetLowering::ComputeNumSignBitsForTargetNode(    case RISCVISD::REMUW:    case RISCVISD::ROLW:    case RISCVISD::RORW: +  case RISCVISD::ABSW:    case RISCVISD::FCVT_W_RV64:    case RISCVISD::FCVT_WU_RV64:    case RISCVISD::STRICT_FCVT_W_RV64: diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 912b82d..c9df787 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -869,7 +869,7 @@ std::optional<unsigned> getFoldedOpcode(MachineFunction &MF, MachineInstr &MI,    }  } -// This is the version used during inline spilling +// This is the version used during InlineSpiller::spillAroundUses  MachineInstr *RISCVInstrInfo::foldMemoryOperandImpl(      MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,      MachineBasicBlock::iterator InsertPt, int FrameIndex, LiveIntervals *LIS, @@ -1699,6 +1699,10 @@ unsigned getPredicatedOpcode(unsigned Opcode) {    case RISCV::AND:   return RISCV::PseudoCCAND;    case RISCV::OR:    return RISCV::PseudoCCOR;    case RISCV::XOR:   return RISCV::PseudoCCXOR; +  case RISCV::MAX:   return RISCV::PseudoCCMAX; +  case RISCV::MAXU:  return RISCV::PseudoCCMAXU; +  case RISCV::MIN:   return RISCV::PseudoCCMIN; +  case RISCV::MINU:  return RISCV::PseudoCCMINU;    case RISCV::ADDI:  return RISCV::PseudoCCADDI;    case RISCV::SLLI:  return RISCV::PseudoCCSLLI; @@ -1735,7 +1739,8 @@ unsigned getPredicatedOpcode(unsigned Opcode) {  /// return the defining instruction.  static MachineInstr *canFoldAsPredicatedOp(Register Reg,                                             const MachineRegisterInfo &MRI, -                                           const TargetInstrInfo *TII) { +                                           const TargetInstrInfo *TII, +                                           const RISCVSubtarget &STI) {    if (!Reg.isVirtual())      return nullptr;    if (!MRI.hasOneNonDBGUse(Reg)) @@ -1743,6 +1748,12 @@ static MachineInstr *canFoldAsPredicatedOp(Register Reg,    MachineInstr *MI = MRI.getVRegDef(Reg);    if (!MI)      return nullptr; + +  if (!STI.hasShortForwardBranchIMinMax() && +      (MI->getOpcode() == RISCV::MAX || MI->getOpcode() == RISCV::MIN || +       MI->getOpcode() == RISCV::MINU || MI->getOpcode() == RISCV::MAXU)) +    return nullptr; +    // Check if MI can be predicated and folded into the CCMOV.    if (getPredicatedOpcode(MI->getOpcode()) == RISCV::INSTRUCTION_LIST_END)      return nullptr; @@ -1806,10 +1817,10 @@ RISCVInstrInfo::optimizeSelect(MachineInstr &MI,    MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();    MachineInstr *DefMI = -      canFoldAsPredicatedOp(MI.getOperand(5).getReg(), MRI, this); +      canFoldAsPredicatedOp(MI.getOperand(5).getReg(), MRI, this, STI);    bool Invert = !DefMI;    if (!DefMI) -    DefMI = canFoldAsPredicatedOp(MI.getOperand(4).getReg(), MRI, this); +    DefMI = canFoldAsPredicatedOp(MI.getOperand(4).getReg(), MRI, this, STI);    if (!DefMI)      return nullptr; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 7c89686..9cb53fb 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -768,7 +768,7 @@ def BGE  : BranchCC_rri<0b101, "bge">;  def BLTU : BranchCC_rri<0b110, "bltu">;  def BGEU : BranchCC_rri<0b111, "bgeu">; -let IsSignExtendingOpW = 1 in { +let IsSignExtendingOpW = 1, canFoldAsLoad = 1 in {  def LB  : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>;  def LH  : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>;  def LW  : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; @@ -889,8 +889,10 @@ def CSRRCI : CSR_ii<0b111, "csrrci">;  /// RV64I instructions  let Predicates = [IsRV64] in { +let canFoldAsLoad = 1 in {  def LWU   : Load_ri<0b110, "lwu">, Sched<[WriteLDW, ReadMemBase]>;  def LD    : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; +}  def SD    : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>;  let IsSignExtendingOpW = 1 in { diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td index afac37d..4ffe3e6 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td @@ -71,6 +71,7 @@ defvar DExtsRV64 = [DExt, ZdinxExt];  //===----------------------------------------------------------------------===//  let Predicates = [HasStdExtD] in { +let canFoldAsLoad = 1 in  def FLD : FPLoad_r<0b011, "fld", FPR64, WriteFLD64>;  // Operands for stores are in the order srcreg, base, offset rather than diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td index 6571d99..b30f8ec 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td @@ -330,6 +330,7 @@ class PseudoFROUND<DAGOperand Ty, ValueType vt, ValueType intvt = XLenVT>  //===----------------------------------------------------------------------===//  let Predicates = [HasStdExtF] in { +let canFoldAsLoad = 1 in  def FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>;  // Operands for stores are in the order srcreg, base, offset rather than diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index cc085bb..4cbbba3 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -1461,5 +1461,10 @@ let Predicates = [HasStdExtP, IsRV32] in {  // Codegen patterns  //===----------------------------------------------------------------------===// +def riscv_absw : RVSDNode<"ABSW", SDTIntUnaryOp>; +  let Predicates = [HasStdExtP] in  def : PatGpr<abs, ABS>; + +let Predicates = [HasStdExtP, IsRV64] in +def : PatGpr<riscv_absw, ABSW>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td index 0114fbd..5a67a5a 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td @@ -106,6 +106,10 @@ def PseudoCCSRA : SFBALU_rr;  def PseudoCCAND : SFBALU_rr;  def PseudoCCOR  : SFBALU_rr;  def PseudoCCXOR : SFBALU_rr; +def PseudoCCMAX : SFBALU_rr; +def PseudoCCMIN : SFBALU_rr; +def PseudoCCMAXU : SFBALU_rr; +def PseudoCCMINU : SFBALU_rr;  def PseudoCCADDI : SFBALU_ri;  def PseudoCCANDI : SFBALU_ri; diff --git a/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp b/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp index d08115b..ea98cdb 100644 --- a/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp +++ b/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp @@ -172,6 +172,7 @@ static bool hasAllNBitUsers(const MachineInstr &OrigMI,        case RISCV::CTZW:        case RISCV::CPOPW:        case RISCV::SLLI_UW: +      case RISCV::ABSW:        case RISCV::FMV_W_X:        case RISCV::FCVT_H_W:        case RISCV::FCVT_H_W_INX: diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index e9f43b9..84bb294 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -438,18 +438,19 @@ void RISCVRegisterInfo::lowerSegmentSpillReload(MachineBasicBlock::iterator II,    TypeSize VRegSize = OldLoc.getValue().divideCoefficientBy(NumRegs);    Register VLENB = 0; -  unsigned PreHandledNum = 0; +  unsigned VLENBShift = 0; +  unsigned PrevHandledNum = 0;    unsigned I = 0;    while (I != NumRegs) {      auto [LMulHandled, RegClass, Opcode] =          getSpillReloadInfo(NumRegs - I, RegEncoding, IsSpill);      auto [RegNumHandled, _] = RISCVVType::decodeVLMUL(LMulHandled);      bool IsLast = I + RegNumHandled == NumRegs; -    if (PreHandledNum) { +    if (PrevHandledNum) {        Register Step;        // Optimize for constant VLEN.        if (auto VLEN = STI.getRealVLen()) { -        int64_t Offset = *VLEN / 8 * PreHandledNum; +        int64_t Offset = *VLEN / 8 * PrevHandledNum;          Step = MRI.createVirtualRegister(&RISCV::GPRRegClass);          STI.getInstrInfo()->movImm(MBB, II, DL, Step, Offset);        } else { @@ -457,15 +458,21 @@ void RISCVRegisterInfo::lowerSegmentSpillReload(MachineBasicBlock::iterator II,            VLENB = MRI.createVirtualRegister(&RISCV::GPRRegClass);            BuildMI(MBB, II, DL, TII->get(RISCV::PseudoReadVLENB), VLENB);          } -        uint32_t ShiftAmount = Log2_32(PreHandledNum); -        if (ShiftAmount == 0) -          Step = VLENB; -        else { -          Step = MRI.createVirtualRegister(&RISCV::GPRRegClass); -          BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), Step) -              .addReg(VLENB, getKillRegState(IsLast)) -              .addImm(ShiftAmount); +        uint32_t ShiftAmount = Log2_32(PrevHandledNum); +        // To avoid using an extra register, we shift the VLENB register and +        // remember how much it has been shifted. We can then use relative +        // shifts to adjust to the desired shift amount. +        if (VLENBShift > ShiftAmount) { +          BuildMI(MBB, II, DL, TII->get(RISCV::SRLI), VLENB) +              .addReg(VLENB, RegState::Kill) +              .addImm(VLENBShift - ShiftAmount); +        } else if (VLENBShift < ShiftAmount) { +          BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), VLENB) +              .addReg(VLENB, RegState::Kill) +              .addImm(ShiftAmount - VLENBShift);          } +        VLENBShift = ShiftAmount; +        Step = VLENB;        }        BuildMI(MBB, II, DL, TII->get(RISCV::ADD), NewBase) @@ -489,7 +496,7 @@ void RISCVRegisterInfo::lowerSegmentSpillReload(MachineBasicBlock::iterator II,      if (IsSpill)        MIB.addReg(Reg, RegState::Implicit); -    PreHandledNum = RegNumHandled; +    PrevHandledNum = RegNumHandled;      RegEncoding += RegNumHandled;      I += RegNumHandled;    } | 
