//===- IfConversion.cpp - Machine code if conversion pass -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the machine instruction level if-conversion pass, which
// tries to convert conditional branches into predicated instructions.
//
//===----------------------------------------------------------------------===//

#include "BranchFolding.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SparseSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MBFIWrapper.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <functional>
#include <iterator>
#include <memory>
#include <utility>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "if-converter"

// Hidden options for help debugging.
static cl::opt<int> IfCvtFnStart("ifcvt-fn-start", cl::init(-1), cl::Hidden);
static cl::opt<int> IfCvtFnStop("ifcvt-fn-stop", cl::init(-1), cl::Hidden);
static cl::opt<int> IfCvtLimit("ifcvt-limit", cl::init(-1), cl::Hidden);
static cl::opt<bool> DisableSimple("disable-ifcvt-simple",
                                   cl::init(false), cl::Hidden);
static cl::opt<bool> DisableSimpleF("disable-ifcvt-simple-false",
                                    cl::init(false), cl::Hidden);
static cl::opt<bool> DisableTriangle("disable-ifcvt-triangle",
                                     cl::init(false), cl::Hidden);
static cl::opt<bool> DisableTriangleR("disable-ifcvt-triangle-rev",
                                      cl::init(false), cl::Hidden);
static cl::opt<bool> DisableTriangleF("disable-ifcvt-triangle-false",
                                      cl::init(false), cl::Hidden);
static cl::opt<bool> DisableDiamond("disable-ifcvt-diamond",
                                    cl::init(false), cl::Hidden);
static cl::opt<bool> DisableForkedDiamond("disable-ifcvt-forked-diamond",
                                        cl::init(false), cl::Hidden);
static cl::opt<bool> IfCvtBranchFold("ifcvt-branch-fold",
                                     cl::init(true), cl::Hidden);

STATISTIC(NumSimple,       "Number of simple if-conversions performed");
STATISTIC(NumSimpleFalse,  "Number of simple (F) if-conversions performed");
STATISTIC(NumTriangle,     "Number of triangle if-conversions performed");
STATISTIC(NumTriangleRev,  "Number of triangle (R) if-conversions performed");
STATISTIC(NumTriangleFalse,"Number of triangle (F) if-conversions performed");
STATISTIC(NumTriangleFRev, "Number of triangle (F/R) if-conversions performed");
STATISTIC(NumDiamonds,     "Number of diamond if-conversions performed");
STATISTIC(NumForkedDiamonds, "Number of forked-diamond if-conversions performed");
STATISTIC(NumIfConvBBs,    "Number of if-converted blocks");
STATISTIC(NumDupBBs,       "Number of duplicated blocks");
STATISTIC(NumUnpred,       "Number of true blocks of diamonds unpredicated");

namespace {

  class IfConverter : public MachineFunctionPass {
    enum IfcvtKind {
      ICNotClassfied,  // BB data valid, but not classified.
      ICSimpleFalse,   // Same as ICSimple, but on the false path.
      ICSimple,        // BB is entry of an one split, no rejoin sub-CFG.
      ICTriangleFRev,  // Same as ICTriangleFalse, but false path rev condition.
      ICTriangleRev,   // Same as ICTriangle, but true path rev condition.
      ICTriangleFalse, // Same as ICTriangle, but on the false path.
      ICTriangle,      // BB is entry of a triangle sub-CFG.
      ICDiamond,       // BB is entry of a diamond sub-CFG.
      ICForkedDiamond  // BB is entry of an almost diamond sub-CFG, with a
                       // common tail that can be shared.
    };

    /// One per MachineBasicBlock, this is used to cache the result
    /// if-conversion feasibility analysis. This includes results from
    /// TargetInstrInfo::analyzeBranch() (i.e. TBB, FBB, and Cond), and its
    /// classification, and common tail block of its successors (if it's a
    /// diamond shape), its size, whether it's predicable, and whether any
    /// instruction can clobber the 'would-be' predicate.
    ///
    /// IsDone          - True if BB is not to be considered for ifcvt.
    /// IsBeingAnalyzed - True if BB is currently being analyzed.
    /// IsAnalyzed      - True if BB has been analyzed (info is still valid).
    /// IsEnqueued      - True if BB has been enqueued to be ifcvt'ed.
    /// IsBrAnalyzable  - True if analyzeBranch() returns false.
    /// HasFallThrough  - True if BB has fallthrough to the following BB.
    ///                   Note that BB may have a fallthrough if both
    ///                   !HasFallThrough and !IsBrAnalyzable is true. Also note
    ///                   that blockNeverFallThrough() can be used to prove that
    ///                   there is no fall through.
    /// IsUnpredicable  - True if BB is known to be unpredicable.
    /// ClobbersPred    - True if BB could modify predicates (e.g. has
    ///                   cmp, call, etc.)
    /// NonPredSize     - Number of non-predicated instructions.
    /// ExtraCost       - Extra cost for multi-cycle instructions.
    /// ExtraCost2      - Some instructions are slower when predicated
    /// BB              - Corresponding MachineBasicBlock.
    /// TrueBB / FalseBB- See analyzeBranch(), but note that FalseBB can be set
    ///                   by AnalyzeBranches even if there is a fallthrough. So
    ///                   it doesn't correspond exactly to the result from
    ///                   TTI::analyzeBranch.
    /// BrCond          - Conditions for end of block conditional branches.
    /// Predicate       - Predicate used in the BB.
    struct BBInfo {
      bool IsDone          : 1;
      bool IsBeingAnalyzed : 1;
      bool IsAnalyzed      : 1;
      bool IsEnqueued      : 1;
      bool IsBrAnalyzable  : 1;
      bool IsBrReversible  : 1;
      bool HasFallThrough  : 1;
      bool IsUnpredicable  : 1;
      bool CannotBeCopied  : 1;
      bool ClobbersPred    : 1;
      unsigned NonPredSize = 0;
      unsigned ExtraCost = 0;
      unsigned ExtraCost2 = 0;
      MachineBasicBlock *BB = nullptr;
      MachineBasicBlock *TrueBB = nullptr;
      MachineBasicBlock *FalseBB = nullptr;
      SmallVector<MachineOperand, 4> BrCond;
      SmallVector<MachineOperand, 4> Predicate;

      BBInfo() : IsDone(false), IsBeingAnalyzed(false),
                 IsAnalyzed(false), IsEnqueued(false), IsBrAnalyzable(false),
                 IsBrReversible(false), HasFallThrough(false),
                 IsUnpredicable(false), CannotBeCopied(false),
                 ClobbersPred(false) {}
    };

    /// Record information about pending if-conversions to attempt:
    /// BBI             - Corresponding BBInfo.
    /// Kind            - Type of block. See IfcvtKind.
    /// NeedSubsumption - True if the to-be-predicated BB has already been
    ///                   predicated.
    /// NumDups      - Number of instructions that would be duplicated due
    ///                   to this if-conversion. (For diamonds, the number of
    ///                   identical instructions at the beginnings of both
    ///                   paths).
    /// NumDups2     - For diamonds, the number of identical instructions
    ///                   at the ends of both paths.
    struct IfcvtToken {
      BBInfo &BBI;
      IfcvtKind Kind;
      unsigned NumDups;
      unsigned NumDups2;
      bool NeedSubsumption : 1;
      bool TClobbersPred : 1;
      bool FClobbersPred : 1;

      IfcvtToken(BBInfo &b, IfcvtKind k, bool s, unsigned d, unsigned d2 = 0,
                 bool tc = false, bool fc = false)
        : BBI(b), Kind(k), NumDups(d), NumDups2(d2), NeedSubsumption(s),
          TClobbersPred(tc), FClobbersPred(fc) {}
    };

    /// Results of if-conversion feasibility analysis indexed by basic block
    /// number.
    std::vector<BBInfo> BBAnalysis;
    TargetSchedModel SchedModel;

    const TargetLoweringBase *TLI = nullptr;
    const TargetInstrInfo *TII = nullptr;
    const TargetRegisterInfo *TRI = nullptr;
    const MachineBranchProbabilityInfo *MBPI = nullptr;
    MachineRegisterInfo *MRI = nullptr;

    LivePhysRegs Redefs;

    bool PreRegAlloc = true;
    bool MadeChange = false;
    int FnNum = -1;
    std::function<bool(const MachineFunction &)> PredicateFtor;

  public:
    static char ID;

