[PATCH] D30558: Fix value numbers in successor blocks if liveout number has changed

Stanislav Mekhanoshin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 2 16:21:06 PST 2017


rampitec created this revision.
Herald added a subscriber: tpr.

The problem can occur in presence of subregs. If we are swapping two
instructions defining different subregs of the same register we will
get a new liveout from a block. Liveins in successor blocks need to
be updated to record the new value number.

The review does not have a dedicated test case since that is very
difficult to force scheduler to reorder two certain instructions, but
when I submit https://reviews.llvm.org/D30557 it will break the test CodeGen/AMDGPU/br_cc.f16.ll
without this patch.

To illustrate the problem exposed by that test: before scheduling we had:

  %vreg12 [48r,96r:0)[96r,112r:1)[112r,400r:2)[464B,560r:2)  0 at 48r 1 at 96r 2 at 112r L00000001 [48r,208r:0)  0 at 48r L00000002 [48r,208r:0)  0 at 48r L00000004 [112r,384r:0)[464B,544r:0)  0 at 112r L000000
   
  0B      BB#0: derived from LLVM BB %entry
              Live Ins: %SGPR0_SGPR1
  16B             %vreg1<def> = COPY %SGPR0_SGPR1; SGPR_64:%vreg1
  32B             %vreg20:sub0_sub1<def,read-undef> = S_LOAD_DWORDX2_IMM %vreg1, 9, 0; mem:LD8[undef(addrspace=2)](nontemporal)(dereferenceable)(invariant) SReg_128:%vreg20 SGPR_64:%vreg1
  48B             %vreg12:sub0_sub1<def,read-undef> = S_LOAD_DWORDX2_IMM %vreg1, 11, 0; mem:LD8[undef(addrspace=2)](nontemporal)(dereferenceable)(invariant) SReg_128:%vreg12 SGPR_64:%vreg1
  96B             %vreg12:sub3<def> = S_MOV_B32 61440; SReg_128:%vreg12
  112B            %vreg12:sub2<def> = S_MOV_B32   -1; SReg_128:%vreg12
  …
   
  464B    BB#2: derived from LLVM BB %two
              Predecessors according to CFG: BB#0
  544B            %vreg20:sub2<def> = COPY %vreg12:sub2; SReg_128:%vreg20,%vreg12
  560B            %vreg20:sub3<def> = COPY %vreg12:sub3; SReg_128:%vreg20,%vreg12

%vreg12 is liveout from BB#0, segment with value #2: 112r,400r:2. Livein into #BB2 has value #2: [464B,560r:2)

After the scheduling:

  %vreg12 [24r,28r:1)[28r,48r:2)[48r,400r:0)[464B,584r:2)  0 at 48r 1 at 24r 2 at 28r L00000001 [48r,208r:0)  0 at 48r L00000002 [48r,208r:0)  0 at 48r L00000004 [28r,384r:0)[464B,580r:0)  0 at 28r L00000008 [24r,400r:0)[464B,584r:0)  0 at 24r
   
  0B      BB#0: derived from LLVM BB %entry
              Live Ins: %SGPR0_SGPR1
  16B             %vreg1<def> = COPY %SGPR0_SGPR1; SGPR_64:%vreg1
  24B             %vreg12:sub3<def,read-undef> = S_MOV_B32 61440; SReg_128:%vreg12
  28B             %vreg12:sub2<def> = S_MOV_B32 -1; SReg_128:%vreg12
  48B             %vreg12:sub0_sub1<def> = S_LOAD_DWORDX2_IMM %vreg1, 11, 0; mem:LD8[undef(addrspace=2)](nontemporal)(dereferenceable)(invariant) SReg_128:%vreg12 SGPR_64:%vreg1
  …
  464B    BB#2: derived from LLVM BB %two
              Predecessors according to CFG: BB#0
  576B            %vreg21<def> = V_CVT_F16_F32_e32 %vreg0, %EXEC<imp-use>; VGPR_32:%vreg21,%vreg0
  580B            %vreg20:sub2<def> = COPY %vreg12:sub2; SReg_128:%vreg20,%vreg12
  584B            %vreg20:sub3<def> = COPY %vreg12:sub3; SReg_128:%vreg20,%vreg12

We have switched %vreg12 subreg definitions, so the new liveout from BB#0 is [48r,400r:0), value number 0. BB#2's livein is not updated: [464B,584r:2).
At this point liveout != livein and LIS is broken. Verifier will report the error.


Repository:
  rL LLVM

https://reviews.llvm.org/D30558

Files:
  lib/CodeGen/LiveIntervalAnalysis.cpp


Index: lib/CodeGen/LiveIntervalAnalysis.cpp
===================================================================
--- lib/CodeGen/LiveIntervalAnalysis.cpp
+++ lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -982,10 +982,38 @@
       handleMoveDown(LR);
     else
       handleMoveUp(LR, Reg, LaneMask);
+
+    // Fix liveins to other blocks which may need to be changed to new liveouts.
+    updateSuccessors(LR, LIS.getSlotIndexes()->getMBBFromIndex(NewIdx));
+
     DEBUG(dbgs() << "        -->\t" << LR << '\n');
     LR.verify();
   }
 
+  // Update value numbers in successor blocks in case if we have a new liveout
+  // replacing an old one. I.e. if we have swapped two instructions defining
+  // subregisters of a same register. Last one becomes a new liveout.
+  // Only update Valno if supplied.
+  void updateSuccessors(LiveRange &LR, const MachineBasicBlock *MBB,
+                        VNInfo *Valno = nullptr) {
+    VNInfo *Out = LR.getVNInfoBefore(LIS.getMBBEndIdx(MBB));
+    if (!Out || (Valno && Out != Valno))
+      return;
+    // This is a liveout.
+    // Find live-ins to other blocks which should connect to this live-out.
+    for (const auto &Succ : MBB->successors()) {
+      // Now set new value number in a successor.
+      auto *InSeg = LR.getSegmentContaining(LIS.getMBBStartIdx(Succ));
+      if (InSeg && !InSeg->valno->isPHIDef() && InSeg->valno != Out) {
+        InSeg->valno = Out;
+        // Iterate next successors. No need to maintain visited list because
+        // when we update all possible segments loop will terminate.
+        if (InSeg->contains(LIS.getMBBEndIdx(Succ).getPrevSlot()))
+          updateSuccessors(LR, Succ, Out);
+      }
+    }
+  }
+
   /// Update LR to reflect an instruction has been moved downwards from OldIdx
   /// to NewIdx (OldIdx < NewIdx).
   void handleMoveDown(LiveRange &LR) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30558.90414.patch
Type: text/x-patch
Size: 1855 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170303/ac376076/attachment.bin>


More information about the llvm-commits mailing list