xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/RenameIndependentSubregs.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- RenameIndependentSubregs.cpp - Live Interval Analysis -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// Rename independent subregisters looks for virtual registers with
100b57cec5SDimitry Andric /// independently used subregisters and renames them to new virtual registers.
110b57cec5SDimitry Andric /// Example: In the following:
120b57cec5SDimitry Andric ///   %0:sub0<read-undef> = ...
130b57cec5SDimitry Andric ///   %0:sub1 = ...
140b57cec5SDimitry Andric ///   use %0:sub0
150b57cec5SDimitry Andric ///   %0:sub0 = ...
160b57cec5SDimitry Andric ///   use %0:sub0
170b57cec5SDimitry Andric ///   use %0:sub1
180b57cec5SDimitry Andric /// sub0 and sub1 are never used together, and we have two independent sub0
190b57cec5SDimitry Andric /// definitions. This pass will rename to:
200b57cec5SDimitry Andric ///   %0:sub0<read-undef> = ...
210b57cec5SDimitry Andric ///   %1:sub1<read-undef> = ...
220b57cec5SDimitry Andric ///   use %1:sub1
230b57cec5SDimitry Andric ///   %2:sub1<read-undef> = ...
240b57cec5SDimitry Andric ///   use %2:sub1
250b57cec5SDimitry Andric ///   use %0:sub0
260b57cec5SDimitry Andric //
270b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #include "LiveRangeUtils.h"
300b57cec5SDimitry Andric #include "PHIEliminationUtils.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
360b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
37480093f4SDimitry Andric #include "llvm/InitializePasses.h"
3881ad6265SDimitry Andric #include "llvm/Pass.h"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using namespace llvm;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric #define DEBUG_TYPE "rename-independent-subregs"
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric namespace {
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric class RenameIndependentSubregs : public MachineFunctionPass {
470b57cec5SDimitry Andric public:
480b57cec5SDimitry Andric   static char ID;
RenameIndependentSubregs()490b57cec5SDimitry Andric   RenameIndependentSubregs() : MachineFunctionPass(ID) {}
500b57cec5SDimitry Andric 
getPassName() const510b57cec5SDimitry Andric   StringRef getPassName() const override {
520b57cec5SDimitry Andric     return "Rename Disconnected Subregister Components";
530b57cec5SDimitry Andric   }
540b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const550b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
560b57cec5SDimitry Andric     AU.setPreservesCFG();
57*0fca6ea1SDimitry Andric     AU.addRequired<LiveIntervalsWrapperPass>();
58*0fca6ea1SDimitry Andric     AU.addPreserved<LiveIntervalsWrapperPass>();
59*0fca6ea1SDimitry Andric     AU.addRequired<SlotIndexesWrapperPass>();
60*0fca6ea1SDimitry Andric     AU.addPreserved<SlotIndexesWrapperPass>();
610b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric private:
670b57cec5SDimitry Andric   struct SubRangeInfo {
680b57cec5SDimitry Andric     ConnectedVNInfoEqClasses ConEQ;
690b57cec5SDimitry Andric     LiveInterval::SubRange *SR;
700b57cec5SDimitry Andric     unsigned Index;
710b57cec5SDimitry Andric 
SubRangeInfo__anon60dd69b50111::RenameIndependentSubregs::SubRangeInfo720b57cec5SDimitry Andric     SubRangeInfo(LiveIntervals &LIS, LiveInterval::SubRange &SR,
730b57cec5SDimitry Andric                  unsigned Index)
740b57cec5SDimitry Andric       : ConEQ(LIS), SR(&SR), Index(Index) {}
750b57cec5SDimitry Andric   };
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   /// Split unrelated subregister components and rename them to new vregs.
780b57cec5SDimitry Andric   bool renameComponents(LiveInterval &LI) const;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   /// Build a vector of SubRange infos and a union find set of
810b57cec5SDimitry Andric   /// equivalence classes.
820b57cec5SDimitry Andric   /// Returns true if more than 1 equivalence class was found.
830b57cec5SDimitry Andric   bool findComponents(IntEqClasses &Classes,
840b57cec5SDimitry Andric                       SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
850b57cec5SDimitry Andric                       LiveInterval &LI) const;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   /// Distribute the LiveInterval segments into the new LiveIntervals
880b57cec5SDimitry Andric   /// belonging to their class.
890b57cec5SDimitry Andric   void distribute(const IntEqClasses &Classes,
900b57cec5SDimitry Andric                   const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
910b57cec5SDimitry Andric                   const SmallVectorImpl<LiveInterval*> &Intervals) const;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   /// Constructs main liverange and add missing undef+dead flags.
940b57cec5SDimitry Andric   void computeMainRangesFixFlags(const IntEqClasses &Classes,
950b57cec5SDimitry Andric       const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
960b57cec5SDimitry Andric       const SmallVectorImpl<LiveInterval*> &Intervals) const;
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   /// Rewrite Machine Operands to use the new vreg belonging to their class.
990b57cec5SDimitry Andric   void rewriteOperands(const IntEqClasses &Classes,
1000b57cec5SDimitry Andric                        const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
1010b57cec5SDimitry Andric                        const SmallVectorImpl<LiveInterval*> &Intervals) const;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric 
10406c3fb27SDimitry Andric   LiveIntervals *LIS = nullptr;
10506c3fb27SDimitry Andric   MachineRegisterInfo *MRI = nullptr;
10606c3fb27SDimitry Andric   const TargetInstrInfo *TII = nullptr;
1070b57cec5SDimitry Andric };
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric } // end anonymous namespace
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric char RenameIndependentSubregs::ID;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric char &llvm::RenameIndependentSubregsID = RenameIndependentSubregs::ID;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(RenameIndependentSubregs, DEBUG_TYPE,
1160b57cec5SDimitry Andric                       "Rename Independent Subregisters", false, false)
INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass)117*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass)
118*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
1190b57cec5SDimitry Andric INITIALIZE_PASS_END(RenameIndependentSubregs, DEBUG_TYPE,
1200b57cec5SDimitry Andric                     "Rename Independent Subregisters", false, false)
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric bool RenameIndependentSubregs::renameComponents(LiveInterval &LI) const {
1230b57cec5SDimitry Andric   // Shortcut: We cannot have split components with a single definition.
1240b57cec5SDimitry Andric   if (LI.valnos.size() < 2)
1250b57cec5SDimitry Andric     return false;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   SmallVector<SubRangeInfo, 4> SubRangeInfos;
1280b57cec5SDimitry Andric   IntEqClasses Classes;
1290b57cec5SDimitry Andric   if (!findComponents(Classes, SubRangeInfos, LI))
1300b57cec5SDimitry Andric     return false;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   // Create a new VReg for each class.
133bdd1243dSDimitry Andric   Register Reg = LI.reg();
1340b57cec5SDimitry Andric   const TargetRegisterClass *RegClass = MRI->getRegClass(Reg);
1350b57cec5SDimitry Andric   SmallVector<LiveInterval*, 4> Intervals;
1360b57cec5SDimitry Andric   Intervals.push_back(&LI);
1370b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << printReg(Reg) << ": Found " << Classes.getNumClasses()
1380b57cec5SDimitry Andric                     << " equivalence classes.\n");
1390b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << printReg(Reg) << ": Splitting into newly created:");
1400b57cec5SDimitry Andric   for (unsigned I = 1, NumClasses = Classes.getNumClasses(); I < NumClasses;
1410b57cec5SDimitry Andric        ++I) {
1428bcb0991SDimitry Andric     Register NewVReg = MRI->createVirtualRegister(RegClass);
1430b57cec5SDimitry Andric     LiveInterval &NewLI = LIS->createEmptyInterval(NewVReg);
1440b57cec5SDimitry Andric     Intervals.push_back(&NewLI);
1450b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ' ' << printReg(NewVReg));
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << '\n');
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   rewriteOperands(Classes, SubRangeInfos, Intervals);
1500b57cec5SDimitry Andric   distribute(Classes, SubRangeInfos, Intervals);
1510b57cec5SDimitry Andric   computeMainRangesFixFlags(Classes, SubRangeInfos, Intervals);
1520b57cec5SDimitry Andric   return true;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
findComponents(IntEqClasses & Classes,SmallVectorImpl<RenameIndependentSubregs::SubRangeInfo> & SubRangeInfos,LiveInterval & LI) const1550b57cec5SDimitry Andric bool RenameIndependentSubregs::findComponents(IntEqClasses &Classes,
1560b57cec5SDimitry Andric     SmallVectorImpl<RenameIndependentSubregs::SubRangeInfo> &SubRangeInfos,
1570b57cec5SDimitry Andric     LiveInterval &LI) const {
1580b57cec5SDimitry Andric   // First step: Create connected components for the VNInfos inside the
1590b57cec5SDimitry Andric   // subranges and count the global number of such components.
1600b57cec5SDimitry Andric   unsigned NumComponents = 0;
1610b57cec5SDimitry Andric   for (LiveInterval::SubRange &SR : LI.subranges()) {
1620b57cec5SDimitry Andric     SubRangeInfos.push_back(SubRangeInfo(*LIS, SR, NumComponents));
1630b57cec5SDimitry Andric     ConnectedVNInfoEqClasses &ConEQ = SubRangeInfos.back().ConEQ;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     unsigned NumSubComponents = ConEQ.Classify(SR);
1660b57cec5SDimitry Andric     NumComponents += NumSubComponents;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric   // Shortcut: With only 1 subrange, the normal separate component tests are
1690b57cec5SDimitry Andric   // enough and we do not need to perform the union-find on the subregister
1700b57cec5SDimitry Andric   // segments.
1710b57cec5SDimitry Andric   if (SubRangeInfos.size() < 2)
1720b57cec5SDimitry Andric     return false;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   // Next step: Build union-find structure over all subranges and merge classes
1750b57cec5SDimitry Andric   // across subranges when they are affected by the same MachineOperand.
1760b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo();
1770b57cec5SDimitry Andric   Classes.grow(NumComponents);
178bdd1243dSDimitry Andric   Register Reg = LI.reg();
1790b57cec5SDimitry Andric   for (const MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) {
1800b57cec5SDimitry Andric     if (!MO.isDef() && !MO.readsReg())
1810b57cec5SDimitry Andric       continue;
1820b57cec5SDimitry Andric     unsigned SubRegIdx = MO.getSubReg();
1830b57cec5SDimitry Andric     LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubRegIdx);
1840b57cec5SDimitry Andric     unsigned MergedID = ~0u;
1850b57cec5SDimitry Andric     for (RenameIndependentSubregs::SubRangeInfo &SRInfo : SubRangeInfos) {
1860b57cec5SDimitry Andric       const LiveInterval::SubRange &SR = *SRInfo.SR;
1870b57cec5SDimitry Andric       if ((SR.LaneMask & LaneMask).none())
1880b57cec5SDimitry Andric         continue;
1890b57cec5SDimitry Andric       SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent());
1900b57cec5SDimitry Andric       Pos = MO.isDef() ? Pos.getRegSlot(MO.isEarlyClobber())
1910b57cec5SDimitry Andric                        : Pos.getBaseIndex();
1920b57cec5SDimitry Andric       const VNInfo *VNI = SR.getVNInfoAt(Pos);
1930b57cec5SDimitry Andric       if (VNI == nullptr)
1940b57cec5SDimitry Andric         continue;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric       // Map to local representant ID.
1970b57cec5SDimitry Andric       unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI);
1980b57cec5SDimitry Andric       // Global ID
1990b57cec5SDimitry Andric       unsigned ID = LocalID + SRInfo.Index;
2000b57cec5SDimitry Andric       // Merge other sets
2010b57cec5SDimitry Andric       MergedID = MergedID == ~0u ? ID : Classes.join(MergedID, ID);
2020b57cec5SDimitry Andric     }
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   // Early exit if we ended up with a single equivalence class.
2060b57cec5SDimitry Andric   Classes.compress();
2070b57cec5SDimitry Andric   unsigned NumClasses = Classes.getNumClasses();
2080b57cec5SDimitry Andric   return NumClasses > 1;
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
rewriteOperands(const IntEqClasses & Classes,const SmallVectorImpl<SubRangeInfo> & SubRangeInfos,const SmallVectorImpl<LiveInterval * > & Intervals) const2110b57cec5SDimitry Andric void RenameIndependentSubregs::rewriteOperands(const IntEqClasses &Classes,
2120b57cec5SDimitry Andric     const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
2130b57cec5SDimitry Andric     const SmallVectorImpl<LiveInterval*> &Intervals) const {
2140b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo();
215e8d8bef9SDimitry Andric   unsigned Reg = Intervals[0]->reg();
2160b57cec5SDimitry Andric   for (MachineRegisterInfo::reg_nodbg_iterator I = MRI->reg_nodbg_begin(Reg),
2170b57cec5SDimitry Andric        E = MRI->reg_nodbg_end(); I != E; ) {
2180b57cec5SDimitry Andric     MachineOperand &MO = *I++;
2190b57cec5SDimitry Andric     if (!MO.isDef() && !MO.readsReg())
2200b57cec5SDimitry Andric       continue;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric     auto *MI = MO.getParent();
2230b57cec5SDimitry Andric     SlotIndex Pos = LIS->getInstructionIndex(*MI);
2240b57cec5SDimitry Andric     Pos = MO.isDef() ? Pos.getRegSlot(MO.isEarlyClobber())
2250b57cec5SDimitry Andric                      : Pos.getBaseIndex();
2260b57cec5SDimitry Andric     unsigned SubRegIdx = MO.getSubReg();
2270b57cec5SDimitry Andric     LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubRegIdx);
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     unsigned ID = ~0u;
2300b57cec5SDimitry Andric     for (const SubRangeInfo &SRInfo : SubRangeInfos) {
2310b57cec5SDimitry Andric       const LiveInterval::SubRange &SR = *SRInfo.SR;
2320b57cec5SDimitry Andric       if ((SR.LaneMask & LaneMask).none())
2330b57cec5SDimitry Andric         continue;
2340b57cec5SDimitry Andric       const VNInfo *VNI = SR.getVNInfoAt(Pos);
2350b57cec5SDimitry Andric       if (VNI == nullptr)
2360b57cec5SDimitry Andric         continue;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric       // Map to local representant ID.
2390b57cec5SDimitry Andric       unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI);
2400b57cec5SDimitry Andric       // Global ID
2410b57cec5SDimitry Andric       ID = Classes[LocalID + SRInfo.Index];
2420b57cec5SDimitry Andric       break;
2430b57cec5SDimitry Andric     }
2440b57cec5SDimitry Andric 
245e8d8bef9SDimitry Andric     unsigned VReg = Intervals[ID]->reg();
2460b57cec5SDimitry Andric     MO.setReg(VReg);
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric     if (MO.isTied() && Reg != VReg) {
2490b57cec5SDimitry Andric       /// Undef use operands are not tracked in the equivalence class,
2500b57cec5SDimitry Andric       /// but need to be updated if they are tied; take care to only
2510b57cec5SDimitry Andric       /// update the tied operand.
25206c3fb27SDimitry Andric       unsigned OperandNo = MO.getOperandNo();
2530b57cec5SDimitry Andric       unsigned TiedIdx = MI->findTiedOperandIdx(OperandNo);
2540b57cec5SDimitry Andric       MI->getOperand(TiedIdx).setReg(VReg);
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric       // above substitution breaks the iterator, so restart.
2570b57cec5SDimitry Andric       I = MRI->reg_nodbg_begin(Reg);
2580b57cec5SDimitry Andric     }
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric   // TODO: We could attempt to recompute new register classes while visiting
2610b57cec5SDimitry Andric   // the operands: Some of the split register may be fine with less constraint
2620b57cec5SDimitry Andric   // classes than the original vreg.
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
distribute(const IntEqClasses & Classes,const SmallVectorImpl<SubRangeInfo> & SubRangeInfos,const SmallVectorImpl<LiveInterval * > & Intervals) const2650b57cec5SDimitry Andric void RenameIndependentSubregs::distribute(const IntEqClasses &Classes,
2660b57cec5SDimitry Andric     const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
2670b57cec5SDimitry Andric     const SmallVectorImpl<LiveInterval*> &Intervals) const {
2680b57cec5SDimitry Andric   unsigned NumClasses = Classes.getNumClasses();
2690b57cec5SDimitry Andric   SmallVector<unsigned, 8> VNIMapping;
2700b57cec5SDimitry Andric   SmallVector<LiveInterval::SubRange*, 8> SubRanges;
2710b57cec5SDimitry Andric   BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
2720b57cec5SDimitry Andric   for (const SubRangeInfo &SRInfo : SubRangeInfos) {
2730b57cec5SDimitry Andric     LiveInterval::SubRange &SR = *SRInfo.SR;
2740b57cec5SDimitry Andric     unsigned NumValNos = SR.valnos.size();
2750b57cec5SDimitry Andric     VNIMapping.clear();
2760b57cec5SDimitry Andric     VNIMapping.reserve(NumValNos);
2770b57cec5SDimitry Andric     SubRanges.clear();
2780b57cec5SDimitry Andric     SubRanges.resize(NumClasses-1, nullptr);
2790b57cec5SDimitry Andric     for (unsigned I = 0; I < NumValNos; ++I) {
2800b57cec5SDimitry Andric       const VNInfo &VNI = *SR.valnos[I];
2810b57cec5SDimitry Andric       unsigned LocalID = SRInfo.ConEQ.getEqClass(&VNI);
2820b57cec5SDimitry Andric       unsigned ID = Classes[LocalID + SRInfo.Index];
2830b57cec5SDimitry Andric       VNIMapping.push_back(ID);
2840b57cec5SDimitry Andric       if (ID > 0 && SubRanges[ID-1] == nullptr)
2850b57cec5SDimitry Andric         SubRanges[ID-1] = Intervals[ID]->createSubRange(Allocator, SR.LaneMask);
2860b57cec5SDimitry Andric     }
2870b57cec5SDimitry Andric     DistributeRange(SR, SubRanges.data(), VNIMapping);
2880b57cec5SDimitry Andric   }
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
subRangeLiveAt(const LiveInterval & LI,SlotIndex Pos)2910b57cec5SDimitry Andric static bool subRangeLiveAt(const LiveInterval &LI, SlotIndex Pos) {
2920b57cec5SDimitry Andric   for (const LiveInterval::SubRange &SR : LI.subranges()) {
2930b57cec5SDimitry Andric     if (SR.liveAt(Pos))
2940b57cec5SDimitry Andric       return true;
2950b57cec5SDimitry Andric   }
2960b57cec5SDimitry Andric   return false;
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
computeMainRangesFixFlags(const IntEqClasses & Classes,const SmallVectorImpl<SubRangeInfo> & SubRangeInfos,const SmallVectorImpl<LiveInterval * > & Intervals) const2990b57cec5SDimitry Andric void RenameIndependentSubregs::computeMainRangesFixFlags(
3000b57cec5SDimitry Andric     const IntEqClasses &Classes,
3010b57cec5SDimitry Andric     const SmallVectorImpl<SubRangeInfo> &SubRangeInfos,
3020b57cec5SDimitry Andric     const SmallVectorImpl<LiveInterval*> &Intervals) const {
3030b57cec5SDimitry Andric   BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
3040b57cec5SDimitry Andric   const SlotIndexes &Indexes = *LIS->getSlotIndexes();
3050b57cec5SDimitry Andric   for (size_t I = 0, E = Intervals.size(); I < E; ++I) {
3060b57cec5SDimitry Andric     LiveInterval &LI = *Intervals[I];
307bdd1243dSDimitry Andric     Register Reg = LI.reg();
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric     LI.removeEmptySubRanges();
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric     // There must be a def (or live-in) before every use. Splitting vregs may
3120b57cec5SDimitry Andric     // violate this principle as the splitted vreg may not have a definition on
3130b57cec5SDimitry Andric     // every path. Fix this by creating IMPLICIT_DEF instruction as necessary.
3140b57cec5SDimitry Andric     for (const LiveInterval::SubRange &SR : LI.subranges()) {
3150b57cec5SDimitry Andric       // Search for "PHI" value numbers in the subranges. We must find a live
3160b57cec5SDimitry Andric       // value in each predecessor block, add an IMPLICIT_DEF where it is
3170b57cec5SDimitry Andric       // missing.
3180b57cec5SDimitry Andric       for (unsigned I = 0; I < SR.valnos.size(); ++I) {
3190b57cec5SDimitry Andric         const VNInfo &VNI = *SR.valnos[I];
3200b57cec5SDimitry Andric         if (VNI.isUnused() || !VNI.isPHIDef())
3210b57cec5SDimitry Andric           continue;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric         SlotIndex Def = VNI.def;
3240b57cec5SDimitry Andric         MachineBasicBlock &MBB = *Indexes.getMBBFromIndex(Def);
3250b57cec5SDimitry Andric         for (MachineBasicBlock *PredMBB : MBB.predecessors()) {
3260b57cec5SDimitry Andric           SlotIndex PredEnd = Indexes.getMBBEndIdx(PredMBB);
3270b57cec5SDimitry Andric           if (subRangeLiveAt(LI, PredEnd.getPrevSlot()))
3280b57cec5SDimitry Andric             continue;
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric           MachineBasicBlock::iterator InsertPos =
3310b57cec5SDimitry Andric             llvm::findPHICopyInsertPoint(PredMBB, &MBB, Reg);
3320b57cec5SDimitry Andric           const MCInstrDesc &MCDesc = TII->get(TargetOpcode::IMPLICIT_DEF);
3330b57cec5SDimitry Andric           MachineInstrBuilder ImpDef = BuildMI(*PredMBB, InsertPos,
3340b57cec5SDimitry Andric                                                DebugLoc(), MCDesc, Reg);
3350b57cec5SDimitry Andric           SlotIndex DefIdx = LIS->InsertMachineInstrInMaps(*ImpDef);
3360b57cec5SDimitry Andric           SlotIndex RegDefIdx = DefIdx.getRegSlot();
337*0fca6ea1SDimitry Andric           LaneBitmask Mask = MRI->getMaxLaneMaskForVReg(Reg);
3380b57cec5SDimitry Andric           for (LiveInterval::SubRange &SR : LI.subranges()) {
339*0fca6ea1SDimitry Andric             Mask = Mask & ~SR.LaneMask;
3400b57cec5SDimitry Andric             VNInfo *SRVNI = SR.getNextValue(RegDefIdx, Allocator);
3410b57cec5SDimitry Andric             SR.addSegment(LiveRange::Segment(RegDefIdx, PredEnd, SRVNI));
3420b57cec5SDimitry Andric           }
343*0fca6ea1SDimitry Andric 
344*0fca6ea1SDimitry Andric           if (!Mask.none()) {
345*0fca6ea1SDimitry Andric             LiveInterval::SubRange *SR = LI.createSubRange(Allocator, Mask);
346*0fca6ea1SDimitry Andric             SR->createDeadDef(RegDefIdx, Allocator);
347*0fca6ea1SDimitry Andric           }
3480b57cec5SDimitry Andric         }
3490b57cec5SDimitry Andric       }
3500b57cec5SDimitry Andric     }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric     for (MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) {
3530b57cec5SDimitry Andric       if (!MO.isDef())
3540b57cec5SDimitry Andric         continue;
3550b57cec5SDimitry Andric       unsigned SubRegIdx = MO.getSubReg();
3560b57cec5SDimitry Andric       if (SubRegIdx == 0)
3570b57cec5SDimitry Andric         continue;
3580b57cec5SDimitry Andric       // After assigning the new vreg we may not have any other sublanes living
3590b57cec5SDimitry Andric       // in and out of the instruction anymore. We need to add new dead and
3600b57cec5SDimitry Andric       // undef flags in these cases.
3610b57cec5SDimitry Andric       if (!MO.isUndef()) {
3620b57cec5SDimitry Andric         SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent());
3630b57cec5SDimitry Andric         if (!subRangeLiveAt(LI, Pos))
3640b57cec5SDimitry Andric           MO.setIsUndef();
3650b57cec5SDimitry Andric       }
3660b57cec5SDimitry Andric       if (!MO.isDead()) {
3670b57cec5SDimitry Andric         SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent()).getDeadSlot();
3680b57cec5SDimitry Andric         if (!subRangeLiveAt(LI, Pos))
3690b57cec5SDimitry Andric           MO.setIsDead();
3700b57cec5SDimitry Andric       }
3710b57cec5SDimitry Andric     }
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric     if (I == 0)
3740b57cec5SDimitry Andric       LI.clear();
3750b57cec5SDimitry Andric     LIS->constructMainRangeFromSubranges(LI);
3760b57cec5SDimitry Andric     // A def of a subregister may be a use of other register lanes. Replacing
3770b57cec5SDimitry Andric     // such a def with a def of a different register will eliminate the use,
3780b57cec5SDimitry Andric     // and may cause the recorded live range to be larger than the actual
3790b57cec5SDimitry Andric     // liveness in the program IR.
3800b57cec5SDimitry Andric     LIS->shrinkToUses(&LI);
3810b57cec5SDimitry Andric   }
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)3840b57cec5SDimitry Andric bool RenameIndependentSubregs::runOnMachineFunction(MachineFunction &MF) {
3850b57cec5SDimitry Andric   // Skip renaming if liveness of subregister is not tracked.
3860b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
3870b57cec5SDimitry Andric   if (!MRI->subRegLivenessEnabled())
3880b57cec5SDimitry Andric     return false;
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Renaming independent subregister live ranges in "
3910b57cec5SDimitry Andric                     << MF.getName() << '\n');
3920b57cec5SDimitry Andric 
393*0fca6ea1SDimitry Andric   LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
3940b57cec5SDimitry Andric   TII = MF.getSubtarget().getInstrInfo();
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric   // Iterate over all vregs. Note that we query getNumVirtRegs() the newly
3970b57cec5SDimitry Andric   // created vregs end up with higher numbers but do not need to be visited as
3980b57cec5SDimitry Andric   // there can't be any further splitting.
3990b57cec5SDimitry Andric   bool Changed = false;
4000b57cec5SDimitry Andric   for (size_t I = 0, E = MRI->getNumVirtRegs(); I < E; ++I) {
401bdd1243dSDimitry Andric     Register Reg = Register::index2VirtReg(I);
4020b57cec5SDimitry Andric     if (!LIS->hasInterval(Reg))
4030b57cec5SDimitry Andric       continue;
4040b57cec5SDimitry Andric     LiveInterval &LI = LIS->getInterval(Reg);
4050b57cec5SDimitry Andric     if (!LI.hasSubRanges())
4060b57cec5SDimitry Andric       continue;
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     Changed |= renameComponents(LI);
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   return Changed;
4120b57cec5SDimitry Andric }
413