    IfConverter(std::function<bool(const MachineFunction &)> Ftor = nullptr)
        : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) {
      initializeIfConverterPass(*PassRegistry::getPassRegistry());
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
      AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
      AU.addRequired<ProfileSummaryInfoWrapperPass>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

    bool runOnMachineFunction(MachineFunction &MF) override;

    MachineFunctionProperties getRequiredProperties() const override {
      return MachineFunctionProperties().setNoVRegs();
    }

  private:
    bool reverseBranchCondition(BBInfo &BBI) const;
    bool ValidSimple(BBInfo &TrueBBI, unsigned &Dups,
                     BranchProbability Prediction) const;
    bool ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI,
                       bool FalseBranch, unsigned &Dups,
                       BranchProbability Prediction) const;
    bool CountDuplicatedInstructions(
        MachineBasicBlock::iterator &TIB, MachineBasicBlock::iterator &FIB,
        MachineBasicBlock::iterator &TIE, MachineBasicBlock::iterator &FIE,
        unsigned &Dups1, unsigned &Dups2,
        MachineBasicBlock &TBB, MachineBasicBlock &FBB,
        bool SkipUnconditionalBranches) const;
    bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
                      unsigned &Dups1, unsigned &Dups2,
                      BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const;
    bool ValidForkedDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
                            unsigned &Dups1, unsigned &Dups2,
                            BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const;
    void AnalyzeBranches(BBInfo &BBI);
    void ScanInstructions(BBInfo &BBI,
                          MachineBasicBlock::iterator &Begin,
                          MachineBasicBlock::iterator &End,
                          bool BranchUnpredicable = false) const;
    bool RescanInstructions(
        MachineBasicBlock::iterator &TIB, MachineBasicBlock::iterator &FIB,
        MachineBasicBlock::iterator &TIE, MachineBasicBlock::iterator &FIE,
        BBInfo &TrueBBI, BBInfo &FalseBBI) const;
    void AnalyzeBlock(MachineBasicBlock &MBB,
                      std::vector<std::unique_ptr<IfcvtToken>> &Tokens);
    bool FeasibilityAnalysis(BBInfo &BBI, SmallVectorImpl<MachineOperand> &Pred,
                             bool isTriangle = false, bool RevBranch = false,
                             bool hasCommonTail = false);
    void AnalyzeBlocks(MachineFunction &MF,
                       std::vector<std::unique_ptr<IfcvtToken>> &Tokens);
    void InvalidatePreds(MachineBasicBlock &MBB);
    bool IfConvertSimple(BBInfo &BBI, IfcvtKind Kind);
    bool IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind);
    bool IfConvertDiamondCommon(BBInfo &BBI, BBInfo &TrueBBI, BBInfo &FalseBBI,
                                unsigned NumDups1, unsigned NumDups2,
                                bool TClobbersPred, bool FClobbersPred,
                                bool RemoveBranch, bool MergeAddEdges);
    bool IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
                          unsigned NumDups1, unsigned NumDups2,
                          bool TClobbers, bool FClobbers);
    bool IfConvertForkedDiamond(BBInfo &BBI, IfcvtKind Kind,
                              unsigned NumDups1, unsigned NumDups2,
                              bool TClobbers, bool FClobbers);
    void PredicateBlock(BBInfo &BBI, MachineBasicBlock::iterator E,
                        SmallVectorImpl<MachineOperand> &Cond,
                        SmallSet<MCRegister, 4> *LaterRedefs = nullptr);
    void CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI,
                               SmallVectorImpl<MachineOperand> &Cond,
                               bool IgnoreBr = false);
    void MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges = true);

    bool MeetIfcvtSizeLimit(MachineBasicBlock &BB,
                            unsigned Cycle, unsigned Extra,
                            BranchProbability Prediction) const {
      return Cycle > 0 && TII->isProfitableToIfCvt(BB, Cycle, Extra,
                                                   Prediction);
    }

    bool MeetIfcvtSizeLimit(BBInfo &TBBInfo, BBInfo &FBBInfo,
                            MachineBasicBlock &CommBB, unsigned Dups,
                            BranchProbability Prediction, bool Forked) const {
      const MachineFunction &MF = *TBBInfo.BB->getParent();
      if (MF.getFunction().hasMinSize()) {
        MachineBasicBlock::iterator TIB = TBBInfo.BB->begin();
        MachineBasicBlock::iterator FIB = FBBInfo.BB->begin();
        MachineBasicBlock::iterator TIE = TBBInfo.BB->end();
        MachineBasicBlock::iterator FIE = FBBInfo.BB->end();

        unsigned Dups1 = 0, Dups2 = 0;
        if (!CountDuplicatedInstructions(TIB, FIB, TIE, FIE, Dups1, Dups2,
                                         *TBBInfo.BB, *FBBInfo.BB,
                                         /*SkipUnconditionalBranches*/ true))
          llvm_unreachable("should already have been checked by ValidDiamond");

        unsigned BranchBytes = 0;
        unsigned CommonBytes = 0;

        // Count common instructions at the start of the true and false blocks.
        for (auto &I : make_range(TBBInfo.BB->begin(), TIB)) {
          LLVM_DEBUG(dbgs() << "Common inst: " << I);
          CommonBytes += TII->getInstSizeInBytes(I);
        }
        for (auto &I : make_range(FBBInfo.BB->begin(), FIB)) {
          LLVM_DEBUG(dbgs() << "Common inst: " << I);
          CommonBytes += TII->getInstSizeInBytes(I);
        }

        // Count instructions at the end of the true and false blocks, after
        // the ones we plan to predicate. Analyzable branches will be removed
        // (unless this is a forked diamond), and all other instructions are
        // common between the two blocks.
        for (auto &I : make_range(TIE, TBBInfo.BB->end())) {
          if (I.isBranch() && TBBInfo.IsBrAnalyzable && !Forked) {
            LLVM_DEBUG(dbgs() << "Saving branch: " << I);
            BranchBytes += TII->predictBranchSizeForIfCvt(I);
          } else {
            LLVM_DEBUG(dbgs() << "Common inst: " << I);
            CommonBytes += TII->getInstSizeInBytes(I);
          }
        }
        for (auto &I : make_range(FIE, FBBInfo.BB->end())) {
          if (I.isBranch() && FBBInfo.IsBrAnalyzable && !Forked) {
            LLVM_DEBUG(dbgs() << "Saving branch: " << I);
            BranchBytes += TII->predictBranchSizeForIfCvt(I);
          } else {
            LLVM_DEBUG(dbgs() << "Common inst: " << I);
            CommonBytes += TII->getInstSizeInBytes(I);
          }
        }
        for (auto &I : CommBB.terminators()) {
          if (I.isBranch()) {
            LLVM_DEBUG(dbgs() << "Saving branch: " << I);
            BranchBytes += TII->predictBranchSizeForIfCvt(I);
          }
        }

        // The common instructions in one branch will be eliminated, halving
        // their code size.
        CommonBytes /= 2;

        // Count the instructions which we need to predicate.
        unsigned NumPredicatedInstructions = 0;
        for (auto &I : make_range(TIB, TIE)) {
          if (!I.isDebugInstr()) {
            LLVM_DEBUG(dbgs() << "Predicating: " << I);
            NumPredicatedInstructions++;
          }
        }
        for (auto &I : make_range(FIB, FIE)) {
          if (!I.isDebugInstr()) {
            LLVM_DEBUG(dbgs() << "Predicating: " << I);
            NumPredicatedInstructions++;
          }
        }

        // Even though we're optimising for size at the expense of performance,
        // avoid creating really long predicated blocks.
        if (NumPredicatedInstructions > 15)
          return false;

        // Some targets (e.g. Thumb2) need to insert extra instructions to
        // start predicated blocks.
        unsigned ExtraPredicateBytes = TII->extraSizeToPredicateInstructions(
            MF, NumPredicatedInstructions);

        LLVM_DEBUG(dbgs() << "MeetIfcvtSizeLimit(BranchBytes=" << BranchBytes
                          << ", CommonBytes=" << CommonBytes
                          << ", NumPredicatedInstructions="
                          << NumPredicatedInstructions
                          << ", ExtraPredicateBytes=" << ExtraPredicateBytes
                          << ")\n");
        return (BranchBytes + CommonBytes) > ExtraPredicateBytes;
      } else {
        unsigned TCycle = TBBInfo.NonPredSize + TBBInfo.ExtraCost - Dups;
        unsigned FCycle = FBBInfo.NonPredSize + FBBInfo.ExtraCost - Dups;
        bool Res = TCycle > 0 && FCycle > 0 &&
                   TII->isProfitableToIfCvt(
                       *TBBInfo.BB, TCycle, TBBInfo.ExtraCost2, *FBBInfo.BB,
                       FCycle, FBBInfo.ExtraCost2, Prediction);
        LLVM_DEBUG(dbgs() << "MeetIfcvtSizeLimit(TCycle=" << TCycle
                          << ", FCycle=" << FCycle
                          << ", TExtra=" << TBBInfo.ExtraCost2 << ", FExtra="
                          << FBBInfo.ExtraCost2 << ") = " << Res << "\n");
        return Res;
      }
    }

    /// Returns true if Block ends without a terminator.
    bool blockAlwaysFallThrough(BBInfo &BBI) const {
      return BBI.IsBrAnalyzable && BBI.TrueBB == nullptr;
    }

    /// Returns true if Block is known not to fallthrough to the following BB.
    bool blockNeverFallThrough(BBInfo &BBI) const {
      // Trust "HasFallThrough" if we could analyze branches.
      if (BBI.IsBrAnalyzable)
        return !BBI.HasFallThrough;
      // If this is the last MBB in the function, or if the textual successor
      // isn't in the successor list, then there is no fallthrough.
      MachineFunction::iterator PI = BBI.BB->getIterator();
      MachineFunction::iterator I = std::next(PI);
      if (I == BBI.BB->getParent()->end() || !PI->isSuccessor(&*I))
        return true;
      // Could not prove that there is no fallthrough.
      return false;
    }

    /// Used to sort if-conversion candidates.
    static bool IfcvtTokenCmp(const std::unique_ptr<IfcvtToken> &C1,
                              const std::unique_ptr<IfcvtToken> &C2) {
      int Incr1 = (C1->Kind == ICDiamond)
        ? -(int)(C1->NumDups + C1->NumDups2) : (int)C1->NumDups;
      int Incr2 = (C2->Kind == ICDiamond)
        ? -(int)(C2->NumDups + C2->NumDups2) : (int)C2->NumDups;
      if (Incr1 > Incr2)
        return true;
      else if (Incr1 == Incr2) {
        // Favors subsumption.
        if (!C1->NeedSubsumption && C2->NeedSubsumption)
          return true;
        else if (C1->NeedSubsumption == C2->NeedSubsumption) {
          // Favors diamond over triangle, etc.
          if ((unsigned)C1->Kind < (unsigned)C2->Kind)
            return true;
          else if (C1->Kind == C2->Kind)
            return C1->BBI.BB->getNumber() < C2->BBI.BB->getNumber();
        }
      }
      return false;
    }
  };

} // end anonymous namespace

char IfConverter::ID = 0;

char &llvm::IfConverterID = IfConverter::ID;

INITIALIZE_PASS_BEGIN(IfConverter, DEBUG_TYPE, "If Converter", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_END(IfConverter, DEBUG_TYPE, "If Converter", false, false)

bool IfConverter::runOnMachineFunction(MachineFunction &MF) {
  if (skipFunction(MF.getFunction()) || (PredicateFtor && !PredicateFtor(MF)))
    return false;

  const TargetSubtargetInfo &ST = MF.getSubtarget();
  TLI = ST.getTargetLowering();
  TII = ST.getInstrInfo();
  TRI = ST.getRegisterInfo();
  MBFIWrapper MBFI(
      getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI());
  MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
  ProfileSummaryInfo *PSI =
      &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
  MRI = &MF.getRegInfo();
  SchedModel.init(&ST);

  if (!TII) return false;

  PreRegAlloc = MRI->isSSA();

  bool BFChange = false;
  if (!PreRegAlloc) {
    // Tail merge tend to expose more if-conversion opportunities.
    BranchFolder BF(true, false, MBFI, *MBPI, PSI);
    BFChange = BF.OptimizeFunction(MF, TII, ST.getRegisterInfo());
  }

  LLVM_DEBUG(dbgs() << "\nIfcvt: function (" << ++FnNum << ") \'"
                    << MF.getName() << "\'");

  if (FnNum < IfCvtFnStart || (IfCvtFnStop != -1 && FnNum > IfCvtFnStop)) {
    LLVM_DEBUG(dbgs() << " skipped\n");
    return false;
  }
  LLVM_DEBUG(dbgs() << "\n");

  MF.RenumberBlocks();
  BBAnalysis.resize(MF.getNumBlockIDs());

  std::vector<std::unique_ptr<IfcvtToken>> Tokens;
  MadeChange = false;
  unsigned NumIfCvts = NumSimple + NumSimpleFalse + NumTriangle +
    NumTriangleRev + NumTriangleFalse + NumTriangleFRev + NumDiamonds;
  while (IfCvtLimit == -1 || (int)NumIfCvts < IfCvtLimit) {
    // Do an initial analysis for each basic block and find all the potential
    // candidates to perform if-conversion.
    bool Change = false;
    AnalyzeBlocks(MF, Tokens);
    while (!Tokens.empty()) {
      std::unique_ptr<IfcvtToken> Token = std::move(Tokens.back());
      Tokens.pop_back();
      BBInfo &BBI = Token->BBI;
      IfcvtKind Kind = Token->Kind;
      unsigned NumDups = Token->NumDups;
      unsigned NumDups2 = Token->NumDups2;

      // If the block has been evicted out of the queue or it has already been
      // marked dead (due to it being predicated), then skip it.
      if (BBI.IsDone)
        BBI.IsEnqueued = false;
      if (!BBI.IsEnqueued)
        continue;

      BBI.IsEnqueued = false;

      bool RetVal = false;
      switch (Kind) {
      default: llvm_unreachable("Unexpected!");
      case ICSimple:
      case ICSimpleFalse: {
        bool isFalse = Kind == ICSimpleFalse;
        if ((isFalse && DisableSimpleF) || (!isFalse && DisableSimple)) break;
        LLVM_DEBUG(dbgs() << "Ifcvt (Simple"
                          << (Kind == ICSimpleFalse ? " false" : "")
                          << "): " << printMBBReference(*BBI.BB) << " ("
                          << ((Kind == ICSimpleFalse) ? BBI.FalseBB->getNumber()
                                                      : BBI.TrueBB->getNumber())
                          << ") ");
        RetVal = IfConvertSimple(BBI, Kind);
        LLVM_DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n");
        if (RetVal) {
          if (isFalse) ++NumSimpleFalse;
          else         ++NumSimple;
        }
       break;
      }
      case ICTriangle:
      case ICTriangleRev:
      case ICTriangleFalse:
      case ICTriangleFRev: {
        bool isFalse = Kind == ICTriangleFalse;
        bool isRev   = (Kind == ICTriangleRev || Kind == ICTriangleFRev);
        if (DisableTriangle && !isFalse && !isRev) break;
        if (DisableTriangleR && !isFalse && isRev) break;
        if (DisableTriangleF && isFalse && !isRev) break;
        LLVM_DEBUG(dbgs() << "Ifcvt (Triangle");
        if (isFalse)
          LLVM_DEBUG(dbgs() << " false");
        if (isRev)
          LLVM_DEBUG(dbgs() << " rev");
        LLVM_DEBUG(dbgs() << "): " << printMBBReference(*BBI.BB)
                          << " (T:" << BBI.TrueBB->getNumber()
                          << ",F:" << BBI.FalseBB->getNumber() << ") ");
        RetVal = IfConvertTriangle(BBI, Kind);
        LLVM_DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n");
        if (RetVal) {
          if (isFalse)
            ++NumTriangleFalse;
          else if (isRev)
            ++NumTriangleRev;
          else
            ++NumTriangle;
        }
        break;
      }
      case ICDiamond:
        if (DisableDiamond) break;
        LLVM_DEBUG(dbgs() << "Ifcvt (Diamond): " << printMBBReference(*BBI.BB)
                          << " (T:" << BBI.TrueBB->getNumber()
                          << ",F:" << BBI.FalseBB->getNumber() << ") ");
        RetVal = IfConvertDiamond(BBI, Kind, NumDups, NumDups2,
                                  Token->TClobbersPred,
                                  Token->FClobbersPred);
        LLVM_DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n");
        if (RetVal) ++NumDiamonds;
        break;
      case ICForkedDiamond:
        if (DisableForkedDiamond) break;
        LLVM_DEBUG(dbgs() << "Ifcvt (Forked Diamond): "
                          << printMBBReference(*BBI.BB)
                          << " (T:" << BBI.TrueBB->getNumber()
                          << ",F:" << BBI.FalseBB->getNumber() << ") ");
        RetVal = IfConvertForkedDiamond(BBI, Kind, NumDups, NumDups2,
                                      Token->TClobbersPred,
                                      Token->FClobbersPred);
        LLVM_DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n");
        if (RetVal) ++NumForkedDiamonds;
        break;
      }

      if (RetVal && MRI->tracksLiveness())
        recomputeLivenessFlags(*BBI.BB);

      Change |= RetVal;

      NumIfCvts = NumSimple + NumSimpleFalse + NumTriangle + NumTriangleRev +
        NumTriangleFalse + NumTriangleFRev + NumDiamonds;
      if (IfCvtLimit != -1 && (int)NumIfCvts >= IfCvtLimit)
        break;
    }

    if (!Change)
      break;
    MadeChange |= Change;
  }

  Tokens.clear();
  BBAnalysis.clear();

  if (MadeChange && IfCvtBranchFold) {
    BranchFolder BF(false, false, MBFI, *MBPI, PSI);
    BF.OptimizeFunction(MF, TII, MF.getSubtarget().getRegisterInfo());
  }

  MadeChange |= BFChange;
  return MadeChange;
}

/// BB has a fallthrough. Find its 'false' successor given its 'true' successor.
static MachineBasicBlock *findFalseBlock(MachineBasicBlock *BB,
                                         MachineBasicBlock *TrueBB) {
  for (MachineBasicBlock *SuccBB : BB->successors()) {
    if (SuccBB != TrueBB)
      return SuccBB;
  }
  return nullptr;
}

/// Reverse the condition of the end of the block branch. Swap block's 'true'
/// and 'false' successors.
bool IfConverter::reverseBranchCondition(BBInfo &BBI) const {
  DebugLoc dl;  // FIXME: this is nowhere
  if (!TII->reverseBranchCondition(BBI.BrCond)) {
    TII->removeBranch(*BBI.BB);
    TII->insertBranch(*BBI.BB, BBI.FalseBB, BBI.TrueBB, BBI.BrCond, dl);
    std::swap(BBI.TrueBB, BBI.FalseBB);
    return true;
  }
  return false;
}

/// Returns the next block in the function blocks ordering. If it is the end,
/// returns NULL.
static inline MachineBasicBlock *getNextBlock(MachineBasicBlock &MBB) {
  MachineFunction::iterator I = MBB.getIterator();
  MachineFunction::iterator E = MBB.getParent()->end();
  if (++I == E)
    return nullptr;
  return &*I;
}

/// Returns true if the 'true' block (along with its predecessor) forms a valid
/// simple shape for ifcvt. It also returns the number of instructions that the
/// ifcvt would need to duplicate if performed in Dups.
bool IfConverter::ValidSimple(BBInfo &TrueBBI, unsigned &Dups,
                              BranchProbability Prediction) const {
  Dups = 0;
  if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone)
    return false;

  if (TrueBBI.IsBrAnalyzable)
    return false;

  if (TrueBBI.BB->pred_size() > 1) {
    if (TrueBBI.CannotBeCopied ||
        !TII->isProfitableToDupForIfCvt(*TrueBBI.BB, TrueBBI.NonPredSize,
                                        Prediction))
      return false;
    Dups = TrueBBI.NonPredSize;
  }

  return true;
}

