[llvm] r271345 - CodeGen: Refactor renameDisconnectedComponents() as a pass

Matthias Braun via llvm-commits llvm-commits at lists.llvm.org
Tue May 31 15:38:07 PDT 2016


Author: matze
Date: Tue May 31 17:38:06 2016
New Revision: 271345

URL: http://llvm.org/viewvc/llvm-project?rev=271345&view=rev
Log:
CodeGen: Refactor renameDisconnectedComponents() as a pass

Refactor LiveIntervals::renameDisconnectedComponents() to be a pass.
Also change the name to "RenameIndependentSubregs":

- renameDisconnectedComponents() worked on a MachineFunction at a time
  so it is a natural candidate for a machine function pass.

- The algorithm is testable with a .mir test now.

- This also fixes a problem where the lazy renaming as part of the
  MachineScheduler introduced IMPLICIT_DEF instructions after the number
  of a nodes in a region were counted leading to a mismatch.

Differential Revision: http://reviews.llvm.org/D20507

Added:
    llvm/trunk/lib/CodeGen/LiveRangeUtils.h
    llvm/trunk/lib/CodeGen/RenameIndependentSubregs.cpp
    llvm/trunk/test/CodeGen/AMDGPU/rename-independent-subregs.mir
Modified:
    llvm/trunk/include/llvm/CodeGen/LiveInterval.h
    llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h
    llvm/trunk/include/llvm/CodeGen/Passes.h
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/lib/CodeGen/CMakeLists.txt
    llvm/trunk/lib/CodeGen/CodeGen.cpp
    llvm/trunk/lib/CodeGen/LiveInterval.cpp
    llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp
    llvm/trunk/lib/CodeGen/MachineScheduler.cpp
    llvm/trunk/lib/CodeGen/TargetPassConfig.cpp

Modified: llvm/trunk/include/llvm/CodeGen/LiveInterval.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveInterval.h?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/LiveInterval.h (original)
+++ llvm/trunk/include/llvm/CodeGen/LiveInterval.h Tue May 31 17:38:06 2016
@@ -864,77 +864,5 @@ namespace llvm {
     void Distribute(LiveInterval &LI, LiveInterval *LIV[],
                     MachineRegisterInfo &MRI);
   };
-
-  /// Helper class that can divide MachineOperands of a virtual register into
-  /// equivalence classes of connected components.
-  /// MachineOperands belong to the same equivalence class when they are part of
-  /// the same SubRange segment or adjacent segments (adjacent in control
-  /// flow); Different subranges affected by the same MachineOperand belong to
-  /// the same equivalence class.
-  ///
-  /// Example:
-  ///   vreg0:sub0 = ...
-  ///   vreg0:sub1 = ...
-  ///   vreg0:sub2 = ...
-  ///   ...
-  ///   xxx        = op vreg0:sub1
-  ///   vreg0:sub1 = ...
-  ///   store vreg0:sub0_sub1
-  ///
-  /// The example contains 3 different equivalence classes:
-  ///   - One for the (dead) vreg0:sub2 definition
-  ///   - One containing the first vreg0:sub1 definition and its use,
-  ///     but not the second definition!
-  ///   - The remaining class contains all other operands involving vreg0.
-  ///
-  /// We provide a utility function here to rename disjunct classes to different
-  /// virtual registers.
-  class ConnectedSubRegClasses {
-    LiveIntervals &LIS;
-    MachineRegisterInfo &MRI;
-    const TargetInstrInfo &TII;
-
-  public:
-    ConnectedSubRegClasses(LiveIntervals &LIS, MachineRegisterInfo &MRI,
-                           const TargetInstrInfo &TII)
-      : LIS(LIS), MRI(MRI), TII(TII) {}
-
-    /// Split unrelated subregister components and rename them to new vregs.
-    void renameComponents(LiveInterval &LI) const;
-
-  private:
-    struct SubRangeInfo {
-      ConnectedVNInfoEqClasses ConEQ;
-      LiveInterval::SubRange *SR;
-      unsigned Index;
-
-      SubRangeInfo(LiveIntervals &LIS, LiveInterval::SubRange &SR,
-                   unsigned Index)
-        : ConEQ(LIS), SR(&SR), Index(Index) {}
-    };
-
-    /// \brief 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;
-
-    /// \brief 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;
-
-    /// \brief 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;
-  };
 }
 #endif

Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h (original)
+++ llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h Tue May 31 17:38:06 2016
@@ -405,11 +405,6 @@ extern cl::opt<bool> UseSegmentSetForPhy
     void splitSeparateComponents(LiveInterval &LI,
                                  SmallVectorImpl<LiveInterval*> &SplitLIs);
 
