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
// 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(); }
const uint32_t mergeLabId =
mergeInst->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
AddBranch(liveLabId, *bi);
+ backedges_.erase(br);
context()->KillInst(br);
context()->KillInst(mergeInst);
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);
}
// 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;