/// Returns true if the 'true' and 'false' blocks (along with their common
/// predecessor) forms a valid triangle shape for ifcvt. If 'FalseBranch' is
/// true, it checks if 'true' block's false branch branches to the 'false' block
/// rather than the other way around. It also returns the number of instructions
/// that the ifcvt would need to duplicate if performed in 'Dups'.
bool IfConverter::ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI,
                                bool FalseBranch, unsigned &Dups,
                                BranchProbability Prediction) const {
  Dups = 0;
  if (TrueBBI.BB == FalseBBI.BB)
    return false;

  if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone)
    return false;

  if (TrueBBI.BB->pred_size() > 1) {
    if (TrueBBI.CannotBeCopied)
      return false;

    unsigned Size = TrueBBI.NonPredSize;
    if (TrueBBI.IsBrAnalyzable) {
      if (TrueBBI.TrueBB && TrueBBI.BrCond.empty())
        // Ends with an unconditional branch. It will be removed.
        --Size;
      else {
        MachineBasicBlock *FExit = FalseBranch
          ? TrueBBI.TrueBB : TrueBBI.FalseBB;
        if (FExit)
          // Require a conditional branch
          ++Size;
      }
    }
    if (!TII->isProfitableToDupForIfCvt(*TrueBBI.BB, Size, Prediction))
      return false;
    Dups = Size;
  }

  MachineBasicBlock *TExit = FalseBranch ? TrueBBI.FalseBB : TrueBBI.TrueBB;
  if (!TExit && blockAlwaysFallThrough(TrueBBI)) {
    MachineFunction::iterator I = TrueBBI.BB->getIterator();
    if (++I == TrueBBI.BB->getParent()->end())
      return false;
    TExit = &*I;
  }
  return TExit && TExit == FalseBBI.BB;
}

/// Count duplicated instructions and move the iterators to show where they
/// are.
/// @param TIB True Iterator Begin
/// @param FIB False Iterator Begin
/// These two iterators initially point to the first instruction of the two
/// blocks, and finally point to the first non-shared instruction.
/// @param TIE True Iterator End
/// @param FIE False Iterator End
/// These two iterators initially point to End() for the two blocks() and
/// finally point to the first shared instruction in the tail.
/// Upon return [TIB, TIE), and [FIB, FIE) mark the un-duplicated portions of
/// two blocks.
/// @param Dups1 count of duplicated instructions at the beginning of the 2
/// blocks.
/// @param Dups2 count of duplicated instructions at the end of the 2 blocks.
/// @param SkipUnconditionalBranches if true, Don't make sure that
/// unconditional branches at the end of the blocks are the same. True is
/// passed when the blocks are analyzable to allow for fallthrough to be
/// handled.
/// @return false if the shared portion prevents if conversion.
bool IfConverter::CountDuplicatedInstructions(
    MachineBasicBlock::iterator &TIB,
    MachineBasicBlock::iterator &FIB,
    MachineBasicBlock::iterator &TIE,
    MachineBasicBlock::iterator &FIE,
    unsigned &Dups1, unsigned &Dups2,
    MachineBasicBlock &TBB, MachineBasicBlock &FBB,
    bool SkipUnconditionalBranches) const {
  while (TIB != TIE && FIB != FIE) {
    // Skip dbg_value instructions. These do not count.
    TIB = skipDebugInstructionsForward(TIB, TIE, false);
    FIB = skipDebugInstructionsForward(FIB, FIE, false);
    if (TIB == TIE || FIB == FIE)
      break;
    if (!TIB->isIdenticalTo(*FIB))
      break;
    // A pred-clobbering instruction in the shared portion prevents
    // if-conversion.
    std::vector<MachineOperand> PredDefs;
    if (TII->ClobbersPredicate(*TIB, PredDefs, false))
      return false;
    // If we get all the way to the branch instructions, don't count them.
    if (!TIB->isBranch())
      ++Dups1;
    ++TIB;
    ++FIB;
  }

  // Check for already containing all of the block.
  if (TIB == TIE || FIB == FIE)
    return true;
  // Now, in preparation for counting duplicate instructions at the ends of the
  // blocks, switch to reverse_iterators. Note that getReverse() returns an
  // iterator that points to the same instruction, unlike std::reverse_iterator.
  // We have to do our own shifting so that we get the same range.
  MachineBasicBlock::reverse_iterator RTIE = std::next(TIE.getReverse());
  MachineBasicBlock::reverse_iterator RFIE = std::next(FIE.getReverse());
  const MachineBasicBlock::reverse_iterator RTIB = std::next(TIB.getReverse());
  const MachineBasicBlock::reverse_iterator RFIB = std::next(FIB.getReverse());

  if (!TBB.succ_empty() || !FBB.succ_empty()) {
    if (SkipUnconditionalBranches) {
      while (RTIE != RTIB && RTIE->isUnconditionalBranch())
        ++RTIE;
      while (RFIE != RFIB && RFIE->isUnconditionalBranch())
        ++RFIE;
    }
  }

  // Count duplicate instructions at the ends of the blocks.
  while (RTIE != RTIB && RFIE != RFIB) {
    // Skip dbg_value instructions. These do not count.
    // Note that these are reverse iterators going forward.
    RTIE = skipDebugInstructionsForward(RTIE, RTIB, false);
    RFIE = skipDebugInstructionsForward(RFIE, RFIB, false);
    if (RTIE == RTIB || RFIE == RFIB)
      break;
    if (!RTIE->isIdenticalTo(*RFIE))
      break;
    // We have to verify that any branch instructions are the same, and then we
    // don't count them toward the # of duplicate instructions.
    if (!RTIE->isBranch())
      ++Dups2;
    ++RTIE;
    ++RFIE;
  }
  TIE = std::next(RTIE.getReverse());
  FIE = std::next(RFIE.getReverse());
  return true;
}

/// RescanInstructions - Run ScanInstructions on a pair of blocks.
/// @param TIB - True Iterator Begin, points to first non-shared instruction
/// @param FIB - False Iterator Begin, points to first non-shared instruction
/// @param TIE - True Iterator End, points past last non-shared instruction
/// @param FIE - False Iterator End, points past last non-shared instruction
/// @param TrueBBI  - BBInfo to update for the true block.
/// @param FalseBBI - BBInfo to update for the false block.
/// @returns - false if either block cannot be predicated or if both blocks end
///   with a predicate-clobbering instruction.
bool IfConverter::RescanInstructions(
    MachineBasicBlock::iterator &TIB, MachineBasicBlock::iterator &FIB,
    MachineBasicBlock::iterator &TIE, MachineBasicBlock::iterator &FIE,
    BBInfo &TrueBBI, BBInfo &FalseBBI) const {
  bool BranchUnpredicable = true;
  TrueBBI.IsUnpredicable = FalseBBI.IsUnpredicable = false;
  ScanInstructions(TrueBBI, TIB, TIE, BranchUnpredicable);
  if (TrueBBI.IsUnpredicable)
    return false;
  ScanInstructions(FalseBBI, FIB, FIE, BranchUnpredicable);
  if (FalseBBI.IsUnpredicable)
    return false;
  if (TrueBBI.ClobbersPred && FalseBBI.ClobbersPred)
    return false;
  return true;
}

#ifndef NDEBUG
static void verifySameBranchInstructions(
    MachineBasicBlock *MBB1,
    MachineBasicBlock *MBB2) {
  const MachineBasicBlock::reverse_iterator B1 = MBB1->rend();
  const MachineBasicBlock::reverse_iterator B2 = MBB2->rend();
  MachineBasicBlock::reverse_iterator E1 = MBB1->rbegin();
  MachineBasicBlock::reverse_iterator E2 = MBB2->rbegin();
  while (E1 != B1 && E2 != B2) {
    skipDebugInstructionsForward(E1, B1, false);
    skipDebugInstructionsForward(E2, B2, false);
    if (E1 == B1 && E2 == B2)
      break;

    if (E1 == B1) {
      assert(!E2->isBranch() && "Branch mis-match, one block is empty.");
      break;
    }
    if (E2 == B2) {
      assert(!E1->isBranch() && "Branch mis-match, one block is empty.");
      break;
    }

    if (E1->isBranch() || E2->isBranch())
      assert(E1->isIdenticalTo(*E2) &&
             "Branch mis-match, branch instructions don't match.");
    else
      break;
    ++E1;
    ++E2;
  }
}
#endif

