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); DEBUG(dbgs() << PrintReg(Reg) << ": Found " << Classes.getNumClasses() << " equivalence classes.\n"); DEBUG(dbgs() << PrintReg(Reg) << ": Splitting into newly created:"); for (unsigned I = 1, NumClasses = Classes.getNumClasses(); I < NumClasses; ++I) { unsigned NewVReg = MRI->createVirtualRegister(RegClass); LiveInterval &NewLI = LIS->createEmptyInterval(NewVReg); Intervals.push_back(&NewLI); DEBUG(dbgs() << ' ' << PrintReg(NewVReg)); } 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) == 0) 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::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); } }
/// Set each node's subtree ID to the representative ID and record connections /// between trees. void finalize() { SubtreeClasses.compress(); R.SubtreeConnections.resize(SubtreeClasses.getNumClasses()); R.SubtreeConnectLevels.resize(SubtreeClasses.getNumClasses()); DEBUG(dbgs() << R.getNumSubtrees() << " subtrees:\n"); for (unsigned Idx = 0, End = R.DFSData.size(); Idx != End; ++Idx) { R.DFSData[Idx].SubtreeID = SubtreeClasses[Idx]; DEBUG(dbgs() << " SU(" << Idx << ") in tree " << R.DFSData[Idx].SubtreeID << '\n'); } for (std::vector<std::pair<const SUnit*, const SUnit*> >::const_iterator I = ConnectionPairs.begin(), E = ConnectionPairs.end(); I != E; ++I) { unsigned PredTree = SubtreeClasses[I->first->NodeNum]; unsigned SuccTree = SubtreeClasses[I->second->NodeNum]; if (PredTree == SuccTree) continue; unsigned Depth = I->first->getDepth(); addConnection(PredTree, SuccTree, Depth); addConnection(SuccTree, PredTree, Depth); } }
/// Determine whether the DFS cross edge should be considered a subtree edge /// or a connection between subtrees. void visitCross(const SDep &PredDep, const SUnit *Succ) { if (PredDep.getKind() == SDep::Data) { // If this is a cross edge to a root, join the subtrees. This happens when // the root was first reached by a non-data dependence. unsigned NodeNum = PredDep.getSUnit()->NodeNum; unsigned PredCnt = R.DFSData[NodeNum].InstrCount; if (R.DFSData[NodeNum].SubtreeID == NodeNum && PredCnt < R.SubtreeLimit) { R.DFSData[NodeNum].SubtreeID = Succ->NodeNum; R.DFSData[Succ->NodeNum].InstrCount += PredCnt; SubtreeClasses.join(Succ->NodeNum, NodeNum); return; } } ConnectionPairs.push_back(std::make_pair(PredDep.getSUnit(), Succ)); }
/// Mark this node as either the root of a subtree or an interior /// node. Increment the parent node's instruction count. void visitPostorder(const SUnit *SU, const SDep *PredDep, const SUnit *Parent) { R.DFSData[SU->NodeNum].SubtreeID = SU->NodeNum; // Join the child to its parent if they are connected via data dependence // and do not exceed the limit. if (!Parent || PredDep->getKind() != SDep::Data) return; unsigned PredCnt = R.DFSData[SU->NodeNum].InstrCount; if (PredCnt > R.SubtreeLimit) return; R.DFSData[SU->NodeNum].SubtreeID = Parent->NodeNum; // Add the recently finished predecessor's bottom-up descendent count. R.DFSData[Parent->NodeNum].InstrCount += PredCnt; SubtreeClasses.join(Parent->NodeNum, SU->NodeNum); }