-    /// Assure dead subregister definitions have their own vreg assigned.
-    /// This calls ConnectedSubRegClasses::splitSeparateSubRegComponent()
-    /// on each virtual register.
-    void renameDisconnectedComponents();
-
     /// For live interval \p LI with correct SubRanges construct matching
     /// information for the main live range. Expects the main live range to not
     /// have any segments or value numbers.

Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/Passes.h Tue May 31 17:38:06 2016
@@ -356,6 +356,11 @@ namespace llvm {
   /// This pass splits the stack into a safe stack and an unsafe stack to
   /// protect against stack-based overflow vulnerabilities.
   FunctionPass *createSafeStackPass(const TargetMachine *TM = nullptr);
+
+  /// This pass detects subregister lanes in a virtual register that are used
+  /// independently of other lanes and splits them into separate virtual
+  /// registers.
+  extern char &RenameIndependentSubregsID;
 } // End llvm namespace
 
 /// Target machine pass initializer for passes with dependencies. Use with

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Tue May 31 17:38:06 2016
@@ -266,6 +266,7 @@ void initializeRegionOnlyPrinterPass(Pas
 void initializeRegionOnlyViewerPass(PassRegistry&);
 void initializeRegionPrinterPass(PassRegistry&);
 void initializeRegionViewerPass(PassRegistry&);
+void initializeRenameIndependentSubregsPass(PassRegistry&);
 void initializeReversePostOrderFunctionAttrsPass(PassRegistry&);
 void initializeRewriteStatepointsForGCPass(PassRegistry&);
 void initializeSafeStackPass(PassRegistry&);

Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
+++ llvm/trunk/lib/CodeGen/CMakeLists.txt Tue May 31 17:38:06 2016
@@ -100,6 +100,7 @@ add_llvm_library(LLVMCodeGen
   RegisterCoalescer.cpp
   RegisterPressure.cpp
   RegisterScavenging.cpp
+  RenameIndependentSubregs.cpp
   SafeStack.cpp
   ScheduleDAG.cpp
   ScheduleDAGInstrs.cpp

Modified: llvm/trunk/lib/CodeGen/CodeGen.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CodeGen.cpp (original)
+++ llvm/trunk/lib/CodeGen/CodeGen.cpp Tue May 31 17:38:06 2016
@@ -68,6 +68,7 @@ void llvm::initializeCodeGen(PassRegistr
   initializePreISelIntrinsicLoweringPass(Registry);
   initializeProcessImplicitDefsPass(Registry);
   initializeRegisterCoalescerPass(Registry);
+  initializeRenameIndependentSubregsPass(Registry);
   initializeShrinkWrapPass(Registry);
   initializeSlotIndexesPass(Registry);
   initializeStackColoringPass(Registry);

Modified: llvm/trunk/lib/CodeGen/LiveInterval.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveInterval.cpp?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveInterval.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveInterval.cpp Tue May 31 17:38:06 2016
@@ -20,16 +20,14 @@
 
 #include "llvm/CodeGen/LiveInterval.h"
 
-#include "PHIEliminationUtils.h"
+#include "LiveRangeUtils.h"
 #include "RegisterCoalescer.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetRegisterInfo.h"
 #include <algorithm>
 using namespace llvm;
@@ -1176,40 +1174,6 @@ unsigned ConnectedVNInfoEqClasses::Class
   return EqClass.getNumClasses();
 }
 
-template<typename LiveRangeT, typename EqClassesT>
-static void DistributeRange(LiveRangeT &LR, LiveRangeT *SplitLRs[],
-                            EqClassesT VNIClasses) {
-  // Move segments to new intervals.
-  LiveRange::iterator J = LR.begin(), E = LR.end();
-  while (J != E && VNIClasses[J->valno->id] == 0)
-    ++J;
-  for (LiveRange::iterator I = J; I != E; ++I) {
-    if (unsigned eq = VNIClasses[I->valno->id]) {
-      assert((SplitLRs[eq-1]->empty() || SplitLRs[eq-1]->expiredAt(I->start)) &&
-             "New intervals should be empty");
-      SplitLRs[eq-1]->segments.push_back(*I);
-    } else
-      *J++ = *I;
-  }
-  LR.segments.erase(J, E);
-
-  // Transfer VNInfos to their new owners and renumber them.
-  unsigned j = 0, e = LR.getNumValNums();
-  while (j != e && VNIClasses[j] == 0)
-    ++j;
-  for (unsigned i = j; i != e; ++i) {
-    VNInfo *VNI = LR.getValNumInfo(i);
-    if (unsigned eq = VNIClasses[i]) {
-      VNI->id = SplitLRs[eq-1]->getNumValNums();
-      SplitLRs[eq-1]->valnos.push_back(VNI);
-    } else {
-      VNI->id = j;
-      LR.valnos[j++] = VNI;
-    }
-  }
-  LR.valnos.resize(j);
-}
-
 void ConnectedVNInfoEqClasses::Distribute(LiveInterval &LI, LiveInterval *LIV[],
                                           MachineRegisterInfo &MRI) {
   // Rewrite instructions.
@@ -1276,232 +1240,3 @@ void ConnectedVNInfoEqClasses::Distribut
   // Distribute main liverange.
   DistributeRange(LI, LIV, EqClass);
 }
-
-void ConnectedSubRegClasses::renameComponents(LiveInterval &LI) const {
-  // Shortcut: We cannot have split components with a single definition.
-  if (LI.valnos.size() < 2)
-    return;
-
-  SmallVector<SubRangeInfo, 4> SubRangeInfos;
-  IntEqClasses Classes;
-  if (!findComponents(Classes, SubRangeInfos, LI))
-    return;
-
-  // 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);
-  for (unsigned I = 1, NumClasses = Classes.getNumClasses(); I < NumClasses;
-       ++I) {
-    unsigned NewVReg = MRI.createVirtualRegister(RegClass);
-    LiveInterval &NewLI = LIS.createEmptyInterval(NewVReg);
-    Intervals.push_back(&NewLI);
-  }
-
-  rewriteOperands(Classes, SubRangeInfos, Intervals);
-  distribute(Classes, SubRangeInfos, Intervals);
-  computeMainRangesFixFlags(Classes, SubRangeInfos, Intervals);
-}
-
-bool ConnectedSubRegClasses::findComponents(IntEqClasses &Classes,
-    SmallVectorImpl<ConnectedSubRegClasses::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 (ConnectedSubRegClasses::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 ConnectedSubRegClasses::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;
-
-    MachineInstr &MI = *MO.getParent();
-
-    SlotIndex Pos = LIS.getInstructionIndex(MI);
-    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) == 0)
-        continue;
-      LiveRange::const_iterator I = SR.find(Pos);
-      if (I == SR.end())
-        continue;
-
-      const VNInfo &VNI = *I->valno;
-      // 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);
-  }
-}
-
-void ConnectedSubRegClasses::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 ConnectedSubRegClasses::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);
-  }
-}

Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Tue May 31 17:38:06 2016
@@ -1566,22 +1566,6 @@ void LiveIntervals::splitSeparateCompone
   ConEQ.Distribute(LI, SplitLIs.data(), *MRI);
 }
 