/// ValidForkedDiamond - Returns true if the 'true' and 'false' blocks (along
/// with their common predecessor) form a diamond if a common tail block is
/// extracted.
/// While not strictly a diamond, this pattern would form a diamond if
/// tail-merging had merged the shared tails.
///           EBB
///         _/   \_
///         |     |
///        TBB   FBB
///        /  \ /   \
///  FalseBB TrueBB FalseBB
/// Currently only handles analyzable branches.
/// Specifically excludes actual diamonds to avoid overlap.
bool IfConverter::ValidForkedDiamond(
    BBInfo &TrueBBI, BBInfo &FalseBBI,
    unsigned &Dups1, unsigned &Dups2,
    BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const {
  Dups1 = Dups2 = 0;
  if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone ||
      FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone)
    return false;

  if (!TrueBBI.IsBrAnalyzable || !FalseBBI.IsBrAnalyzable)
    return false;
  // Don't IfConvert blocks that can't be folded into their predecessor.
  if  (TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1)
    return false;

  // This function is specifically looking for conditional tails, as
  // unconditional tails are already handled by the standard diamond case.
  if (TrueBBI.BrCond.size() == 0 ||
      FalseBBI.BrCond.size() == 0)
    return false;

  MachineBasicBlock *TT = TrueBBI.TrueBB;
  MachineBasicBlock *TF = TrueBBI.FalseBB;
  MachineBasicBlock *FT = FalseBBI.TrueBB;
  MachineBasicBlock *FF = FalseBBI.FalseBB;

  if (!TT)
    TT = getNextBlock(*TrueBBI.BB);
  if (!TF)
    TF = getNextBlock(*TrueBBI.BB);
  if (!FT)
    FT = getNextBlock(*FalseBBI.BB);
  if (!FF)
    FF = getNextBlock(*FalseBBI.BB);

  if (!TT || !TF)
    return false;

  // Check successors. If they don't match, bail.
  if (!((TT == FT && TF == FF) || (TF == FT && TT == FF)))
    return false;

  bool FalseReversed = false;
  if (TF == FT && TT == FF) {
    // If the branches are opposing, but we can't reverse, don't do it.
    if (!FalseBBI.IsBrReversible)
      return false;
    FalseReversed = true;
    reverseBranchCondition(FalseBBI);
  }
  auto UnReverseOnExit = make_scope_exit([&]() {
    if (FalseReversed)
      reverseBranchCondition(FalseBBI);
  });

  // Count duplicate instructions at the beginning of the true and false blocks.
  MachineBasicBlock::iterator TIB = TrueBBI.BB->begin();
  MachineBasicBlock::iterator FIB = FalseBBI.BB->begin();
  MachineBasicBlock::iterator TIE = TrueBBI.BB->end();
  MachineBasicBlock::iterator FIE = FalseBBI.BB->end();
  if(!CountDuplicatedInstructions(TIB, FIB, TIE, FIE, Dups1, Dups2,
                                  *TrueBBI.BB, *FalseBBI.BB,
                                  /* SkipUnconditionalBranches */ true))
    return false;

  TrueBBICalc.BB = TrueBBI.BB;
  FalseBBICalc.BB = FalseBBI.BB;
  TrueBBICalc.IsBrAnalyzable = TrueBBI.IsBrAnalyzable;
  FalseBBICalc.IsBrAnalyzable = FalseBBI.IsBrAnalyzable;
  if (!RescanInstructions(TIB, FIB, TIE, FIE, TrueBBICalc, FalseBBICalc))
    return false;

  // The size is used to decide whether to if-convert, and the shared portions
  // are subtracted off. Because of the subtraction, we just use the size that
  // was calculated by the original ScanInstructions, as it is correct.
  TrueBBICalc.NonPredSize = TrueBBI.NonPredSize;
  FalseBBICalc.NonPredSize = FalseBBI.NonPredSize;
  return true;
}

/// ValidDiamond - Returns true if the 'true' and 'false' blocks (along
/// with their common predecessor) forms a valid diamond shape for ifcvt.
bool IfConverter::ValidDiamond(
    BBInfo &TrueBBI, BBInfo &FalseBBI,
    unsigned &Dups1, unsigned &Dups2,
    BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const {
  Dups1 = Dups2 = 0;
  if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone ||
      FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone)
    return false;

  // If the True and False BBs are equal we're dealing with a degenerate case
  // that we don't treat as a diamond.
  if (TrueBBI.BB == FalseBBI.BB)
    return false;

  MachineBasicBlock *TT = TrueBBI.TrueBB;
  MachineBasicBlock *FT = FalseBBI.TrueBB;

  if (!TT && blockAlwaysFallThrough(TrueBBI))
    TT = getNextBlock(*TrueBBI.BB);
  if (!FT && blockAlwaysFallThrough(FalseBBI))
    FT = getNextBlock(*FalseBBI.BB);
  if (TT != FT)
    return false;
  if (!TT && (TrueBBI.IsBrAnalyzable || FalseBBI.IsBrAnalyzable))
    return false;
  if  (TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1)
    return false;

  // FIXME: Allow true block to have an early exit?
  if (TrueBBI.FalseBB || FalseBBI.FalseBB)
    return false;

  // Count duplicate instructions at the beginning and end of the true and
  // false blocks.
  // Skip unconditional branches only if we are considering an analyzable
  // diamond. Otherwise the branches must be the same.
  bool SkipUnconditionalBranches =
      TrueBBI.IsBrAnalyzable && FalseBBI.IsBrAnalyzable;
  MachineBasicBlock::iterator TIB = TrueBBI.BB->begin();
  MachineBasicBlock::iterator FIB = FalseBBI.BB->begin();
  MachineBasicBlock::iterator TIE = TrueBBI.BB->end();
  MachineBasicBlock::iterator FIE = FalseBBI.BB->end();
  if(!CountDuplicatedInstructions(TIB, FIB, TIE, FIE, Dups1, Dups2,
                                  *TrueBBI.BB, *FalseBBI.BB,
                                  SkipUnconditionalBranches))
    return false;

  TrueBBICalc.BB = TrueBBI.BB;
  FalseBBICalc.BB = FalseBBI.BB;
  TrueBBICalc.IsBrAnalyzable = TrueBBI.IsBrAnalyzable;
  FalseBBICalc.IsBrAnalyzable = FalseBBI.IsBrAnalyzable;
  if (!RescanInstructions(TIB, FIB, TIE, FIE, TrueBBICalc, FalseBBICalc))
    return false;
  // The size is used to decide whether to if-convert, and the shared portions
  // are subtracted off. Because of the subtraction, we just use the size that
  // was calculated by the original ScanInstructions, as it is correct.
  TrueBBICalc.NonPredSize = TrueBBI.NonPredSize;
  FalseBBICalc.NonPredSize = FalseBBI.NonPredSize;
  return true;
}

/// AnalyzeBranches - Look at the branches at the end of a block to determine if
/// the block is predicable.
void IfConverter::AnalyzeBranches(BBInfo &BBI) {
  if (BBI.IsDone)
    return;

  BBI.TrueBB = BBI.FalseBB = nullptr;
  BBI.BrCond.clear();
  BBI.IsBrAnalyzable =
      !TII->analyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond);
  if (!BBI.IsBrAnalyzable) {
    BBI.TrueBB = nullptr;
    BBI.FalseBB = nullptr;
    BBI.BrCond.clear();
  }

  SmallVector<MachineOperand, 4> RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
  BBI.IsBrReversible = (RevCond.size() == 0) ||
      !TII->reverseBranchCondition(RevCond);
  BBI.HasFallThrough = BBI.IsBrAnalyzable && BBI.FalseBB == nullptr;

  if (BBI.BrCond.size()) {
    // No false branch. This BB must end with a conditional branch and a
    // fallthrough.
    if (!BBI.FalseBB)
      BBI.FalseBB = findFalseBlock(BBI.BB, BBI.TrueBB);
    if (!BBI.FalseBB) {
      // Malformed bcc? True and false blocks are the same?
      BBI.IsUnpredicable = true;
    }
  }
}

/// ScanInstructions - Scan all the instructions in the block to determine if
/// the block is predicable. In most cases, that means all the instructions
/// in the block are isPredicable(). Also checks if the block contains any
/// instruction which can clobber a predicate (e.g. condition code register).
/// If so, the block is not predicable unless it's the last instruction.
void IfConverter::ScanInstructions(BBInfo &BBI,
                                   MachineBasicBlock::iterator &Begin,
                                   MachineBasicBlock::iterator &End,
                                   bool BranchUnpredicable) const {
  if (BBI.IsDone || BBI.IsUnpredicable)
    return;

  bool AlreadyPredicated = !BBI.Predicate.empty();

  BBI.NonPredSize = 0;
  BBI.ExtraCost = 0;
  BBI.ExtraCost2 = 0;
  BBI.ClobbersPred = false;
  for (MachineInstr &MI : make_range(Begin, End)) {
    if (MI.isDebugInstr())
      continue;

    // It's unsafe to duplicate convergent instructions in this context, so set
    // BBI.CannotBeCopied to true if MI is convergent.  To see why, consider the
    // following CFG, which is subject to our "simple" transformation.
    //
    //    BB0     // if (c1) goto BB1; else goto BB2;
    //   /   \
    //  BB1   |
    //   |   BB2  // if (c2) goto TBB; else goto FBB;
    //   |   / |
    //   |  /  |
    //   TBB   |
    //    |    |
    //    |   FBB
    //    |
    //    exit
    //
    // Suppose we want to move TBB's contents up into BB1 and BB2 (in BB1 they'd
    // be unconditional, and in BB2, they'd be predicated upon c2), and suppose
    // TBB contains a convergent instruction.  This is safe iff doing so does
    // not add a control-flow dependency to the convergent instruction -- i.e.,
    // it's safe iff the set of control flows that leads us to the convergent
    // instruction does not get smaller after the transformation.
    //
    // Originally we executed TBB if c1 || c2.  After the transformation, there
    // are two copies of TBB's instructions.  We get to the first if c1, and we
    // get to the second if !c1 && c2.
    //
    // There are clearly fewer ways to satisfy the condition "c1" than
    // "c1 || c2".  Since we've shrunk the set of control flows which lead to
    // our convergent instruction, the transformation is unsafe.
    if (MI.isNotDuplicable() || MI.isConvergent())
      BBI.CannotBeCopied = true;

    bool isPredicated = TII->isPredicated(MI);
    bool isCondBr = BBI.IsBrAnalyzable && MI.isConditionalBranch();

    if (BranchUnpredicable && MI.isBranch()) {
      BBI.IsUnpredicable = true;
      return;
    }

    // A conditional branch is not predicable, but it may be eliminated.
    if (isCondBr)
      continue;

    if (!isPredicated) {
      BBI.NonPredSize++;
      unsigned ExtraPredCost = TII->getPredicationCost(MI);
      unsigned NumCycles = SchedModel.computeInstrLatency(&MI, false);
      if (NumCycles > 1)
        BBI.ExtraCost += NumCycles-1;
      BBI.ExtraCost2 += ExtraPredCost;
    } else if (!AlreadyPredicated) {
      // FIXME: This instruction is already predicated before the
      // if-conversion pass. It's probably something like a conditional move.
      // Mark this block unpredicable for now.
      BBI.IsUnpredicable = true;
      return;
    }

    if (BBI.ClobbersPred && !isPredicated) {
      // Predicate modification instruction should end the block (except for
      // already predicated instructions and end of block branches).
      // Predicate may have been modified, the subsequent (currently)
      // unpredicated instructions cannot be correctly predicated.
      BBI.IsUnpredicable = true;
      return;
    }

    // FIXME: Make use of PredDefs? e.g. ADDC, SUBC sets predicates but are
    // still potentially predicable.
    std::vector<MachineOperand> PredDefs;
    if (TII->ClobbersPredicate(MI, PredDefs, true))
      BBI.ClobbersPred = true;

    if (!TII->isPredicable(MI)) {
      BBI.IsUnpredicable = true;
      return;
    }
  }
}

