/// UpdateSuccessorsPHIs - After FromBB is tail duplicated into its predecessor
/// blocks, the successors have gained new predecessors. Update the PHI
/// instructions in them accordingly.
void
TailDuplicatePass::UpdateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead,
                                        SmallVector<MachineBasicBlock*, 8> &TDBBs,
                                        SmallSetVector<MachineBasicBlock*,8> &Succs) {
    for (SmallSetVector<MachineBasicBlock*, 8>::iterator SI = Succs.begin(),
            SE = Succs.end(); SI != SE; ++SI) {
        MachineBasicBlock *SuccBB = *SI;
        for (MachineBasicBlock::iterator II = SuccBB->begin(), EE = SuccBB->end();
                II != EE; ++II) {
            if (!II->isPHI())
                break;
            unsigned Idx = 0;
            for (unsigned i = 1, e = II->getNumOperands(); i != e; i += 2) {
                MachineOperand &MO = II->getOperand(i+1);
                if (MO.getMBB() == FromBB) {
                    Idx = i;
                    break;
                }
            }

            assert(Idx != 0);
            MachineOperand &MO0 = II->getOperand(Idx);
            unsigned Reg = MO0.getReg();
            if (isDead) {
                // Folded into the previous BB.
                // There could be duplicate phi source entries. FIXME: Should sdisel
                // or earlier pass fixed this?
                for (unsigned i = II->getNumOperands()-2; i != Idx; i -= 2) {
                    MachineOperand &MO = II->getOperand(i+1);
                    if (MO.getMBB() == FromBB) {
                        II->RemoveOperand(i+1);
                        II->RemoveOperand(i);
                    }
                }
            } else
                Idx = 0;

            // If Idx is set, the operands at Idx and Idx+1 must be removed.
            // We reuse the location to avoid expensive RemoveOperand calls.

            DenseMap<unsigned,AvailableValsTy>::iterator LI=SSAUpdateVals.find(Reg);
            if (LI != SSAUpdateVals.end()) {
                // This register is defined in the tail block.
                for (unsigned j = 0, ee = LI->second.size(); j != ee; ++j) {
                    MachineBasicBlock *SrcBB = LI->second[j].first;
                    // If we didn't duplicate a bb into a particular predecessor, we
                    // might still have added an entry to SSAUpdateVals to correcly
                    // recompute SSA. If that case, avoid adding a dummy extra argument
                    // this PHI.
                    if (!SrcBB->isSuccessor(SuccBB))
                        continue;

                    unsigned SrcReg = LI->second[j].second;
                    if (Idx != 0) {
                        II->getOperand(Idx).setReg(SrcReg);
                        II->getOperand(Idx+1).setMBB(SrcBB);
                        Idx = 0;
                    } else {
                        II->addOperand(MachineOperand::CreateReg(SrcReg, false));
                        II->addOperand(MachineOperand::CreateMBB(SrcBB));
                    }
                }
            } else {
                // Live in tail block, must also be live in predecessors.
                for (unsigned j = 0, ee = TDBBs.size(); j != ee; ++j) {
                    MachineBasicBlock *SrcBB = TDBBs[j];
                    if (Idx != 0) {
                        II->getOperand(Idx).setReg(Reg);
                        II->getOperand(Idx+1).setMBB(SrcBB);
                        Idx = 0;
                    } else {
                        II->addOperand(MachineOperand::CreateReg(Reg, false));
                        II->addOperand(MachineOperand::CreateMBB(SrcBB));
                    }
                }
            }
            if (Idx != 0) {
                II->RemoveOperand(Idx+1);
                II->RemoveOperand(Idx);
            }
        }
    }
}
bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) {
  SmallPtrSet<MachineBasicBlock*, 8> Reachable;
  bool ModifiedPHI = false;

  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
  MachineDominatorTree *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
  MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>();

  // Mark all reachable blocks.
  for (MachineBasicBlock *BB : depth_first_ext(&F, Reachable))
    (void)BB/* Mark all reachable blocks */;

  // Loop over all dead blocks, remembering them and deleting all instructions
  // in them.
  std::vector<MachineBasicBlock*> DeadBlocks;
  for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    MachineBasicBlock *BB = I;

    // Test for deadness.
    if (!Reachable.count(BB)) {
      DeadBlocks.push_back(BB);

      // Update dominator and loop info.
      if (MLI) MLI->removeBlock(BB);
      if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB);

      while (BB->succ_begin() != BB->succ_end()) {
        MachineBasicBlock* succ = *BB->succ_begin();

        MachineBasicBlock::iterator start = succ->begin();
        while (start != succ->end() && start->isPHI()) {
          for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2)
            if (start->getOperand(i).isMBB() &&
                start->getOperand(i).getMBB() == BB) {
              start->RemoveOperand(i);
              start->RemoveOperand(i-1);
            }

          start++;
        }

        BB->removeSuccessor(BB->succ_begin());
      }
    }
  }

  // Actually remove the blocks now.
  for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i)
    DeadBlocks[i]->eraseFromParent();

  // Cleanup PHI nodes.
  for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    MachineBasicBlock *BB = I;
    // Prune unneeded PHI entries.
    SmallPtrSet<MachineBasicBlock*, 8> preds(BB->pred_begin(),
                                             BB->pred_end());
    MachineBasicBlock::iterator phi = BB->begin();
    while (phi != BB->end() && phi->isPHI()) {
      for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2)
        if (!preds.count(phi->getOperand(i).getMBB())) {
          phi->RemoveOperand(i);
          phi->RemoveOperand(i-1);
          ModifiedPHI = true;
        }

      if (phi->getNumOperands() == 3) {
        unsigned Input = phi->getOperand(1).getReg();
        unsigned Output = phi->getOperand(0).getReg();

        MachineInstr* temp = phi;
        ++phi;
        temp->eraseFromParent();
        ModifiedPHI = true;

        if (Input != Output) {
          MachineRegisterInfo &MRI = F.getRegInfo();
          MRI.constrainRegClass(Input, MRI.getRegClass(Output));
          MRI.replaceRegWith(Output, Input);
        }

        continue;
      }

      ++phi;
    }
  }

  F.RenumberBlocks();

  return (DeadBlocks.size() || ModifiedPHI);
}