-void LiveIntervals::renameDisconnectedComponents() {
-  ConnectedSubRegClasses SubRegClasses(*this, *MRI, *TII);
-
-  // 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.
-  for (size_t I = 0, E = MRI->getNumVirtRegs(); I < E; ++I) {
-    unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
-    LiveInterval *LI = VirtRegIntervals[Reg];
-    if (LI == nullptr || !LI->hasSubRanges())
-      continue;
-
-    SubRegClasses.renameComponents(*LI);
-  }
-}
-
 void LiveIntervals::constructMainRangeFromSubranges(LiveInterval &LI) {
   assert(LRCalc && "LRCalc not initialized.");
   LRCalc->reset(MF, getSlotIndexes(), DomTree, &getVNInfoAllocator());

Added: llvm/trunk/lib/CodeGen/LiveRangeUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveRangeUtils.h?rev=271345&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveRangeUtils.h (added)
+++ llvm/trunk/lib/CodeGen/LiveRangeUtils.h Tue May 31 17:38:06 2016
@@ -0,0 +1,62 @@
+//===-- LiveRangeUtils.h - Live Range modification utilities ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// This file contains helper functions to modify live ranges.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_LIVERANGEUTILS_H
+#define LLVM_LIB_CODEGEN_LIVERANGEUTILS_H
+
+#include "llvm/CodeGen/LiveInterval.h"
+
+namespace llvm {
+
+/// Helper function that distributes live range value numbers and the
+/// corresponding segments of a master live range \p LR to a list of newly
+/// created live ranges \p SplitLRs. \p VNIClasses maps each value number in \p
+/// LR to 0 meaning it should stay or to 1..N meaning it should go to a specific
+/// live range in the \p SplitLRs array.
+template<typename LiveRangeT, typename EqClassesT>
+static void DistributeRange(LiveRangeT &LR, LiveRangeT *SplitLRs[],
+                            EqClassesT VNIClasses) {
+  // Move segments to new intervals.
+  typename LiveRangeT::iterator J = LR.begin(), E = LR.end();
+  while (J != E && VNIClasses[J->valno->id] == 0)
+    ++J;
+  for (typename LiveRangeT::iterator I = J; I != E; ++I) {
+    if (unsigned eq = VNIClasses[I->valno->id]) {
+      assert((SplitLRs[eq-1]->empty() || SplitLRs[eq-1]->expiredAt(I->start)) &&
+             "New intervals should be empty");
+      SplitLRs[eq-1]->segments.push_back(*I);
+    } else
+      *J++ = *I;
+  }
+  LR.segments.erase(J, E);
+
+  // Transfer VNInfos to their new owners and renumber them.
+  unsigned j = 0, e = LR.getNumValNums();
+  while (j != e && VNIClasses[j] == 0)
+    ++j;
+  for (unsigned i = j; i != e; ++i) {
+    VNInfo *VNI = LR.getValNumInfo(i);
+    if (unsigned eq = VNIClasses[i]) {
+      VNI->id = SplitLRs[eq-1]->getNumValNums();
+      SplitLRs[eq-1]->valnos.push_back(VNI);
+    } else {
+      VNI->id = j;
+      LR.valnos[j++] = VNI;
+    }
+  }
+  LR.valnos.resize(j);
+}
+
+} // End llvm namespace
+
+#endif

Modified: llvm/trunk/lib/CodeGen/MachineScheduler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineScheduler.cpp?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineScheduler.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineScheduler.cpp Tue May 31 17:38:06 2016
@@ -882,16 +882,8 @@ void ScheduleDAGMILive::enterRegion(Mach
   ShouldTrackPressure = SchedImpl->shouldTrackPressure();
   ShouldTrackLaneMasks = SchedImpl->shouldTrackLaneMasks();
 
-  if (ShouldTrackLaneMasks) {
-    if (!ShouldTrackPressure)
-      report_fatal_error("ShouldTrackLaneMasks requires ShouldTrackPressure");
-    // Dead subregister defs have no users and therefore no dependencies,
-    // moving them around may cause liveintervals to degrade into multiple
-    // components. Change independent components to have their own vreg to avoid
-    // this.
-    if (!DisconnectedComponentsRenamed)
-      LIS->renameDisconnectedComponents();
-  }
+  assert((!ShouldTrackLaneMasks || ShouldTrackPressure) &&
+         "ShouldTrackLaneMasks requires ShouldTrackPressure");
 }
 
 // Setup the register pressure trackers for the top scheduled top and bottom

Added: llvm/trunk/lib/CodeGen/RenameIndependentSubregs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RenameIndependentSubregs.cpp?rev=271345&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/RenameIndependentSubregs.cpp (added)
+++ llvm/trunk/lib/CodeGen/RenameIndependentSubregs.cpp Tue May 31 17:38:06 2016
@@ -0,0 +1,388 @@
+//===-- RenameIndependentSubregs.cpp - Live Interval Analysis -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// Rename independent subregisters looks for virtual registers with
+/// independently used subregisters and renames them to new virtual registers.
+/// Example: In the following:
+///   %vreg0:sub0<read-undef> = ...
+///   %vreg0:sub1 = ...
+///   use %vreg0:sub0
+///   %vreg0:sub0 = ...
+///   use %vreg0:sub0
+///   use %vreg0:sub1
+/// sub0 and sub1 are never used together, and we have two independent sub0
+/// definitions. This pass will rename to:
+///   %vreg0:sub0<read-undef> = ...
+///   %vreg1:sub1<read-undef> = ...
+///   use %vreg1:sub1
+///   %vreg2:sub1<read-undef> = ...
+///   use %vreg2:sub1
+///   use %vreg0:sub0
+//
+//===----------------------------------------------------------------------===//
+
+#include "LiveRangeUtils.h"
+#include "PHIEliminationUtils.h"
+#include "llvm/CodeGen/LiveInterval.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "rename-independent-subregs"
+
+namespace {
+
+class RenameIndependentSubregs : public MachineFunctionPass {
+public:
+  static char ID;
+  RenameIndependentSubregs() : MachineFunctionPass(ID) {}
+
+  const char *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;
+
+  /// \brief 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;
+
+  /// \brief 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;
+
+  /// \brief 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, "rename-independent-subregs",
+                      "Rename Independent Subregisters", false, false)
+INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
+INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
+INITIALIZE_PASS_END(RenameIndependentSubregs, "rename-independent-subregs",
+                    "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);
+  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::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;
+
+    MachineInstr &MI = *MO.getParent();
+
+    SlotIndex Pos = LIS->getInstructionIndex(MI);
+    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) == 0)
+        continue;
+      LiveRange::const_iterator I = SR.find(Pos);
+      if (I == SR.end())
+        continue;
+
+      const VNInfo &VNI = *I->valno;
+      // 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);
+  }
+  // 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);
+  }
+}
+
+bool RenameIndependentSubregs::runOnMachineFunction(MachineFunction &MF) {
+  // Skip renaming if liveness of subregister is not tracked.
+  if (!MF.getSubtarget().enableSubRegLiveness())
+    return false;
+
+  DEBUG(dbgs() << "Renaming independent subregister live ranges in "
+        << MF.getName() << '\n');
+
+  LIS = &getAnalysis<LiveIntervals>();
+  MRI = &MF.getRegInfo();
+  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 = TargetRegisterInfo::index2VirtReg(I);
+    if (!LIS->hasInterval(Reg))
+      continue;
+    LiveInterval &LI = LIS->getInterval(Reg);
+    if (!LI.hasSubRanges())
+      continue;
+
+    Changed |= renameComponents(LI);
+  }
+
+  return Changed;
+}