/// Determine if the block is a suitable candidate to be predicated by the
/// specified predicate.
/// @param BBI BBInfo for the block to check
/// @param Pred Predicate array for the branch that leads to BBI
/// @param isTriangle true if the Analysis is for a triangle
/// @param RevBranch true if Reverse(Pred) leads to BBI (e.g. BBI is the false
///        case
/// @param hasCommonTail true if BBI shares a tail with a sibling block that
///        contains any instruction that would make the block unpredicable.
bool IfConverter::FeasibilityAnalysis(BBInfo &BBI,
                                      SmallVectorImpl<MachineOperand> &Pred,
                                      bool isTriangle, bool RevBranch,
                                      bool hasCommonTail) {
  // If the block is dead or unpredicable, then it cannot be predicated.
  // Two blocks may share a common unpredicable tail, but this doesn't prevent
  // them from being if-converted. The non-shared portion is assumed to have
  // been checked
  if (BBI.IsDone || (BBI.IsUnpredicable && !hasCommonTail))
    return false;

  // If it is already predicated but we couldn't analyze its terminator, the
  // latter might fallthrough, but we can't determine where to.
  // Conservatively avoid if-converting again.
  if (BBI.Predicate.size() && !BBI.IsBrAnalyzable)
    return false;

  // If it is already predicated, check if the new predicate subsumes
  // its predicate.
  if (BBI.Predicate.size() && !TII->SubsumesPredicate(Pred, BBI.Predicate))
    return false;

  if (!hasCommonTail && BBI.BrCond.size()) {
    if (!isTriangle)
      return false;

    // Test predicate subsumption.
    SmallVector<MachineOperand, 4> RevPred(Pred.begin(), Pred.end());
    SmallVector<MachineOperand, 4> Cond(BBI.BrCond.begin(), BBI.BrCond.end());
    if (RevBranch) {
      if (TII->reverseBranchCondition(Cond))
        return false;
    }
    if (TII->reverseBranchCondition(RevPred) ||
        !TII->SubsumesPredicate(Cond, RevPred))
      return false;
  }

  return true;
}

/// Analyze the structure of the sub-CFG starting from the specified block.
/// Record its successors and whether it looks like an if-conversion candidate.
void IfConverter::AnalyzeBlock(
    MachineBasicBlock &MBB, std::vector<std::unique_ptr<IfcvtToken>> &Tokens) {
  struct BBState {
    BBState(MachineBasicBlock &MBB) : MBB(&MBB) {}
    MachineBasicBlock *MBB;

    /// This flag is true if MBB's successors have been analyzed.
    bool SuccsAnalyzed = false;
  };

  // Push MBB to the stack.
  SmallVector<BBState, 16> BBStack(1, MBB);

  while (!BBStack.empty()) {
    BBState &State = BBStack.back();
    MachineBasicBlock *BB = State.MBB;
    BBInfo &BBI = BBAnalysis[BB->getNumber()];

    if (!State.SuccsAnalyzed) {
      if (BBI.IsAnalyzed || BBI.IsBeingAnalyzed) {
        BBStack.pop_back();
        continue;
      }

      BBI.BB = BB;
      BBI.IsBeingAnalyzed = true;

      AnalyzeBranches(BBI);
      MachineBasicBlock::iterator Begin = BBI.BB->begin();
      MachineBasicBlock::iterator End = BBI.BB->end();
      ScanInstructions(BBI, Begin, End);

      // Unanalyzable or ends with fallthrough or unconditional branch, or if is
      // not considered for ifcvt anymore.
      if (!BBI.IsBrAnalyzable || BBI.BrCond.empty() || BBI.IsDone) {
        BBI.IsBeingAnalyzed = false;
        BBI.IsAnalyzed = true;
        BBStack.pop_back();
        continue;
      }

      // Do not ifcvt if either path is a back edge to the entry block.
      if (BBI.TrueBB == BB || BBI.FalseBB == BB) {
        BBI.IsBeingAnalyzed = false;
        BBI.IsAnalyzed = true;
        BBStack.pop_back();
        continue;
      }

      // Do not ifcvt if true and false fallthrough blocks are the same.
      if (!BBI.FalseBB) {
        BBI.IsBeingAnalyzed = false;
        BBI.IsAnalyzed = true;
        BBStack.pop_back();
        continue;
      }

      // Push the False and True blocks to the stack.
      State.SuccsAnalyzed = true;
      BBStack.push_back(*BBI.FalseBB);
      BBStack.push_back(*BBI.TrueBB);
      continue;
    }

    BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
    BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];

    if (TrueBBI.IsDone && FalseBBI.IsDone) {
      BBI.IsBeingAnalyzed = false;
      BBI.IsAnalyzed = true;
      BBStack.pop_back();
      continue;
    }

    SmallVector<MachineOperand, 4>
        RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
    bool CanRevCond = !TII->reverseBranchCondition(RevCond);

    unsigned Dups = 0;
    unsigned Dups2 = 0;
    bool TNeedSub = !TrueBBI.Predicate.empty();
    bool FNeedSub = !FalseBBI.Predicate.empty();
    bool Enqueued = false;

    BranchProbability Prediction = MBPI->getEdgeProbability(BB, TrueBBI.BB);

    if (CanRevCond) {
      BBInfo TrueBBICalc, FalseBBICalc;
      auto feasibleDiamond = [&](bool Forked) {
        bool MeetsSize = MeetIfcvtSizeLimit(TrueBBICalc, FalseBBICalc, *BB,
                                            Dups + Dups2, Prediction, Forked);
        bool TrueFeasible = FeasibilityAnalysis(TrueBBI, BBI.BrCond,
                                                /* IsTriangle */ false, /* RevCond */ false,
                                                /* hasCommonTail */ true);
        bool FalseFeasible = FeasibilityAnalysis(FalseBBI, RevCond,
                                                 /* IsTriangle */ false, /* RevCond */ false,
                                                 /* hasCommonTail */ true);
        return MeetsSize && TrueFeasible && FalseFeasible;
      };

      if (ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2,
                       TrueBBICalc, FalseBBICalc)) {
        if (feasibleDiamond(false)) {
          // Diamond:
          //   EBB
          //   / \_
          //  |   |
          // TBB FBB
          //   \ /
          //  TailBB
          // Note TailBB can be empty.
          Tokens.push_back(std::make_unique<IfcvtToken>(
              BBI, ICDiamond, TNeedSub | FNeedSub, Dups, Dups2,
              (bool) TrueBBICalc.ClobbersPred, (bool) FalseBBICalc.ClobbersPred));
          Enqueued = true;
        }
      } else if (ValidForkedDiamond(TrueBBI, FalseBBI, Dups, Dups2,
                                    TrueBBICalc, FalseBBICalc)) {
        if (feasibleDiamond(true)) {
          // ForkedDiamond:
          // if TBB and FBB have a common tail that includes their conditional
          // branch instructions, then we can If Convert this pattern.
          //          EBB
          //         _/ \_
          //         |   |
          //        TBB  FBB
          //        / \ /   \
          //  FalseBB TrueBB FalseBB
          //
          Tokens.push_back(std::make_unique<IfcvtToken>(
              BBI, ICForkedDiamond, TNeedSub | FNeedSub, Dups, Dups2,
              (bool) TrueBBICalc.ClobbersPred, (bool) FalseBBICalc.ClobbersPred));
          Enqueued = true;
        }
      }
    }

    if (ValidTriangle(TrueBBI, FalseBBI, false, Dups, Prediction) &&
        MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
                           TrueBBI.ExtraCost2, Prediction) &&
        FeasibilityAnalysis(TrueBBI, BBI.BrCond, true)) {
      // Triangle:
      //   EBB
      //   | \_
      //   |  |
      //   | TBB
      //   |  /
      //   FBB
      Tokens.push_back(
          std::make_unique<IfcvtToken>(BBI, ICTriangle, TNeedSub, Dups));
      Enqueued = true;
    }

    if (ValidTriangle(TrueBBI, FalseBBI, true, Dups, Prediction) &&
        MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
                           TrueBBI.ExtraCost2, Prediction) &&
        FeasibilityAnalysis(TrueBBI, BBI.BrCond, true, true)) {
      Tokens.push_back(
          std::make_unique<IfcvtToken>(BBI, ICTriangleRev, TNeedSub, Dups));
      Enqueued = true;
    }

    if (ValidSimple(TrueBBI, Dups, Prediction) &&
        MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
                           TrueBBI.ExtraCost2, Prediction) &&
        FeasibilityAnalysis(TrueBBI, BBI.BrCond)) {
      // Simple (split, no rejoin):
      //   EBB
      //   | \_
      //   |  |
      //   | TBB---> exit
      //   |
      //   FBB
      Tokens.push_back(
          std::make_unique<IfcvtToken>(BBI, ICSimple, TNeedSub, Dups));
      Enqueued = true;
    }

    if (CanRevCond) {
      // Try the other path...
      if (ValidTriangle(FalseBBI, TrueBBI, false, Dups,
                        Prediction.getCompl()) &&
          MeetIfcvtSizeLimit(*FalseBBI.BB,
                             FalseBBI.NonPredSize + FalseBBI.ExtraCost,
                             FalseBBI.ExtraCost2, Prediction.getCompl()) &&
          FeasibilityAnalysis(FalseBBI, RevCond, true)) {
        Tokens.push_back(std::make_unique<IfcvtToken>(BBI, ICTriangleFalse,
                                                       FNeedSub, Dups));
        Enqueued = true;
      }

      if (ValidTriangle(FalseBBI, TrueBBI, true, Dups,
                        Prediction.getCompl()) &&
          MeetIfcvtSizeLimit(*FalseBBI.BB,
                             FalseBBI.NonPredSize + FalseBBI.ExtraCost,
                           FalseBBI.ExtraCost2, Prediction.getCompl()) &&
        FeasibilityAnalysis(FalseBBI, RevCond, true, true)) {
        Tokens.push_back(
            std::make_unique<IfcvtToken>(BBI, ICTriangleFRev, FNeedSub, Dups));
        Enqueued = true;
      }

      if (ValidSimple(FalseBBI, Dups, Prediction.getCompl()) &&
          MeetIfcvtSizeLimit(*FalseBBI.BB,
                             FalseBBI.NonPredSize + FalseBBI.ExtraCost,
                             FalseBBI.ExtraCost2, Prediction.getCompl()) &&
          FeasibilityAnalysis(FalseBBI, RevCond)) {
        Tokens.push_back(
            std::make_unique<IfcvtToken>(BBI, ICSimpleFalse, FNeedSub, Dups));
        Enqueued = true;
      }
    }

    BBI.IsEnqueued = Enqueued;
    BBI.IsBeingAnalyzed = false;
    BBI.IsAnalyzed = true;
    BBStack.pop_back();
  }
}

/// Analyze all blocks and find entries for all if-conversion candidates.
void IfConverter::AnalyzeBlocks(
    MachineFunction &MF, std::vector<std::unique_ptr<IfcvtToken>> &Tokens) {
  for (MachineBasicBlock &MBB : MF)
    AnalyzeBlock(MBB, Tokens);

  // Sort to favor more complex ifcvt scheme.
  llvm::stable_sort(Tokens, IfcvtTokenCmp);
}

/// Returns true either if ToMBB is the next block after MBB or that all the
/// intervening blocks are empty (given MBB can fall through to its next block).
static bool canFallThroughTo(MachineBasicBlock &MBB, MachineBasicBlock &ToMBB) {
  MachineFunction::iterator PI = MBB.getIterator();
  MachineFunction::iterator I = std::next(PI);
  MachineFunction::iterator TI = ToMBB.getIterator();
  MachineFunction::iterator E = MBB.getParent()->end();
  while (I != TI) {
    // Check isSuccessor to avoid case where the next block is empty, but
    // it's not a successor.
    if (I == E || !I->empty() || !PI->isSuccessor(&*I))
      return false;
    PI = I++;
  }
  // Finally see if the last I is indeed a successor to PI.
  return PI->isSuccessor(&*I);
}

/// Invalidate predecessor BB info so it would be re-analyzed to determine if it
/// can be if-converted. If predecessor is already enqueued, dequeue it!
void IfConverter::InvalidatePreds(MachineBasicBlock &MBB) {
  for (const MachineBasicBlock *Predecessor : MBB.predecessors()) {
    BBInfo &PBBI = BBAnalysis[Predecessor->getNumber()];
    if (PBBI.IsDone || PBBI.BB == &MBB)
      continue;
    PBBI.IsAnalyzed = false;
    PBBI.IsEnqueued = false;
  }
}

/// Inserts an unconditional branch from \p MBB to \p ToMBB.
static void InsertUncondBranch(MachineBasicBlock &MBB, MachineBasicBlock &ToMBB,
                               const TargetInstrInfo *TII) {
  DebugLoc dl;  // FIXME: this is nowhere
  SmallVector<MachineOperand, 0> NoCond;
  TII->insertBranch(MBB, &ToMBB, nullptr, NoCond, dl);
}

/// Behaves like LiveRegUnits::StepForward() but also adds implicit uses to all
/// values defined in MI which are also live/used by MI.
static void UpdatePredRedefs(MachineInstr &MI, LivePhysRegs &Redefs) {
  const TargetRegisterInfo *TRI = MI.getMF()->getSubtarget().getRegisterInfo();

  // Before stepping forward past MI, remember which regs were live
  // before MI. This is needed to set the Undef flag only when reg is
  // dead.
  SparseSet<MCPhysReg, identity<MCPhysReg>> LiveBeforeMI;
  LiveBeforeMI.setUniverse(TRI->getNumRegs());
  for (unsigned Reg : Redefs)
    LiveBeforeMI.insert(Reg);

  SmallVector<std::pair<MCPhysReg, const MachineOperand*>, 4> Clobbers;
  Redefs.stepForward(MI, Clobbers);

  // Now add the implicit uses for each of the clobbered values.
  for (auto Clobber : Clobbers) {
    // FIXME: Const cast here is nasty, but better than making StepForward
    // take a mutable instruction instead of const.
    unsigned Reg = Clobber.first;
    MachineOperand &Op = const_cast<MachineOperand&>(*Clobber.second);
    MachineInstr *OpMI = Op.getParent();
    MachineInstrBuilder MIB(*OpMI->getMF(), OpMI);
    if (Op.isRegMask()) {
      // First handle regmasks.  They clobber any entries in the mask which
      // means that we need a def for those registers.
      if (LiveBeforeMI.count(Reg))
        MIB.addReg(Reg, RegState::Implicit);

      // We also need to add an implicit def of this register for the later
      // use to read from.
      // For the register allocator to have allocated a register clobbered
      // by the call which is used later, it must be the case that
      // the call doesn't return.
      MIB.addReg(Reg, RegState::Implicit | RegState::Define);
      continue;
    }
    if (any_of(TRI->subregs_inclusive(Reg),
               [&](MCPhysReg S) { return LiveBeforeMI.count(S); }))
      MIB.addReg(Reg, RegState::Implicit);
  }
}

/// If convert a simple (split, no rejoin) sub-CFG.
bool IfConverter::IfConvertSimple(BBInfo &BBI, IfcvtKind Kind) {
  BBInfo &TrueBBI  = BBAnalysis[BBI.TrueBB->getNumber()];
  BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
  BBInfo *CvtBBI = &TrueBBI;
  BBInfo *NextBBI = &FalseBBI;

  SmallVector<MachineOperand, 4> Cond(BBI.BrCond.begin(), BBI.BrCond.end());
  if (Kind == ICSimpleFalse)
    std::swap(CvtBBI, NextBBI);

  MachineBasicBlock &CvtMBB = *CvtBBI->BB;
  MachineBasicBlock &NextMBB = *NextBBI->BB;
  if (CvtBBI->IsDone ||
      (CvtBBI->CannotBeCopied && CvtMBB.pred_size() > 1)) {
    // Something has changed. It's no longer safe to predicate this block.
    BBI.IsAnalyzed = false;
    CvtBBI->IsAnalyzed = false;
    return false;
  }

  if (CvtMBB.hasAddressTaken())
    // Conservatively abort if-conversion if BB's address is taken.
    return false;

  if (Kind == ICSimpleFalse)
    if (TII->reverseBranchCondition(Cond))
      llvm_unreachable("Unable to reverse branch condition!");

  Redefs.init(*TRI);

  if (MRI->tracksLiveness()) {
    // Initialize liveins to the first BB. These are potentially redefined by
    // predicated instructions.
    Redefs.addLiveInsNoPristines(CvtMBB);
    Redefs.addLiveInsNoPristines(NextMBB);
  }

  // Remove the branches from the entry so we can add the contents of the true
  // block to it.
  BBI.NonPredSize -= TII->removeBranch(*BBI.BB);

  if (CvtMBB.pred_size() > 1) {
    // Copy instructions in the true block, predicate them, and add them to
    // the entry block.
    CopyAndPredicateBlock(BBI, *CvtBBI, Cond);

    // Keep the CFG updated.
    BBI.BB->removeSuccessor(&CvtMBB, true);
  } else {
    // Predicate the instructions in the true block.
    PredicateBlock(*CvtBBI, CvtMBB.end(), Cond);

    // Merge converted block into entry block. The BB to Cvt edge is removed
    // by MergeBlocks.
    MergeBlocks(BBI, *CvtBBI);
  }

  bool IterIfcvt = true;
  if (!canFallThroughTo(*BBI.BB, NextMBB)) {
    InsertUncondBranch(*BBI.BB, NextMBB, TII);
    BBI.HasFallThrough = false;
    // Now ifcvt'd block will look like this:
    // BB:
    // ...
    // t, f = cmp
    // if t op
    // b BBf
    //
    // We cannot further ifcvt this block because the unconditional branch
    // will have to be predicated on the new condition, that will not be
    // available if cmp executes.
    IterIfcvt = false;
  }

  // Update block info. BB can be iteratively if-converted.
  if (!IterIfcvt)
    BBI.IsDone = true;
  InvalidatePreds(*BBI.BB);
  CvtBBI->IsDone = true;

  // FIXME: Must maintain LiveIns.
  return true;
}

/// If convert a triangle sub-CFG.
bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) {
  BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
  BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
  BBInfo *CvtBBI = &TrueBBI;
  BBInfo *NextBBI = &FalseBBI;
  DebugLoc dl;  // FIXME: this is nowhere

  SmallVector<MachineOperand, 4> Cond(BBI.BrCond.begin(), BBI.BrCond.end());
  if (Kind == ICTriangleFalse || Kind == ICTriangleFRev)
    std::swap(CvtBBI, NextBBI);

  MachineBasicBlock &CvtMBB = *CvtBBI->BB;
  MachineBasicBlock &NextMBB = *NextBBI->BB;
  if (CvtBBI->IsDone ||
      (CvtBBI->CannotBeCopied && CvtMBB.pred_size() > 1)) {
    // Something has changed. It's no longer safe to predicate this block.
    BBI.IsAnalyzed = false;
    CvtBBI->IsAnalyzed = false;
    return false;
  }

  if (CvtMBB.hasAddressTaken())
    // Conservatively abort if-conversion if BB's address is taken.
    return false;

  if (Kind == ICTriangleFalse || Kind == ICTriangleFRev)
    if (TII->reverseBranchCondition(Cond))
      llvm_unreachable("Unable to reverse branch condition!");

  if (Kind == ICTriangleRev || Kind == ICTriangleFRev) {
    if (reverseBranchCondition(*CvtBBI)) {
      // BB has been changed, modify its predecessors (except for this
      // one) so they don't get ifcvt'ed based on bad intel.
      for (MachineBasicBlock *PBB : CvtMBB.predecessors()) {
        if (PBB == BBI.BB)
          continue;
        BBInfo &PBBI = BBAnalysis[PBB->getNumber()];
        if (PBBI.IsEnqueued) {
          PBBI.IsAnalyzed = false;
          PBBI.IsEnqueued = false;
        }
      }
    }
  }

  // Initialize liveins to the first BB. These are potentially redefined by
  // predicated instructions.
  Redefs.init(*TRI);
  if (MRI->tracksLiveness()) {
    Redefs.addLiveInsNoPristines(CvtMBB);
    Redefs.addLiveInsNoPristines(NextMBB);
  }

  bool HasEarlyExit = CvtBBI->FalseBB != nullptr;
  BranchProbability CvtNext, CvtFalse, BBNext, BBCvt;

  if (HasEarlyExit) {
    // Get probabilities before modifying CvtMBB and BBI.BB.
    CvtNext = MBPI->getEdgeProbability(&CvtMBB, &NextMBB);
    CvtFalse = MBPI->getEdgeProbability(&CvtMBB, CvtBBI->FalseBB);
    BBNext = MBPI->getEdgeProbability(BBI.BB, &NextMBB);
    BBCvt = MBPI->getEdgeProbability(BBI.BB, &CvtMBB);
  }

  // Remove the branches from the entry so we can add the contents of the true
  // block to it.
  BBI.NonPredSize -= TII->removeBranch(*BBI.BB);

  if (CvtMBB.pred_size() > 1) {
    // Copy instructions in the true block, predicate them, and add them to
    // the entry block.
    CopyAndPredicateBlock(BBI, *CvtBBI, Cond, true);
  } else {
    // Predicate the 'true' block after removing its branch.
    CvtBBI->NonPredSize -= TII->removeBranch(CvtMBB);
    PredicateBlock(*CvtBBI, CvtMBB.end(), Cond);

    // Now merge the entry of the triangle with the true block.
    MergeBlocks(BBI, *CvtBBI, false);
  }

  // Keep the CFG updated.
  BBI.BB->removeSuccessor(&CvtMBB, true);

  // If 'true' block has a 'false' successor, add an exit branch to it.
  if (HasEarlyExit) {
    SmallVector<MachineOperand, 4> RevCond(CvtBBI->BrCond.begin(),
                                           CvtBBI->BrCond.end());
    if (TII->reverseBranchCondition(RevCond))
      llvm_unreachable("Unable to reverse branch condition!");

    // Update the edge probability for both CvtBBI->FalseBB and NextBBI.
    // NewNext = New_Prob(BBI.BB, NextMBB) =
    //   Prob(BBI.BB, NextMBB) +
    //   Prob(BBI.BB, CvtMBB) * Prob(CvtMBB, NextMBB)
    // NewFalse = New_Prob(BBI.BB, CvtBBI->FalseBB) =
    //   Prob(BBI.BB, CvtMBB) * Prob(CvtMBB, CvtBBI->FalseBB)
    auto NewTrueBB = getNextBlock(*BBI.BB);
    auto NewNext = BBNext + BBCvt * CvtNext;
    auto NewTrueBBIter = find(BBI.BB->successors(), NewTrueBB);
    if (NewTrueBBIter != BBI.BB->succ_end())
      BBI.BB->setSuccProbability(NewTrueBBIter, NewNext);

    auto NewFalse = BBCvt * CvtFalse;
    TII->insertBranch(*BBI.BB, CvtBBI->FalseBB, nullptr, RevCond, dl);
    BBI.BB->addSuccessor(CvtBBI->FalseBB, NewFalse);
  }

  // Merge in the 'false' block if the 'false' block has no other
  // predecessors. Otherwise, add an unconditional branch to 'false'.
  bool FalseBBDead = false;
  bool IterIfcvt = true;
  bool isFallThrough = canFallThroughTo(*BBI.BB, NextMBB);
  if (!isFallThrough) {
    // Only merge them if the true block does not fallthrough to the false
    // block. By not merging them, we make it possible to iteratively
    // ifcvt the blocks.
    if (!HasEarlyExit && NextMBB.pred_size() == 1 &&
        blockNeverFallThrough(*NextBBI) && !NextMBB.hasAddressTaken()) {
      MergeBlocks(BBI, *NextBBI);
      FalseBBDead = true;
    } else {
      InsertUncondBranch(*BBI.BB, NextMBB, TII);
      BBI.HasFallThrough = false;
    }
    // Mixed predicated and unpredicated code. This cannot be iteratively
    // predicated.
    IterIfcvt = false;
  }

  // Update block info. BB can be iteratively if-converted.
  if (!IterIfcvt)
    BBI.IsDone = true;
  InvalidatePreds(*BBI.BB);
  CvtBBI->IsDone = true;
  if (FalseBBDead)
    NextBBI->IsDone = true;

  // FIXME: Must maintain LiveIns.
  return true;
}

