123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- //===-- RenameIndependentSubregs.cpp - Live Interval Analysis -------------===//
- //
- // 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
- //
- //===----------------------------------------------------------------------===//
- //
- /// Rename independent subregisters looks for virtual registers with
- /// independently used subregisters and renames them to new virtual registers.
- /// Example: In the following:
- /// %0:sub0<read-undef> = ...
- /// %0:sub1 = ...
- /// use %0:sub0
- /// %0:sub0 = ...
- /// use %0:sub0
- /// use %0:sub1
- /// sub0 and sub1 are never used together, and we have two independent sub0
- /// definitions. This pass will rename to:
- /// %0:sub0<read-undef> = ...
- /// %1:sub1<read-undef> = ...
- /// use %1:sub1
- /// %2:sub1<read-undef> = ...
- /// use %2:sub1
- /// use %0:sub0
- //
- //===----------------------------------------------------------------------===//
- #include "LiveRangeUtils.h"
- #include "PHIEliminationUtils.h"
- #include "llvm/CodeGen/LiveInterval.h"
- #include "llvm/CodeGen/LiveIntervals.h"
- #include "llvm/CodeGen/MachineFunctionPass.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- #include "llvm/CodeGen/MachineRegisterInfo.h"
- #include "llvm/CodeGen/Passes.h"
- #include "llvm/CodeGen/TargetInstrInfo.h"
- #include "llvm/InitializePasses.h"
- using namespace llvm;
- #define DEBUG_TYPE "rename-independent-subregs"
- namespace {
- class RenameIndependentSubregs : public MachineFunctionPass {
- public:
- static char ID;
- RenameIndependentSubregs() : MachineFunctionPass(ID) {}
- StringRef getPassName() const override {
- return "Rename Disconnected Subregister Components";
- }
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
- AU.addRequired<LiveIntervals>();
- AU.addPreserved<LiveIntervals>();
- AU.addRequired<SlotIndexes>();
- AU.addPreserved<SlotIndexes>();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
- bool runOnMachineFunction(MachineFunction &MF) override;
- private:
- struct SubRangeInfo {
- ConnectedVNInfoEqClasses ConEQ;
- LiveInterval::SubRange *SR;
- unsigned Index;
- SubRangeInfo(LiveIntervals &LIS, LiveInterval::SubRange &SR,
- unsigned Index)
- : ConEQ(LIS), SR(&SR), Index(Index) {}
- };
- /// Split unrelated subregister components and rename them to new vregs.
- bool renameComponents(LiveInterval &LI) const;
- /// Build a vector of SubRange infos and a union find set of
- /// equivalence classes.
- /// Returns true if more than 1 equivalence class was found.
- bool findComponents(IntEqClasses &Classes,
- SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
- LiveInterval &LI) const;
- /// Distribute the LiveInterval segments into the new LiveIntervals
- /// belonging to their class.
- void distribute(const IntEqClasses &Classes,
- const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
- const SmallVectorImpl<LiveInterval*> &Intervals) const;
- /// Constructs main liverange and add missing undef+dead flags.
- void computeMainRangesFixFlags(const IntEqClasses &Classes,
- const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
- const SmallVectorImpl<LiveInterval*> &Intervals) const;
- /// Rewrite Machine Operands to use the new vreg belonging to their class.
- void rewriteOperands(const IntEqClasses &Classes,
- const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
- const SmallVectorImpl<LiveInterval*> &Intervals) const;
- LiveIntervals *LIS;
- MachineRegisterInfo *MRI;
- const TargetInstrInfo *TII;
- };
- } // end anonymous namespace
- char RenameIndependentSubregs::ID;
- char &llvm::RenameIndependentSubregsID = RenameIndependentSubregs::ID;
- INITIALIZE_PASS_BEGIN(RenameIndependentSubregs, DEBUG_TYPE,
- "Rename Independent Subregisters", false, false)
- INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
- INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
- INITIALIZE_PASS_END(RenameIndependentSubregs, DEBUG_TYPE,
- "Rename Independent Subregisters", false, false)
- bool RenameIndependentSubregs::renameComponents(LiveInterval &LI) const {
- // Shortcut: We cannot have split components with a single definition.
- if (LI.valnos.size() < 2)
- return false;
- SmallVector<SubRangeInfo, 4> SubRangeInfos;
- IntEqClasses Classes;
- if (!findComponents(Classes, SubRangeInfos, LI))
- return false;
- // Create a new VReg for each class.
- unsigned Reg = LI.reg();
- const TargetRegisterClass *RegClass = MRI->getRegClass(Reg);
- SmallVector<LiveInterval*, 4> Intervals;
- Intervals.push_back(&LI);
- LLVM_DEBUG(dbgs() << printReg(Reg) << ": Found " << Classes.getNumClasses()
- << " equivalence classes.\n");
- LLVM_DEBUG(dbgs() << printReg(Reg) << ": Splitting into newly created:");
- for (unsigned I = 1, NumClasses = Classes.getNumClasses(); I < NumClasses;
- ++I) {
- Register NewVReg = MRI->createVirtualRegister(RegClass);
- LiveInterval &NewLI = LIS->createEmptyInterval(NewVReg);
- Intervals.push_back(&NewLI);
- LLVM_DEBUG(dbgs() << ' ' << printReg(NewVReg));
- }
- LLVM_DEBUG(dbgs() << '\n');
- rewriteOperands(Classes, SubRangeInfos, Intervals);
- distribute(Classes, SubRangeInfos, Intervals);
- computeMainRangesFixFlags(Classes, SubRangeInfos, Intervals);
- return true;
- }
- bool RenameIndependentSubregs::findComponents(IntEqClasses &Classes,
- SmallVectorImpl<RenameIndependentSubregs::SubRangeInfo> &SubRangeInfos,
- LiveInterval &LI) const {
- // First step: Create connected components for the VNInfos inside the
- // subranges and count the global number of such components.
- unsigned NumComponents = 0;
- for (LiveInterval::SubRange &SR : LI.subranges()) {
- SubRangeInfos.push_back(SubRangeInfo(*LIS, SR, NumComponents));
- ConnectedVNInfoEqClasses &ConEQ = SubRangeInfos.back().ConEQ;
- unsigned NumSubComponents = ConEQ.Classify(SR);
- NumComponents += NumSubComponents;
- }
- // Shortcut: With only 1 subrange, the normal separate component tests are
- // enough and we do not need to perform the union-find on the subregister
- // segments.
- if (SubRangeInfos.size() < 2)
- return false;
- // Next step: Build union-find structure over all subranges and merge classes
- // across subranges when they are affected by the same MachineOperand.
- const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo();
- Classes.grow(NumComponents);
- unsigned Reg = LI.reg();
- for (const MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) {
- if (!MO.isDef() && !MO.readsReg())
- continue;
- unsigned SubRegIdx = MO.getSubReg();
- LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubRegIdx);
- unsigned MergedID = ~0u;
- for (RenameIndependentSubregs::SubRangeInfo &SRInfo : SubRangeInfos) {
- const LiveInterval::SubRange &SR = *SRInfo.SR;
- if ((SR.LaneMask & LaneMask).none())
- continue;
- SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent());
- Pos = MO.isDef() ? Pos.getRegSlot(MO.isEarlyClobber())
- : Pos.getBaseIndex();
- const VNInfo *VNI = SR.getVNInfoAt(Pos);
- if (VNI == nullptr)
- continue;
- // Map to local representant ID.
- unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI);
- // Global ID
- unsigned ID = LocalID + SRInfo.Index;
- // Merge other sets
- MergedID = MergedID == ~0u ? ID : Classes.join(MergedID, ID);
- }
- }
- // Early exit if we ended up with a single equivalence class.
- Classes.compress();
- unsigned NumClasses = Classes.getNumClasses();
- return NumClasses > 1;
- }
- void RenameIndependentSubregs::rewriteOperands(const IntEqClasses &Classes,
- const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
- const SmallVectorImpl<LiveInterval*> &Intervals) const {
- const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo();
- unsigned Reg = Intervals[0]->reg();
- for (MachineRegisterInfo::reg_nodbg_iterator I = MRI->reg_nodbg_begin(Reg),
- E = MRI->reg_nodbg_end(); I != E; ) {
- MachineOperand &MO = *I++;
- if (!MO.isDef() && !MO.readsReg())
- continue;
- auto *MI = MO.getParent();
- SlotIndex Pos = LIS->getInstructionIndex(*MI);
- Pos = MO.isDef() ? Pos.getRegSlot(MO.isEarlyClobber())
- : Pos.getBaseIndex();
- unsigned SubRegIdx = MO.getSubReg();
- LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubRegIdx);
- unsigned ID = ~0u;
- for (const SubRangeInfo &SRInfo : SubRangeInfos) {
- const LiveInterval::SubRange &SR = *SRInfo.SR;
- if ((SR.LaneMask & LaneMask).none())
- continue;
- const VNInfo *VNI = SR.getVNInfoAt(Pos);
- if (VNI == nullptr)
- continue;
- // Map to local representant ID.
- unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI);
- // Global ID
- ID = Classes[LocalID + SRInfo.Index];
- break;
- }
- unsigned VReg = Intervals[ID]->reg();
- MO.setReg(VReg);
- if (MO.isTied() && Reg != VReg) {
- /// Undef use operands are not tracked in the equivalence class,
- /// but need to be updated if they are tied; take care to only
- /// update the tied operand.
- unsigned OperandNo = MI->getOperandNo(&MO);
- unsigned TiedIdx = MI->findTiedOperandIdx(OperandNo);
- MI->getOperand(TiedIdx).setReg(VReg);
- // above substitution breaks the iterator, so restart.
- I = MRI->reg_nodbg_begin(Reg);
- }
- }
- // TODO: We could attempt to recompute new register classes while visiting
- // the operands: Some of the split register may be fine with less constraint
- // classes than the original vreg.
- }
- void RenameIndependentSubregs::distribute(const IntEqClasses &Classes,
- const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
- const SmallVectorImpl<LiveInterval*> &Intervals) const {
- unsigned NumClasses = Classes.getNumClasses();
- SmallVector<unsigned, 8> VNIMapping;
- SmallVector<LiveInterval::SubRange*, 8> SubRanges;
- BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
- for (const SubRangeInfo &SRInfo : SubRangeInfos) {
- LiveInterval::SubRange &SR = *SRInfo.SR;
- unsigned NumValNos = SR.valnos.size();
- VNIMapping.clear();
- VNIMapping.reserve(NumValNos);
- SubRanges.clear();
- SubRanges.resize(NumClasses-1, nullptr);
- for (unsigned I = 0; I < NumValNos; ++I) {
- const VNInfo &VNI = *SR.valnos[I];
- unsigned LocalID = SRInfo.ConEQ.getEqClass(&VNI);
- unsigned ID = Classes[LocalID + SRInfo.Index];
- VNIMapping.push_back(ID);
- if (ID > 0 && SubRanges[ID-1] == nullptr)
- SubRanges[ID-1] = Intervals[ID]->createSubRange(Allocator, SR.LaneMask);
- }
- DistributeRange(SR, SubRanges.data(), VNIMapping);
- }
- }
- static bool subRangeLiveAt(const LiveInterval &LI, SlotIndex Pos) {
- for (const LiveInterval::SubRange &SR : LI.subranges()) {
- if (SR.liveAt(Pos))
- return true;
- }
- return false;
- }
- void RenameIndependentSubregs::computeMainRangesFixFlags(
- const IntEqClasses &Classes,
- const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
- const SmallVectorImpl<LiveInterval*> &Intervals) const {
- BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
- const SlotIndexes &Indexes = *LIS->getSlotIndexes();
- for (size_t I = 0, E = Intervals.size(); I < E; ++I) {
- LiveInterval &LI = *Intervals[I];
- unsigned Reg = LI.reg();
- LI.removeEmptySubRanges();
- // There must be a def (or live-in) before every use. Splitting vregs may
- // violate this principle as the splitted vreg may not have a definition on
- // every path. Fix this by creating IMPLICIT_DEF instruction as necessary.
- for (const LiveInterval::SubRange &SR : LI.subranges()) {
- // Search for "PHI" value numbers in the subranges. We must find a live
- // value in each predecessor block, add an IMPLICIT_DEF where it is
- // missing.
- for (unsigned I = 0; I < SR.valnos.size(); ++I) {
- const VNInfo &VNI = *SR.valnos[I];
- if (VNI.isUnused() || !VNI.isPHIDef())
- continue;
- SlotIndex Def = VNI.def;
- MachineBasicBlock &MBB = *Indexes.getMBBFromIndex(Def);
- for (MachineBasicBlock *PredMBB : MBB.predecessors()) {
- SlotIndex PredEnd = Indexes.getMBBEndIdx(PredMBB);
- if (subRangeLiveAt(LI, PredEnd.getPrevSlot()))
- continue;
- MachineBasicBlock::iterator InsertPos =
- llvm::findPHICopyInsertPoint(PredMBB, &MBB, Reg);
- const MCInstrDesc &MCDesc = TII->get(TargetOpcode::IMPLICIT_DEF);
- MachineInstrBuilder ImpDef = BuildMI(*PredMBB, InsertPos,
- DebugLoc(), MCDesc, Reg);
- SlotIndex DefIdx = LIS->InsertMachineInstrInMaps(*ImpDef);
- SlotIndex RegDefIdx = DefIdx.getRegSlot();
- for (LiveInterval::SubRange &SR : LI.subranges()) {
- VNInfo *SRVNI = SR.getNextValue(RegDefIdx, Allocator);
- SR.addSegment(LiveRange::Segment(RegDefIdx, PredEnd, SRVNI));
- }
- }
- }
- }
- for (MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) {
- if (!MO.isDef())
- continue;
- unsigned SubRegIdx = MO.getSubReg();
- if (SubRegIdx == 0)
- continue;
- // After assigning the new vreg we may not have any other sublanes living
- // in and out of the instruction anymore. We need to add new dead and
- // undef flags in these cases.
- if (!MO.isUndef()) {
- SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent());
- if (!subRangeLiveAt(LI, Pos))
- MO.setIsUndef();
- }
- if (!MO.isDead()) {
- SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent()).getDeadSlot();
- if (!subRangeLiveAt(LI, Pos))
- MO.setIsDead();
- }
- }
- if (I == 0)
- LI.clear();
- LIS->constructMainRangeFromSubranges(LI);
- // A def of a subregister may be a use of other register lanes. Replacing
- // such a def with a def of a different register will eliminate the use,
- // and may cause the recorded live range to be larger than the actual
- // liveness in the program IR.
- LIS->shrinkToUses(&LI);
- }
- }
- bool RenameIndependentSubregs::runOnMachineFunction(MachineFunction &MF) {
- // Skip renaming if liveness of subregister is not tracked.
- MRI = &MF.getRegInfo();
- if (!MRI->subRegLivenessEnabled())
- return false;
- LLVM_DEBUG(dbgs() << "Renaming independent subregister live ranges in "
- << MF.getName() << '\n');
- LIS = &getAnalysis<LiveIntervals>();
- TII = MF.getSubtarget().getInstrInfo();
- // Iterate over all vregs. Note that we query getNumVirtRegs() the newly
- // created vregs end up with higher numbers but do not need to be visited as
- // there can't be any further splitting.
- bool Changed = false;
- for (size_t I = 0, E = MRI->getNumVirtRegs(); I < E; ++I) {
- unsigned Reg = Register::index2VirtReg(I);
- if (!LIS->hasInterval(Reg))
- continue;
- LiveInterval &LI = LIS->getInterval(Reg);
- if (!LI.hasSubRanges())
- continue;
- Changed |= renameComponents(LI);
- }
- return Changed;
- }
|