[PATCH] D20092: [AMDGPU] Fix issues introduced by aggressive block placement

Chuang-Yu Cheng via llvm-commits llvm-commits at lists.llvm.org
Tue May 10 02:04:25 PDT 2016


cycheng created this revision.
cycheng added reviewers: tstellarAMD, tjablin, kbarton.
cycheng added subscribers: hfinkel, nemanjai, amehsan, llvm-commits.
Herald added subscribers: kzhuravl, arsenm.

Patch D20017 aggressively choosing the best loop top in a loop, this introduces 2 issues for AMDGPU backend:

  # Crash issue: it breaks assumption of basic block order in shouldSkip(), e.g.
```
   bb2<--+   bb2 (From)      Block      Flow (To)
   /   \ |   bb6        => Placement => bb2 (From)
bb6 -> Flow  Flow (To)                  bb6        
```
In original code, To MBB is assumed after From MBB, so it gets crash when this is not true.

  # Unnecessary branch in fall through path, e.g.
```
   bb2<--+   Flow (Latch)  
   /   \ |   bb2  (Header) 
bb6 -> Flow  bb6
  
Flow: 
    s_cbranch_execnz bb2
    s_branch end
bb2:
    s_cbranch_execz Flow
bb6:
    s_branch Flow
end:
```

Flow can fall through bb2, so we can replace two branches into one conditional branch.

http://reviews.llvm.org/D20092

Files:
  lib/Target/AMDGPU/SILowerControlFlow.cpp

Index: lib/Target/AMDGPU/SILowerControlFlow.cpp
===================================================================
--- lib/Target/AMDGPU/SILowerControlFlow.cpp
+++ lib/Target/AMDGPU/SILowerControlFlow.cpp
@@ -130,6 +130,19 @@
 
   unsigned NumInstr = 0;
 
+  // Check whether 'To MBB' is before 'From MBB', this is possible after Block
+  // Placement Pass:
+  //    bb2<--+   bb2 (From)      Block      Flow (To)
+  //    /   \ |   bb6        => Placement => bb2 (From)
+  // bb6 -> Flow  Flow (To)                  bb6
+  for (MachineFunction::iterator MBBI = MachineFunction::iterator(From),
+                                 ToI = MachineFunction::iterator(To);
+                                 ToI != From->getParent()->end(); ++ToI) {
+    // return true so we generate conditional branch for 'From MBB'
+    if (MBBI == ToI)
+      return true;
+  }
+
   for (MachineFunction::iterator MBBI = MachineFunction::iterator(From),
                                  ToI = MachineFunction::iterator(To); MBBI != ToI; ++MBBI) {
 
@@ -295,8 +308,38 @@
           .addReg(AMDGPU::EXEC)
           .addReg(Src);
 
-  BuildMI(MBB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
-    .addOperand(MI.getOperand(1));
+  // After Block Placement Pass, Latch block might before Header block
+  //    bb2<--+   Flow (Latch)  MBB
+  //    /   \ |   bb2  (Header) NextBB
+  // bb6 -> Flow  bb6
+  //
+  // If this is the case, then 'Flow MBB' can fall through 'bb2 MBB'. But we
+  // need to change branch condition for 'Flow MBB'
+
+  // Check if Latch is before Header.
+  // %Flow:
+  //   SI_LOOP %SGPR0_SGPR1, bb2, ..
+  //   S_BRANCH end
+  // %bb2:
+  //   ..
+  MachineBasicBlock &NextBB = *std::next(MachineFunction::iterator(MBB));
+  if (&NextBB == MI.getOperand(1).getMBB()) {
+    MachineInstr &NextMI = *std::next(MachineBasicBlock::iterator(MI));
+
+    assert(NextMI.getOpcode() == AMDGPU::S_BRANCH &&
+      "Next instruction of SI_LOOP should be S_BRANCH");
+
+    // Result:
+    //   s_cbranch_execz end
+    //   s_branch end
+    // The 's_branch end' is removed at Branch()
+    BuildMI(MBB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECZ))
+      .addOperand(NextMI.getOperand(0));
+  }
+  else {
+    BuildMI(MBB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
+      .addOperand(MI.getOperand(1));
+  }
 
   MI.eraseFromParent();
 }
@@ -315,10 +358,20 @@
 }
 
 void SILowerControlFlow::Branch(MachineInstr &MI) {
+  // If these aren't equal, this is probably an infinite loop.
   if (MI.getOperand(0).getMBB() == MI.getParent()->getNextNode())
     MI.eraseFromParent();
-
-  // If these aren't equal, this is probably an infinite loop.
+  else if (&*MI.getParent()->begin() != &MI) {
+    MachineInstr &PrevMI = *std::prev(MachineBasicBlock::iterator(MI));
+
+    // Look at this pattern (see comments in Loop()):
+    //   s_cbranch_execz end
+    //   s_branch end
+    // Remove 's_branch end'
+    if (PrevMI.getOpcode() == AMDGPU::S_CBRANCH_EXECZ &&
+        PrevMI.getOperand(0).getMBB() == MI.getOperand(0).getMBB())
+      MI.eraseFromParent();
+  }
 }
 
 void SILowerControlFlow::Kill(MachineInstr &MI) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D20092.56678.patch
Type: text/x-patch
Size: 3121 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160510/36609976/attachment.bin>


More information about the llvm-commits mailing list