/// Common code shared between diamond conversions.
/// \p BBI, \p TrueBBI, and \p FalseBBI form the diamond shape.
/// \p NumDups1 - number of shared instructions at the beginning of \p TrueBBI
///               and FalseBBI
/// \p NumDups2 - number of shared instructions at the end of \p TrueBBI
///               and \p FalseBBI
/// \p RemoveBranch - Remove the common branch of the two blocks before
///                   predicating. Only false for unanalyzable fallthrough
///                   cases. The caller will replace the branch if necessary.
/// \p MergeAddEdges - Add successor edges when merging blocks. Only false for
///                    unanalyzable fallthrough
bool IfConverter::IfConvertDiamondCommon(
    BBInfo &BBI, BBInfo &TrueBBI, BBInfo &FalseBBI,
    unsigned NumDups1, unsigned NumDups2,
    bool TClobbersPred, bool FClobbersPred,
    bool RemoveBranch, bool MergeAddEdges) {

  if (TrueBBI.IsDone || FalseBBI.IsDone ||
      TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1) {
    // Something has changed. It's no longer safe to predicate these blocks.
    BBI.IsAnalyzed = false;
    TrueBBI.IsAnalyzed = false;
    FalseBBI.IsAnalyzed = false;
    return false;
  }

  if (TrueBBI.BB->hasAddressTaken() || FalseBBI.BB->hasAddressTaken())
    // Conservatively abort if-conversion if either BB has its address taken.
    return false;

  // Put the predicated instructions from the 'true' block before the
  // instructions from the 'false' block, unless the true block would clobber
  // the predicate, in which case, do the opposite.
  BBInfo *BBI1 = &TrueBBI;
  BBInfo *BBI2 = &FalseBBI;
  SmallVector<MachineOperand, 4> RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
  if (TII->reverseBranchCondition(RevCond))
    llvm_unreachable("Unable to reverse branch condition!");
  SmallVector<MachineOperand, 4> *Cond1 = &BBI.BrCond;
  SmallVector<MachineOperand, 4> *Cond2 = &RevCond;

  // Figure out the more profitable ordering.
  bool DoSwap = false;
  if (TClobbersPred && !FClobbersPred)
    DoSwap = true;
  else if (!TClobbersPred && !FClobbersPred) {
    if (TrueBBI.NonPredSize > FalseBBI.NonPredSize)
      DoSwap = true;
  } else if (TClobbersPred && FClobbersPred)
    llvm_unreachable("Predicate info cannot be clobbered by both sides.");
  if (DoSwap) {
    std::swap(BBI1, BBI2);
    std::swap(Cond1, Cond2);
  }

  // Remove the conditional branch from entry to the blocks.
  BBI.NonPredSize -= TII->removeBranch(*BBI.BB);

  MachineBasicBlock &MBB1 = *BBI1->BB;
  MachineBasicBlock &MBB2 = *BBI2->BB;

  // Initialize the Redefs:
  // - BB2 live-in regs need implicit uses before being redefined by BB1
  //   instructions.
  // - BB1 live-out regs need implicit uses before being redefined by BB2
  //   instructions. We start with BB1 live-ins so we have the live-out regs
  //   after tracking the BB1 instructions.
  Redefs.init(*TRI);
  if (MRI->tracksLiveness()) {
    Redefs.addLiveInsNoPristines(MBB1);
    Redefs.addLiveInsNoPristines(MBB2);
  }

  // Remove the duplicated instructions at the beginnings of both paths.
  // Skip dbg_value instructions.
  MachineBasicBlock::iterator DI1 = MBB1.getFirstNonDebugInstr(false);
  MachineBasicBlock::iterator DI2 = MBB2.getFirstNonDebugInstr(false);
  BBI1->NonPredSize -= NumDups1;
  BBI2->NonPredSize -= NumDups1;

  // Skip past the dups on each side separately since there may be
  // differing dbg_value entries. NumDups1 can include a "return"
  // instruction, if it's not marked as "branch".
  for (unsigned i = 0; i < NumDups1; ++DI1) {
    if (DI1 == MBB1.end())
      break;
    if (!DI1->isDebugInstr())
      ++i;
  }
  while (NumDups1 != 0) {
    // Since this instruction is going to be deleted, update call
    // info state if the instruction is call instruction.
    if (DI2->shouldUpdateAdditionalCallInfo())
      MBB2.getParent()->eraseAdditionalCallInfo(&*DI2);

    ++DI2;
    if (DI2 == MBB2.end())
      break;
    if (!DI2->isDebugInstr())
      --NumDups1;
  }

  if (MRI->tracksLiveness()) {
    for (const MachineInstr &MI : make_range(MBB1.begin(), DI1)) {
      SmallVector<std::pair<MCPhysReg, const MachineOperand*>, 4> Dummy;
      Redefs.stepForward(MI, Dummy);
    }
  }

  BBI.BB->splice(BBI.BB->end(), &MBB1, MBB1.begin(), DI1);
  MBB2.erase(MBB2.begin(), DI2);

  // The branches have been checked to match, so it is safe to remove the
  // branch in BB1 and rely on the copy in BB2. The complication is that
  // the blocks may end with a return instruction, which may or may not
  // be marked as "branch". If it's not, then it could be included in
  // "dups1", leaving the blocks potentially empty after moving the common
  // duplicates.
#ifndef NDEBUG
  // Unanalyzable branches must match exactly. Check that now.
  if (!BBI1->IsBrAnalyzable)
    verifySameBranchInstructions(&MBB1, &MBB2);
#endif
  // Remove duplicated instructions from the tail of MBB1: any branch
  // instructions, and the common instructions counted by NumDups2.
  DI1 = MBB1.end();
  while (DI1 != MBB1.begin()) {
    MachineBasicBlock::iterator Prev = std::prev(DI1);
    if (!Prev->isBranch() && !Prev->isDebugInstr())
      break;
    DI1 = Prev;
  }
  for (unsigned i = 0; i != NumDups2; ) {
    // NumDups2 only counted non-dbg_value instructions, so this won't
    // run off the head of the list.
    assert(DI1 != MBB1.begin());

    --DI1;

    // Since this instruction is going to be deleted, update call
    // info state if the instruction is call instruction.
    if (DI1->shouldUpdateAdditionalCallInfo())
      MBB1.getParent()->eraseAdditionalCallInfo(&*DI1);

    // skip dbg_value instructions
    if (!DI1->isDebugInstr())
      ++i;
  }
  MBB1.erase(DI1, MBB1.end());

  DI2 = BBI2->BB->end();
  // The branches have been checked to match. Skip over the branch in the false
  // block so that we don't try to predicate it.
  if (RemoveBranch)
    BBI2->NonPredSize -= TII->removeBranch(*BBI2->BB);
  else {
    // Make DI2 point to the end of the range where the common "tail"
    // instructions could be found.
    while (DI2 != MBB2.begin()) {
      MachineBasicBlock::iterator Prev = std::prev(DI2);
      if (!Prev->isBranch() && !Prev->isDebugInstr())
        break;
      DI2 = Prev;
    }
  }
  while (NumDups2 != 0) {
    // NumDups2 only counted non-dbg_value instructions, so this won't
    // run off the head of the list.
    assert(DI2 != MBB2.begin());
    --DI2;
    // skip dbg_value instructions
    if (!DI2->isDebugInstr())
      --NumDups2;
  }

  // Remember which registers would later be defined by the false block.
  // This allows us not to predicate instructions in the true block that would
  // later be re-defined. That is, rather than
  //   subeq  r0, r1, #1
  //   addne  r0, r1, #1
  // generate:
  //   sub    r0, r1, #1
  //   addne  r0, r1, #1
  SmallSet<MCRegister, 4> RedefsByFalse;
  SmallSet<MCRegister, 4> ExtUses;
  if (TII->isProfitableToUnpredicate(MBB1, MBB2)) {
    for (const MachineInstr &FI : make_range(MBB2.begin(), DI2)) {
      if (FI.isDebugInstr())
        continue;
      SmallVector<MCRegister, 4> Defs;
      for (const MachineOperand &MO : FI.operands()) {
        if (!MO.isReg())
          continue;
        Register Reg = MO.getReg();
        if (!Reg)
          continue;
        if (MO.isDef()) {
          Defs.push_back(Reg);
        } else if (!RedefsByFalse.count(Reg)) {
          // These are defined before ctrl flow reach the 'false' instructions.
          // They cannot be modified by the 'true' instructions.
          ExtUses.insert_range(TRI->subregs_inclusive(Reg));
        }
      }

      for (MCRegister Reg : Defs) {
        if (!ExtUses.contains(Reg))
          RedefsByFalse.insert_range(TRI->subregs_inclusive(Reg));
      }
    }
  }

  // Predicate the 'true' block.
  PredicateBlock(*BBI1, MBB1.end(), *Cond1, &RedefsByFalse);

  // After predicating BBI1, if there is a predicated terminator in BBI1 and
  // a non-predicated in BBI2, then we don't want to predicate the one from
  // BBI2. The reason is that if we merged these blocks, we would end up with
  // two predicated terminators in the same block.
  // Also, if the branches in MBB1 and MBB2 were non-analyzable, then don't
  // predicate them either. They were checked to be identical, and so the
  // same branch would happen regardless of which path was taken.
  if (!MBB2.empty() && (DI2 == MBB2.end())) {
    MachineBasicBlock::iterator BBI1T = MBB1.getFirstTerminator();
    MachineBasicBlock::iterator BBI2T = MBB2.getFirstTerminator();
    bool BB1Predicated = BBI1T != MBB1.end() && TII->isPredicated(*BBI1T);
    bool BB2NonPredicated = BBI2T != MBB2.end() && !TII->isPredicated(*BBI2T);
    if (BB2NonPredicated && (BB1Predicated || !BBI2->IsBrAnalyzable))
      --DI2;
  }

  // Predicate the 'false' block.
  PredicateBlock(*BBI2, DI2, *Cond2);

  // Merge the true block into the entry of the diamond.
  MergeBlocks(BBI, *BBI1, MergeAddEdges);
  MergeBlocks(BBI, *BBI2, MergeAddEdges);
  return true;
}

/// If convert an almost-diamond sub-CFG where the true
/// and false blocks share a common tail.
bool IfConverter::IfConvertForkedDiamond(
    BBInfo &BBI, IfcvtKind Kind,
    unsigned NumDups1, unsigned NumDups2,
    bool TClobbersPred, bool FClobbersPred) {
  BBInfo &TrueBBI  = BBAnalysis[BBI.TrueBB->getNumber()];
  BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];

  // Save the debug location for later.
  DebugLoc dl;
  MachineBasicBlock::iterator TIE = TrueBBI.BB->getFirstTerminator();
  if (TIE != TrueBBI.BB->end())
    dl = TIE->getDebugLoc();
  // Removing branches from both blocks is safe, because we have already
  // determined that both blocks have the same branch instructions. The branch
  // will be added back at the end, unpredicated.
  if (!IfConvertDiamondCommon(
      BBI, TrueBBI, FalseBBI,
      NumDups1, NumDups2,
      TClobbersPred, FClobbersPred,
      /* RemoveBranch */ true, /* MergeAddEdges */ true))
    return false;

  // Add back the branch.
  // Debug location saved above when removing the branch from BBI2
  TII->insertBranch(*BBI.BB, TrueBBI.TrueBB, TrueBBI.FalseBB,
                    TrueBBI.BrCond, dl);

  // Update block info.
  BBI.IsDone = TrueBBI.IsDone = FalseBBI.IsDone = true;
  InvalidatePreds(*BBI.BB);

  // FIXME: Must maintain LiveIns.
  return true;
}

/// If convert a diamond sub-CFG.
bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
                                   unsigned NumDups1, unsigned NumDups2,
                                   bool TClobbersPred, bool FClobbersPred) {
  BBInfo &TrueBBI  = BBAnalysis[BBI.TrueBB->getNumber()];
  BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
  MachineBasicBlock *TailBB = TrueBBI.TrueBB;

  // True block must fall through or end with an unanalyzable terminator.
  if (!TailBB) {
    if (blockAlwaysFallThrough(TrueBBI))
      TailBB = FalseBBI.TrueBB;
    assert((TailBB || !TrueBBI.IsBrAnalyzable) && "Unexpected!");
  }

  if (!IfConvertDiamondCommon(
      BBI, TrueBBI, FalseBBI,
      NumDups1, NumDups2,
      TClobbersPred, FClobbersPred,
      /* RemoveBranch */ TrueBBI.IsBrAnalyzable,
      /* MergeAddEdges */ TailBB == nullptr))
    return false;

  // If the if-converted block falls through or unconditionally branches into
  // the tail block, and the tail block does not have other predecessors, then
  // fold the tail block in as well. Otherwise, unless it falls through to the
  // tail, add a unconditional branch to it.
  if (TailBB) {
    // We need to remove the edges to the true and false blocks manually since
    // we didn't let IfConvertDiamondCommon update the CFG.
    BBI.BB->removeSuccessor(TrueBBI.BB);
    BBI.BB->removeSuccessor(FalseBBI.BB, true);

    BBInfo &TailBBI = BBAnalysis[TailBB->getNumber()];
    bool CanMergeTail =
        blockNeverFallThrough(TailBBI) && !TailBBI.BB->hasAddressTaken();
    // The if-converted block can still have a predicated terminator
    // (e.g. a predicated return). If that is the case, we cannot merge
    // it with the tail block.
    MachineBasicBlock::const_iterator TI = BBI.BB->getFirstTerminator();
    if (TI != BBI.BB->end() && TII->isPredicated(*TI))
      CanMergeTail = false;
    // There may still be a fall-through edge from BBI1 or BBI2 to TailBB;
    // check if there are any other predecessors besides those.
    unsigned NumPreds = TailBB->pred_size();
    if (NumPreds > 1)
      CanMergeTail = false;
    else if (NumPreds == 1 && CanMergeTail) {
      MachineBasicBlock::pred_iterator PI = TailBB->pred_begin();
      if (*PI != TrueBBI.BB && *PI != FalseBBI.BB)
        CanMergeTail = false;
    }
    if (CanMergeTail) {
      MergeBlocks(BBI, TailBBI);
      TailBBI.IsDone = true;
    } else {
      BBI.BB->addSuccessor(TailBB, BranchProbability::getOne());
      InsertUncondBranch(*BBI.BB, *TailBB, TII);
      BBI.HasFallThrough = false;
    }
  }

  // Update block info.
  BBI.IsDone = TrueBBI.IsDone = FalseBBI.IsDone = true;
  InvalidatePreds(*BBI.BB);

  // FIXME: Must maintain LiveIns.
  return true;
}

