diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt --- a/llvm/lib/Target/RISCV/CMakeLists.txt +++ b/llvm/lib/Target/RISCV/CMakeLists.txt @@ -40,6 +40,7 @@ RISCVRedundantCopyElimination.cpp RISCVRegisterBankInfo.cpp RISCVRegisterInfo.cpp + RISCVRVVInitUndef.cpp RISCVSExtWRemoval.cpp RISCVSubtarget.cpp RISCVTargetMachine.cpp diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h --- a/llvm/lib/Target/RISCV/RISCV.h +++ b/llvm/lib/Target/RISCV/RISCV.h @@ -68,6 +68,9 @@ FunctionPass *createRISCVRedundantCopyEliminationPass(); void initializeRISCVRedundantCopyEliminationPass(PassRegistry &); +FunctionPass *createRISCVInitUndefPass(); +void initializeRISCVInitUndefPass(PassRegistry &); + InstructionSelector *createRISCVInstructionSelector(const RISCVTargetMachine &, RISCVSubtarget &, RISCVRegisterBankInfo &); diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -47,6 +47,8 @@ MachineBasicBlock::iterator &NextMBBI); bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI); + bool removeTempRVVInitUndef(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI); bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); bool expandVMSET_VMCLR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned Opcode); @@ -132,11 +134,29 @@ case RISCV::PseudoVRELOAD7_M1: case RISCV::PseudoVRELOAD8_M1: return expandVRELOAD(MBB, MBBI); + case RISCV::PseudoRVVInitUndefM1: + case RISCV::PseudoRVVInitUndefM2: + case RISCV::PseudoRVVInitUndefM4: + case RISCV::PseudoRVVInitUndefM8: + return removeTempRVVInitUndef(MBB, MBBI); } return false; } +bool RISCVExpandPseudo::removeTempRVVInitUndef( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) { + MachineRegisterInfo *MRI = &(MBB.getParent()->getRegInfo()); + MachineInstr &MI = *MBBI; + Register Reg = MI.getOperand(0).getReg(); + + for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) + MO.setIsUndef(); + + MI.eraseFromParent(); + return true; +} + bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI) { diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1766,6 +1766,14 @@ (AddiPairImmSmall AddiPair:$rs2))>; } +/// Empty pseudo for RISCVInitUndefPass +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 0, isCodeGenOnly = 1 in { + def PseudoRVVInitUndefM1 : Pseudo<(outs VR:$vd), (ins), [], "">; + def PseudoRVVInitUndefM2 : Pseudo<(outs VRM2:$vd), (ins), [], "">; + def PseudoRVVInitUndefM4 : Pseudo<(outs VRM4:$vd), (ins), [], "">; + def PseudoRVVInitUndefM8 : Pseudo<(outs VRM8:$vd), (ins), [], "">; +} + //===----------------------------------------------------------------------===// // Standard extensions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp b/llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp @@ -0,0 +1,388 @@ +//===- RISCVInitUndef.cpp - Initialize undef vector value to pesudo -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function pass that initializes undef vector value to +// temporary pesudo instruction and remove it in expandpesudo pass to prevent +// register allocation resulting in a constraint violated result for vector +// instruction. +// +// RISC-V vector instruction has register overlapping constraint for certain +// instructions, and will cause illegal instruction trap if violated, we use +// early clobber to model this constraint, but it can't prevent register +// allocator allocated same or overlapped if the input register is undef value, +// so convert IMPLICIT_DEF to temporary pesudo instruction and remove it latter +// could prevent that happen, it's not best way to resolve this, and it might +// change the order of program or increase the register pressure, so ideally we +// should model the constraint right, but before we model the constraint right, +// it's the only way to prevent that happen. +// +// When we enable the subregister liveness option, it will also trigger same +// issue due to the partial of register is undef. If we pesudoinit the whole +// register, then it will generate redundant COPY instruction. Currently, it +// will generate INSERT_SUBREG to make sure the whole register is be occupied +// when program encounter operation that has early-clobber constraint. +// +// +// See also: https://github.com/llvm/llvm-project/issues/50157 +// +//===----------------------------------------------------------------------===// + +#include "RISCV.h" +#include "RISCVSubtarget.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +using namespace llvm; + +#define DEBUG_TYPE "riscv-init-undef" +#define RISCV_INIT_UNDEF_NAME "RISCV init undef pass" + +namespace { + +class RISCVInitUndef : public MachineFunctionPass { + const TargetInstrInfo *TII; + MachineRegisterInfo *MRI; + const RISCVSubtarget *ST; + const TargetRegisterInfo *TRI; + llvm::SmallPtrSet Seen; + +public: + static char ID; + + RISCVInitUndef() : MachineFunctionPass(ID) { + initializeRISCVInitUndefPass(*PassRegistry::getPassRegistry()); + } + bool runOnMachineFunction(MachineFunction &MF) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + StringRef getPassName() const override { return RISCV_INIT_UNDEF_NAME; } + +private: + bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB); + bool handleImplicitDef(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &Inst); + bool isVectorRegClass(const Register &R); + bool handleSubRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &Inst); + void findSubRegDefChainNeedToFix( + MachineInstr *Curr, std::vector InstrChain, + std::vector> &Candidates); + const TargetRegisterClass * + getVRLargestSuperClass(const TargetRegisterClass *RC) const; +}; + +} // end anonymous namespace + +char RISCVInitUndef::ID = 0; + +INITIALIZE_PASS(RISCVInitUndef, DEBUG_TYPE, RISCV_INIT_UNDEF_NAME, false, false) + +const TargetRegisterClass * +RISCVInitUndef::getVRLargestSuperClass(const TargetRegisterClass *RC) const { + const TargetRegisterClass *Super = RC; + TargetRegisterClass::sc_iterator I = RC->getSuperClasses(); + do { + switch (Super->getID()) { + // We only care vector register. + case RISCV::VRRegClassID: + case RISCV::VRM2RegClassID: + case RISCV::VRM4RegClassID: + case RISCV::VRM8RegClassID: + return Super; + } + Super = *I++; + } while (Super); + // If we don't encounter VR then return origin one. + return RC; +} + +bool RISCVInitUndef::isVectorRegClass(const Register &R) { + unsigned RegClassID = getVRLargestSuperClass(MRI->getRegClass(R))->getID(); + switch (RegClassID) { + case RISCV::VRRegClassID: + case RISCV::VRM2RegClassID: + case RISCV::VRM4RegClassID: + case RISCV::VRM8RegClassID: + return true; + default: + return false; + } +} + +static unsigned getUndefInitOpcode(unsigned RegClassID) { + unsigned Opcode; + switch (RegClassID) { + case RISCV::VRRegClassID: + Opcode = RISCV::PseudoRVVInitUndefM1; + break; + case RISCV::VRM2RegClassID: + Opcode = RISCV::PseudoRVVInitUndefM2; + break; + case RISCV::VRM4RegClassID: + Opcode = RISCV::PseudoRVVInitUndefM4; + break; + case RISCV::VRM8RegClassID: + Opcode = RISCV::PseudoRVVInitUndefM8; + break; + default: + llvm_unreachable("Unexpected register class."); + } + return Opcode; +} + +void RISCVInitUndef::findSubRegDefChainNeedToFix( + MachineInstr *Curr, std::vector InstrChain, + std::vector> &Candidates) { + unsigned Reg = Curr->getOperand(0).getReg(); + for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) { + MachineInstr *UserMI = MO.getParent(); + // Avoid infinite loop + if (Seen.contains(UserMI)) + continue; + InstrChain.push_back(UserMI); + Seen.insert(UserMI); + // If we encounter instruction that using sub-register and + // have early-clobber flag, then set it as candidate. + for (MachineOperand &UseMO : UserMI->operands()) { + if (!UseMO.isReg()) + continue; + if (UseMO.isEarlyClobber()) { + Candidates.push_back(InstrChain); + } + } + // If there are other inst define the register, then ignore it due to + // register is all defined (for all sub-register). + // FIXME: Are there other MachineInstrs could pass the partial defined + // register? + if (UserMI->getOpcode() == TargetOpcode::INSERT_SUBREG || + UserMI->getOpcode() == TargetOpcode::PHI || + UserMI->getOpcode() == TargetOpcode::COPY) + findSubRegDefChainNeedToFix(UserMI, InstrChain, Candidates); + InstrChain.pop_back(); + Seen.erase(UserMI); + } +} + +static std::vector +filterInsertSubRegInst(std::vector Insts) { + std::vector rst; + for (auto Inst : Insts) { + if (Inst->getOpcode() == TargetOpcode::INSERT_SUBREG) + rst.push_back(Inst); + } + return rst; +} + +static MachineOperand *getLastRegUser(std::vector Insts, + unsigned Reg) { + for (size_t i = Insts.size(); i != 0; i--) { + for (MachineOperand &UseMO : Insts[i - 1]->operands()) { + if (!UseMO.isReg()) + continue; + if (UseMO.getReg() == Reg) + return &UseMO; + } + } + LLVM_DEBUG(dbgs() << "Can't find the Inst that using this Register " << Reg + << '\n'); + return nullptr; +} + +static MachineInstr * +getLastInsertSubRegInst(std::vector Insts) { + MachineInstr *Rst = nullptr; + for (auto Inst : Insts) { + if (Inst->getOpcode() == TargetOpcode::INSERT_SUBREG) + Rst = Inst; + } + return Rst; +} + +// If Sub-register liveness is enable, then we only need to PesudoInit undef +// sub-register instead of whole regitser. Otherwise, it will generate redundant +// COPY. For this purpose, there are some steps to meet this requirement. +// +// 1. Find the def-use chain from INSERT_SUBREG. +// V0 = Implicit_def +// ^ Don't add it to vector due to it will pass from function args +// V1 = INSERT_SUBREG V0, SubV0, subreg_index0 V2 = INSERT_SUBREG +// V1, SubV1, subreg_index1 V3 = INSERT_SUBREG V2, SubV2, subreg_index2 +// ... +// INSERT_SUBREG || COPY || PHI +// ... +// VN = INSERT_SUBREG V(N-1), SubV(N-1), subreg_index(N-1) +// early-clobber vd = Op VN +// 2. Compute the which subregister is undef. +// 3. Insert the more INSERT_SUBREG Node between the +// last INSERT_SUBREG and Op with early-clobber constraint. +// +// Note: We assume this sub-register def-use will be SSA-form. +bool RISCVInitUndef::handleSubRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &Inst) { + MachineInstr *CurrInst = &(*Inst); + + Seen.clear(); + std::vector> Candidates; + findSubRegDefChainNeedToFix(CurrInst, std::vector(), + Candidates); + + if (Candidates.empty()) + return false; + + bool Changed = false; + unsigned TargetReg = Inst->getOperand(0).getReg(); + const TargetRegisterClass *TargetRegClass = + getVRLargestSuperClass(MRI->getRegClass(TargetReg)); + for (auto Candidate : Candidates) { + LaneBitmask TargetRegLaneMask = TargetRegClass->getLaneMask(); + LaneBitmask CandidataLaneMask = TargetRegLaneMask; + + // Step 2 Compute the which subregister is undef. + for (auto SRDef : filterInsertSubRegInst(Candidate)) { + MachineOperand SubRegInd = SRDef->getOperand(3); + LaneBitmask SubRegLaneMask = + TRI->getSubRegIndexLaneMask(SubRegInd.getImm()); + CandidataLaneMask = CandidataLaneMask & ~SubRegLaneMask; + } + + SmallVector CandidateSubRegIndex; + TRI->getCoveringSubRegIndexes(*MRI, TargetRegClass, CandidataLaneMask, + CandidateSubRegIndex); + + // Step 3 Insert the more INSERT_SUBREG according Step 2 result. + MachineInstr *LastInsertSubRegInst = getLastInsertSubRegInst(Candidate); + MachineInstr *InsertPoint = LastInsertSubRegInst; + unsigned RegOriginUsedbyEC = LastInsertSubRegInst->getOperand(0).getReg(); + unsigned LastestReg = RegOriginUsedbyEC; + // PseudoDef the sub-register until whole target register is fully defined. + // It will insert multiple times according to getCoveringSubRegIndexes + // result. + // + // SubV0 = PseudoRVVInitUndef + // V1 = INSERT_SUBREG V0, SubV0, subreg_index0 + // + // Then replace the V0 with V1 for early-clobber user. + for (auto ind : CandidateSubRegIndex) { + Changed = true; + const TargetRegisterClass *SubRegClass = + getVRLargestSuperClass(TRI->getSubRegisterClass(TargetRegClass, ind)); + unsigned TmpInitSubReg = MRI->createVirtualRegister(SubRegClass); + BuildMI(MBB, Inst, Inst->getDebugLoc(), + TII->get(getUndefInitOpcode(SubRegClass->getID())), + TmpInitSubReg); + unsigned NewReg = MRI->createVirtualRegister(TargetRegClass); + MachineInstr *NewInsertSubRegInst = + BuildMI(*InsertPoint->getParent(), InsertPoint, + InsertPoint->getDebugLoc(), + TII->get(TargetOpcode::INSERT_SUBREG), NewReg) + .addReg(LastestReg) + .addReg(TmpInitSubReg) + .addImm(ind); + // FIXME: Is there better method to insert instruction after another + // instruction. + InsertPoint->moveBefore(NewInsertSubRegInst); + InsertPoint = NewInsertSubRegInst; + LastestReg = NewReg; + } + + getLastRegUser(Candidate, RegOriginUsedbyEC)->setReg(LastestReg); + } + + return Changed; +} + +bool RISCVInitUndef::handleImplicitDef(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &Inst) { + const TargetRegisterInfo &TRI = + *MBB.getParent()->getSubtarget().getRegisterInfo(); + + assert(Inst->getOpcode() == TargetOpcode::IMPLICIT_DEF); + + unsigned Reg = Inst->getOperand(0).getReg(); + if (!Register::isVirtualRegister(Reg)) + return false; + + bool NeedPseudoInit = false; + SmallVector UserMOs; + for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) { + MachineInstr *UserMI = MO.getParent(); + + if (ST->enableSubRegLiveness() && + UserMI->getOpcode() == TargetOpcode::INSERT_SUBREG) + return handleSubRegister(MBB, Inst); + + bool HasEarlyClobber = false; + bool TiedToDef = false; + for (MachineOperand &UseMO : UserMI->operands()) { + if (!UseMO.isReg()) + continue; + if (UseMO.isEarlyClobber()) + HasEarlyClobber = true; + if (UseMO.isUse() && UseMO.isTied() && + TRI.regsOverlap(UseMO.getReg(), Reg)) + TiedToDef = true; + } + if (HasEarlyClobber && !TiedToDef) { + NeedPseudoInit = true; + UserMOs.push_back(&MO); + } + } + + if (!NeedPseudoInit) + return false; + + LLVM_DEBUG( + dbgs() << "Emitting PseudoRVVInitUndef for implicit vector register " + << Reg << '\n'); + + unsigned RegClassID = getVRLargestSuperClass(MRI->getRegClass(Reg))->getID(); + unsigned Opcode = getUndefInitOpcode(RegClassID); + + BuildMI(MBB, Inst, Inst->getDebugLoc(), TII->get(Opcode), Reg); + + Inst = MBB.erase(Inst); + + for (auto MO : UserMOs) + MO->setIsUndef(false); + + return true; +} + +bool RISCVInitUndef::processBasicBlock(MachineFunction &MF, + MachineBasicBlock &MBB) { + bool Changed = false; + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { + MachineInstr &MI = *I; + if (MI.isImplicitDef()) { + auto DstReg = MI.getOperand(0).getReg(); + if (isVectorRegClass(DstReg)) + Changed |= handleImplicitDef(MBB, I); + } + } + return Changed; +} + +bool RISCVInitUndef::runOnMachineFunction(MachineFunction &MF) { + ST = &MF.getSubtarget(); + if (!ST->hasVInstructions()) + return false; + + MRI = &MF.getRegInfo(); + TII = ST->getInstrInfo(); + TRI = MRI->getTargetRegisterInfo(); + + bool Changed = false; + for (MachineBasicBlock &BB : MF) + Changed |= processBasicBlock(MF, BB); + + return Changed; +} + +FunctionPass *llvm::createRISCVInitUndefPass() { return new RISCVInitUndef(); } diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -65,6 +65,7 @@ initializeRISCVPreRAExpandPseudoPass(*PR); initializeRISCVExpandPseudoPass(*PR); initializeRISCVInsertVSETVLIPass(*PR); + initializeRISCVInitUndefPass(*PR); } static StringRef computeDataLayout(const Triple &TT) { @@ -280,6 +281,8 @@ if (TM->getOptLevel() != CodeGenOpt::None) addPass(createRISCVMergeBaseOffsetOptPass()); addPass(createRISCVInsertVSETVLIPass()); + if (getOptimizeRegAlloc()) + addPass(createRISCVInitUndefPass()); } void RISCVPassConfig::addPostRegAlloc() { diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll --- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll +++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll @@ -104,6 +104,7 @@ ; CHECK-NEXT: RISCV Pre-RA pseudo instruction expansion pass ; CHECK-NEXT: RISCV Merge Base Offset ; CHECK-NEXT: RISCV Insert VSETVLI pass +; CHECK-NEXT: RISCV init undef pass ; CHECK-NEXT: Detect Dead Lanes ; CHECK-NEXT: Process Implicit Definitions ; CHECK-NEXT: Remove unreachable machine basic blocks diff --git a/llvm/test/CodeGen/RISCV/regalloc-last-chance-recoloring-failure.ll b/llvm/test/CodeGen/RISCV/regalloc-last-chance-recoloring-failure.ll --- a/llvm/test/CodeGen/RISCV/regalloc-last-chance-recoloring-failure.ll +++ b/llvm/test/CodeGen/RISCV/regalloc-last-chance-recoloring-failure.ll @@ -25,26 +25,26 @@ ; CHECK-NEXT: sub sp, sp, a0 ; CHECK-NEXT: li a0, 55 ; CHECK-NEXT: vsetvli zero, a0, e16, m4, ta, ma -; CHECK-NEXT: vloxseg2ei32.v v8, (a0), v8 +; CHECK-NEXT: vloxseg2ei32.v v16, (a0), v8 ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: csrr a1, vlenb ; CHECK-NEXT: slli a1, a1, 2 -; CHECK-NEXT: vs4r.v v8, (a0) # Unknown-size Folded Spill +; CHECK-NEXT: vs4r.v v16, (a0) # Unknown-size Folded Spill ; CHECK-NEXT: add a0, a0, a1 -; CHECK-NEXT: vs4r.v v12, (a0) # Unknown-size Folded Spill +; CHECK-NEXT: vs4r.v v20, (a0) # Unknown-size Folded Spill ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma ; CHECK-NEXT: vmclr.m v0 ; CHECK-NEXT: li s0, 36 ; CHECK-NEXT: vsetvli zero, s0, e16, m4, ta, ma -; CHECK-NEXT: vfwadd.vv v8, v8, v8, v0.t +; CHECK-NEXT: vfwadd.vv v16, v8, v8, v0.t ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 4 ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 -; CHECK-NEXT: vs8r.v v8, (a0) # Unknown-size Folded Spill +; CHECK-NEXT: vs8r.v v16, (a0) # Unknown-size Folded Spill ; CHECK-NEXT: call func@plt ; CHECK-NEXT: li a0, 32 ; CHECK-NEXT: vsetvli zero, a0, e16, m4, ta, ma @@ -101,23 +101,23 @@ ; SUBREGLIVENESS-NEXT: sub sp, sp, a0 ; SUBREGLIVENESS-NEXT: li a0, 55 ; SUBREGLIVENESS-NEXT: vsetvli zero, a0, e16, m4, ta, ma -; SUBREGLIVENESS-NEXT: vloxseg2ei32.v v8, (a0), v8 +; SUBREGLIVENESS-NEXT: vloxseg2ei32.v v16, (a0), v8 ; SUBREGLIVENESS-NEXT: csrr a0, vlenb ; SUBREGLIVENESS-NEXT: slli a0, a0, 3 ; SUBREGLIVENESS-NEXT: add a0, sp, a0 ; SUBREGLIVENESS-NEXT: addi a0, a0, 16 ; SUBREGLIVENESS-NEXT: csrr a1, vlenb ; SUBREGLIVENESS-NEXT: slli a1, a1, 2 -; SUBREGLIVENESS-NEXT: vs4r.v v8, (a0) # Unknown-size Folded Spill +; SUBREGLIVENESS-NEXT: vs4r.v v16, (a0) # Unknown-size Folded Spill ; SUBREGLIVENESS-NEXT: add a0, a0, a1 -; SUBREGLIVENESS-NEXT: vs4r.v v12, (a0) # Unknown-size Folded Spill +; SUBREGLIVENESS-NEXT: vs4r.v v20, (a0) # Unknown-size Folded Spill ; SUBREGLIVENESS-NEXT: vsetvli a0, zero, e8, m2, ta, ma ; SUBREGLIVENESS-NEXT: vmclr.m v0 ; SUBREGLIVENESS-NEXT: li s0, 36 ; SUBREGLIVENESS-NEXT: vsetvli zero, s0, e16, m4, ta, ma -; SUBREGLIVENESS-NEXT: vfwadd.vv v8, v8, v8, v0.t +; SUBREGLIVENESS-NEXT: vfwadd.vv v16, v8, v8, v0.t ; SUBREGLIVENESS-NEXT: addi a0, sp, 16 -; SUBREGLIVENESS-NEXT: vs8r.v v8, (a0) # Unknown-size Folded Spill +; SUBREGLIVENESS-NEXT: vs8r.v v16, (a0) # Unknown-size Folded Spill ; SUBREGLIVENESS-NEXT: call func@plt ; SUBREGLIVENESS-NEXT: li a0, 32 ; SUBREGLIVENESS-NEXT: vsetvli zero, a0, e16, m4, ta, ma diff --git a/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll b/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll --- a/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll +++ b/llvm/test/CodeGen/RISCV/rvv/undef-earlyclobber-chain.ll @@ -7,9 +7,9 @@ ; CHECK-NEXT: addi sp, sp, -400 ; CHECK-NEXT: .cfi_def_cfa_offset 400 ; CHECK-NEXT: vsetivli zero, 0, e32, m1, ta, ma -; CHECK-NEXT: vrgather.vi v8, v8, 0 +; CHECK-NEXT: vrgather.vi v9, v8, 0 ; CHECK-NEXT: mv a0, sp -; CHECK-NEXT: vse32.v v8, (a0) +; CHECK-NEXT: vse32.v v9, (a0) ; CHECK-NEXT: li a0, 0 ; CHECK-NEXT: addi sp, sp, 400 ; CHECK-NEXT: ret @@ -34,20 +34,20 @@ ; CHECK-NEXT: j .LBB1_3 ; CHECK-NEXT: .LBB1_2: # %Cond2 ; CHECK-NEXT: vsetvli a0, zero, e16, mf4, ta, ma -; CHECK-NEXT: vid.v v9 +; CHECK-NEXT: vid.v v12 ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: srli a0, a0, 3 ; CHECK-NEXT: add a1, a0, a0 ; CHECK-NEXT: vsetvli zero, a1, e16, m1, ta, ma -; CHECK-NEXT: vslideup.vx v8, v9, a0 +; CHECK-NEXT: vslideup.vx v8, v12, a0 ; CHECK-NEXT: vsetvli a2, zero, e16, mf4, ta, ma -; CHECK-NEXT: vadd.vi v11, v9, 1 +; CHECK-NEXT: vadd.vi v11, v12, 1 ; CHECK-NEXT: vsetvli zero, a1, e16, m1, ta, ma ; CHECK-NEXT: vslideup.vx v10, v11, a0 ; CHECK-NEXT: vsetvli a2, zero, e16, mf4, ta, ma -; CHECK-NEXT: vadd.vi v9, v9, 3 +; CHECK-NEXT: vadd.vi v13, v12, 3 ; CHECK-NEXT: vsetvli zero, a1, e16, m1, ta, ma -; CHECK-NEXT: vslideup.vx v12, v9, a0 +; CHECK-NEXT: vslideup.vx v12, v13, a0 ; CHECK-NEXT: .LBB1_3: # %UseSR ; CHECK-NEXT: vl1r.v v14, (zero) ; CHECK-NEXT: vsetivli zero, 4, e8, m1, ta, ma @@ -106,17 +106,17 @@ ; CHECK-NEXT: vadd.vi v12, v8, 3 ; CHECK-NEXT: .LBB2_1: # %loopIR3.i.i ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: vl1r.v v9, (zero) +; CHECK-NEXT: vl1r.v v14, (zero) ; CHECK-NEXT: vsetivli zero, 4, e8, m1, ta, ma -; CHECK-NEXT: vrgatherei16.vv v11, v9, v8 -; CHECK-NEXT: vrgatherei16.vv v13, v9, v10 +; CHECK-NEXT: vrgatherei16.vv v15, v14, v8 +; CHECK-NEXT: vrgatherei16.vv v16, v14, v10 ; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma -; CHECK-NEXT: vand.vv v11, v11, v13 +; CHECK-NEXT: vand.vv v15, v15, v16 ; CHECK-NEXT: vsetivli zero, 4, e8, m1, ta, ma -; CHECK-NEXT: vrgatherei16.vv v13, v9, v12 +; CHECK-NEXT: vrgatherei16.vv v16, v14, v12 ; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma -; CHECK-NEXT: vand.vv v9, v11, v13 -; CHECK-NEXT: vs1r.v v9, (zero) +; CHECK-NEXT: vand.vv v14, v15, v16 +; CHECK-NEXT: vs1r.v v14, (zero) ; CHECK-NEXT: j .LBB2_1 loopIR.preheader.i.i: %v15 = tail call @llvm.experimental.stepvector.nxv1i16() diff --git a/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll b/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll --- a/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vrgatherei16-subreg-liveness.ll @@ -44,10 +44,10 @@ ; SUBREG-NEXT: # =>This Inner Loop Header: Depth=1 ; SUBREG-NEXT: vl1r.v v9, (zero) ; SUBREG-NEXT: vsetivli zero, 4, e8, m1, tu, ma -; SUBREG-NEXT: vmv1r.v v11, v12 -; SUBREG-NEXT: vrgatherei16.vv v11, v9, v10 +; SUBREG-NEXT: vmv1r.v v13, v12 +; SUBREG-NEXT: vrgatherei16.vv v13, v9, v10 ; SUBREG-NEXT: vsetvli a0, zero, e8, m1, ta, ma -; SUBREG-NEXT: vand.vv v9, v8, v11 +; SUBREG-NEXT: vand.vv v9, v8, v13 ; SUBREG-NEXT: vs1r.v v9, (zero) ; SUBREG-NEXT: j .LBB0_1 loopIR.preheader.i.i: