dead branch elim: Track killed backedges
authorDavid Neto <dneto@google.com>
Thu, 4 Jan 2018 23:52:38 +0000 (18:52 -0500)
committerDavid Neto <dneto@google.com>
Fri, 5 Jan 2018 00:06:55 +0000 (19:06 -0500)
When deleting branches and blocks, also remove them from
the backedges set, in case they were there.

This prevents us from keeping stale pointers to deleted Instruction
objects.  That memory could be used later by another instruction,
incorrectly signaling that something has a backedge reference, and
the dead branch eliminator could end up deleting live blocks.

Adds accessor method ir::BasicBlock::terminator

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1168

source/opt/basic_block.h
source/opt/dead_branch_elim_pass.cpp

index 751b3a2..3e3a347 100644 (file)
@@ -143,6 +143,9 @@ class BasicBlock {
   // this block, if any.  If none, returns zero.
   uint32_t ContinueBlockIdIfAny() const;
 
+  // Returns the terminator instruction.  Assumes the terminator exists.
+  Instruction* terminator() { return &*tail(); }
+
   // Returns true if this basic block exits this function and returns to its
   // caller.
   bool IsReturn() const { return ctail()->IsReturn(); }
index e165c51..a8c3068 100644 (file)
@@ -220,6 +220,7 @@ bool DeadBranchElimPass::EliminateDeadBranches(ir::Function* func) {
     const uint32_t mergeLabId =
         mergeInst->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
     AddBranch(liveLabId, *bi);
+    backedges_.erase(br);
     context()->KillInst(br);
     context()->KillInst(mergeInst);
 
@@ -232,6 +233,7 @@ bool DeadBranchElimPass::EliminateDeadBranches(ir::Function* func) {
     while (dLabId != mergeLabId) {
       if (!HasNonPhiNonBackedgeRef(dLabId)) {
         // Kill use/def for all instructions and mark block for elimination
+        backedges_.erase((*dbi)->terminator());
         KillAllInsts(*dbi);
         elimBlocks.insert(*dbi);
       }
@@ -242,6 +244,7 @@ bool DeadBranchElimPass::EliminateDeadBranches(ir::Function* func) {
     // If merge block is unreachable, continue eliminating blocks until
     // a live block or last block is reached.
     while (!HasNonPhiNonBackedgeRef(dLabId)) {
+      backedges_.erase((*dbi)->terminator());
       KillAllInsts(*dbi);
       elimBlocks.insert(*dbi);
       ++dbi;