static bool MaySpeculate(const MachineInstr &MI,
                         SmallSet<MCRegister, 4> &LaterRedefs) {
  bool SawStore = true;
  if (!MI.isSafeToMove(SawStore))
    return false;

  for (const MachineOperand &MO : MI.operands()) {
    if (!MO.isReg())
      continue;
    Register Reg = MO.getReg();
    if (!Reg)
      continue;
    if (MO.isDef() && !LaterRedefs.count(Reg))
      return false;
  }

  return true;
}

/// Predicate instructions from the start of the block to the specified end with
/// the specified condition.
void IfConverter::PredicateBlock(BBInfo &BBI, MachineBasicBlock::iterator E,
                                 SmallVectorImpl<MachineOperand> &Cond,
                                 SmallSet<MCRegister, 4> *LaterRedefs) {
  bool AnyUnpred = false;
  bool MaySpec = LaterRedefs != nullptr;
  for (MachineInstr &I : make_range(BBI.BB->begin(), E)) {
    if (I.isDebugInstr() || TII->isPredicated(I))
      continue;
    // It may be possible not to predicate an instruction if it's the 'true'
    // side of a diamond and the 'false' side may re-define the instruction's
    // defs.
    if (MaySpec && MaySpeculate(I, *LaterRedefs)) {
      AnyUnpred = true;
      continue;
    }
    // If any instruction is predicated, then every instruction after it must
    // be predicated.
    MaySpec = false;
    if (!TII->PredicateInstruction(I, Cond)) {
#ifndef NDEBUG
      dbgs() << "Unable to predicate " << I << "!\n";
#endif
      llvm_unreachable(nullptr);
    }

    // If the predicated instruction now redefines a register as the result of
    // if-conversion, add an implicit kill.
    UpdatePredRedefs(I, Redefs);
  }

  BBI.Predicate.append(Cond.begin(), Cond.end());

  BBI.IsAnalyzed = false;
  BBI.NonPredSize = 0;

  ++NumIfConvBBs;
  if (AnyUnpred)
    ++NumUnpred;
}

/// Copy and predicate instructions from source BB to the destination block.
/// Skip end of block branches if IgnoreBr is true.
void IfConverter::CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI,
                                        SmallVectorImpl<MachineOperand> &Cond,
                                        bool IgnoreBr) {
  MachineFunction &MF = *ToBBI.BB->getParent();

  MachineBasicBlock &FromMBB = *FromBBI.BB;
  for (MachineInstr &I : FromMBB) {
    // Do not copy the end of the block branches.
    if (IgnoreBr && I.isBranch())
      break;

    MachineInstr *MI = MF.CloneMachineInstr(&I);
    // Make a copy of the call info.
    if (I.isCandidateForAdditionalCallInfo())
      MF.copyAdditionalCallInfo(&I, MI);

    ToBBI.BB->insert(ToBBI.BB->end(), MI);
    ToBBI.NonPredSize++;
    unsigned ExtraPredCost = TII->getPredicationCost(I);
    unsigned NumCycles = SchedModel.computeInstrLatency(&I, false);
    if (NumCycles > 1)
      ToBBI.ExtraCost += NumCycles-1;
    ToBBI.ExtraCost2 += ExtraPredCost;

    if (!TII->isPredicated(I) && !MI->isDebugInstr()) {
      if (!TII->PredicateInstruction(*MI, Cond)) {
#ifndef NDEBUG
        dbgs() << "Unable to predicate " << I << "!\n";
#endif
        llvm_unreachable(nullptr);
      }
    }

    // If the predicated instruction now redefines a register as the result of
    // if-conversion, add an implicit kill.
    UpdatePredRedefs(*MI, Redefs);
  }

  if (!IgnoreBr) {
    std::vector<MachineBasicBlock *> Succs(FromMBB.succ_begin(),
                                           FromMBB.succ_end());
    MachineBasicBlock *NBB = getNextBlock(FromMBB);
    MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : nullptr;

    for (MachineBasicBlock *Succ : Succs) {
      // Fallthrough edge can't be transferred.
      if (Succ == FallThrough)
        continue;
      ToBBI.BB->addSuccessor(Succ);
    }
  }

  ToBBI.Predicate.append(FromBBI.Predicate.begin(), FromBBI.Predicate.end());
  ToBBI.Predicate.append(Cond.begin(), Cond.end());

  ToBBI.ClobbersPred |= FromBBI.ClobbersPred;
  ToBBI.IsAnalyzed = false;

  ++NumDupBBs;
}

/// Move all instructions from FromBB to the end of ToBB.  This will leave
/// FromBB as an empty block, so remove all of its successor edges and move it
/// to the end of the function.  If AddEdges is true, i.e., when FromBBI's
/// branch is being moved, add those successor edges to ToBBI and remove the old
/// edge from ToBBI to FromBBI.
void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges) {
  MachineBasicBlock &FromMBB = *FromBBI.BB;
  assert(!FromMBB.hasAddressTaken() &&
         "Removing a BB whose address is taken!");

  // If we're about to splice an INLINEASM_BR from FromBBI, we need to update
  // ToBBI's successor list accordingly.
  if (FromMBB.mayHaveInlineAsmBr())
    for (MachineInstr &MI : FromMBB)
      if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
        for (MachineOperand &MO : MI.operands())
          if (MO.isMBB() && !ToBBI.BB->isSuccessor(MO.getMBB()))
            ToBBI.BB->addSuccessor(MO.getMBB(), BranchProbability::getZero());

  // In case FromMBB contains terminators (e.g. return instruction),
  // first move the non-terminator instructions, then the terminators.
  MachineBasicBlock::iterator FromTI = FromMBB.getFirstTerminator();
  MachineBasicBlock::iterator ToTI = ToBBI.BB->getFirstTerminator();
  ToBBI.BB->splice(ToTI, &FromMBB, FromMBB.begin(), FromTI);

  // If FromBB has non-predicated terminator we should copy it at the end.
  if (FromTI != FromMBB.end() && !TII->isPredicated(*FromTI))
    ToTI = ToBBI.BB->end();
  ToBBI.BB->splice(ToTI, &FromMBB, FromTI, FromMBB.end());

  // Force normalizing the successors' probabilities of ToBBI.BB to convert all
  // unknown probabilities into known ones.
  // FIXME: This usage is too tricky and in the future we would like to
  // eliminate all unknown probabilities in MBB.
  if (ToBBI.IsBrAnalyzable)
    ToBBI.BB->normalizeSuccProbs();

  SmallVector<MachineBasicBlock *, 4> FromSuccs(FromMBB.successors());
  MachineBasicBlock *NBB = getNextBlock(FromMBB);
  MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : nullptr;
  // The edge probability from ToBBI.BB to FromMBB, which is only needed when
  // AddEdges is true and FromMBB is a successor of ToBBI.BB.
  auto To2FromProb = BranchProbability::getZero();
  if (AddEdges && ToBBI.BB->isSuccessor(&FromMBB)) {
    // Remove the old edge but remember the edge probability so we can calculate
    // the correct weights on the new edges being added further down.
    To2FromProb = MBPI->getEdgeProbability(ToBBI.BB, &FromMBB);
    ToBBI.BB->removeSuccessor(&FromMBB);
  }

  for (MachineBasicBlock *Succ : FromSuccs) {
    // Fallthrough edge can't be transferred.
    if (Succ == FallThrough) {
      FromMBB.removeSuccessor(Succ);
      continue;
    }

    auto NewProb = BranchProbability::getZero();
    if (AddEdges) {
      // Calculate the edge probability for the edge from ToBBI.BB to Succ,
      // which is a portion of the edge probability from FromMBB to Succ. The
      // portion ratio is the edge probability from ToBBI.BB to FromMBB (if
      // FromBBI is a successor of ToBBI.BB. See comment below for exception).
      NewProb = MBPI->getEdgeProbability(&FromMBB, Succ);

      // To2FromProb is 0 when FromMBB is not a successor of ToBBI.BB. This
      // only happens when if-converting a diamond CFG and FromMBB is the
      // tail BB.  In this case FromMBB post-dominates ToBBI.BB and hence we
      // could just use the probabilities on FromMBB's out-edges when adding
      // new successors.
      if (!To2FromProb.isZero())
        NewProb *= To2FromProb;
    }

    FromMBB.removeSuccessor(Succ);

    if (AddEdges) {
      // If the edge from ToBBI.BB to Succ already exists, update the
      // probability of this edge by adding NewProb to it. An example is shown
      // below, in which A is ToBBI.BB and B is FromMBB. In this case we
      // don't have to set C as A's successor as it already is. We only need to
      // update the edge probability on A->C. Note that B will not be
      // immediately removed from A's successors. It is possible that B->D is
      // not removed either if D is a fallthrough of B. Later the edge A->D
      // (generated here) and B->D will be combined into one edge. To maintain
      // correct edge probability of this combined edge, we need to set the edge
      // probability of A->B to zero, which is already done above. The edge
      // probability on A->D is calculated by scaling the original probability
      // on A->B by the probability of B->D.
      //
      // Before ifcvt:      After ifcvt (assume B->D is kept):
      //
      //       A                A
      //      /|               /|\
      //     / B              / B|
      //    | /|             |  ||
      //    |/ |             |  |/
      //    C  D             C  D
      //
      if (ToBBI.BB->isSuccessor(Succ))
        ToBBI.BB->setSuccProbability(
            find(ToBBI.BB->successors(), Succ),
            MBPI->getEdgeProbability(ToBBI.BB, Succ) + NewProb);
      else
        ToBBI.BB->addSuccessor(Succ, NewProb);
    }
  }

  // Move the now empty FromMBB out of the way to the end of the function so
  // it doesn't interfere with fallthrough checks done by canFallThroughTo().
  MachineBasicBlock *Last = &*FromMBB.getParent()->rbegin();
  if (Last != &FromMBB)
    FromMBB.moveAfter(Last);

  // Normalize the probabilities of ToBBI.BB's successors with all adjustment
  // we've done above.
  if (ToBBI.IsBrAnalyzable && FromBBI.IsBrAnalyzable)
    ToBBI.BB->normalizeSuccProbs();

  ToBBI.Predicate.append(FromBBI.Predicate.begin(), FromBBI.Predicate.end());
  FromBBI.Predicate.clear();

  ToBBI.NonPredSize += FromBBI.NonPredSize;
  ToBBI.ExtraCost += FromBBI.ExtraCost;
  ToBBI.ExtraCost2 += FromBBI.ExtraCost2;
  FromBBI.NonPredSize = 0;
  FromBBI.ExtraCost = 0;
  FromBBI.ExtraCost2 = 0;

  ToBBI.ClobbersPred |= FromBBI.ClobbersPred;
  ToBBI.HasFallThrough = FromBBI.HasFallThrough;
  ToBBI.IsAnalyzed = false;
  FromBBI.IsAnalyzed = false;
}

FunctionPass *
llvm::createIfConverter(std::function<bool(const MachineFunction &)> Ftor) {
  return new IfConverter(std::move(Ftor));
}