Modified: llvm/trunk/lib/CodeGen/TargetPassConfig.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetPassConfig.cpp?rev=271345&r1=271344&r2=271345&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetPassConfig.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetPassConfig.cpp Tue May 31 17:38:06 2016
@@ -775,6 +775,11 @@ void TargetPassConfig::addOptimizedRegAl
   addPass(&TwoAddressInstructionPassID, false);
   addPass(&RegisterCoalescerID);
 
+  // The machine scheduler may accidentally create disconnected components
+  // when moving subregister definitions around, avoid this by splitting them to
+  // separate vregs before. Splitting can also improve reg. allocation quality.
+  addPass(&RenameIndependentSubregsID);
+
   // PreRA instruction scheduling.
   addPass(&MachineSchedulerID);
 

Added: llvm/trunk/test/CodeGen/AMDGPU/rename-independent-subregs.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AMDGPU/rename-independent-subregs.mir?rev=271345&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AMDGPU/rename-independent-subregs.mir (added)
+++ llvm/trunk/test/CodeGen/AMDGPU/rename-independent-subregs.mir Tue May 31 17:38:06 2016
@@ -0,0 +1,30 @@
+# RUN: llc -march=amdgcn -run-pass rename-independent-subregs -o /dev/null %s 2>&1 | FileCheck %s
+--- |
+  define void @test0() { ret void }
+...
+---
+# In the test below we have two independent def+use pairs of subregister1 which
+# can be moved to a new virtual register. The third def of sub1 however is used
+# in combination with sub0 and needs to stay with the original vreg.
+# CHECK-LABEL: name: test0
+# CHECK: S_NOP 0, implicit-def undef %0:sub0
+# CHECK: S_NOP 0, implicit-def undef %2:sub1
+# CHECK: S_NOP 0, implicit %2:sub1
+# CHECK: S_NOP 0, implicit-def undef %1:sub1
+# CHECK: S_NOP 0, implicit %1:sub1
+# CHECK: S_NOP 0, implicit-def %0:sub1
+# CHECK: S_NOP 0, implicit %0
+name: test0
+isSSA: true
+registers:
+  - { id: 0, class: sreg_128 }
+body: |
+  bb.0:
+    S_NOP 0, implicit-def undef %0:sub0
+    S_NOP 0, implicit-def %0:sub1
+    S_NOP 0, implicit %0:sub1
+    S_NOP 0, implicit-def %0:sub1
+    S_NOP 0, implicit %0:sub1
+    S_NOP 0, implicit-def %0:sub1
+    S_NOP 0, implicit %0
+...




More information about the llvm-commits mailing list