//===- SimplifyCFG.cpp - Code to perform CFG simplification ---------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Peephole optimize the CFG.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/GuardUtils.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/NoFolder.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LockstepReverseIterator.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <map>
#include <optional>
#include <set>
#include <tuple>
#include <utility>
#include <vector>

using namespace llvm;
using namespace PatternMatch;

#define DEBUG_TYPE "simplifycfg"

namespace llvm {

cl::opt<bool> RequireAndPreserveDomTree(
    "simplifycfg-require-and-preserve-domtree", cl::Hidden,

    cl::desc(
        "Temporary development switch used to gradually uplift SimplifyCFG "
        "into preserving DomTree,"));

// Chosen as 2 so as to be cheap, but still to have enough power to fold
// a select, so the "clamp" idiom (of a min followed by a max) will be caught.
// To catch this, we need to fold a compare and a select, hence '2' being the
// minimum reasonable default.
static cl::opt<unsigned> PHINodeFoldingThreshold(
    "phi-node-folding-threshold", cl::Hidden, cl::init(2),
    cl::desc(
        "Control the amount of phi node folding to perform (default = 2)"));

static cl::opt<unsigned> TwoEntryPHINodeFoldingThreshold(
    "two-entry-phi-node-folding-threshold", cl::Hidden, cl::init(4),
    cl::desc("Control the maximal total instruction cost that we are willing "
             "to speculatively execute to fold a 2-entry PHI node into a "
             "select (default = 4)"));

static cl::opt<bool>
    HoistCommon("simplifycfg-hoist-common", cl::Hidden, cl::init(true),
                cl::desc("Hoist common instructions up to the parent block"));

static cl::opt<bool> HoistLoadsWithCondFaulting(
    "simplifycfg-hoist-loads-with-cond-faulting", cl::Hidden, cl::init(true),
    cl::desc("Hoist loads if the target supports conditional faulting"));

static cl::opt<bool> HoistStoresWithCondFaulting(
    "simplifycfg-hoist-stores-with-cond-faulting", cl::Hidden, cl::init(true),
    cl::desc("Hoist stores if the target supports conditional faulting"));

static cl::opt<unsigned> HoistLoadsStoresWithCondFaultingThreshold(
    "hoist-loads-stores-with-cond-faulting-threshold", cl::Hidden, cl::init(6),
    cl::desc("Control the maximal conditional load/store that we are willing "
             "to speculatively execute to eliminate conditional branch "
             "(default = 6)"));

static cl::opt<unsigned>
    HoistCommonSkipLimit("simplifycfg-hoist-common-skip-limit", cl::Hidden,
                         cl::init(20),
                         cl::desc("Allow reordering across at most this many "
                                  "instructions when hoisting"));

static cl::opt<bool>
    SinkCommon("simplifycfg-sink-common", cl::Hidden, cl::init(true),
               cl::desc("Sink common instructions down to the end block"));

static cl::opt<bool> HoistCondStores(
    "simplifycfg-hoist-cond-stores", cl::Hidden, cl::init(true),
    cl::desc("Hoist conditional stores if an unconditional store precedes"));

static cl::opt<bool> MergeCondStores(
    "simplifycfg-merge-cond-stores", cl::Hidden, cl::init(true),
    cl::desc("Hoist conditional stores even if an unconditional store does not "
             "precede - hoist multiple conditional stores into a single "
             "predicated store"));

static cl::opt<bool> MergeCondStoresAggressively(
    "simplifycfg-merge-cond-stores-aggressively", cl::Hidden, cl::init(false),
    cl::desc("When merging conditional stores, do so even if the resultant "
             "basic blocks are unlikely to be if-converted as a result"));

static cl::opt<bool> SpeculateOneExpensiveInst(
    "speculate-one-expensive-inst", cl::Hidden, cl::init(true),
    cl::desc("Allow exactly one expensive instruction to be speculatively "
             "executed"));

static cl::opt<unsigned> MaxSpeculationDepth(
    "max-speculation-depth", cl::Hidden, cl::init(10),
    cl::desc("Limit maximum recursion depth when calculating costs of "
             "speculatively executed instructions"));

static cl::opt<int>
    MaxSmallBlockSize("simplifycfg-max-small-block-size", cl::Hidden,
                      cl::init(10),
                      cl::desc("Max size of a block which is still considered "
                               "small enough to thread through"));

// Two is chosen to allow one negation and a logical combine.
static cl::opt<unsigned>
    BranchFoldThreshold("simplifycfg-branch-fold-threshold", cl::Hidden,
                        cl::init(2),
                        cl::desc("Maximum cost of combining conditions when "
                                 "folding branches"));

static cl::opt<unsigned> BranchFoldToCommonDestVectorMultiplier(
    "simplifycfg-branch-fold-common-dest-vector-multiplier", cl::Hidden,
    cl::init(2),
    cl::desc("Multiplier to apply to threshold when determining whether or not "
             "to fold branch to common destination when vector operations are "
             "present"));

static cl::opt<bool> EnableMergeCompatibleInvokes(
    "simplifycfg-merge-compatible-invokes", cl::Hidden, cl::init(true),
    cl::desc("Allow SimplifyCFG to merge invokes together when appropriate"));

static cl::opt<unsigned> MaxSwitchCasesPerResult(
    "max-switch-cases-per-result", cl::Hidden, cl::init(16),
    cl::desc("Limit cases to analyze when converting a switch to select"));

static cl::opt<unsigned> MaxJumpThreadingLiveBlocks(
    "max-jump-threading-live-blocks", cl::Hidden, cl::init(24),
    cl::desc("Limit number of blocks a define in a threaded block is allowed "
             "to be live in"));

extern cl::opt<bool> ProfcheckDisableMetadataFixes;

} // end namespace llvm

STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");
STATISTIC(NumLinearMaps,
          "Number of switch instructions turned into linear mapping");
STATISTIC(NumLookupTables,
          "Number of switch instructions turned into lookup tables");
STATISTIC(
    NumLookupTablesHoles,
    "Number of switch instructions turned into lookup tables (holes checked)");
STATISTIC(NumTableCmpReuses, "Number of reused switch table lookup compares");
STATISTIC(NumFoldValueComparisonIntoPredecessors,
          "Number of value comparisons folded into predecessor basic blocks");
STATISTIC(NumFoldBranchToCommonDest,
          "Number of branches folded into predecessor basic block");
STATISTIC(
    NumHoistCommonCode,
    "Number of common instruction 'blocks' hoisted up to the begin block");
STATISTIC(NumHoistCommonInstrs,
          "Number of common instructions hoisted up to the begin block");
STATISTIC(NumSinkCommonCode,
          "Number of common instruction 'blocks' sunk down to the end block");
STATISTIC(NumSinkCommonInstrs,
          "Number of common instructions sunk down to the end block");
STATISTIC(NumSpeculations, "Number of speculative executed instructions");
STATISTIC(NumInvokes,
          "Number of invokes with empty resume blocks simplified into calls");
STATISTIC(NumInvokesMerged, "Number of invokes that were merged together");
STATISTIC(NumInvokeSetsFormed, "Number of invoke sets that were formed");

namespace {

// The first field contains the value that the switch produces when a certain
// case group is selected, and the second field is a vector containing the
// cases composing the case group.
using SwitchCaseResultVectorTy =
    SmallVector<std::pair<Constant *, SmallVector<ConstantInt *, 4>>, 2>;

// The first field contains the phi node that generates a result of the switch
// and the second field contains the value generated for a certain case in the
// switch for that PHI.
using SwitchCaseResultsTy = SmallVector<std::pair<PHINode *, Constant *>, 4>;

/// ValueEqualityComparisonCase - Represents a case of a switch.
struct ValueEqualityComparisonCase {
  ConstantInt *Value;
  BasicBlock *Dest;

  ValueEqualityComparisonCase(ConstantInt *Value, BasicBlock *Dest)
      : Value(Value), Dest(Dest) {}

  bool operator<(ValueEqualityComparisonCase RHS) const {
    // Comparing pointers is ok as we only rely on the order for uniquing.
    return Value < RHS.Value;
  }

  bool operator==(BasicBlock *RHSDest) const { return Dest == RHSDest; }
};

class SimplifyCFGOpt {
  const TargetTransformInfo &TTI;
  DomTreeUpdater *DTU;
  const DataLayout &DL;
  ArrayRef<WeakVH> LoopHeaders;
  const SimplifyCFGOptions &Options;
  bool Resimplify;

  Value *isValueEqualityComparison(Instruction *TI);
  BasicBlock *getValueEqualityComparisonCases(
      Instruction *TI, std::vector<ValueEqualityComparisonCase> &Cases);
  bool simplifyEqualityComparisonWithOnlyPredecessor(Instruction *TI,
                                                     BasicBlock *Pred,
                                                     IRBuilder<> &Builder);
  bool performValueComparisonIntoPredecessorFolding(Instruction *TI, Value *&CV,
                                                    Instruction *PTI,
                                                    IRBuilder<> &Builder);
  bool foldValueComparisonIntoPredecessors(Instruction *TI,
                                           IRBuilder<> &Builder);

  bool simplifyResume(ResumeInst *RI, IRBuilder<> &Builder);
  bool simplifySingleResume(ResumeInst *RI);
  bool simplifyCommonResume(ResumeInst *RI);
  bool simplifyCleanupReturn(CleanupReturnInst *RI);
  bool simplifyUnreachable(UnreachableInst *UI);
  bool simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder);
  bool simplifyDuplicateSwitchArms(SwitchInst *SI, DomTreeUpdater *DTU);
  bool simplifyIndirectBr(IndirectBrInst *IBI);
  bool simplifyUncondBranch(UncondBrInst *BI, IRBuilder<> &Builder);
  bool simplifyCondBranch(CondBrInst *BI, IRBuilder<> &Builder);
  bool foldCondBranchOnValueKnownInPredecessor(CondBrInst *BI);

  bool tryToSimplifyUncondBranchWithICmpInIt(ICmpInst *ICI,
                                             IRBuilder<> &Builder);
  bool tryToSimplifyUncondBranchWithICmpSelectInIt(ICmpInst *ICI,
                                                   SelectInst *Select,
                                                   IRBuilder<> &Builder);
  bool hoistCommonCodeFromSuccessors(Instruction *TI, bool AllInstsEqOnly);
  bool hoistSuccIdenticalTerminatorToSwitchOrIf(
      Instruction *TI, Instruction *I1,
      SmallVectorImpl<Instruction *> &OtherSuccTIs,
      ArrayRef<BasicBlock *> UniqueSuccessors);
  bool speculativelyExecuteBB(CondBrInst *BI, BasicBlock *ThenBB);
  bool simplifyTerminatorOnSelect(Instruction *OldTerm, Value *Cond,
                                  BasicBlock *TrueBB, BasicBlock *FalseBB,
                                  uint32_t TrueWeight, uint32_t FalseWeight);
  bool simplifyBranchOnICmpChain(CondBrInst *BI, IRBuilder<> &Builder,
                                 const DataLayout &DL);
  bool simplifySwitchOnSelect(SwitchInst *SI, SelectInst *Select);
  bool simplifySwitchOnSelectRemap(SwitchInst *SI, SelectInst *Select, Value *X,
                                   ConstantInt *C, bool Negate);
  bool simplifyIndirectBrOnSelect(IndirectBrInst *IBI, SelectInst *SI);
  bool turnSwitchRangeIntoICmp(SwitchInst *SI, IRBuilder<> &Builder);
  bool simplifyDuplicatePredecessors(BasicBlock *Succ, DomTreeUpdater *DTU);

public:
  SimplifyCFGOpt(const TargetTransformInfo &TTI, DomTreeUpdater *DTU,
                 const DataLayout &DL, ArrayRef<WeakVH> LoopHeaders,
                 const SimplifyCFGOptions &Opts)
      : TTI(TTI), DTU(DTU), DL(DL), LoopHeaders(LoopHeaders), Options(Opts) {
    assert((!DTU || !DTU->hasPostDomTree()) &&
           "SimplifyCFG is not yet capable of maintaining validity of a "
           "PostDomTree, so don't ask for it.");
  }

  bool simplifyOnce(BasicBlock *BB);
  bool run(BasicBlock *BB);

  // Helper to set Resimplify and return change indication.
  bool requestResimplify() {
    Resimplify = true;
    return true;
  }
};

// we synthesize a || b as select a, true, b
// we synthesize a && b as select a, b, false
// this function determines if SI is playing one of those roles.
[[maybe_unused]] bool
isSelectInRoleOfConjunctionOrDisjunction(const SelectInst *SI) {
  return ((isa<ConstantInt>(SI->getTrueValue()) &&
           (dyn_cast<ConstantInt>(SI->getTrueValue())->isOne())) ||
          (isa<ConstantInt>(SI->getFalseValue()) &&
           (dyn_cast<ConstantInt>(SI->getFalseValue())->isNullValue())));
}

} // end anonymous namespace

/// Return true if all the PHI nodes in the basic block \p BB
/// receive compatible (identical) incoming values when coming from
/// all of the predecessor blocks that are specified in \p IncomingBlocks.
///
/// Note that if the values aren't exactly identical, but \p EquivalenceSet
/// is provided, and *both* of the values are present in the set,
/// then they are considered equal.
static bool incomingValuesAreCompatible(
    BasicBlock *BB, ArrayRef<BasicBlock *> IncomingBlocks,
    SmallPtrSetImpl<Value *> *EquivalenceSet = nullptr) {
  assert(IncomingBlocks.size() == 2 &&
         "Only for a pair of incoming blocks at the time!");

  // FIXME: it is okay if one of the incoming values is an `undef` value,
  //        iff the other incoming value is guaranteed to be a non-poison value.
  // FIXME: it is okay if one of the incoming values is a `poison` value.
  return all_of(BB->phis(), [IncomingBlocks, EquivalenceSet](PHINode &PN) {
    Value *IV0 = PN.getIncomingValueForBlock(IncomingBlocks[0]);
    Value *IV1 = PN.getIncomingValueForBlock(IncomingBlocks[1]);
    if (IV0 == IV1)
      return true;
    if (EquivalenceSet && EquivalenceSet->contains(IV0) &&
        EquivalenceSet->contains(IV1))
      return true;
    return false;
  });
}

/// Return true if it is safe to merge these two
/// terminator instructions together.
static bool
safeToMergeTerminators(Instruction *SI1, Instruction *SI2,
                       SmallSetVector<BasicBlock *, 4> *FailBlocks = nullptr) {
  if (SI1 == SI2)
    return false; // Can't merge with self!

  // It is not safe to merge these two switch instructions if they have a common
  // successor, and if that successor has a PHI node, and if *that* PHI node has
  // conflicting incoming values from the two switch blocks.
  BasicBlock *SI1BB = SI1->getParent();
  BasicBlock *SI2BB = SI2->getParent();

  SmallPtrSet<BasicBlock *, 16> SI1Succs(llvm::from_range, successors(SI1BB));
  bool Fail = false;
  for (BasicBlock *Succ : successors(SI2BB)) {
    if (!SI1Succs.count(Succ))
      continue;
    if (incomingValuesAreCompatible(Succ, {SI1BB, SI2BB}))
      continue;
    Fail = true;
    if (FailBlocks)
      FailBlocks->insert(Succ);
    else
      break;
  }

  return !Fail;
}

/// Update PHI nodes in Succ to indicate that there will now be entries in it
/// from the 'NewPred' block. The values that will be flowing into the PHI nodes
/// will be the same as those coming in from ExistPred, an existing predecessor
/// of Succ.
static void addPredecessorToBlock(BasicBlock *Succ, BasicBlock *NewPred,
                                  BasicBlock *ExistPred,
                                  MemorySSAUpdater *MSSAU = nullptr) {
  for (PHINode &PN : Succ->phis())
    PN.addIncoming(PN.getIncomingValueForBlock(ExistPred), NewPred);
  if (MSSAU)
    if (auto *MPhi = MSSAU->getMemorySSA()->getMemoryAccess(Succ))
      MPhi->addIncoming(MPhi->getIncomingValueForBlock(ExistPred), NewPred);
}

/// Compute an abstract "cost" of speculating the given instruction,
/// which is assumed to be safe to speculate. TCC_Free means cheap,
/// TCC_Basic means less cheap, and TCC_Expensive means prohibitively
/// expensive.
static InstructionCost computeSpeculationCost(const User *I,
                                              const TargetTransformInfo &TTI) {
  return TTI.getInstructionCost(I, TargetTransformInfo::TCK_SizeAndLatency);
}

/// If we have a merge point of an "if condition" as accepted above,
/// return true if the specified value dominates the block.  We don't handle
/// the true generality of domination here, just a special case which works
/// well enough for us.
///
/// If AggressiveInsts is non-null, and if V does not dominate BB, we check to
/// see if V (which must be an instruction) and its recursive operands
/// that do not dominate BB have a combined cost lower than Budget and
/// are non-trapping.  If both are true, the instruction is inserted into the
/// set and true is returned.
///
/// The cost for most non-trapping instructions is defined as 1 except for
/// Select whose cost is 2.
///
/// After this function returns, Cost is increased by the cost of
/// V plus its non-dominating operands.  If that cost is greater than
/// Budget, false is returned and Cost is undefined.
static bool dominatesMergePoint(
    Value *V, BasicBlock *BB, Instruction *InsertPt,
    SmallPtrSetImpl<Instruction *> &AggressiveInsts, InstructionCost &Cost,
    InstructionCost Budget, const TargetTransformInfo &TTI, AssumptionCache *AC,
    SmallPtrSetImpl<Instruction *> &ZeroCostInstructions, unsigned Depth = 0) {
  // It is possible to hit a zero-cost cycle (phi/gep instructions for example),
  // so limit the recursion depth.
  // TODO: While this recursion limit does prevent pathological behavior, it
  // would be better to track visited instructions to avoid cycles.
  if (Depth == MaxSpeculationDepth)
    return false;

  Instruction *I = dyn_cast<Instruction>(V);
  if (!I) {
    // Non-instructions dominate all instructions and can be executed
    // unconditionally.
    return true;
  }
  BasicBlock *PBB = I->getParent();

  // We don't want to allow weird loops that might have the "if condition" in
  // the bottom of this block.
  if (PBB == BB)
    return false;

  // If this instruction is defined in a block that contains an unconditional
  // branch to BB, then it must be in the 'conditional' part of the "if
  // statement".  If not, it definitely dominates the region.
  UncondBrInst *BI = dyn_cast<UncondBrInst>(PBB->getTerminator());
  if (!BI || BI->getSuccessor() != BB)
    return true;

  // If we have seen this instruction before, don't count it again.
  if (AggressiveInsts.count(I))
    return true;

  // Okay, it looks like the instruction IS in the "condition".  Check to
  // see if it's a cheap instruction to unconditionally compute, and if it
  // only uses stuff defined outside of the condition.  If so, hoist it out.
  if (!isSafeToSpeculativelyExecute(I, InsertPt, AC))
    return false;

  // Overflow arithmetic instruction plus extract value are usually generated
  // when a division is being replaced. But, in this case, the zero check may
  // still be kept in the code. In that case it would be worth to hoist these
  // two instruction out of the basic block. Let's treat this pattern as one
  // single cheap instruction here!
  WithOverflowInst *OverflowInst;
  if (match(I, m_ExtractValue<1>(m_OneUse(m_WithOverflowInst(OverflowInst))))) {
    ZeroCostInstructions.insert(OverflowInst);
    Cost += 1;
  } else if (!ZeroCostInstructions.contains(I))
    Cost += computeSpeculationCost(I, TTI);

  // Allow exactly one instruction to be speculated regardless of its cost
  // (as long as it is safe to do so).
  // This is intended to flatten the CFG even if the instruction is a division
  // or other expensive operation. The speculation of an expensive instruction
  // is expected to be undone in CodeGenPrepare if the speculation has not
  // enabled further IR optimizations.
  if (Cost > Budget &&
      (!SpeculateOneExpensiveInst || !AggressiveInsts.empty() || Depth > 0 ||
       !Cost.isValid()))
    return false;

  // Okay, we can only really hoist these out if their operands do
  // not take us over the cost threshold.
  for (Use &Op : I->operands())
    if (!dominatesMergePoint(Op, BB, InsertPt, AggressiveInsts, Cost, Budget,
                             TTI, AC, ZeroCostInstructions, Depth + 1))
      return false;
  // Okay, it's safe to do this!  Remember this instruction.
  AggressiveInsts.insert(I);
  return true;
}

/// Extract ConstantInt from value, looking through IntToPtr
/// and PointerNullValue. Return NULL if value is not a constant int.
static ConstantInt *getConstantInt(Value *V, const DataLayout &DL) {
  // Normal constant int.
  ConstantInt *CI = dyn_cast<ConstantInt>(V);
  if (CI || !isa<Constant>(V) || !V->getType()->isPointerTy())
    return CI;

  // It is not safe to look through inttoptr or ptrtoint when using unstable
  // pointer types.
  if (DL.hasUnstableRepresentation(V->getType()))
    return nullptr;

  // This is some kind of pointer constant. Turn it into a pointer-sized
  // ConstantInt if possible.
  IntegerType *IntPtrTy = cast<IntegerType>(DL.getIntPtrType(V->getType()));

  // Null pointer means 0, see SelectionDAGBuilder::getValue(const Value*).
  if (isa<ConstantPointerNull>(V))
    return ConstantInt::get(IntPtrTy, 0);

  // IntToPtr const int, we can look through this if the semantics of
  // inttoptr for this address space are a simple (truncating) bitcast.
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
    if (CE->getOpcode() == Instruction::IntToPtr)
      if (ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(0))) {
        // The constant is very likely to have the right type already.
        if (CI->getType() == IntPtrTy)
          return CI;
        else
          return cast<ConstantInt>(
              ConstantFoldIntegerCast(CI, IntPtrTy, /*isSigned=*/false, DL));
      }
  return nullptr;
}

namespace {

/// Given a chain of or (||) or and (&&) comparison of a value against a
/// constant, this will try to recover the information required for a switch
/// structure.
/// It will depth-first traverse the chain of comparison, seeking for patterns
/// like %a == 12 or %a < 4 and combine them to produce a set of integer
/// representing the different cases for the switch.
/// Note that if the chain is composed of '||' it will build the set of elements
/// that matches the comparisons (i.e. any of this value validate the chain)
/// while for a chain of '&&' it will build the set elements that make the test
/// fail.
struct ConstantComparesGatherer {
  const DataLayout &DL;

  /// Value found for the switch comparison
  Value *CompValue = nullptr;

  /// Extra clause to be checked before the switch
  Value *Extra = nullptr;

  /// Set of integers to match in switch
  SmallVector<ConstantInt *, 8> Vals;

  /// Number of comparisons matched in the and/or chain
  unsigned UsedICmps = 0;

  /// If the elements in Vals matches the comparisons
  bool IsEq = false;

  // Used to check if the first matched CompValue shall be the Extra check.
  bool IgnoreFirstMatch = false;
  bool MultipleMatches = false;

  /// Construct and compute the result for the comparison instruction Cond
  ConstantComparesGatherer(Instruction *Cond, const DataLayout &DL) : DL(DL) {
    gather(Cond);
    if (CompValue || !MultipleMatches)
      return;
    Extra = nullptr;
    Vals.clear();
    UsedICmps = 0;
    IgnoreFirstMatch = true;
    gather(Cond);
  }

  ConstantComparesGatherer(const ConstantComparesGatherer &) = delete;
  ConstantComparesGatherer &
  operator=(const ConstantComparesGatherer &) = delete;

private:
  /// Try to set the current value used for the comparison, it succeeds only if
  /// it wasn't set before or if the new value is the same as the old one
  bool setValueOnce(Value *NewVal) {
    if (IgnoreFirstMatch) {
      IgnoreFirstMatch = false;
      return false;
    }
    if (CompValue && CompValue != NewVal) {
      MultipleMatches = true;
      return false;
    }
    CompValue = NewVal;
    return true;
  }

  /// Try to match Instruction "I" as a comparison against a constant and
  /// populates the array Vals with the set of values that match (or do not
  /// match depending on isEQ).
  /// Return false on failure. On success, the Value the comparison matched
  /// against is placed in CompValue.
  /// If CompValue is already set, the function is expected to fail if a match
  /// is found but the value compared to is different.
  bool matchInstruction(Instruction *I, bool isEQ) {
    if (match(I, m_Not(m_Instruction(I))))
      isEQ = !isEQ;

    Value *Val;
    if (match(I, m_NUWTrunc(m_Value(Val)))) {
      // If we already have a value for the switch, it has to match!
      if (!setValueOnce(Val))
        return false;
      UsedICmps++;
      Vals.push_back(ConstantInt::get(cast<IntegerType>(Val->getType()), isEQ));
      return true;
    }
    // If this is an icmp against a constant, handle this as one of the cases.
    ICmpInst *ICI;
    ConstantInt *C;
    if (!((ICI = dyn_cast<ICmpInst>(I)) &&
          (C = getConstantInt(I->getOperand(1), DL)))) {
      return false;
    }

    Value *RHSVal;
    const APInt *RHSC;

    // Pattern match a special case
    // (x & ~2^z) == y --> x == y || x == y|2^z
    // This undoes a transformation done by instcombine to fuse 2 compares.
    if (ICI->getPredicate() == (isEQ ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE)) {
      // It's a little bit hard to see why the following transformations are
      // correct. Here is a CVC3 program to verify them for 64-bit values:

      /*
         ONE  : BITVECTOR(64) = BVZEROEXTEND(0bin1, 63);
         x    : BITVECTOR(64);
         y    : BITVECTOR(64);
         z    : BITVECTOR(64);
         mask : BITVECTOR(64) = BVSHL(ONE, z);
         QUERY( (y & ~mask = y) =>
                ((x & ~mask = y) <=> (x = y OR x = (y |  mask)))
         );
         QUERY( (y |  mask = y) =>
                ((x |  mask = y) <=> (x = y OR x = (y & ~mask)))
         );
      */

      // Please note that each pattern must be a dual implication (<--> or
      // iff). One directional implication can create spurious matches. If the
      // implication is only one-way, an unsatisfiable condition on the left
      // side can imply a satisfiable condition on the right side. Dual
      // implication ensures that satisfiable conditions are transformed to
      // other satisfiable conditions and unsatisfiable conditions are
      // transformed to other unsatisfiable conditions.

      // Here is a concrete example of a unsatisfiable condition on the left
      // implying a satisfiable condition on the right:
      //
      // mask = (1 << z)
      // (x & ~mask) == y  --> (x == y || x == (y | mask))
      //
      // Substituting y = 3, z = 0 yields:
      // (x & -2) == 3 --> (x == 3 || x == 2)

      // Pattern match a special case:
      /*
        QUERY( (y & ~mask = y) =>
               ((x & ~mask = y) <=> (x = y OR x = (y |  mask)))
        );
      */
      if (match(ICI->getOperand(0),
                m_And(m_Value(RHSVal), m_APInt(RHSC)))) {
        APInt Mask = ~*RHSC;
        if (Mask.isPowerOf2() && (C->getValue() & ~Mask) == C->getValue()) {
          // If we already have a value for the switch, it has to match!
          if (!setValueOnce(RHSVal))
            return false;

          Vals.push_back(C);
          Vals.push_back(
              ConstantInt::get(C->getContext(),
                               C->getValue() | Mask));
          UsedICmps++;
          return true;
        }
      }

      // Pattern match a special case:
      /*
        QUERY( (y |  mask = y) =>
               ((x |  mask = y) <=> (x = y OR x = (y & ~mask)))
        );
      */
      if (match(ICI->getOperand(0),
                m_Or(m_Value(RHSVal), m_APInt(RHSC)))) {
        APInt Mask = *RHSC;
        if (Mask.isPowerOf2() && (C->getValue() | Mask) == C->getValue()) {
          // If we already have a value for the switch, it has to match!
          if (!setValueOnce(RHSVal))
            return false;

          Vals.push_back(C);
          Vals.push_back(ConstantInt::get(C->getContext(),
                                          C->getValue() & ~Mask));
          UsedICmps++;
          return true;
        }
      }

      // If we already have a value for the switch, it has to match!
      if (!setValueOnce(ICI->getOperand(0)))
        return false;

      UsedICmps++;
      Vals.push_back(C);
      return true;
    }

    // If we have "x ult 3", for example, then we can add 0,1,2 to the set.
    ConstantRange Span =
        ConstantRange::makeExactICmpRegion(ICI->getPredicate(), C->getValue());

    // Shift the range if the compare is fed by an add. This is the range
    // compare idiom as emitted by instcombine.
    Value *CandidateVal = I->getOperand(0);
    if (match(I->getOperand(0), m_Add(m_Value(RHSVal), m_APInt(RHSC)))) {
      Span = Span.subtract(*RHSC);
      CandidateVal = RHSVal;
    }

    // If this is an and/!= check, then we are looking to build the set of
    // value that *don't* pass the and chain. I.e. to turn "x ugt 2" into
    // x != 0 && x != 1.
    if (!isEQ)
      Span = Span.inverse();

    // If there are a ton of values, we don't want to make a ginormous switch.
    if (Span.isSizeLargerThan(8) || Span.isEmptySet()) {
      return false;
    }

    // If we already have a value for the switch, it has to match!
    if (!setValueOnce(CandidateVal))
      return false;

    // Add all values from the range to the set
    APInt Tmp = Span.getLower();
    do
      Vals.push_back(ConstantInt::get(I->getContext(), Tmp));
    while (++Tmp != Span.getUpper());

    UsedICmps++;
    return true;
  }

  /// Given a potentially 'or'd or 'and'd together collection of icmp
  /// eq/ne/lt/gt instructions that compare a value against a constant, extract
  /// the value being compared, and stick the list constants into the Vals
  /// vector.
  /// One "Extra" case is allowed to differ from the other.
  void gather(Value *V) {
    Value *Op0, *Op1;
    if (match(V, m_LogicalOr(m_Value(Op0), m_Value(Op1))))
      IsEq = true;
    else if (match(V, m_LogicalAnd(m_Value(Op0), m_Value(Op1))))
      IsEq = false;
    else
      return;
    // Keep a stack (SmallVector for efficiency) for depth-first traversal
    SmallVector<Value *, 8> DFT{Op0, Op1};
    SmallPtrSet<Value *, 8> Visited{V, Op0, Op1};

    while (!DFT.empty()) {
      V = DFT.pop_back_val();

      if (Instruction *I = dyn_cast<Instruction>(V)) {
        // If it is a || (or && depending on isEQ), process the operands.
        if (IsEq ? match(I, m_LogicalOr(m_Value(Op0), m_Value(Op1)))
                 : match(I, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
          if (Visited.insert(Op1).second)
            DFT.push_back(Op1);
          if (Visited.insert(Op0).second)
            DFT.push_back(Op0);

          continue;
        }

        // Try to match the current instruction
        if (matchInstruction(I, IsEq))
          // Match succeed, continue the loop
          continue;
      }

      // One element of the sequence of || (or &&) could not be match as a
      // comparison against the same value as the others.
      // We allow only one "Extra" case to be checked before the switch
      if (!Extra) {
        Extra = V;
        continue;
      }
      // Failed to parse a proper sequence, abort now
      CompValue = nullptr;
      break;
    }
  }
};

} // end anonymous namespace

static void eraseTerminatorAndDCECond(Instruction *TI,
                                      MemorySSAUpdater *MSSAU = nullptr) {
  Instruction *Cond = nullptr;
  if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
    Cond = dyn_cast<Instruction>(SI->getCondition());
  } else if (CondBrInst *BI = dyn_cast<CondBrInst>(TI)) {
    Cond = dyn_cast<Instruction>(BI->getCondition());
  } else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(TI)) {
    Cond = dyn_cast<Instruction>(IBI->getAddress());
  }

  TI->eraseFromParent();
  if (Cond)
    RecursivelyDeleteTriviallyDeadInstructions(Cond, nullptr, MSSAU);
}

/// Return true if the specified terminator checks
/// to see if a value is equal to constant integer value.
Value *SimplifyCFGOpt::isValueEqualityComparison(Instruction *TI) {
  Value *CV = nullptr;
  if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
    // Do not permit merging of large switch instructions into their
    // predecessors unless there is only one predecessor.
    if (!SI->getParent()->hasNPredecessorsOrMore(128 / SI->getNumSuccessors()))
      CV = SI->getCondition();
  } else if (CondBrInst *BI = dyn_cast<CondBrInst>(TI))
    if (BI->getCondition()->hasOneUse()) {
      if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) {
        if (ICI->isEquality() && getConstantInt(ICI->getOperand(1), DL))
          CV = ICI->getOperand(0);
      } else if (auto *Trunc = dyn_cast<TruncInst>(BI->getCondition())) {
        if (Trunc->hasNoUnsignedWrap())
          CV = Trunc->getOperand(0);
      }
    }

  // Unwrap any lossless ptrtoint cast (except for unstable pointers).
  if (CV) {
    if (PtrToIntInst *PTII = dyn_cast<PtrToIntInst>(CV)) {
      Value *Ptr = PTII->getPointerOperand();
      if (DL.hasUnstableRepresentation(Ptr->getType()))
        return CV;
      if (PTII->getType() == DL.getIntPtrType(Ptr->getType()))
        CV = Ptr;
    }
  }
  return CV;
}

/// Given a value comparison instruction,
/// decode all of the 'cases' that it represents and return the 'default' block.
BasicBlock *SimplifyCFGOpt::getValueEqualityComparisonCases(
    Instruction *TI, std::vector<ValueEqualityComparisonCase> &Cases) {
  if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
    Cases.reserve(SI->getNumCases());
    for (auto Case : SI->cases())
      Cases.push_back(ValueEqualityComparisonCase(Case.getCaseValue(),
                                                  Case.getCaseSuccessor()));
    return SI->getDefaultDest();
  }

  CondBrInst *BI = cast<CondBrInst>(TI);
  Value *Cond = BI->getCondition();
  ICmpInst::Predicate Pred;
  ConstantInt *C;
  if (auto *ICI = dyn_cast<ICmpInst>(Cond)) {
    Pred = ICI->getPredicate();
    C = getConstantInt(ICI->getOperand(1), DL);
  } else {
    Pred = ICmpInst::ICMP_NE;
    auto *Trunc = cast<TruncInst>(Cond);
    C = ConstantInt::get(cast<IntegerType>(Trunc->getOperand(0)->getType()), 0);
  }
  BasicBlock *Succ = BI->getSuccessor(Pred == ICmpInst::ICMP_NE);
  Cases.push_back(ValueEqualityComparisonCase(C, Succ));
  return BI->getSuccessor(Pred == ICmpInst::ICMP_EQ);
}

/// Given a vector of bb/value pairs, remove any entries
/// in the list that match the specified block.
static void
eliminateBlockCases(BasicBlock *BB,
                    std::vector<ValueEqualityComparisonCase> &Cases) {
  llvm::erase(Cases, BB);
}

/// Return true if there are any keys in C1 that exist in C2 as well.
static bool valuesOverlap(std::vector<ValueEqualityComparisonCase> &C1,
                          std::vector<ValueEqualityComparisonCase> &C2) {
  std::vector<ValueEqualityComparisonCase> *V1 = &C1, *V2 = &C2;

  // Make V1 be smaller than V2.
  if (V1->size() > V2->size())
    std::swap(V1, V2);

  if (V1->empty())
    return false;
  if (V1->size() == 1) {
    // Just scan V2.
    ConstantInt *TheVal = (*V1)[0].Value;
    for (const ValueEqualityComparisonCase &VECC : *V2)
      if (TheVal == VECC.Value)
        return true;
  }

  // Otherwise, just sort both lists and compare element by element.
  array_pod_sort(V1->begin(), V1->end());
  array_pod_sort(V2->begin(), V2->end());
  unsigned i1 = 0, i2 = 0, e1 = V1->size(), e2 = V2->size();
  while (i1 != e1 && i2 != e2) {
    if ((*V1)[i1].Value == (*V2)[i2].Value)
      return true;
    if ((*V1)[i1].Value < (*V2)[i2].Value)
      ++i1;
    else
      ++i2;
  }
  return false;
}

/// If TI is known to be a terminator instruction and its block is known to
/// only have a single predecessor block, check to see if that predecessor is
/// also a value comparison with the same value, and if that comparison
/// determines the outcome of this comparison. If so, simplify TI. This does a
/// very limited form of jump threading.
bool SimplifyCFGOpt::simplifyEqualityComparisonWithOnlyPredecessor(
    Instruction *TI, BasicBlock *Pred, IRBuilder<> &Builder) {
  Value *PredVal = isValueEqualityComparison(Pred->getTerminator());
  if (!PredVal)
    return false; // Not a value comparison in predecessor.

  Value *ThisVal = isValueEqualityComparison(TI);
  assert(ThisVal && "This isn't a value comparison!!");
  if (ThisVal != PredVal)
    return false; // Different predicates.

  // TODO: Preserve branch weight metadata, similarly to how
  // foldValueComparisonIntoPredecessors preserves it.

  // Find out information about when control will move from Pred to TI's block.
  std::vector<ValueEqualityComparisonCase> PredCases;
  BasicBlock *PredDef =
      getValueEqualityComparisonCases(Pred->getTerminator(), PredCases);
  eliminateBlockCases(PredDef, PredCases); // Remove default from cases.

  // Find information about how control leaves this block.
  std::vector<ValueEqualityComparisonCase> ThisCases;
  BasicBlock *ThisDef = getValueEqualityComparisonCases(TI, ThisCases);
  eliminateBlockCases(ThisDef, ThisCases); // Remove default from cases.

  // If TI's block is the default block from Pred's comparison, potentially
  // simplify TI based on this knowledge.
  if (PredDef == TI->getParent()) {
    // If we are here, we know that the value is none of those cases listed in
    // PredCases.  If there are any cases in ThisCases that are in PredCases, we
    // can simplify TI.
    if (!valuesOverlap(PredCases, ThisCases))
      return false;

    if (isa<CondBrInst>(TI)) {
      // Okay, one of the successors of this condbr is dead.  Convert it to a
      // uncond br.
      assert(ThisCases.size() == 1 && "Branch can only have one case!");
      // Insert the new branch.
      Instruction *NI = Builder.CreateBr(ThisDef);
      (void)NI;

      // Remove PHI node entries for the dead edge.
      ThisCases[0].Dest->removePredecessor(PredDef);

      LLVM_DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
                        << "Through successor TI: " << *TI << "Leaving: " << *NI
                        << "\n");

      eraseTerminatorAndDCECond(TI);

      if (DTU)
        DTU->applyUpdates(
            {{DominatorTree::Delete, PredDef, ThisCases[0].Dest}});

      return true;
    }

    SwitchInstProfUpdateWrapper SI = *cast<SwitchInst>(TI);
    // Okay, TI has cases that are statically dead, prune them away.
    SmallPtrSet<Constant *, 16> DeadCases;
    for (const ValueEqualityComparisonCase &Case : PredCases)
      DeadCases.insert(Case.Value);

    LLVM_DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
                      << "Through successor TI: " << *TI);

    SmallDenseMap<BasicBlock *, int, 8> NumPerSuccessorCases;
    for (SwitchInst::CaseIt i = SI->case_end(), e = SI->case_begin(); i != e;) {
      --i;
      auto *Successor = i->getCaseSuccessor();
      if (DTU)
        ++NumPerSuccessorCases[Successor];
      if (DeadCases.count(i->getCaseValue())) {
        Successor->removePredecessor(PredDef);
        SI.removeCase(i);
        if (DTU)
          --NumPerSuccessorCases[Successor];
      }
    }

    if (DTU) {
      std::vector<DominatorTree::UpdateType> Updates;
      for (const auto &I : NumPerSuccessorCases)
        if (I.second == 0)
          Updates.push_back({DominatorTree::Delete, PredDef, I.first});
      DTU->applyUpdates(Updates);
    }

    LLVM_DEBUG(dbgs() << "Leaving: " << *TI << "\n");
    return true;
  }

  // Otherwise, TI's block must correspond to some matched value.  Find out
  // which value (or set of values) this is.
  ConstantInt *TIV = nullptr;
  BasicBlock *TIBB = TI->getParent();
  for (const auto &[Value, Dest] : PredCases)
    if (Dest == TIBB) {
      if (TIV)
        return false; // Cannot handle multiple values coming to this block.
      TIV = Value;
    }
  assert(TIV && "No edge from pred to succ?");

  // Okay, we found the one constant that our value can be if we get into TI's
  // BB.  Find out which successor will unconditionally be branched to.
  BasicBlock *TheRealDest = nullptr;
  for (const auto &[Value, Dest] : ThisCases)
    if (Value == TIV) {
      TheRealDest = Dest;
      break;
    }

  // If not handled by any explicit cases, it is handled by the default case.
  if (!TheRealDest)
    TheRealDest = ThisDef;

  SmallPtrSet<BasicBlock *, 2> RemovedSuccs;

  // Remove PHI node entries for dead edges.
  BasicBlock *CheckEdge = TheRealDest;
  for (BasicBlock *Succ : successors(TIBB))
    if (Succ != CheckEdge) {
      if (Succ != TheRealDest)
        RemovedSuccs.insert(Succ);
      Succ->removePredecessor(TIBB);
    } else
      CheckEdge = nullptr;

  // Insert the new branch.
  Instruction *NI = Builder.CreateBr(TheRealDest);
  (void)NI;

  LLVM_DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
                    << "Through successor TI: " << *TI << "Leaving: " << *NI
                    << "\n");

  eraseTerminatorAndDCECond(TI);
  if (DTU) {
    SmallVector<DominatorTree::UpdateType, 2> Updates;
    Updates.reserve(RemovedSuccs.size());
    for (auto *RemovedSucc : RemovedSuccs)
      Updates.push_back({DominatorTree::Delete, TIBB, RemovedSucc});
    DTU->applyUpdates(Updates);
  }
  return true;
}

namespace {

/// This class implements a stable ordering of constant
/// integers that does not depend on their address.  This is important for
/// applications that sort ConstantInt's to ensure uniqueness.
struct ConstantIntOrdering {
  bool operator()(const ConstantInt *LHS, const ConstantInt *RHS) const {
    return LHS->getValue().ult(RHS->getValue());
  }
};

} // end anonymous namespace

static int constantIntSortPredicate(ConstantInt *const *P1,
                                    ConstantInt *const *P2) {
  const ConstantInt *LHS = *P1;
  const ConstantInt *RHS = *P2;
  if (LHS == RHS)
    return 0;
  return LHS->getValue().ult(RHS->getValue()) ? 1 : -1;
}

/// Get Weights of a given terminator, the default weight is at the front
/// of the vector. If TI is a conditional eq, we need to swap the branch-weight
/// metadata.
static void getBranchWeights(Instruction *TI,
                             SmallVectorImpl<uint64_t> &Weights) {
  MDNode *MD = TI->getMetadata(LLVMContext::MD_prof);
  assert(MD && "Invalid branch-weight metadata");
  extractFromBranchWeightMD64(MD, Weights);

  // If TI is a conditional eq, the default case is the false case,
  // and the corresponding branch-weight data is at index 2. We swap the
  // default weight to be the first entry.
  if (CondBrInst *BI = dyn_cast<CondBrInst>(TI)) {
    assert(Weights.size() == 2);
    auto *ICI = dyn_cast<ICmpInst>(BI->getCondition());
    if (!ICI)
      return;

    if (ICI->getPredicate() == ICmpInst::ICMP_EQ)
      std::swap(Weights.front(), Weights.back());
  }
}

static void cloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(
    BasicBlock *BB, BasicBlock *PredBlock, ValueToValueMapTy &VMap) {
  Instruction *PTI = PredBlock->getTerminator();

  // If we have bonus instructions, clone them into the predecessor block.
  // Note that there may be multiple predecessor blocks, so we cannot move
  // bonus instructions to a predecessor block.
  for (Instruction &BonusInst : *BB) {
    if (BonusInst.isTerminator())
      continue;

    // Skip cloning pseudo probes into the predecessor, as it would overcount
    // otherwise.
    if (isa<PseudoProbeInst>(BonusInst))
      continue;

    Instruction *NewBonusInst = BonusInst.clone();
    NewBonusInst->insertInto(PredBlock, PTI->getIterator());

    if (!NewBonusInst->getDebugLoc().isSameSourceLocation(PTI->getDebugLoc())) {
      // Unless the instruction has the same !dbg location as the original
      // branch, drop it. When we fold the bonus instructions we want to make
      // sure we reset their debug locations in order to avoid stepping on
      // dead code caused by folding dead branches.
      NewBonusInst->dropLocation();
    } else if (const DebugLoc &DL = NewBonusInst->getDebugLoc()) {
      mapAtomInstance(DL, VMap);
    }

    RemapInstruction(NewBonusInst, VMap,
                     RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);

    // If we speculated an instruction, we need to drop any metadata that may
    // result in undefined behavior, as the metadata might have been valid
    // only given the branch precondition.
    // Similarly strip attributes on call parameters that may cause UB in
    // location the call is moved to.
    NewBonusInst->dropUBImplyingAttrsAndMetadata();

    auto Range = NewBonusInst->cloneDebugInfoFrom(&BonusInst);
    RemapDbgRecordRange(NewBonusInst->getModule(), Range, VMap,
                        RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);

    NewBonusInst->takeName(&BonusInst);
    BonusInst.setName(NewBonusInst->getName() + ".old");
    VMap[&BonusInst] = NewBonusInst;

    // Update (liveout) uses of bonus instructions,
    // now that the bonus instruction has been cloned into predecessor.
    // Note that we expect to be in a block-closed SSA form for this to work!
    for (Use &U : make_early_inc_range(BonusInst.uses())) {
      auto *UI = cast<Instruction>(U.getUser());
      auto *PN = dyn_cast<PHINode>(UI);
      if (!PN) {
        assert(UI->getParent() == BB && BonusInst.comesBefore(UI) &&
               "If the user is not a PHI node, then it should be in the same "
               "block as, and come after, the original bonus instruction.");
        continue; // Keep using the original bonus instruction.
      }
      // Is this the block-closed SSA form PHI node?
      if (PN->getIncomingBlock(U) == BB)
        continue; // Great, keep using the original bonus instruction.
      // The only other alternative is an "use" when coming from
      // the predecessor block - here we should refer to the cloned bonus instr.
      assert(PN->getIncomingBlock(U) == PredBlock &&
             "Not in block-closed SSA form?");
      U.set(NewBonusInst);
    }
  }

  // Key Instructions: We may have propagated atom info into the pred. If the
  // pred's terminator already has atom info do nothing as merging would drop
  // one atom group anyway. If it doesn't, propagte the remapped atom group
  // from BB's terminator.
  if (auto &PredDL = PTI->getDebugLoc()) {
    auto &DL = BB->getTerminator()->getDebugLoc();
    if (!PredDL->getAtomGroup() && DL && DL->getAtomGroup() &&
        PredDL.isSameSourceLocation(DL)) {
      PTI->setDebugLoc(DL);
      RemapSourceAtom(PTI, VMap);
    }
  }
}

bool SimplifyCFGOpt::performValueComparisonIntoPredecessorFolding(
    Instruction *TI, Value *&CV, Instruction *PTI, IRBuilder<> &Builder) {
  BasicBlock *BB = TI->getParent();
  BasicBlock *Pred = PTI->getParent();

  SmallVector<DominatorTree::UpdateType, 32> Updates;

  // Figure out which 'cases' to copy from SI to PSI.
  std::vector<ValueEqualityComparisonCase> BBCases;
  BasicBlock *BBDefault = getValueEqualityComparisonCases(TI, BBCases);

  std::vector<ValueEqualityComparisonCase> PredCases;
  BasicBlock *PredDefault = getValueEqualityComparisonCases(PTI, PredCases);

  // Based on whether the default edge from PTI goes to BB or not, fill in
  // PredCases and PredDefault with the new switch cases we would like to
  // build.
  SmallMapVector<BasicBlock *, int, 8> NewSuccessors;

  // Update the branch weight metadata along the way
  SmallVector<uint64_t, 8> Weights;
  bool PredHasWeights = hasBranchWeightMD(*PTI);
  bool SuccHasWeights = hasBranchWeightMD(*TI);

  if (PredHasWeights) {
    getBranchWeights(PTI, Weights);
    // branch-weight metadata is inconsistent here.
    if (Weights.size() != 1 + PredCases.size())
      PredHasWeights = SuccHasWeights = false;
  } else if (SuccHasWeights)
    // If there are no predecessor weights but there are successor weights,
    // populate Weights with 1, which will later be scaled to the sum of
    // successor's weights
    Weights.assign(1 + PredCases.size(), 1);

  SmallVector<uint64_t, 8> SuccWeights;
  if (SuccHasWeights) {
    getBranchWeights(TI, SuccWeights);
    // branch-weight metadata is inconsistent here.
    if (SuccWeights.size() != 1 + BBCases.size())
      PredHasWeights = SuccHasWeights = false;
  } else if (PredHasWeights)
    SuccWeights.assign(1 + BBCases.size(), 1);

  if (PredDefault == BB) {
    // If this is the default destination from PTI, only the edges in TI
    // that don't occur in PTI, or that branch to BB will be activated.
    std::set<ConstantInt *, ConstantIntOrdering> PTIHandled;
    for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
      if (PredCases[i].Dest != BB)
        PTIHandled.insert(PredCases[i].Value);
      else {
        // The default destination is BB, we don't need explicit targets.
        std::swap(PredCases[i], PredCases.back());

        if (PredHasWeights || SuccHasWeights) {
          // Increase weight for the default case.
          Weights[0] += Weights[i + 1];
          std::swap(Weights[i + 1], Weights.back());
          Weights.pop_back();
        }

        PredCases.pop_back();
        --i;
        --e;
      }

    // Reconstruct the new switch statement we will be building.
    if (PredDefault != BBDefault) {
      PredDefault->removePredecessor(Pred);
      if (DTU && PredDefault != BB)
        Updates.push_back({DominatorTree::Delete, Pred, PredDefault});
      PredDefault = BBDefault;
      ++NewSuccessors[BBDefault];
    }

    unsigned CasesFromPred = Weights.size();
    uint64_t ValidTotalSuccWeight = 0;
    for (unsigned i = 0, e = BBCases.size(); i != e; ++i)
      if (!PTIHandled.count(BBCases[i].Value) && BBCases[i].Dest != BBDefault) {
        PredCases.push_back(BBCases[i]);
        ++NewSuccessors[BBCases[i].Dest];
        if (SuccHasWeights || PredHasWeights) {
          // The default weight is at index 0, so weight for the ith case
          // should be at index i+1. Scale the cases from successor by
          // PredDefaultWeight (Weights[0]).
          Weights.push_back(Weights[0] * SuccWeights[i + 1]);
          ValidTotalSuccWeight += SuccWeights[i + 1];
        }
      }

    if (SuccHasWeights || PredHasWeights) {
      ValidTotalSuccWeight += SuccWeights[0];
      // Scale the cases from predecessor by ValidTotalSuccWeight.
      for (unsigned i = 1; i < CasesFromPred; ++i)
        Weights[i] *= ValidTotalSuccWeight;
      // Scale the default weight by SuccDefaultWeight (SuccWeights[0]).
      Weights[0] *= SuccWeights[0];
    }
  } else {
    // If this is not the default destination from PSI, only the edges
    // in SI that occur in PSI with a destination of BB will be
    // activated.
    std::set<ConstantInt *, ConstantIntOrdering> PTIHandled;
    std::map<ConstantInt *, uint64_t> WeightsForHandled;
    for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
      if (PredCases[i].Dest == BB) {
        PTIHandled.insert(PredCases[i].Value);

        if (PredHasWeights || SuccHasWeights) {
          WeightsForHandled[PredCases[i].Value] = Weights[i + 1];
          std::swap(Weights[i + 1], Weights.back());
          Weights.pop_back();
        }

        std::swap(PredCases[i], PredCases.back());
        PredCases.pop_back();
        --i;
        --e;
      }

    // Okay, now we know which constants were sent to BB from the
    // predecessor.  Figure out where they will all go now.
    for (const ValueEqualityComparisonCase &Case : BBCases)
      if (PTIHandled.count(Case.Value)) {
        // If this is one we are capable of getting...
        if (PredHasWeights || SuccHasWeights)
          Weights.push_back(WeightsForHandled[Case.Value]);
        PredCases.push_back(Case);
        ++NewSuccessors[Case.Dest];
        PTIHandled.erase(Case.Value); // This constant is taken care of
      }

    // If there are any constants vectored to BB that TI doesn't handle,
    // they must go to the default destination of TI.
    for (ConstantInt *I : PTIHandled) {
      if (PredHasWeights || SuccHasWeights)
        Weights.push_back(WeightsForHandled[I]);
      PredCases.push_back(ValueEqualityComparisonCase(I, BBDefault));
      ++NewSuccessors[BBDefault];
    }
  }

  // Okay, at this point, we know which new successor Pred will get.  Make
  // sure we update the number of entries in the PHI nodes for these
  // successors.
  SmallPtrSet<BasicBlock *, 2> SuccsOfPred;
  if (DTU) {
    SuccsOfPred = {llvm::from_range, successors(Pred)};
    Updates.reserve(Updates.size() + NewSuccessors.size());
  }
  for (const std::pair<BasicBlock *, int /*Num*/> &NewSuccessor :
       NewSuccessors) {
    for (auto I : seq(NewSuccessor.second)) {
      (void)I;
      addPredecessorToBlock(NewSuccessor.first, Pred, BB);
    }
    if (DTU && !SuccsOfPred.contains(NewSuccessor.first))
      Updates.push_back({DominatorTree::Insert, Pred, NewSuccessor.first});
  }

  Builder.SetInsertPoint(PTI);
  // Convert pointer to int before we switch.
  if (CV->getType()->isPointerTy()) {
    assert(!DL.hasUnstableRepresentation(CV->getType()) &&
           "Should not end up here with unstable pointers");
    CV =
        Builder.CreatePtrToInt(CV, DL.getIntPtrType(CV->getType()), "magicptr");
  }

  // Now that the successors are updated, create the new Switch instruction.
  SwitchInst *NewSI = Builder.CreateSwitch(CV, PredDefault, PredCases.size());
  NewSI->setDebugLoc(PTI->getDebugLoc());
  for (ValueEqualityComparisonCase &V : PredCases)
    NewSI->addCase(V.Value, V.Dest);

  if (PredHasWeights || SuccHasWeights)
    setFittedBranchWeights(*NewSI, Weights, /*IsExpected=*/false,
                           /*ElideAllZero=*/true);
  else
    setExplicitlyUnknownBranchWeightsIfProfiled(*NewSI, DEBUG_TYPE);

  // The new switch is only known to be unpredictable if both of the comparisons
  // it was built from were unpredictable.
  if (MDNode *Unpredictable = PTI->getMetadata(LLVMContext::MD_unpredictable))
    if (TI->hasMetadata(LLVMContext::MD_unpredictable))
      NewSI->setMetadata(LLVMContext::MD_unpredictable, Unpredictable);

  eraseTerminatorAndDCECond(PTI);

  // Okay, last check.  If BB is still a successor of PSI, then we must
  // have an infinite loop case.  If so, add an infinitely looping block
  // to handle the case to preserve the behavior of the code.
  BasicBlock *InfLoopBlock = nullptr;
  for (unsigned i = 0, e = NewSI->getNumSuccessors(); i != e; ++i)
    if (NewSI->getSuccessor(i) == BB) {
      if (!InfLoopBlock) {
        // Insert it at the end of the function, because it's either code,
        // or it won't matter if it's hot. :)
        InfLoopBlock =
            BasicBlock::Create(BB->getContext(), "infloop", BB->getParent());
        UncondBrInst::Create(InfLoopBlock, InfLoopBlock);
        if (DTU)
          Updates.push_back(
              {DominatorTree::Insert, InfLoopBlock, InfLoopBlock});
      }
      NewSI->setSuccessor(i, InfLoopBlock);
    }

  if (DTU) {
    if (InfLoopBlock)
      Updates.push_back({DominatorTree::Insert, Pred, InfLoopBlock});

    Updates.push_back({DominatorTree::Delete, Pred, BB});

    DTU->applyUpdates(Updates);
  }

  ++NumFoldValueComparisonIntoPredecessors;
  return true;
}

/// The specified terminator is a value equality comparison instruction
/// (either a switch or a branch on "X == c").
/// See if any of the predecessors of the terminator block are value comparisons
/// on the same value.  If so, and if safe to do so, fold them together.
bool SimplifyCFGOpt::foldValueComparisonIntoPredecessors(Instruction *TI,
                                                         IRBuilder<> &Builder) {
  BasicBlock *BB = TI->getParent();
  Value *CV = isValueEqualityComparison(TI); // CondVal
  assert(CV && "Not a comparison?");

  bool Changed = false;

  SmallSetVector<BasicBlock *, 16> Preds(pred_begin(BB), pred_end(BB));
  while (!Preds.empty()) {
    BasicBlock *Pred = Preds.pop_back_val();
    Instruction *PTI = Pred->getTerminator();

    // Don't try to fold into itself.
    if (Pred == BB)
      continue;

    // See if the predecessor is a comparison with the same value.
    Value *PCV = isValueEqualityComparison(PTI); // PredCondVal
    if (PCV != CV)
      continue;

    SmallSetVector<BasicBlock *, 4> FailBlocks;
    if (!safeToMergeTerminators(TI, PTI, &FailBlocks)) {
      for (auto *Succ : FailBlocks) {
        if (!SplitBlockPredecessors(Succ, TI->getParent(), ".fold.split", DTU))
          return false;
      }
    }

    performValueComparisonIntoPredecessorFolding(TI, CV, PTI, Builder);
    Changed = true;
  }
  return Changed;
}

// If we would need to insert a select that uses the value of this invoke
// (comments in hoistSuccIdenticalTerminatorToSwitchOrIf explain why we would
// need to do this), we can't hoist the invoke, as there is nowhere to put the
// select in this case.
static bool isSafeToHoistInvoke(BasicBlock *BB1, BasicBlock *BB2,
                                Instruction *I1, Instruction *I2) {
  for (BasicBlock *Succ : successors(BB1)) {
    for (const PHINode &PN : Succ->phis()) {
      Value *BB1V = PN.getIncomingValueForBlock(BB1);
      Value *BB2V = PN.getIncomingValueForBlock(BB2);
      if (BB1V != BB2V && (BB1V == I1 || BB2V == I2)) {
        return false;
      }
    }
  }
  return true;
}

// Get interesting characteristics of instructions that
// `hoistCommonCodeFromSuccessors` didn't hoist. They restrict what kind of
// instructions can be reordered across.
enum SkipFlags {
  SkipReadMem = 1,
  SkipSideEffect = 2,
  SkipImplicitControlFlow = 4
};

static unsigned skippedInstrFlags(Instruction *I) {
  // Pseudo probes don't constrain reordering of other instructions.
  if (isa<PseudoProbeInst>(I))
    return 0;
  unsigned Flags = 0;
  if (I->mayReadFromMemory())
    Flags |= SkipReadMem;
  // We can't arbitrarily move around allocas, e.g. moving allocas (especially
  // inalloca) across stacksave/stackrestore boundaries.
  if (I->mayHaveSideEffects() || isa<AllocaInst>(I))
    Flags |= SkipSideEffect;
  if (!isGuaranteedToTransferExecutionToSuccessor(I))
    Flags |= SkipImplicitControlFlow;
  return Flags;
}

// Returns true if it is safe to reorder an instruction across preceding
// instructions in a basic block.
static bool isSafeToHoistInstr(Instruction *I, unsigned Flags) {
  // Don't reorder a store over a load.
  if ((Flags & SkipReadMem) && I->mayWriteToMemory())
    return false;

  // If we have seen an instruction with side effects, it's unsafe to reorder an
  // instruction which reads memory or itself has side effects.
  if ((Flags & SkipSideEffect) &&
      (I->mayReadFromMemory() || I->mayHaveSideEffects() || isa<AllocaInst>(I)))
    return false;

  // Reordering across an instruction which does not necessarily transfer
  // control to the next instruction is speculation.
  if ((Flags & SkipImplicitControlFlow) && !isSafeToSpeculativelyExecute(I))
    return false;

  // Hoisting of llvm.deoptimize is only legal together with the next return
  // instruction, which this pass is not always able to do.
  if (auto *CB = dyn_cast<CallBase>(I))
    if (CB->getIntrinsicID() == Intrinsic::experimental_deoptimize)
      return false;

  // It's also unsafe/illegal to hoist an instruction above its instruction
  // operands
  BasicBlock *BB = I->getParent();
  for (Value *Op : I->operands()) {
    if (auto *J = dyn_cast<Instruction>(Op))
      if (J->getParent() == BB)
        return false;
  }

  return true;
}

static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified = false);

/// Helper function for hoistCommonCodeFromSuccessors. Return true if identical
/// instructions \p I1 and \p I2 can and should be hoisted.
static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2,
                                          const TargetTransformInfo &TTI) {
  // If we're going to hoist a call, make sure that the two instructions
  // we're commoning/hoisting are both marked with musttail, or neither of
  // them is marked as such. Otherwise, we might end up in a situation where
  // we hoist from a block where the terminator is a `ret` to a block where
  // the terminator is a `br`, and `musttail` calls expect to be followed by
  // a return.
  auto *C1 = dyn_cast<CallInst>(I1);
  auto *C2 = dyn_cast<CallInst>(I2);
  if (C1 && C2)
    if (C1->isMustTailCall() != C2->isMustTailCall())
      return false;

  if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2))
    return false;

  // If any of the two call sites has nomerge or convergent attribute, stop
  // hoisting.
  if (const auto *CB1 = dyn_cast<CallBase>(I1))
    if (CB1->cannotMerge() || CB1->isConvergent())
      return false;
  if (const auto *CB2 = dyn_cast<CallBase>(I2))
    if (CB2->cannotMerge() || CB2->isConvergent())
      return false;

  return true;
}

/// Hoists DbgVariableRecords from \p I1 and \p OtherInstrs that are identical
/// in lock-step to \p TI. This matches how dbg.* intrinsics are hoisting in
/// hoistCommonCodeFromSuccessors. e.g. The input:
///    I1                DVRs: { x, z },
///    OtherInsts: { I2  DVRs: { x, y, z } }
/// would result in hoisting only DbgVariableRecord x.
static void hoistLockstepIdenticalDbgVariableRecords(
    Instruction *TI, Instruction *I1,
    SmallVectorImpl<Instruction *> &OtherInsts) {
  if (!I1->hasDbgRecords())
    return;
  using CurrentAndEndIt =
      std::pair<DbgRecord::self_iterator, DbgRecord::self_iterator>;
  // Vector of {Current, End} iterators.
  SmallVector<CurrentAndEndIt> Itrs;
  Itrs.reserve(OtherInsts.size() + 1);
  // Helper lambdas for lock-step checks:
  // Return true if this Current == End.
  auto atEnd = [](const CurrentAndEndIt &Pair) {
    return Pair.first == Pair.second;
  };
  // Return true if all Current are identical.
  auto allIdentical = [](const SmallVector<CurrentAndEndIt> &Itrs) {
    return all_of(make_first_range(ArrayRef(Itrs).drop_front()),
                  [&](DbgRecord::self_iterator I) {
                    return Itrs[0].first->isIdenticalToWhenDefined(*I);
                  });
  };

  // Collect the iterators.
  Itrs.push_back(
      {I1->getDbgRecordRange().begin(), I1->getDbgRecordRange().end()});
  for (Instruction *Other : OtherInsts) {
    if (!Other->hasDbgRecords())
      return;
    Itrs.push_back(
        {Other->getDbgRecordRange().begin(), Other->getDbgRecordRange().end()});
  }

  // Iterate in lock-step until any of the DbgRecord lists are exausted. If
  // the lock-step DbgRecord are identical, hoist all of them to TI.
  // This replicates the dbg.* intrinsic behaviour in
  // hoistCommonCodeFromSuccessors.
  while (none_of(Itrs, atEnd)) {
    bool HoistDVRs = allIdentical(Itrs);
    for (CurrentAndEndIt &Pair : Itrs) {
      // Increment Current iterator now as we may be about to move the
      // DbgRecord.
      DbgRecord &DR = *Pair.first++;
      if (HoistDVRs) {
        DR.removeFromParent();
        TI->getParent()->insertDbgRecordBefore(&DR, TI->getIterator());
      }
    }
  }
}

static bool areIdenticalUpToCommutativity(const Instruction *I1,
                                          const Instruction *I2) {
  if (I1->isIdenticalToWhenDefined(I2, /*IntersectAttrs=*/true))
    return true;

  if (auto *Cmp1 = dyn_cast<CmpInst>(I1))
    if (auto *Cmp2 = dyn_cast<CmpInst>(I2))
      return Cmp1->getPredicate() == Cmp2->getSwappedPredicate() &&
             Cmp1->getOperand(0) == Cmp2->getOperand(1) &&
             Cmp1->getOperand(1) == Cmp2->getOperand(0);

  if (I1->isCommutative() && I1->isSameOperationAs(I2)) {
    return I1->getOperand(0) == I2->getOperand(1) &&
           I1->getOperand(1) == I2->getOperand(0) &&
           equal(drop_begin(I1->operands(), 2), drop_begin(I2->operands(), 2));
  }

  return false;
}

/// If the target supports conditional faulting,
/// we look for the following pattern:
/// \code
///   BB:
///     ...
///     %cond = icmp ult %x, %y
///     br i1 %cond, label %TrueBB, label %FalseBB
///   FalseBB:
///     store i32 1, ptr %q, align 4
///     ...
///   TrueBB:
///     %maskedloadstore = load i32, ptr %b, align 4
///     store i32 %maskedloadstore, ptr %p, align 4
///     ...
/// \endcode
///
/// and transform it into:
///
/// \code
///   BB:
///     ...
///     %cond = icmp ult %x, %y
///     %maskedloadstore = cload i32, ptr %b, %cond
///     cstore i32 %maskedloadstore, ptr %p, %cond
///     cstore i32 1, ptr %q, ~%cond
///     br i1 %cond, label %TrueBB, label %FalseBB
///   FalseBB:
///     ...
///   TrueBB:
///     ...
/// \endcode
///
/// where cload/cstore are represented by llvm.masked.load/store intrinsics,
/// e.g.
///
/// \code
///   %vcond = bitcast i1 %cond to <1 x i1>
///   %v0 = call <1 x i32> @llvm.masked.load.v1i32.p0
///                         (ptr %b, i32 4, <1 x i1> %vcond, <1 x i32> poison)
///   %maskedloadstore = bitcast <1 x i32> %v0 to i32
///   call void @llvm.masked.store.v1i32.p0
///                          (<1 x i32> %v0, ptr %p, i32 4, <1 x i1> %vcond)
///   %cond.not = xor i1 %cond, true
///   %vcond.not = bitcast i1 %cond.not to <1 x i>
///   call void @llvm.masked.store.v1i32.p0
///              (<1 x i32> <i32 1>, ptr %q, i32 4, <1x i1> %vcond.not)
/// \endcode
///
/// So we need to turn hoisted load/store into cload/cstore.
///
/// \param BI The branch instruction.
/// \param SpeculatedConditionalLoadsStores The load/store instructions that
///                                         will be speculated.
/// \param Invert indicates if speculates FalseBB. Only used in triangle CFG.
static void hoistConditionalLoadsStores(
    CondBrInst *BI,
    SmallVectorImpl<Instruction *> &SpeculatedConditionalLoadsStores,
    std::optional<bool> Invert, Instruction *Sel) {
  auto &Context = BI->getParent()->getContext();
  auto *VCondTy = FixedVectorType::get(Type::getInt1Ty(Context), 1);
  auto *Cond = BI->getCondition();
  // Construct the condition if needed.
  BasicBlock *BB = BI->getParent();
  Value *Mask = nullptr;
  Value *MaskFalse = nullptr;
  Value *MaskTrue = nullptr;
  if (Invert.has_value()) {
    IRBuilder<> Builder(Sel ? Sel : SpeculatedConditionalLoadsStores.back());
    Mask = Builder.CreateBitCast(
        *Invert ? Builder.CreateXor(Cond, ConstantInt::getTrue(Context)) : Cond,
        VCondTy);
  } else {
    IRBuilder<> Builder(BI);
    MaskFalse = Builder.CreateBitCast(
        Builder.CreateXor(Cond, ConstantInt::getTrue(Context)), VCondTy);
    MaskTrue = Builder.CreateBitCast(Cond, VCondTy);
  }
  auto PeekThroughBitcasts = [](Value *V) {
    while (auto *BitCast = dyn_cast<BitCastInst>(V))
      V = BitCast->getOperand(0);
    return V;
  };
  for (auto *I : SpeculatedConditionalLoadsStores) {
    IRBuilder<> Builder(Invert.has_value() ? I : BI);
    if (!Invert.has_value())
      Mask = I->getParent() == BI->getSuccessor(0) ? MaskTrue : MaskFalse;
    // We currently assume conditional faulting load/store is supported for
    // scalar types only when creating new instructions. This can be easily
    // extended for vector types in the future.
    assert(!getLoadStoreType(I)->isVectorTy() && "not implemented");
    auto *Op0 = I->getOperand(0);
    CallInst *MaskedLoadStore = nullptr;
    if (auto *LI = dyn_cast<LoadInst>(I)) {
      // Handle Load.
      auto *Ty = I->getType();
      PHINode *PN = nullptr;
      Value *PassThru = nullptr;
      if (Invert.has_value())
        for (User *U : I->users()) {
          if ((PN = dyn_cast<PHINode>(U))) {
            PassThru = Builder.CreateBitCast(
                PeekThroughBitcasts(PN->getIncomingValueForBlock(BB)),
                FixedVectorType::get(Ty, 1));
          } else if (auto *Ins = cast<Instruction>(U);
                     Sel && Ins->getParent() == BB) {
            // This happens when store or/and a speculative instruction between
            // load and store were hoisted to the BB. Make sure the masked load
            // inserted before its use.
            // We assume there's one of such use.
            Builder.SetInsertPoint(Ins);
          }
        }
      MaskedLoadStore = Builder.CreateMaskedLoad(
          FixedVectorType::get(Ty, 1), Op0, LI->getAlign(), Mask, PassThru);
      if (const MDNode *Ranges = I->getMetadata(LLVMContext::MD_range)) {
        ConstantRange CR = getConstantRangeFromMetadata(*Ranges);
        if (PassThru && !isa<PoisonValue>(PassThru)) {
          auto *C = dyn_cast<Constant>(PassThru);
          CR = C ? CR.unionWith(C->toConstantRange())
                 : ConstantRange::getFull(CR.getBitWidth());
        }
        MaskedLoadStore->addRangeRetAttr(CR);
      }
      Value *NewLoadStore = Builder.CreateBitCast(MaskedLoadStore, Ty);
      if (PN)
        PN->setIncomingValue(PN->getBasicBlockIndex(BB), NewLoadStore);
      I->replaceAllUsesWith(NewLoadStore);
    } else {
      // Handle Store.
      auto *StoredVal = Builder.CreateBitCast(
          PeekThroughBitcasts(Op0), FixedVectorType::get(Op0->getType(), 1));
      MaskedLoadStore = Builder.CreateMaskedStore(
          StoredVal, I->getOperand(1), cast<StoreInst>(I)->getAlign(), Mask);
    }
    // For non-debug metadata, only !annotation, !range, !nonnull and !align are
    // kept when hoisting (see Instruction::dropUBImplyingAttrsAndMetadata).
    //
    // !nonnull, !align : Not support pointer type, no need to keep.
    // !range: Kept as a return attribute, widened over PassThru (see above).
    // !annotation: Not impact semantics. Keep it.
    I->dropUBImplyingAttrsAndUnknownMetadata({LLVMContext::MD_annotation});
    // FIXME: DIAssignID is not supported for masked store yet.
    // (Verifier::visitDIAssignIDMetadata)
    at::deleteAssignmentMarkers(I);
    I->eraseMetadataIf([](unsigned MDKind, MDNode *Node) {
      return Node->getMetadataID() == Metadata::DIAssignIDKind;
    });
    MaskedLoadStore->copyMetadata(*I);
    I->eraseFromParent();
  }
}

static bool isSafeCheapLoadStore(const Instruction *I,
                                 const TargetTransformInfo &TTI) {
  // Not handle volatile or atomic.
  bool IsStore = false;
  if (auto *L = dyn_cast<LoadInst>(I)) {
    if (!L->isSimple() || !HoistLoadsWithCondFaulting)
      return false;
  } else if (auto *S = dyn_cast<StoreInst>(I)) {
    if (!S->isSimple() || !HoistStoresWithCondFaulting)
      return false;
    IsStore = true;
  } else
    return false;

  // llvm.masked.load/store use i32 for alignment while load/store use i64.
  // That's why we have the alignment limitation.
  // FIXME: Update the prototype of the intrinsics?
  return TTI.hasConditionalLoadStoreForType(getLoadStoreType(I), IsStore) &&
         getLoadStoreAlignment(I) < Value::MaximumAlignment;
}

/// Hoist any common code in the successor blocks up into the block. This
/// function guarantees that BB dominates all successors. If AllInstsEqOnly is
/// given, only perform hoisting in case all successors blocks contain matching
/// instructions only. In that case, all instructions can be hoisted and the
/// original branch will be replaced and selects for PHIs are added.
bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(Instruction *TI,
                                                   bool AllInstsEqOnly) {
  // This does very trivial matching, with limited scanning, to find identical
  // instructions in the two blocks. In particular, we don't want to get into
  // O(N1*N2*...) situations here where Ni are the sizes of these successors. As
  // such, we currently just scan for obviously identical instructions in an
  // identical order, possibly separated by the same number of non-identical
  // instructions.
  BasicBlock *BB = TI->getParent();
  unsigned int SuccSize = succ_size(BB);
  if (SuccSize < 2)
    return false;

  // If either of the blocks has it's address taken, then we can't do this fold,
  // because the code we'd hoist would no longer run when we jump into the block
  // by it's address.
  SmallSetVector<BasicBlock *, 4> UniqueSuccessors(from_range, successors(BB));
  for (auto *Succ : UniqueSuccessors) {
    if (Succ->hasAddressTaken())
      return false;
    // Use getUniquePredecessor instead of getSinglePredecessor to support
    // multi-cases successors in switch.
    if (Succ->getUniquePredecessor())
      continue;
    // If Succ has >1 predecessors, continue to check if the Succ contains only
    // one `unreachable` inst. Since executing `unreachable` inst is an UB, we
    // can relax the condition based on the assumptiom that the program would
    // never enter Succ and trigger such an UB.
    if (isa<UnreachableInst>(*Succ->begin()))
      continue;
    return false;
  }
  // The second of pair is a SkipFlags bitmask.
  using SuccIterPair = std::pair<BasicBlock::iterator, unsigned>;
  SmallVector<SuccIterPair, 8> SuccIterPairs;
  for (auto *Succ : UniqueSuccessors) {
    BasicBlock::iterator SuccItr = Succ->begin();
    if (isa<PHINode>(*SuccItr))
      return false;
    SuccIterPairs.push_back(SuccIterPair(SuccItr, 0));
  }

  if (AllInstsEqOnly) {
    // Check if all instructions in the successor blocks match. This allows
    // hoisting all instructions and removing the blocks we are hoisting from,
    // so does not add any new instructions.

    // Check if sizes and terminators of all successors match.
    unsigned Size0 = UniqueSuccessors[0]->size();
    Instruction *Term0 = UniqueSuccessors[0]->getTerminator();
    bool AllSame =
        all_of(drop_begin(UniqueSuccessors), [Term0, Size0](BasicBlock *Succ) {
          return Succ->getTerminator()->isIdenticalTo(Term0) &&
                 Succ->size() == Size0;
        });
    if (!AllSame)
      return false;
    LockstepReverseIterator<true> LRI(UniqueSuccessors.getArrayRef());
    while (LRI.isValid()) {
      Instruction *I0 = (*LRI)[0];
      if (any_of(*LRI, [I0](Instruction *I) {
            return !areIdenticalUpToCommutativity(I0, I);
          })) {
        return false;
      }
      --LRI;
    }
    // Now we know that all instructions in all successors can be hoisted. Let
    // the loop below handle the hoisting.
  }

  // Count how many instructions were not hoisted so far. There's a limit on how
  // many instructions we skip, serving as a compilation time control as well as
  // preventing excessive increase of life ranges.
  unsigned NumSkipped = 0;
  // If we find an unreachable instruction at the beginning of a basic block, we
  // can still hoist instructions from the rest of the basic blocks.
  if (SuccIterPairs.size() > 2) {
    erase_if(SuccIterPairs,
             [](const auto &Pair) { return isa<UnreachableInst>(Pair.first); });
    if (SuccIterPairs.size() < 2)
      return false;
  }

  bool Changed = false;

  for (;;) {
    auto *SuccIterPairBegin = SuccIterPairs.begin();
    auto &BB1ItrPair = *SuccIterPairBegin++;
    auto OtherSuccIterPairRange =
        iterator_range(SuccIterPairBegin, SuccIterPairs.end());
    auto OtherSuccIterRange = make_first_range(OtherSuccIterPairRange);

    Instruction *I1 = &*BB1ItrPair.first;

    bool AllInstsAreIdentical = true;
    bool HasTerminator = I1->isTerminator();
    for (auto &SuccIter : OtherSuccIterRange) {
      Instruction *I2 = &*SuccIter;
      HasTerminator |= I2->isTerminator();
      if (AllInstsAreIdentical && (!areIdenticalUpToCommutativity(I1, I2) ||
                                   MMRAMetadata(*I1) != MMRAMetadata(*I2)))
        AllInstsAreIdentical = false;
    }

    SmallVector<Instruction *, 8> OtherInsts;
    for (auto &SuccIter : OtherSuccIterRange)
      OtherInsts.push_back(&*SuccIter);

    // If we are hoisting the terminator instruction, don't move one (making a
    // broken BB), instead clone it, and remove BI.
    if (HasTerminator) {
      // Even if BB, which contains only one unreachable instruction, is ignored
      // at the beginning of the loop, we can hoist the terminator instruction.
      // If any instructions remain in the block, we cannot hoist terminators.
      if (NumSkipped || !AllInstsAreIdentical) {
        hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherInsts);
        return Changed;
      }

      return hoistSuccIdenticalTerminatorToSwitchOrIf(
                 TI, I1, OtherInsts, UniqueSuccessors.getArrayRef()) ||
             Changed;
    }

    if (AllInstsAreIdentical) {
      unsigned SkipFlagsBB1 = BB1ItrPair.second;
      AllInstsAreIdentical =
          isSafeToHoistInstr(I1, SkipFlagsBB1) &&
          all_of(OtherSuccIterPairRange, [=](const auto &Pair) {
            Instruction *I2 = &*Pair.first;
            unsigned SkipFlagsBB2 = Pair.second;
            // Even if the instructions are identical, it may not
            // be safe to hoist them if we have skipped over
            // instructions with side effects or their operands
            // weren't hoisted.
            return isSafeToHoistInstr(I2, SkipFlagsBB2) &&
                   shouldHoistCommonInstructions(I1, I2, TTI);
          });
    }

    // A musttail call must be immediately followed by a ret, so hoisting is
    // only legal if its ret is hoisted with it on the next iteration. That is,
    // no instruction has been skipped (the entire successor can be hoisted into
    // the predecessor) and the call is directly followed by a ret.
    if (auto *CI = dyn_cast<CallInst>(I1);
        AllInstsAreIdentical && CI && CI->isMustTailCall()) {
      AllInstsAreIdentical =
          NumSkipped == 0 && all_of(SuccIterPairs, [](const SuccIterPair &P) {
            return isa<ReturnInst>(*std::next(P.first));
          });
    }

    if (AllInstsAreIdentical) {
      BB1ItrPair.first++;
      // For a normal instruction, we just move one to right before the
      // branch, then replace all uses of the other with the first.  Finally,
      // we remove the now redundant second instruction.
      hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherInsts);
      // We've just hoisted DbgVariableRecords; move I1 after them (before TI)
      // and leave any that were not hoisted behind (by calling moveBefore
      // rather than moveBeforePreserving).
      I1->moveBefore(TI->getIterator());
      for (auto &SuccIter : OtherSuccIterRange) {
        Instruction *I2 = &*SuccIter++;
        assert(I2 != I1);
        if (!I2->use_empty())
          I2->replaceAllUsesWith(I1);
        I1->andIRFlags(I2);
        if (auto *CB = dyn_cast<CallBase>(I1)) {
          bool Success = CB->tryIntersectAttributes(cast<CallBase>(I2));
          assert(Success && "We should not be trying to hoist callbases "
                            "with non-intersectable attributes");
          // For NDEBUG Compile.
          (void)Success;
        }

        combineMetadataForCSE(I1, I2, true);
        // If we are combining select instructions, we mark the profile
        // explicitly unknown given we are hoisting the instruction across
        // control flow and we have no guarantee that the control flow condition
        // we are hoisting across is independent of the select condition.
        if (auto *SI = dyn_cast<SelectInst>(I1))
          setExplicitlyUnknownBranchWeightsIfProfiled(*SI, DEBUG_TYPE);
        // I1 and I2 are being combined into a single instruction.  Its debug
        // location is the merged locations of the original instructions.
        I1->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc());
        I2->eraseFromParent();
      }
      // I1 now executes before the instructions we skipped.
      unsigned SkippedFlags = 0;
      for (const SuccIterPair &P : SuccIterPairs)
        SkippedFlags |= P.second;
      if (SkippedFlags & SkipImplicitControlFlow) {
        // One of them may throw or not return, so I1 is speculated.
        I1->dropUBImplyingAttrsAndMetadata();
      }
      if (!Changed)
        NumHoistCommonCode += SuccIterPairs.size();
      Changed = true;
      NumHoistCommonInstrs += SuccIterPairs.size();
    } else {
      if (NumSkipped >= HoistCommonSkipLimit) {
        hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherInsts);
        return Changed;
      }
      // We are about to skip over a pair of non-identical instructions. Record
      // if any have characteristics that would prevent reordering instructions
      // across them.
      for (auto &SuccIterPair : SuccIterPairs) {
        Instruction *I = &*SuccIterPair.first++;
        SuccIterPair.second |= skippedInstrFlags(I);
      }
      ++NumSkipped;
    }
  }
}

bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
    Instruction *TI, Instruction *I1,
    SmallVectorImpl<Instruction *> &OtherSuccTIs,
    ArrayRef<BasicBlock *> UniqueSuccessors) {

  auto *BI = dyn_cast<CondBrInst>(TI);

  bool Changed = false;
  BasicBlock *TIParent = TI->getParent();
  BasicBlock *BB1 = I1->getParent();

  // Use only for an if statement.
  auto *I2 = *OtherSuccTIs.begin();
  auto *BB2 = I2->getParent();
  if (BI) {
    assert(OtherSuccTIs.size() == 1);
    assert(BI->getSuccessor(0) == I1->getParent());
    assert(BI->getSuccessor(1) == I2->getParent());
  }

  // In the case of an if statement, we try to hoist an invoke.
  // FIXME: Can we define a safety predicate for CallBr?
  // FIXME: Test case llvm/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll
  // removed in 4c923b3b3fd0ac1edebf0603265ca3ba51724937 commit?
  if (isa<InvokeInst>(I1) && (!BI || !isSafeToHoistInvoke(BB1, BB2, I1, I2)))
    return false;

  // TODO: callbr hoisting currently disabled pending further study.
  if (isa<CallBrInst>(I1))
    return false;

  for (BasicBlock *Succ : successors(BB1)) {
    for (PHINode &PN : Succ->phis()) {
      Value *BB1V = PN.getIncomingValueForBlock(BB1);
      for (Instruction *OtherSuccTI : OtherSuccTIs) {
        Value *BB2V = PN.getIncomingValueForBlock(OtherSuccTI->getParent());
        if (BB1V == BB2V)
          continue;

        // In the case of an if statement, check for
        // passingValueIsAlwaysUndefined here because we would rather eliminate
        // undefined control flow then converting it to a select.
        if (!BI || passingValueIsAlwaysUndefined(BB1V, &PN) ||
            passingValueIsAlwaysUndefined(BB2V, &PN))
          return false;
      }
    }
  }

  // Hoist DbgVariableRecords attached to the terminator to match dbg.*
  // intrinsic hoisting behaviour in hoistCommonCodeFromSuccessors.
  hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherSuccTIs);
  // Clone the terminator and hoist it into the pred, without any debug info.
  Instruction *NT = I1->clone();
  NT->insertInto(TIParent, TI->getIterator());
  if (!NT->getType()->isVoidTy()) {
    I1->replaceAllUsesWith(NT);
    for (Instruction *OtherSuccTI : OtherSuccTIs)
      OtherSuccTI->replaceAllUsesWith(NT);
    NT->takeName(I1);
  }
  Changed = true;
  NumHoistCommonInstrs += OtherSuccTIs.size() + 1;

  // Ensure terminator gets a debug location, even an unknown one, in case
  // it involves inlinable calls.
  SmallVector<DebugLoc, 4> Locs;
  Locs.push_back(I1->getDebugLoc());
  for (auto *OtherSuccTI : OtherSuccTIs)
    Locs.push_back(OtherSuccTI->getDebugLoc());
  NT->setDebugLoc(DebugLoc::getMergedLocations(Locs));

  // PHIs created below will adopt NT's merged DebugLoc.
  IRBuilder<NoFolder> Builder(NT);

  // In the case of an if statement, hoisting one of the terminators from our
  // successor is a great thing. Unfortunately, the successors of the if/else
  // blocks may have PHI nodes in them.  If they do, all PHI entries for BB1/BB2
  // must agree for all PHI nodes, so we insert select instruction to compute
  // the final result.
  if (BI) {
    std::map<std::pair<Value *, Value *>, SelectInst *> InsertedSelects;
    for (BasicBlock *Succ : successors(BB1)) {
      for (PHINode &PN : Succ->phis()) {
        Value *BB1V = PN.getIncomingValueForBlock(BB1);
        Value *BB2V = PN.getIncomingValueForBlock(BB2);
        if (BB1V == BB2V)
          continue;

        // These values do not agree.  Insert a select instruction before NT
        // that determines the right value.
        SelectInst *&SI = InsertedSelects[std::make_pair(BB1V, BB2V)];
        if (!SI) {
          // Propagate fast-math-flags from phi node to its replacement select.
          SI = cast<SelectInst>(Builder.CreateSelectFMF(
              BI->getCondition(), BB1V, BB2V,
              isa<FPMathOperator>(PN) ? &PN : nullptr,
              BB1V->getName() + "." + BB2V->getName(), BI));
        }

        // Make the PHI node use the select for all incoming values for BB1/BB2
        for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
          if (PN.getIncomingBlock(i) == BB1 || PN.getIncomingBlock(i) == BB2)
            PN.setIncomingValue(i, SI);
      }
    }
  }

  SmallVector<DominatorTree::UpdateType, 4> Updates;

  // Update any PHI nodes in our new successors.
  SmallPtrSet<BasicBlock *, 8> VisitedSuccs;
  for (BasicBlock *Succ : successors(BB1)) {
    addPredecessorToBlock(Succ, TIParent, BB1);

    if (DTU && VisitedSuccs.insert(Succ).second)
      Updates.push_back({DominatorTree::Insert, TIParent, Succ});
  }

  if (DTU) {
    // TI might be a switch with multi-cases destination, so we need to care for
    // the duplication of successors.
    for (BasicBlock *Succ : UniqueSuccessors)
      Updates.push_back({DominatorTree::Delete, TIParent, Succ});
  }

  eraseTerminatorAndDCECond(TI);
  if (DTU)
    DTU->applyUpdates(Updates);
  return Changed;
}

// TODO: Refine this. This should avoid cases like turning constant memcpy sizes
// into variables.
static bool replacingOperandWithVariableIsCheap(const Instruction *I,
                                                int OpIdx) {
  // Divide/Remainder by constant is typically much cheaper than by variable.
  if (I->isIntDivRem())
    return OpIdx != 1;
  return !isa<IntrinsicInst>(I);
}

// All instructions in Insts belong to different blocks that all unconditionally
// branch to a common successor. Analyze each instruction and return true if it
// would be possible to sink them into their successor, creating one common
// instruction instead. For every value that would be required to be provided by
// PHI node (because an operand varies in each input block), add to PHIOperands.
static bool canSinkInstructions(
    ArrayRef<Instruction *> Insts,
    DenseMap<const Use *, SmallVector<Value *, 4>> &PHIOperands) {
  // Prune out obviously bad instructions to move. Each instruction must have
  // the same number of uses, and we check later that the uses are consistent.
  std::optional<unsigned> NumUses;
  for (auto *I : Insts) {
    // These instructions may change or break semantics if moved.
    if (isa<PHINode>(I) || I->isEHPad() || isa<AllocaInst>(I) ||
        I->getType()->isTokenTy())
      return false;

    // Do not try to sink an instruction in an infinite loop - it can cause
    // this algorithm to infinite loop.
    if (I->getParent()->getSingleSuccessor() == I->getParent())
      return false;

    // Conservatively return false if I is an inline-asm instruction. Sinking
    // and merging inline-asm instructions can potentially create arguments
    // that cannot satisfy the inline-asm constraints.
    // If the instruction has nomerge or convergent attribute, return false.
    if (const auto *C = dyn_cast<CallBase>(I))
      if (C->isInlineAsm() || C->cannotMerge() || C->isConvergent())
        return false;

    if (!NumUses)
      NumUses = I->getNumUses();
    else if (NumUses != I->getNumUses())
      return false;
  }

  const Instruction *I0 = Insts.front();
  const auto I0MMRA = MMRAMetadata(*I0);
  for (auto *I : Insts) {
    if (!I->isSameOperationAs(I0, Instruction::CompareUsingIntersectedAttrs))
      return false;

    // Treat MMRAs conservatively. This pass can be quite aggressive and
    // could drop a lot of MMRAs otherwise.
    if (MMRAMetadata(*I) != I0MMRA)
      return false;
  }

  // Uses must be consistent: If I0 is used in a phi node in the sink target,
  // then the other phi operands must match the instructions from Insts. This
  // also has to hold true for any phi nodes that would be created as a result
  // of sinking. Both of these cases are represented by PhiOperands.
  for (const Use &U : I0->uses()) {
    auto It = PHIOperands.find(&U);
    if (It == PHIOperands.end())
      // There may be uses in other blocks when sinking into a loop header.
      return false;
    if (!equal(Insts, It->second))
      return false;
  }

  // For calls to be sinkable, they must all be indirect, or have same callee.
  // I.e. if we have two direct calls to different callees, we don't want to
  // turn that into an indirect call. Likewise, if we have an indirect call,
  // and a direct call, we don't actually want to have a single indirect call.
  if (isa<CallBase>(I0)) {
    auto IsIndirectCall = [](const Instruction *I) {
      return cast<CallBase>(I)->isIndirectCall();
    };
    bool HaveIndirectCalls = any_of(Insts, IsIndirectCall);
    bool AllCallsAreIndirect = all_of(Insts, IsIndirectCall);
    if (HaveIndirectCalls) {
      if (!AllCallsAreIndirect)
        return false;
    } else {
      // All callees must be identical.
      Value *Callee = nullptr;
      for (const Instruction *I : Insts) {
        Value *CurrCallee = cast<CallBase>(I)->getCalledOperand();
        if (!Callee)
          Callee = CurrCallee;
        else if (Callee != CurrCallee)
          return false;
      }
    }
  }

  for (unsigned OI = 0, OE = I0->getNumOperands(); OI != OE; ++OI) {
    Value *Op = I0->getOperand(OI);
    auto SameAsI0 = [&I0, OI](const Instruction *I) {
      assert(I->getNumOperands() == I0->getNumOperands());
      return I->getOperand(OI) == I0->getOperand(OI);
    };
    if (!all_of(Insts, SameAsI0)) {
      auto CanReplaceOperand = [OI](const Instruction *I) {
        return canReplaceOperandWithVariable(I, OI);
      };
      if ((isa<Constant>(Op) && !replacingOperandWithVariableIsCheap(I0, OI)) ||
          !all_of(Insts, CanReplaceOperand))
        // We can't create a PHI from this operand.
        return false;
      auto &Ops = PHIOperands[&I0->getOperandUse(OI)];
      for (auto *I : Insts)
        Ops.push_back(I->getOperand(OI));
    }
  }
  return true;
}

// Assuming canSinkInstructions(Blocks) has returned true, sink the last
// instruction of every block in Blocks to their common successor, commoning
// into one instruction.
static void sinkLastInstruction(ArrayRef<BasicBlock*> Blocks) {
  auto *BBEnd = Blocks[0]->getTerminator()->getSuccessor(0);

  // canSinkInstructions returning true guarantees that every block has at
  // least one non-terminator instruction.
  SmallVector<Instruction*,4> Insts;
  for (auto *BB : Blocks) {
    Instruction *I = BB->getTerminator();
    I = I->getPrevNode();
    Insts.push_back(I);
  }

  // We don't need to do any more checking here; canSinkInstructions should
  // have done it all for us.
  SmallVector<Value*, 4> NewOperands;
  Instruction *I0 = Insts.front();
  for (unsigned O = 0, E = I0->getNumOperands(); O != E; ++O) {
    // This check is different to that in canSinkInstructions. There, we
    // cared about the global view once simplifycfg (and instcombine) have
    // completed - it takes into account PHIs that become trivially
    // simplifiable.  However here we need a more local view; if an operand
    // differs we create a PHI and rely on instcombine to clean up the very
    // small mess we may make.
    bool NeedPHI = any_of(Insts, [&I0, O](const Instruction *I) {
      return I->getOperand(O) != I0->getOperand(O);
    });
    if (!NeedPHI) {
      NewOperands.push_back(I0->getOperand(O));
      continue;
    }

    // Create a new PHI in the successor block and populate it.
    auto *Op = I0->getOperand(O);
    assert(!Op->getType()->isTokenTy() && "Can't PHI tokens!");
    auto *PN =
        PHINode::Create(Op->getType(), Insts.size(), Op->getName() + ".sink");
    PN->insertBefore(BBEnd->begin());
    for (auto *I : Insts)
      PN->addIncoming(I->getOperand(O), I->getParent());
    NewOperands.push_back(PN);
  }

  // Arbitrarily use I0 as the new "common" instruction; remap its operands
  // and move it to the start of the successor block.
  for (unsigned O = 0, E = I0->getNumOperands(); O != E; ++O)
    I0->getOperandUse(O).set(NewOperands[O]);

  I0->moveBefore(*BBEnd, BBEnd->getFirstInsertionPt());

  // Update metadata and IR flags, and merge debug locations.
  for (auto *I : Insts)
    if (I != I0) {
      // The debug location for the "common" instruction is the merged locations
      // of all the commoned instructions.  We start with the original location
      // of the "common" instruction and iteratively merge each location in the
      // loop below.
      // This is an N-way merge, which will be inefficient if I0 is a CallInst.
      // However, as N-way merge for CallInst is rare, so we use simplified API
      // instead of using complex API for N-way merge.
      I0->applyMergedLocation(I0->getDebugLoc(), I->getDebugLoc());
      combineMetadataForCSE(I0, I, true);
      // We mark branch weights explicitly unknown for select instructions as we
      // might be sinking through control flow with conditions not independent
      // of the select condition, or pulling multiple conditions together
      // through a phi node.
      if (auto *SI = dyn_cast<SelectInst>(I0))
        setExplicitlyUnknownBranchWeightsIfProfiled(*SI, DEBUG_TYPE);
      I0->andIRFlags(I);
      if (auto *CB = dyn_cast<CallBase>(I0)) {
        bool Success = CB->tryIntersectAttributes(cast<CallBase>(I));
        assert(Success && "We should not be trying to sink callbases "
                          "with non-intersectable attributes");
        // For NDEBUG Compile.
        (void)Success;
      }
    }

  for (User *U : make_early_inc_range(I0->users())) {
    // canSinkLastInstruction checked that all instructions are only used by
    // phi nodes in a way that allows replacing the phi node with the common
    // instruction.
    auto *PN = cast<PHINode>(U);
    PN->replaceAllUsesWith(I0);
    PN->eraseFromParent();
  }

  // Finally nuke all instructions apart from the common instruction.
  for (auto *I : Insts) {
    if (I == I0)
      continue;
    // The remaining uses are debug users, replace those with the common inst.
    // In most (all?) cases this just introduces a use-before-def.
    assert(I->user_empty() && "Inst unexpectedly still has non-dbg users");
    I->replaceAllUsesWith(I0);
    I->eraseFromParent();
  }
}

/// Check whether BB's predecessors end with unconditional branches. If it is
/// true, sink any common code from the predecessors to BB.
static bool sinkCommonCodeFromPredecessors(BasicBlock *BB,
                                           DomTreeUpdater *DTU) {
  // We support two situations:
  //   (1) all incoming arcs are unconditional
  //   (2) there are non-unconditional incoming arcs
  //
  // (2) is very common in switch defaults and
  // else-if patterns;
  //
  //   if (a) f(1);
  //   else if (b) f(2);
  //
  // produces:
  //
  //       [if]
  //      /    \
  //    [f(1)] [if]
  //      |     | \
  //      |     |  |
  //      |  [f(2)]|
  //       \    | /
  //        [ end ]
  //
  // [end] has two unconditional predecessor arcs and one conditional. The
  // conditional refers to the implicit empty 'else' arc. This conditional
  // arc can also be caused by an empty default block in a switch.
  //
  // In this case, we attempt to sink code from all *unconditional* arcs.
  // If we can sink instructions from these arcs (determined during the scan
  // phase below) we insert a common successor for all unconditional arcs and
  // connect that to [end], to enable sinking:
  //
  //       [if]
  //      /    \
  //    [x(1)] [if]
  //      |     | \
  //      |     |  \
  //      |  [x(2)] |
  //       \   /    |
  //   [sink.split] |
  //         \     /
  //         [ end ]
  //
  SmallVector<BasicBlock*,4> UnconditionalPreds;
  bool HaveNonUnconditionalPredecessors = false;
  for (auto *PredBB : predecessors(BB)) {
    auto *PredBr = dyn_cast<UncondBrInst>(PredBB->getTerminator());
    if (PredBr)
      UnconditionalPreds.push_back(PredBB);
    else
      HaveNonUnconditionalPredecessors = true;
  }
  if (UnconditionalPreds.size() < 2)
    return false;

  // We take a two-step approach to tail sinking. First we scan from the end of
  // each block upwards in lockstep. If the n'th instruction from the end of each
  // block can be sunk, those instructions are added to ValuesToSink and we
  // carry on. If we can sink an instruction but need to PHI-merge some operands
  // (because they're not identical in each instruction) we add these to
  // PHIOperands.
  // We prepopulate PHIOperands with the phis that already exist in BB.
  DenseMap<const Use *, SmallVector<Value *, 4>> PHIOperands;
  for (PHINode &PN : BB->phis()) {
    SmallDenseMap<BasicBlock *, const Use *, 4> IncomingVals;
    for (const Use &U : PN.incoming_values())
      IncomingVals.insert({PN.getIncomingBlock(U), &U});
    auto &Ops = PHIOperands[IncomingVals[UnconditionalPreds[0]]];
    for (BasicBlock *Pred : UnconditionalPreds)
      Ops.push_back(*IncomingVals[Pred]);
  }

  int ScanIdx = 0;
  SmallPtrSet<Value*,4> InstructionsToSink;
  LockstepReverseIterator<true> LRI(UnconditionalPreds);
  while (LRI.isValid() &&
         canSinkInstructions(*LRI, PHIOperands)) {
    LLVM_DEBUG(dbgs() << "SINK: instruction can be sunk: " << *(*LRI)[0]
                      << "\n");
    InstructionsToSink.insert_range(*LRI);
    ++ScanIdx;
    --LRI;
  }

  // If no instructions can be sunk, early-return.
  if (ScanIdx == 0)
    return false;

  bool followedByDeoptOrUnreachable = IsBlockFollowedByDeoptOrUnreachable(BB);

  if (!followedByDeoptOrUnreachable) {
    // Check whether this is the pointer operand of a load/store.
    auto IsMemOperand = [](Use &U) {
      auto *I = cast<Instruction>(U.getUser());
      if (isa<LoadInst>(I))
        return U.getOperandNo() == LoadInst::getPointerOperandIndex();
      if (isa<StoreInst>(I))
        return U.getOperandNo() == StoreInst::getPointerOperandIndex();
      return false;
    };

    // Okay, we *could* sink last ScanIdx instructions. But how many can we
    // actually sink before encountering instruction that is unprofitable to
    // sink?
    auto ProfitableToSinkInstruction = [&](LockstepReverseIterator<true> &LRI) {
      unsigned NumPHIInsts = 0;
      for (Use &U : (*LRI)[0]->operands()) {
        auto It = PHIOperands.find(&U);
        if (It != PHIOperands.end() && !all_of(It->second, [&](Value *V) {
              return InstructionsToSink.contains(V);
            })) {
          ++NumPHIInsts;
          // Do not separate a load/store from the gep producing the address.
          // The gep can likely be folded into the load/store as an addressing
          // mode. Additionally, a load of a gep is easier to analyze than a
          // load of a phi.
          if (IsMemOperand(U) &&
              any_of(It->second, [](Value *V) { return isa<GEPOperator>(V); }))
            return false;
          // FIXME: this check is overly optimistic. We may end up not sinking
          // said instruction, due to the very same profitability check.
          // See @creating_too_many_phis in sink-common-code.ll.
        }
      }
      LLVM_DEBUG(dbgs() << "SINK: #phi insts: " << NumPHIInsts << "\n");
      return NumPHIInsts <= 1;
    };

    // We've determined that we are going to sink last ScanIdx instructions,
    // and recorded them in InstructionsToSink. Now, some instructions may be
    // unprofitable to sink. But that determination depends on the instructions
    // that we are going to sink.

    // First, forward scan: find the first instruction unprofitable to sink,
    // recording all the ones that are profitable to sink.
    // FIXME: would it be better, after we detect that not all are profitable.
    // to either record the profitable ones, or erase the unprofitable ones?
    // Maybe we need to choose (at runtime) the one that will touch least
    // instrs?
    LRI.reset();
    int Idx = 0;
    SmallPtrSet<Value *, 4> InstructionsProfitableToSink;
    while (Idx < ScanIdx) {
      if (!ProfitableToSinkInstruction(LRI)) {
        // Too many PHIs would be created.
        LLVM_DEBUG(
            dbgs() << "SINK: stopping here, too many PHIs would be created!\n");
        break;
      }
      InstructionsProfitableToSink.insert_range(*LRI);
      --LRI;
      ++Idx;
    }

    // If no instructions can be sunk, early-return.
    if (Idx == 0)
      return false;

    // Did we determine that (only) some instructions are unprofitable to sink?
    if (Idx < ScanIdx) {
      // Okay, some instructions are unprofitable.
      ScanIdx = Idx;
      InstructionsToSink = InstructionsProfitableToSink;

      // But, that may make other instructions unprofitable, too.
      // So, do a backward scan, do any earlier instructions become
      // unprofitable?
      assert(
          !ProfitableToSinkInstruction(LRI) &&
          "We already know that the last instruction is unprofitable to sink");
      ++LRI;
      --Idx;
      while (Idx >= 0) {
        // If we detect that an instruction becomes unprofitable to sink,
        // all earlier instructions won't be sunk either,
        // so preemptively keep InstructionsProfitableToSink in sync.
        // FIXME: is this the most performant approach?
        for (auto *I : *LRI)
          InstructionsProfitableToSink.erase(I);
        if (!ProfitableToSinkInstruction(LRI)) {
          // Everything starting with this instruction won't be sunk.
          ScanIdx = Idx;
          InstructionsToSink = InstructionsProfitableToSink;
        }
        ++LRI;
        --Idx;
      }
    }

    // If no instructions can be sunk, early-return.
    if (ScanIdx == 0)
      return false;
  }

  bool Changed = false;

  if (HaveNonUnconditionalPredecessors) {
    if (!followedByDeoptOrUnreachable) {
      // It is always legal to sink common instructions from unconditional
      // predecessors. However, if not all predecessors are unconditional,
      // this transformation might be pessimizing. So as a rule of thumb,
      // don't do it unless we'd sink at least one non-speculatable instruction.
      // See https://bugs.llvm.org/show_bug.cgi?id=30244
      LRI.reset();
      int Idx = 0;
      bool Profitable = false;
      while (Idx < ScanIdx) {
        if (!isSafeToSpeculativelyExecute((*LRI)[0])) {
          Profitable = true;
          break;
        }
        --LRI;
        ++Idx;
      }
      if (!Profitable)
        return false;
    }

    LLVM_DEBUG(dbgs() << "SINK: Splitting edge\n");
    // We have a conditional edge and we're going to sink some instructions.
    // Insert a new block postdominating all blocks we're going to sink from.
    if (!SplitBlockPredecessors(BB, UnconditionalPreds, ".sink.split", DTU))
      // Edges couldn't be split.
      return false;
    Changed = true;
  }

  // Now that we've analyzed all potential sinking candidates, perform the
  // actual sink. We iteratively sink the last non-terminator of the source
  // blocks into their common successor unless doing so would require too
  // many PHI instructions to be generated (currently only one PHI is allowed
  // per sunk instruction).
  //
  // We can use InstructionsToSink to discount values needing PHI-merging that will
  // actually be sunk in a later iteration. This allows us to be more
  // aggressive in what we sink. This does allow a false positive where we
  // sink presuming a later value will also be sunk, but stop half way through
  // and never actually sink it which means we produce more PHIs than intended.
  // This is unlikely in practice though.
  int SinkIdx = 0;
  for (; SinkIdx != ScanIdx; ++SinkIdx) {
    LLVM_DEBUG(dbgs() << "SINK: Sink: "
                      << *UnconditionalPreds[0]->getTerminator()->getPrevNode()
                      << "\n");

    // Because we've sunk every instruction in turn, the current instruction to
    // sink is always at index 0.
    LRI.reset();

    sinkLastInstruction(UnconditionalPreds);
    NumSinkCommonInstrs++;
    Changed = true;
  }
  if (SinkIdx != 0)
    ++NumSinkCommonCode;
  return Changed;
}

namespace {

struct CompatibleSets {
  using SetTy = SmallVector<InvokeInst *, 2>;

  SmallVector<SetTy, 1> Sets;

  static bool shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes);

  SetTy &getCompatibleSet(InvokeInst *II);

  void insert(InvokeInst *II);
};

CompatibleSets::SetTy &CompatibleSets::getCompatibleSet(InvokeInst *II) {
  // Perform a linear scan over all the existing sets, see if the new `invoke`
  // is compatible with any particular set. Since we know that all the `invokes`
  // within a set are compatible, only check the first `invoke` in each set.
  // WARNING: at worst, this has quadratic complexity.
  for (CompatibleSets::SetTy &Set : Sets) {
    if (CompatibleSets::shouldBelongToSameSet({Set.front(), II}))
      return Set;
  }

  // Otherwise, we either had no sets yet, or this invoke forms a new set.
  return Sets.emplace_back();
}

void CompatibleSets::insert(InvokeInst *II) {
  getCompatibleSet(II).emplace_back(II);
}

bool CompatibleSets::shouldBelongToSameSet(ArrayRef<InvokeInst *> Invokes) {
  assert(Invokes.size() == 2 && "Always called with exactly two candidates.");

  // Can we theoretically merge these `invoke`s?
  auto IsIllegalToMerge = [](InvokeInst *II) {
    return II->cannotMerge() || II->isInlineAsm();
  };
  if (any_of(Invokes, IsIllegalToMerge))
    return false;

  // Either both `invoke`s must be   direct,
  // or     both `invoke`s must be indirect.
  auto IsIndirectCall = [](InvokeInst *II) { return II->isIndirectCall(); };
  bool HaveIndirectCalls = any_of(Invokes, IsIndirectCall);
  bool AllCallsAreIndirect = all_of(Invokes, IsIndirectCall);
  if (HaveIndirectCalls) {
    if (!AllCallsAreIndirect)
      return false;
  } else {
    // All callees must be identical.
    Value *Callee = nullptr;
    for (InvokeInst *II : Invokes) {
      Value *CurrCallee = II->getCalledOperand();
      assert(CurrCallee && "There is always a called operand.");
      if (!Callee)
        Callee = CurrCallee;
      else if (Callee != CurrCallee)
        return false;
    }
  }

  // Either both `invoke`s must not have a normal destination,
  // or     both `invoke`s must     have a normal destination,
  auto HasNormalDest = [](InvokeInst *II) {
    return !isa<UnreachableInst>(II->getNormalDest()->getFirstNonPHIIt());
  };
  if (any_of(Invokes, HasNormalDest)) {
    // Do not merge `invoke` that does not have a normal destination with one
    // that does have a normal destination, even though doing so would be legal.
    if (!all_of(Invokes, HasNormalDest))
      return false;

    // All normal destinations must be identical.
    BasicBlock *NormalBB = nullptr;
    for (InvokeInst *II : Invokes) {
      BasicBlock *CurrNormalBB = II->getNormalDest();
      assert(CurrNormalBB && "There is always a 'continue to' basic block.");
      if (!NormalBB)
        NormalBB = CurrNormalBB;
      else if (NormalBB != CurrNormalBB)
        return false;
    }

    // In the normal destination, the incoming values for these two `invoke`s
    // must be compatible.
    SmallPtrSet<Value *, 16> EquivalenceSet(llvm::from_range, Invokes);
    if (!incomingValuesAreCompatible(
            NormalBB, {Invokes[0]->getParent(), Invokes[1]->getParent()},
            &EquivalenceSet))
      return false;
  }

#ifndef NDEBUG
  // All unwind destinations must be identical.
  // We know that because we have started from said unwind destination.
  BasicBlock *UnwindBB = nullptr;
  for (InvokeInst *II : Invokes) {
    BasicBlock *CurrUnwindBB = II->getUnwindDest();
    assert(CurrUnwindBB && "There is always an 'unwind to' basic block.");
    if (!UnwindBB)
      UnwindBB = CurrUnwindBB;
    else
      assert(UnwindBB == CurrUnwindBB && "Unexpected unwind destination.");
  }
#endif

  // In the unwind destination, the incoming values for these two `invoke`s
  // must be compatible.
  if (!incomingValuesAreCompatible(
          Invokes.front()->getUnwindDest(),
          {Invokes[0]->getParent(), Invokes[1]->getParent()}))
    return false;

  // Ignoring arguments, these `invoke`s must be identical,
  // including operand bundles.
  const InvokeInst *II0 = Invokes.front();
  for (auto *II : Invokes.drop_front())
    if (!II->isSameOperationAs(II0, Instruction::CompareUsingIntersectedAttrs))
      return false;

  // Can we theoretically form the data operands for the merged `invoke`?
  auto IsIllegalToMergeArguments = [](auto Ops) {
    Use &U0 = std::get<0>(Ops);
    Use &U1 = std::get<1>(Ops);
    if (U0 == U1)
      return false;
    return !canReplaceOperandWithVariable(cast<Instruction>(U0.getUser()),
                                          U0.getOperandNo());
  };
  assert(Invokes.size() == 2 && "Always called with exactly two candidates.");
  if (any_of(zip(Invokes[0]->data_ops(), Invokes[1]->data_ops()),
             IsIllegalToMergeArguments))
    return false;

  return true;
}

} // namespace

// Merge all invokes in the provided set, all of which are compatible
// as per the `CompatibleSets::shouldBelongToSameSet()`.
static void mergeCompatibleInvokesImpl(ArrayRef<InvokeInst *> Invokes,
                                       DomTreeUpdater *DTU) {
  assert(Invokes.size() >= 2 && "Must have at least two invokes to merge.");

  SmallVector<DominatorTree::UpdateType, 8> Updates;
  if (DTU)
    Updates.reserve(2 + 3 * Invokes.size());

  bool HasNormalDest =
      !isa<UnreachableInst>(Invokes[0]->getNormalDest()->getFirstNonPHIIt());

  // Clone one of the invokes into a new basic block.
  // Since they are all compatible, it doesn't matter which invoke is cloned.
  InvokeInst *MergedInvoke = [&Invokes, HasNormalDest]() {
    InvokeInst *II0 = Invokes.front();
    BasicBlock *II0BB = II0->getParent();
    BasicBlock *InsertBeforeBlock =
        II0->getParent()->getIterator()->getNextNode();
    Function *Func = II0BB->getParent();
    LLVMContext &Ctx = II0->getContext();

    BasicBlock *MergedInvokeBB = BasicBlock::Create(
        Ctx, II0BB->getName() + ".invoke", Func, InsertBeforeBlock);

    auto *MergedInvoke = cast<InvokeInst>(II0->clone());
    // NOTE: all invokes have the same attributes, so no handling needed.
    MergedInvoke->insertInto(MergedInvokeBB, MergedInvokeBB->end());

    if (!HasNormalDest) {
      // This set does not have a normal destination,
      // so just form a new block with unreachable terminator.
      BasicBlock *MergedNormalDest = BasicBlock::Create(
          Ctx, II0BB->getName() + ".cont", Func, InsertBeforeBlock);
      auto *UI = new UnreachableInst(Ctx, MergedNormalDest);
      UI->setDebugLoc(DebugLoc::getTemporary());
      MergedInvoke->setNormalDest(MergedNormalDest);
    }

    // The unwind destination, however, remainds identical for all invokes here.

    return MergedInvoke;
  }();

  if (DTU) {
    // Predecessor blocks that contained these invokes will now branch to
    // the new block that contains the merged invoke, ...
    for (InvokeInst *II : Invokes)
      Updates.push_back(
          {DominatorTree::Insert, II->getParent(), MergedInvoke->getParent()});

    // ... which has the new `unreachable` block as normal destination,
    // or unwinds to the (same for all `invoke`s in this set) `landingpad`,
    for (BasicBlock *SuccBBOfMergedInvoke : successors(MergedInvoke))
      Updates.push_back({DominatorTree::Insert, MergedInvoke->getParent(),
                         SuccBBOfMergedInvoke});

    // Since predecessor blocks now unconditionally branch to a new block,
    // they no longer branch to their original successors.
    for (InvokeInst *II : Invokes)
      for (BasicBlock *SuccOfPredBB : successors(II->getParent()))
        Updates.push_back(
            {DominatorTree::Delete, II->getParent(), SuccOfPredBB});
  }

  bool IsIndirectCall = Invokes[0]->isIndirectCall();

  // Form the merged operands for the merged invoke.
  for (Use &U : MergedInvoke->operands()) {
    // Only PHI together the indirect callees and data operands.
    if (MergedInvoke->isCallee(&U)) {
      if (!IsIndirectCall)
        continue;
    } else if (!MergedInvoke->isDataOperand(&U))
      continue;

    // Don't create trivial PHI's with all-identical incoming values.
    bool NeedPHI = any_of(Invokes, [&U](InvokeInst *II) {
      return II->getOperand(U.getOperandNo()) != U.get();
    });
    if (!NeedPHI)
      continue;

    // Form a PHI out of all the data ops under this index.
    PHINode *PN = PHINode::Create(
        U->getType(), /*NumReservedValues=*/Invokes.size(), "", MergedInvoke->getIterator());
    for (InvokeInst *II : Invokes)
      PN->addIncoming(II->getOperand(U.getOperandNo()), II->getParent());

    U.set(PN);
  }

  // We've ensured that each PHI node has compatible (identical) incoming values
  // when coming from each of the `invoke`s in the current merge set,
  // so update the PHI nodes accordingly.
  for (BasicBlock *Succ : successors(MergedInvoke))
    addPredecessorToBlock(Succ, /*NewPred=*/MergedInvoke->getParent(),
                          /*ExistPred=*/Invokes.front()->getParent());

  // And finally, replace the original `invoke`s with an unconditional branch
  // to the block with the merged `invoke`. Also, give that merged `invoke`
  // the merged debugloc of all the original `invoke`s.
  DILocation *MergedDebugLoc = nullptr;
  for (InvokeInst *II : Invokes) {
    // Compute the debug location common to all the original `invoke`s.
    if (!MergedDebugLoc)
      MergedDebugLoc = II->getDebugLoc();
    else
      MergedDebugLoc =
          DebugLoc::getMergedLocation(MergedDebugLoc, II->getDebugLoc());

    // And replace the old `invoke` with an unconditionally branch
    // to the block with the merged `invoke`.
    for (BasicBlock *OrigSuccBB : successors(II->getParent()))
      OrigSuccBB->removePredecessor(II->getParent());
    auto *BI = UncondBrInst::Create(MergedInvoke->getParent(), II->getParent());
    // The unconditional branch is part of the replacement for the original
    // invoke, so should use its DebugLoc.
    BI->setDebugLoc(II->getDebugLoc());
    bool Success = MergedInvoke->tryIntersectAttributes(II);
    assert(Success && "Merged invokes with incompatible attributes");
    // For NDEBUG Compile
    (void)Success;
    II->replaceAllUsesWith(MergedInvoke);
    II->eraseFromParent();
    ++NumInvokesMerged;
  }
  MergedInvoke->setDebugLoc(MergedDebugLoc);
  ++NumInvokeSetsFormed;

  if (DTU)
    DTU->applyUpdates(Updates);
}

/// If this block is a `landingpad` exception handling block, categorize all
/// the predecessor `invoke`s into sets, with all `invoke`s in each set
/// being "mergeable" together, and then merge invokes in each set together.
///
/// This is a weird mix of hoisting and sinking. Visually, it goes from:
///          [...]        [...]
///            |            |
///        [invoke0]    [invoke1]
///           / \          / \
///     [cont0] [landingpad] [cont1]
/// to:
///      [...] [...]
///          \ /
///       [invoke]
///          / \
///     [cont] [landingpad]
///
/// But of course we can only do that if the invokes share the `landingpad`,
/// edges invoke0->cont0 and invoke1->cont1 are "compatible",
/// and the invoked functions are "compatible".
static bool mergeCompatibleInvokes(BasicBlock *BB, DomTreeUpdater *DTU) {
  if (!EnableMergeCompatibleInvokes)
    return false;

  bool Changed = false;

  // FIXME: generalize to all exception handling blocks?
  if (!BB->isLandingPad())
    return Changed;

  CompatibleSets Grouper;

  // Record all the predecessors of this `landingpad`. As per verifier,
  // the only allowed predecessor is the unwind edge of an `invoke`.
  // We want to group "compatible" `invokes` into the same set to be merged.
  for (BasicBlock *PredBB : predecessors(BB))
    Grouper.insert(cast<InvokeInst>(PredBB->getTerminator()));

  // And now, merge `invoke`s that were grouped togeter.
  for (ArrayRef<InvokeInst *> Invokes : Grouper.Sets) {
    if (Invokes.size() < 2)
      continue;
    Changed = true;
    mergeCompatibleInvokesImpl(Invokes, DTU);
  }

  return Changed;
}

namespace {
/// Track ephemeral values, which should be ignored for cost-modelling
/// purposes. Requires walking instructions in reverse order.
class EphemeralValueTracker {
  SmallPtrSet<const Instruction *, 32> EphValues;

  bool isEphemeral(const Instruction *I) {
    if (isa<AssumeInst>(I))
      return true;
    return !I->mayHaveSideEffects() && !I->isTerminator() &&
           all_of(I->users(), [&](const User *U) {
             return EphValues.count(cast<Instruction>(U));
           });
  }

public:
  bool track(const Instruction *I) {
    if (isEphemeral(I)) {
      EphValues.insert(I);
      return true;
    }
    return false;
  }

  bool contains(const Instruction *I) const { return EphValues.contains(I); }
};
} // namespace

/// Determine if we can hoist sink a sole store instruction out of a
/// conditional block.
///
/// We are looking for code like the following:
///   BrBB:
///     store i32 %add, i32* %arrayidx2
///     ... // No other stores or function calls (we could be calling a memory
///     ... // function).
///     %cmp = icmp ult %x, %y
///     br i1 %cmp, label %EndBB, label %ThenBB
///   ThenBB:
///     store i32 %add5, i32* %arrayidx2
///     br label EndBB
///   EndBB:
///     ...
///   We are going to transform this into:
///   BrBB:
///     store i32 %add, i32* %arrayidx2
///     ... //
///     %cmp = icmp ult %x, %y
///     %add.add5 = select i1 %cmp, i32 %add, %add5
///     store i32 %add.add5, i32* %arrayidx2
///     ...
///
/// \return The value from the previous access if the store can be hoisted into
///         the predecessor block. PreviousAccess is set to that access. Return
///         null otherwise.
static Value *isSafeToSpeculateStore(Instruction *I, BasicBlock *BrBB,
                                     BasicBlock *StoreBB, BasicBlock *EndBB,
                                     Instruction *&PreviousAccess) {
  StoreInst *StoreToHoist = dyn_cast<StoreInst>(I);
  if (!StoreToHoist)
    return nullptr;

  // Volatile or atomic.
  if (!StoreToHoist->isSimple())
    return nullptr;

  Value *StorePtr = StoreToHoist->getPointerOperand();
  Type *StoreTy = StoreToHoist->getValueOperand()->getType();

  // Look for a store to the same pointer in BrBB.
  unsigned MaxNumInstToLookAt = 9;
  // Skip pseudo probe intrinsic calls which are not really killing any memory
  // accesses.
  for (Instruction &CurI : reverse(*BrBB)) {
    if (!MaxNumInstToLookAt)
      break;
    --MaxNumInstToLookAt;

    if (isa<PseudoProbeInst>(CurI))
      continue;

    // Could be calling an instruction that affects memory like free().
    if (CurI.mayWriteToMemory() && !isa<StoreInst>(CurI))
      return nullptr;

    if (auto *SI = dyn_cast<StoreInst>(&CurI)) {
      // Found the previous store to same location and type. Make sure it is
      // simple, to avoid introducing a spurious non-atomic write after an
      // atomic write.
      if (SI->getPointerOperand() == StorePtr &&
          SI->getValueOperand()->getType() == StoreTy && SI->isSimple() &&
          SI->getAlign() >= StoreToHoist->getAlign()) {
        // Found the previous store, return its value operand.
        PreviousAccess = SI;
        return SI->getValueOperand();
      }
      return nullptr; // Unknown store.
    }

    if (auto *LI = dyn_cast<LoadInst>(&CurI)) {
      if (LI->getPointerOperand() == StorePtr && LI->getType() == StoreTy &&
          LI->isSimple() && LI->getAlign() >= StoreToHoist->getAlign()) {
        Value *Obj = getUnderlyingObject(StorePtr);
        bool ExplicitlyDereferenceableOnly;
        // The dereferenceability query here is only required to satisfy the
        // writable contract, actual dereferenceability is proven by the
        // presence of an access. As such, we can ignore frees.
        if (isWritableObject(Obj, ExplicitlyDereferenceableOnly) &&
            capturesNothing(
                PointerMayBeCaptured(Obj, CaptureComponents::Provenance)
                    .WithoutRet) &&
            (!ExplicitlyDereferenceableOnly ||
             isDereferenceablePointer(StorePtr, StoreTy, LI->getDataLayout(),
                                      /*IgnoreFree=*/true))) {
          // Found a previous load, return it.
          PreviousAccess = LI;
          return LI;
        }
      }
      // The load didn't work out, but we may still find a store.
    }
  }

  return nullptr;
}

/// Estimate the cost of the insertion(s) and check that the PHI nodes can be
/// converted to selects.
static bool validateAndCostRequiredSelects(BasicBlock *BB, BasicBlock *ThenBB,
                                           BasicBlock *EndBB,
                                           unsigned &SpeculatedInstructions,
                                           InstructionCost &Cost,
                                           const TargetTransformInfo &TTI) {
  TargetTransformInfo::TargetCostKind CostKind =
    BB->getParent()->hasMinSize()
    ? TargetTransformInfo::TCK_CodeSize
    : TargetTransformInfo::TCK_SizeAndLatency;

  bool HaveRewritablePHIs = false;
  for (PHINode &PN : EndBB->phis()) {
    Value *OrigV = PN.getIncomingValueForBlock(BB);
    Value *ThenV = PN.getIncomingValueForBlock(ThenBB);

    // FIXME: Try to remove some of the duplication with
    // hoistCommonCodeFromSuccessors. Skip PHIs which are trivial.
    if (ThenV == OrigV)
      continue;

    Cost += TTI.getCmpSelInstrCost(Instruction::Select, PN.getType(),
                                   Type::getInt1Ty(PN.getContext()),
                                   CmpInst::BAD_ICMP_PREDICATE, CostKind);

    // Don't convert to selects if we could remove undefined behavior instead.
    if (passingValueIsAlwaysUndefined(OrigV, &PN) ||
        passingValueIsAlwaysUndefined(ThenV, &PN))
      return false;

    HaveRewritablePHIs = true;
    ConstantExpr *OrigCE = dyn_cast<ConstantExpr>(OrigV);
    ConstantExpr *ThenCE = dyn_cast<ConstantExpr>(ThenV);
    if (!OrigCE && !ThenCE)
      continue; // Known cheap (FIXME: Maybe not true for aggregates).

    InstructionCost OrigCost = OrigCE ? computeSpeculationCost(OrigCE, TTI) : 0;
    InstructionCost ThenCost = ThenCE ? computeSpeculationCost(ThenCE, TTI) : 0;
    InstructionCost MaxCost =
        2 * PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic;
    if (OrigCost + ThenCost > MaxCost)
      return false;

    // Account for the cost of an unfolded ConstantExpr which could end up
    // getting expanded into Instructions.
    // FIXME: This doesn't account for how many operations are combined in the
    // constant expression.
    ++SpeculatedInstructions;
    if (SpeculatedInstructions > 1)
      return false;
  }

  return HaveRewritablePHIs;
}

static bool isProfitableToSpeculate(const CondBrInst *BI,
                                    std::optional<bool> Invert,
                                    const TargetTransformInfo &TTI) {
  // If the branch is non-unpredictable, and is predicted to *not* branch to
  // the `then` block, then avoid speculating it.
  if (BI->getMetadata(LLVMContext::MD_unpredictable))
    return true;

  uint64_t TWeight, FWeight;
  if (!extractBranchWeights(*BI, TWeight, FWeight) || (TWeight + FWeight) == 0)
    return true;

  if (!Invert.has_value())
    return false;

  uint64_t EndWeight = *Invert ? TWeight : FWeight;
  BranchProbability BIEndProb =
      BranchProbability::getBranchProbability(EndWeight, TWeight + FWeight);
  BranchProbability Likely = TTI.getPredictableBranchThreshold();
  return BIEndProb < Likely;
}

/// Speculate a conditional basic block flattening the CFG.
///
/// Note that this is a very risky transform currently. Speculating
/// instructions like this is most often not desirable. Instead, there is an MI
/// pass which can do it with full awareness of the resource constraints.
/// However, some cases are "obvious" and we should do directly. An example of
/// this is speculating a single, reasonably cheap instruction.
///
/// There is only one distinct advantage to flattening the CFG at the IR level:
/// it makes very common but simplistic optimizations such as are common in
/// instcombine and the DAG combiner more powerful by removing CFG edges and
/// modeling their effects with easier to reason about SSA value graphs.
///
///
/// An illustration of this transform is turning this IR:
/// \code
///   BB:
///     %cmp = icmp ult %x, %y
///     br i1 %cmp, label %EndBB, label %ThenBB
///   ThenBB:
///     %sub = sub %x, %y
///     br label BB2
///   EndBB:
///     %phi = phi [ %sub, %ThenBB ], [ 0, %BB ]
///     ...
/// \endcode
///
/// Into this IR:
/// \code
///   BB:
///     %cmp = icmp ult %x, %y
///     %sub = sub %x, %y
///     %cond = select i1 %cmp, 0, %sub
///     ...
/// \endcode
///
/// \returns true if the conditional block is removed.
bool SimplifyCFGOpt::speculativelyExecuteBB(CondBrInst *BI,
                                            BasicBlock *ThenBB) {
  if (!Options.SpeculateBlocks)
    return false;

  BasicBlock *BB = BI->getParent();
  BasicBlock *EndBB = ThenBB->getTerminator()->getSuccessor(0);
  InstructionCost Budget =
      PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic;

  // If ThenBB is actually on the false edge of the conditional branch, remember
  // to swap the select operands later.
  bool Invert = false;
  if (ThenBB != BI->getSuccessor(0)) {
    assert(ThenBB == BI->getSuccessor(1) && "No edge from 'if' block?");
    Invert = true;
  }
  assert(EndBB == BI->getSuccessor(!Invert) && "No edge from to end block");

  if (!isProfitableToSpeculate(BI, Invert, TTI))
    return false;

  // Keep a count of how many times instructions are used within ThenBB when
  // they are candidates for sinking into ThenBB. Specifically:
  // - They are defined in BB, and
  // - They have no side effects, and
  // - All of their uses are in ThenBB.
  SmallDenseMap<Instruction *, unsigned, 4> SinkCandidateUseCounts;

  SmallVector<Instruction *, 4> SpeculatedPseudoProbes;

  unsigned SpeculatedInstructions = 0;
  bool HoistLoadsStores = Options.HoistLoadsStoresWithCondFaulting;
  SmallVector<Instruction *, 2> SpeculatedConditionalLoadsStores;
  Value *SpeculatedStoreValue = nullptr;
  StoreInst *SpeculatedStore = nullptr;
  Instruction *PreviousStoreAccess = nullptr;
  EphemeralValueTracker EphTracker;
  for (Instruction &I : reverse(drop_end(*ThenBB))) {
    // Skip pseudo probes. The consequence is we lose track of the branch
    // probability for ThenBB, which is fine since the optimization here takes
    // place regardless of the branch probability.
    if (isa<PseudoProbeInst>(I)) {
      // The probe should be deleted so that it will not be over-counted when
      // the samples collected on the non-conditional path are counted towards
      // the conditional path. We leave it for the counts inference algorithm to
      // figure out a proper count for an unknown probe.
      SpeculatedPseudoProbes.push_back(&I);
      continue;
    }

    // Ignore ephemeral values, they will be dropped by the transform.
    if (EphTracker.track(&I))
      continue;

    // Only speculatively execute a single instruction (not counting the
    // terminator) for now.
    bool IsSafeCheapLoadStore = HoistLoadsStores &&
                                isSafeCheapLoadStore(&I, TTI) &&
                                SpeculatedConditionalLoadsStores.size() <
                                    HoistLoadsStoresWithCondFaultingThreshold;
    // Not count load/store into cost if target supports conditional faulting
    // b/c it's cheap to speculate it.
    if (IsSafeCheapLoadStore)
      SpeculatedConditionalLoadsStores.push_back(&I);
    else
      ++SpeculatedInstructions;

    if (SpeculatedInstructions > 1)
      return false;

    // Don't hoist the instruction if it's unsafe or expensive.
    if (!IsSafeCheapLoadStore &&
        !isSafeToSpeculativelyExecute(&I, BI, Options.AC) &&
        !(HoistCondStores && !SpeculatedStoreValue &&
          (SpeculatedStoreValue = isSafeToSpeculateStore(&I, BB, ThenBB, EndBB,
                                                         PreviousStoreAccess))))
      return false;
    if (!IsSafeCheapLoadStore && !SpeculatedStoreValue &&
        computeSpeculationCost(&I, TTI) >
            PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic)
      return false;

    // Store the store speculation candidate.
    if (!SpeculatedStore && SpeculatedStoreValue)
      SpeculatedStore = cast<StoreInst>(&I);

    // Do not hoist the instruction if any of its operands are defined but not
    // used in BB. The transformation will prevent the operand from
    // being sunk into the use block.
    for (Use &Op : I.operands()) {
      Instruction *OpI = dyn_cast<Instruction>(Op);
      if (!OpI || OpI->getParent() != BB || OpI->mayHaveSideEffects())
        continue; // Not a candidate for sinking.

      ++SinkCandidateUseCounts[OpI];
    }
  }

  // Consider any sink candidates which are only used in ThenBB as costs for
  // speculation. Note, while we iterate over a DenseMap here, we are summing
  // and so iteration order isn't significant.
  for (const auto &[Inst, Count] : SinkCandidateUseCounts)
    if (Inst->hasNUses(Count)) {
      ++SpeculatedInstructions;
      if (SpeculatedInstructions > 1)
        return false;
    }

  // Check that we can insert the selects and that it's not too expensive to do
  // so.
  bool Convert =
      SpeculatedStore != nullptr || !SpeculatedConditionalLoadsStores.empty();
  InstructionCost Cost = 0;
  Convert |= validateAndCostRequiredSelects(BB, ThenBB, EndBB,
                                            SpeculatedInstructions, Cost, TTI);
  if (!Convert || Cost > Budget)
    return false;

  // If we get here, we can hoist the instruction and if-convert.
  LLVM_DEBUG(dbgs() << "SPECULATIVELY EXECUTING BB" << *ThenBB << "\n";);

  Instruction *Sel = nullptr;
  Value *BrCond = BI->getCondition();
  // Insert a select of the value of the speculated store.
  if (SpeculatedStoreValue) {
    IRBuilder<NoFolder> Builder(BI);
    Value *OrigV = SpeculatedStore->getValueOperand();
    Value *TrueV = SpeculatedStore->getValueOperand();
    Value *FalseV = SpeculatedStoreValue;
    if (Invert)
      std::swap(TrueV, FalseV);
    Value *S = Builder.CreateSelect(
        BrCond, TrueV, FalseV, "spec.store.select", BI);
    Sel = cast<Instruction>(S);
    SpeculatedStore->setOperand(0, S);
    SpeculatedStore->applyMergedLocation(BI->getDebugLoc(),
                                         SpeculatedStore->getDebugLoc());
    // The value stored is still conditional, but the store itself is now
    // unconditionally executed, so we must be sure that any linked dbg.assign
    // intrinsics are tracking the new stored value (the result of the
    // select). If we don't, and the store were to be removed by another pass
    // (e.g. DSE), then we'd eventually end up emitting a location describing
    // the conditional value, unconditionally.
    //
    // === Before this transformation ===
    // pred:
    //   store %one, %x.dest, !DIAssignID !1
    //   dbg.assign %one, "x", ..., !1, ...
    //   br %cond if.then
    //
    // if.then:
    //   store %two, %x.dest, !DIAssignID !2
    //   dbg.assign %two, "x", ..., !2, ...
    //
    // === After this transformation ===
    // pred:
    //   store %one, %x.dest, !DIAssignID !1
    //   dbg.assign %one, "x", ..., !1
    ///  ...
    //   %merge = select %cond, %two, %one
    //   store %merge, %x.dest, !DIAssignID !2
    //   dbg.assign %merge, "x", ..., !2
    for (DbgVariableRecord *DbgAssign :
         at::getDVRAssignmentMarkers(SpeculatedStore))
      if (llvm::is_contained(DbgAssign->location_ops(), OrigV))
        DbgAssign->replaceVariableLocationOp(OrigV, S);
  }

  // Metadata can be dependent on the condition we are hoisting above.
  // Strip all UB-implying metadata on the instruction. Drop the debug loc
  // to avoid making it appear as if the condition is a constant, which would
  // be misleading while debugging.
  // Similarly strip attributes that maybe dependent on condition we are
  // hoisting above.
  for (auto &I : make_early_inc_range(*ThenBB)) {
    if (!SpeculatedStoreValue || &I != SpeculatedStore) {
      I.dropLocation();
      I.dropUBImplyingAttrsAndMetadata();
    } else {
      assert(PreviousStoreAccess && "Missing previous store access");
      AAMDNodes MergedAA = SpeculatedStore->getAAMetadata().merge(
          PreviousStoreAccess->getAAMetadata());
      I.dropUBImplyingAttrsAndMetadata();
      I.setAAMetadata(MergedAA);
    }

    // Drop ephemeral values.
    if (EphTracker.contains(&I)) {
      I.replaceAllUsesWith(PoisonValue::get(I.getType()));
      I.eraseFromParent();
    }
  }

  // Hoist the instructions.
  // Drop DbgVariableRecords attached to these instructions.
  for (auto &It : *ThenBB)
    for (DbgRecord &DR : make_early_inc_range(It.getDbgRecordRange()))
      // Drop all records except assign-kind DbgVariableRecords (dbg.assign
      // equivalent).
      if (DbgVariableRecord *DVR = dyn_cast<DbgVariableRecord>(&DR);
          !DVR || !DVR->isDbgAssign())
        It.dropOneDbgRecord(&DR);
  BB->splice(BI->getIterator(), ThenBB, ThenBB->begin(),
             std::prev(ThenBB->end()));

  if (!SpeculatedConditionalLoadsStores.empty())
    hoistConditionalLoadsStores(BI, SpeculatedConditionalLoadsStores, Invert,
                                Sel);

  // Insert selects and rewrite the PHI operands.
  IRBuilder<NoFolder> Builder(BI);
  for (PHINode &PN : EndBB->phis()) {
    unsigned OrigI = PN.getBasicBlockIndex(BB);
    unsigned ThenI = PN.getBasicBlockIndex(ThenBB);
    Value *OrigV = PN.getIncomingValue(OrigI);
    Value *ThenV = PN.getIncomingValue(ThenI);

    // Skip PHIs which are trivial.
    if (OrigV == ThenV)
      continue;

    // Create a select whose true value is the speculatively executed value and
    // false value is the pre-existing value. Swap them if the branch
    // destinations were inverted.
    Value *TrueV = ThenV, *FalseV = OrigV;
    if (Invert)
      std::swap(TrueV, FalseV);
    // Propagate fast-math flags from the phi node to the replacement select.
    Value *V = Builder.CreateSelectFMF(
        BrCond, TrueV, FalseV, PN.getFastMathFlagsOrNone(), "spec.select", BI);
    PN.setIncomingValue(OrigI, V);
    PN.setIncomingValue(ThenI, V);
  }

  // Remove speculated pseudo probes.
  for (Instruction *I : SpeculatedPseudoProbes)
    I->eraseFromParent();

  ++NumSpeculations;
  return true;
}

using BlocksSet = SmallPtrSet<BasicBlock *, 8>;

// Return false if number of blocks searched is too much.
static bool findReaching(BasicBlock *BB, BasicBlock *DefBB,
                         BlocksSet &ReachesNonLocalUses) {
  if (BB == DefBB)
    return true;
  if (!ReachesNonLocalUses.insert(BB).second)
    return true;

  if (ReachesNonLocalUses.size() > MaxJumpThreadingLiveBlocks)
    return false;
  for (BasicBlock *Pred : predecessors(BB))
    if (!findReaching(Pred, DefBB, ReachesNonLocalUses))
      return false;
  return true;
}

/// Return true if we can thread a branch across this block.
static bool blockIsSimpleEnoughToThreadThrough(BasicBlock *BB,
                                               BlocksSet &NonLocalUseBlocks) {
  int Size = 0;
  EphemeralValueTracker EphTracker;

  // Walk the loop in reverse so that we can identify ephemeral values properly
  // (values only feeding assumes).
  for (Instruction &I : reverse(*BB)) {
    // Can't fold blocks that contain noduplicate or convergent calls.
    if (CallInst *CI = dyn_cast<CallInst>(&I))
      if (CI->cannotDuplicate() || CI->isConvergent())
        return false;

    // Ignore ephemeral values which are deleted during codegen.
    // We will delete Phis while threading, so Phis should not be accounted in
    // block's size.
    if (!EphTracker.track(&I) && !isa<PHINode>(I)) {
      if (Size++ > MaxSmallBlockSize)
        return false; // Don't clone large BB's.
    }

    // Record blocks with non-local uses of values defined in the current basic
    // block.
    for (User *U : I.users()) {
      Instruction *UI = cast<Instruction>(U);
      BasicBlock *UsedInBB = UI->getParent();
      if (UsedInBB == BB) {
        if (isa<PHINode>(UI))
          return false;
      } else
        NonLocalUseBlocks.insert(UsedInBB);
    }

    // Looks ok, continue checking.
  }

  return true;
}

static ConstantInt *getKnownValueOnEdge(Value *V, BasicBlock *From,
                                        BasicBlock *To) {
  // Don't look past the block defining the value, we might get the value from
  // a previous loop iteration.
  auto *I = dyn_cast<Instruction>(V);
  if (I && I->getParent() == To)
    return nullptr;

  // We know the value if the From block branches on it.
  auto *BI = dyn_cast<CondBrInst>(From->getTerminator());
  if (BI && BI->getCondition() == V &&
      BI->getSuccessor(0) != BI->getSuccessor(1))
    return BI->getSuccessor(0) == To ? ConstantInt::getTrue(BI->getContext())
                                     : ConstantInt::getFalse(BI->getContext());

  return nullptr;
}

static bool isUncontrolledConvergentCall(CallBase *CB) {
  return CB->isConvergent() && !isa<ConvergenceControlInst>(CB) &&
         !CB->getConvergenceControlToken();
}

static bool reachesUncontrolledConvergentCallBeforeBlock(BasicBlock *From,
                                                         BasicBlock *StopBB) {
  static constexpr unsigned MaxInstructionsToScan = 512;

  // Walk predecessors of StopBB to find blocks that can reach it. Only
  // convergent calls on a cycle with StopBB matter - a convergent call on a
  // path to function exit cannot have its dynamic instance changed by
  // threading.
  SmallPtrSet<BasicBlock *, 8> CanReachStop;
  SmallPtrSet<BasicBlock *, 8> BlocksWithUncontrolledConvergentCalls;
  SmallVector<BasicBlock *, 8> Worklist;
  for (BasicBlock *Pred : predecessors(StopBB))
    Worklist.push_back(Pred);

  // Cache blocks with relevant calls while building CanReachStop. This keeps
  // the instruction scan bounded without a separate block limit.
  unsigned NumScannedInstructions = 0;
  while (!Worklist.empty()) {
    BasicBlock *BB = Worklist.pop_back_val();
    if (BB == StopBB)
      continue;
    if (!CanReachStop.insert(BB).second)
      continue;

    for (Instruction &I : *BB) {
      if (++NumScannedInstructions > MaxInstructionsToScan)
        return true;
      auto *CB = dyn_cast<CallBase>(&I);
      if (CB && isUncontrolledConvergentCall(CB)) {
        BlocksWithUncontrolledConvergentCalls.insert(BB);
        break;
      }
    }

    append_range(Worklist, predecessors(BB));
  }

  if (!CanReachStop.contains(From))
    return false;

  SmallPtrSet<BasicBlock *, 8> Visited;
  Worklist.push_back(From);

  while (!Worklist.empty()) {
    BasicBlock *BB = Worklist.pop_back_val();
    if (BB == StopBB || !CanReachStop.contains(BB))
      continue;

    if (!Visited.insert(BB).second)
      continue;

    if (BlocksWithUncontrolledConvergentCalls.contains(BB))
      return true;

    append_range(Worklist, successors(BB));
  }

  return false;
}

/// If we have a conditional branch on something for which we know the constant
/// value in predecessors (e.g. a phi node in the current block), thread edges
/// from the predecessor to their ultimate destination.
static std::optional<bool> foldCondBranchOnValueKnownInPredecessorImpl(
    CondBrInst *BI, const TargetTransformInfo &TTI, DomTreeUpdater *DTU,
    AssumptionCache *AC, const DataLayout &DL) {
  SmallMapVector<ConstantInt *, SmallSetVector<BasicBlock *, 2>, 2> KnownValues;
  BasicBlock *BB = BI->getParent();
  Value *Cond = BI->getCondition();
  PHINode *PN = dyn_cast<PHINode>(Cond);
  if (PN && PN->getParent() == BB) {
    // Degenerate case of a single entry PHI.
    if (PN->getNumIncomingValues() == 1) {
      FoldSingleEntryPHINodes(PN->getParent());
      return true;
    }

    for (Use &U : PN->incoming_values())
      if (auto *CB = dyn_cast<ConstantInt>(U))
        KnownValues[CB].insert(PN->getIncomingBlock(U));
  } else {
    for (BasicBlock *Pred : predecessors(BB)) {
      if (ConstantInt *CB = getKnownValueOnEdge(Cond, Pred, BB))
        KnownValues[CB].insert(Pred);
    }
  }

  if (KnownValues.empty())
    return false;

  // Now we know that this block has multiple preds and two succs.
  // Check that the block is small enough and record which non-local blocks use
  // values defined in the block.

  BlocksSet NonLocalUseBlocks;
  BlocksSet ReachesNonLocalUseBlocks;
  if (!blockIsSimpleEnoughToThreadThrough(BB, NonLocalUseBlocks))
    return false;

  // Jump-threading can only be done to destinations where no values defined
  // in BB are live.

  // Quickly check if both destinations have uses.  If so, jump-threading cannot
  // be done.
  if (NonLocalUseBlocks.contains(BI->getSuccessor(0)) &&
      NonLocalUseBlocks.contains(BI->getSuccessor(1)))
    return false;

  // Search backward from NonLocalUseBlocks to find which blocks
  // reach non-local uses.
  for (BasicBlock *UseBB : NonLocalUseBlocks)
    // Give up if too many blocks are searched.
    if (!findReaching(UseBB, BB, ReachesNonLocalUseBlocks))
      return false;

  for (const auto &Pair : KnownValues) {
    ConstantInt *CB = Pair.first;
    ArrayRef<BasicBlock *> PredBBs = Pair.second.getArrayRef();
    BasicBlock *RealDest = BI->getSuccessor(!CB->getZExtValue());

    // Okay, we now know that all edges from PredBB should be revectored to
    // branch to RealDest.
    if (RealDest == BB)
      continue; // Skip self loops.

    // Skip if the predecessor's terminator is an indirect branch.
    if (any_of(PredBBs, [](BasicBlock *PredBB) {
          return isa<IndirectBrInst>(PredBB->getTerminator());
        }))
      continue;

    // Only revector to RealDest if no values defined in BB are live.
    if (ReachesNonLocalUseBlocks.contains(RealDest))
      continue;

    // Threading through a branch can bypass a reconvergence point. If the
    // destination can execute an uncontrolled convergent operation before
    // returning to this block, this may change the dynamic instance of that
    // operation.
    if (TTI.hasBranchDivergence(BB->getParent()) &&
        reachesUncontrolledConvergentCallBeforeBlock(RealDest, BB))
      continue;

    LLVM_DEBUG({
      dbgs() << "Condition " << *Cond << " in " << BB->getName()
             << " has value " << *Pair.first << " in predecessors:\n";
      for (const BasicBlock *PredBB : Pair.second)
        dbgs() << "  " << PredBB->getName() << "\n";
      dbgs() << "Threading to destination " << RealDest->getName() << ".\n";
    });

    // Split the predecessors we are threading into a new edge block. We'll
    // clone the instructions into this block, and then redirect it to RealDest.
    BasicBlock *EdgeBB = SplitBlockPredecessors(BB, PredBBs, ".critedge", DTU);
    if (!EdgeBB)
      continue;

    // TODO: These just exist to reduce test diff, we can drop them if we like.
    EdgeBB->setName(RealDest->getName() + ".critedge");
    EdgeBB->moveBefore(RealDest);

    // Update PHI nodes.
    addPredecessorToBlock(RealDest, EdgeBB, BB);

    // BB may have instructions that are being threaded over.  Clone these
    // instructions into EdgeBB.  We know that there will be no uses of the
    // cloned instructions outside of EdgeBB.
    BasicBlock::iterator InsertPt = EdgeBB->getFirstInsertionPt();
    ValueToValueMapTy TranslateMap; // Track translated values.
    TranslateMap[Cond] = CB;

    // RemoveDIs: track instructions that we optimise away while folding, so
    // that we can copy DbgVariableRecords from them later.
    BasicBlock::iterator SrcDbgCursor = BB->begin();
    for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI) {
      if (PHINode *PN = dyn_cast<PHINode>(BBI)) {
        TranslateMap[PN] = PN->getIncomingValueForBlock(EdgeBB);
        continue;
      }
      // Clone the instruction.
      Instruction *N = BBI->clone();
      // Insert the new instruction into its new home.
      N->insertInto(EdgeBB, InsertPt);

      if (BBI->hasName())
        N->setName(BBI->getName() + ".c");

      // Update operands due to translation.
      // Key Instructions: Remap all the atom groups.
      if (const DebugLoc &DL = BBI->getDebugLoc())
        mapAtomInstance(DL, TranslateMap);
      RemapInstruction(N, TranslateMap,
                       RF_IgnoreMissingLocals | RF_NoModuleLevelChanges);

      // Check for trivial simplification.
      if (Value *V = simplifyInstruction(N, {DL, nullptr, nullptr, AC})) {
        if (!BBI->use_empty())
          TranslateMap[&*BBI] = V;
        if (!N->mayHaveSideEffects()) {
          N->eraseFromParent(); // Instruction folded away, don't need actual
                                // inst
          N = nullptr;
        }
      } else {
        if (!BBI->use_empty())
          TranslateMap[&*BBI] = N;
      }
      if (N) {
        // Copy all debug-info attached to instructions from the last we
        // successfully clone, up to this instruction (they might have been
        // folded away).
        for (; SrcDbgCursor != BBI; ++SrcDbgCursor)
          N->cloneDebugInfoFrom(&*SrcDbgCursor);
        SrcDbgCursor = std::next(BBI);
        // Clone debug-info on this instruction too.
        N->cloneDebugInfoFrom(&*BBI);

        // Register the new instruction with the assumption cache if necessary.
        if (auto *Assume = dyn_cast<AssumeInst>(N))
          if (AC)
            AC->registerAssumption(Assume);
      }
    }

    for (; &*SrcDbgCursor != BI; ++SrcDbgCursor)
      InsertPt->cloneDebugInfoFrom(&*SrcDbgCursor);
    InsertPt->cloneDebugInfoFrom(BI);

    BB->removePredecessor(EdgeBB);
    UncondBrInst *EdgeBI = cast<UncondBrInst>(EdgeBB->getTerminator());
    EdgeBI->setSuccessor(0, RealDest);
    EdgeBI->setDebugLoc(BI->getDebugLoc());

    if (DTU) {
      SmallVector<DominatorTree::UpdateType, 2> Updates;
      Updates.push_back({DominatorTree::Delete, EdgeBB, BB});
      Updates.push_back({DominatorTree::Insert, EdgeBB, RealDest});
      DTU->applyUpdates(Updates);
    }

    // For simplicity, we created a separate basic block for the edge. Merge
    // it back into the predecessor if possible. This not only avoids
    // unnecessary SimplifyCFG iterations, but also makes sure that we don't
    // bypass the check for trivial cycles above.
    MergeBlockIntoPredecessor(EdgeBB, DTU);

    // Signal repeat, simplifying any other constants.
    return std::nullopt;
  }

  return false;
}

bool SimplifyCFGOpt::foldCondBranchOnValueKnownInPredecessor(CondBrInst *BI) {
  // Note: If BB is a loop header then there is a risk that threading introduces
  // a non-canonical loop by moving a back edge. So we avoid this optimization
  // for loop headers if NeedCanonicalLoop is set.
  if (Options.NeedCanonicalLoop && is_contained(LoopHeaders, BI->getParent()))
    return false;

  std::optional<bool> Result;
  bool EverChanged = false;
  do {
    // Note that None means "we changed things, but recurse further."
    Result = foldCondBranchOnValueKnownInPredecessorImpl(BI, TTI, DTU,
                                                         Options.AC, DL);
    EverChanged |= Result == std::nullopt || *Result;
  } while (Result == std::nullopt);
  return EverChanged;
}

/// Given a BB that starts with the specified two-entry PHI node,
/// see if we can eliminate it.
static bool foldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
                                DomTreeUpdater *DTU, AssumptionCache *AC,
                                const DataLayout &DL,
                                bool SpeculateUnpredictables) {
  // Ok, this is a two entry PHI node.  Check to see if this is a simple "if
  // statement", which has a very simple dominance structure.  Basically, we
  // are trying to find the condition that is being branched on, which
  // subsequently causes this merge to happen.  We really want control
  // dependence information for this check, but simplifycfg can't keep it up
  // to date, and this catches most of the cases we care about anyway.
  BasicBlock *BB = PN->getParent();

  BasicBlock *IfTrue, *IfFalse;
  CondBrInst *DomBI = GetIfCondition(BB, IfTrue, IfFalse);
  if (!DomBI)
    return false;
  Value *IfCond = DomBI->getCondition();
  // Don't bother if the branch will be constant folded trivially.
  if (isa<ConstantInt>(IfCond))
    return false;

  BasicBlock *DomBlock = DomBI->getParent();
  SmallVector<BasicBlock *, 2> IfBlocks;
  llvm::copy_if(PN->blocks(), std::back_inserter(IfBlocks),
                [](BasicBlock *IfBlock) {
                  return isa<UncondBrInst>(IfBlock->getTerminator());
                });
  assert((IfBlocks.size() == 1 || IfBlocks.size() == 2) &&
         "Will have either one or two blocks to speculate.");

  // If the branch is non-unpredictable, see if we either predictably jump to
  // the merge bb (if we have only a single 'then' block), or if we predictably
  // jump to one specific 'then' block (if we have two of them).
  // It isn't beneficial to speculatively execute the code
  // from the block that we know is predictably not entered.
  bool IsUnpredictable = DomBI->getMetadata(LLVMContext::MD_unpredictable);
  if (!IsUnpredictable) {
    uint64_t TWeight, FWeight;
    if (extractBranchWeights(*DomBI, TWeight, FWeight) &&
        (TWeight + FWeight) != 0) {
      BranchProbability BITrueProb =
          BranchProbability::getBranchProbability(TWeight, TWeight + FWeight);
      BranchProbability Likely = TTI.getPredictableBranchThreshold();
      BranchProbability BIFalseProb = BITrueProb.getCompl();
      if (IfBlocks.size() == 1) {
        BranchProbability BIBBProb =
            DomBI->getSuccessor(0) == BB ? BITrueProb : BIFalseProb;
        if (BIBBProb >= Likely)
          return false;
      } else {
        if (BITrueProb >= Likely || BIFalseProb >= Likely)
          return false;
      }
    }
  }

  // Don't try to fold an unreachable block. For example, the phi node itself
  // can't be the candidate if-condition for a select that we want to form.
  if (auto *IfCondPhiInst = dyn_cast<PHINode>(IfCond))
    if (IfCondPhiInst->getParent() == BB)
      return false;

  // Okay, we found that we can merge this two-entry phi node into a select.
  // Doing so would require us to fold *all* two entry phi nodes in this block.
  // At some point this becomes non-profitable (particularly if the target
  // doesn't support cmov's).  Only do this transformation if there are two or
  // fewer PHI nodes in this block.
  unsigned NumPhis = 0;
  for (BasicBlock::iterator I = BB->begin(); isa<PHINode>(I); ++NumPhis, ++I)
    if (NumPhis > 2)
      return false;

  // Loop over the PHI's seeing if we can promote them all to select
  // instructions.  While we are at it, keep track of the instructions
  // that need to be moved to the dominating block.
  SmallPtrSet<Instruction *, 4> AggressiveInsts;
  SmallPtrSet<Instruction *, 2> ZeroCostInstructions;
  InstructionCost Cost = 0;
  InstructionCost Budget =
      TwoEntryPHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic;
  if (SpeculateUnpredictables && IsUnpredictable)
    Budget += TTI.getBranchMispredictPenalty();

  bool Changed = false;
  for (BasicBlock::iterator II = BB->begin(); isa<PHINode>(II);) {
    PHINode *PN = cast<PHINode>(II++);
    if (Value *V = simplifyInstruction(PN, {DL, PN})) {
      PN->replaceAllUsesWith(V);
      PN->eraseFromParent();
      Changed = true;
      continue;
    }

    if (!dominatesMergePoint(PN->getIncomingValue(0), BB, DomBI,
                             AggressiveInsts, Cost, Budget, TTI, AC,
                             ZeroCostInstructions) ||
        !dominatesMergePoint(PN->getIncomingValue(1), BB, DomBI,
                             AggressiveInsts, Cost, Budget, TTI, AC,
                             ZeroCostInstructions))
      return Changed;
  }

  // If we folded the first phi, PN dangles at this point.  Refresh it.  If
  // we ran out of PHIs then we simplified them all.
  PN = dyn_cast<PHINode>(BB->begin());
  if (!PN)
    return true;

  // Don't fold i1 branches on PHIs which contain binary operators or
  // (possibly inverted) select form of or/ands if their parameters are
  // an equality test.
  auto IsBinOpOrAndEq = [](Value *V) {
    CmpPredicate Pred;
    if (match(V, m_CombineOr(
                     m_CombineOr(
                         m_BinOp(m_Cmp(Pred, m_Value(), m_Value()), m_Value()),
                         m_BinOp(m_Value(), m_Cmp(Pred, m_Value(), m_Value()))),
                     m_c_Select(m_ImmConstant(),
                                m_Cmp(Pred, m_Value(), m_Value()))))) {
      return CmpInst::isEquality(Pred);
    }
    return false;
  };
  if (PN->getType()->isIntegerTy(1) &&
      (IsBinOpOrAndEq(PN->getIncomingValue(0)) ||
       IsBinOpOrAndEq(PN->getIncomingValue(1)) || IsBinOpOrAndEq(IfCond)))
    return Changed;

  // If all PHI nodes are promotable, check to make sure that all instructions
  // in the predecessor blocks can be promoted as well. If not, we won't be able
  // to get rid of the control flow, so it's not worth promoting to select
  // instructions.
  for (BasicBlock *IfBlock : IfBlocks)
    for (BasicBlock::iterator I = IfBlock->begin(); !I->isTerminator(); ++I)
      if (!AggressiveInsts.count(&*I) && !isa<PseudoProbeInst>(I)) {
        // This is not an aggressive instruction that we can promote.
        // Because of this, we won't be able to get rid of the control flow, so
        // the xform is not worth it.
        return Changed;
      }

  // If either of the blocks has it's address taken, we can't do this fold.
  if (any_of(IfBlocks,
             [](BasicBlock *IfBlock) { return IfBlock->hasAddressTaken(); }))
    return Changed;

  LLVM_DEBUG(dbgs() << "FOUND IF CONDITION!  " << *IfCond;
             if (IsUnpredictable) dbgs() << " (unpredictable)";
             dbgs() << "  T: " << IfTrue->getName()
                    << "  F: " << IfFalse->getName() << "\n");

  // If we can still promote the PHI nodes after this gauntlet of tests,
  // do all of the PHI's now.

  // Move all 'aggressive' instructions, which are defined in the
  // conditional parts of the if's up to the dominating block.
  for (BasicBlock *IfBlock : IfBlocks)
      hoistAllInstructionsInto(DomBlock, DomBI, IfBlock);

  IRBuilder<NoFolder> Builder(DomBI);
  // Propagate fast-math-flags from phi nodes to replacement selects.
  while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) {
    // Change the PHI node into a select instruction.
    Value *TrueVal = PN->getIncomingValueForBlock(IfTrue);
    Value *FalseVal = PN->getIncomingValueForBlock(IfFalse);

    Value *Sel = Builder.CreateSelectFMF(IfCond, TrueVal, FalseVal,
                                         isa<FPMathOperator>(PN) ? PN : nullptr,
                                         "", DomBI);
    PN->replaceAllUsesWith(Sel);
    Sel->takeName(PN);
    PN->eraseFromParent();
  }

  // At this point, all IfBlocks are empty, so our if statement
  // has been flattened.  Change DomBlock to jump directly to our new block to
  // avoid other simplifycfg's kicking in on the diamond.
  Builder.CreateBr(BB);

  SmallVector<DominatorTree::UpdateType, 3> Updates;
  if (DTU) {
    Updates.push_back({DominatorTree::Insert, DomBlock, BB});
    for (auto *Successor : successors(DomBlock))
      Updates.push_back({DominatorTree::Delete, DomBlock, Successor});
  }

  DomBI->eraseFromParent();
  if (DTU)
    DTU->applyUpdates(Updates);

  return true;
}

static Value *createLogicalOp(IRBuilderBase &Builder,
                              Instruction::BinaryOps Opc, Value *LHS,
                              Value *RHS, const Twine &Name = "") {
  // Try to relax logical op to binary op.
  if (impliesPoison(RHS, LHS))
    return Builder.CreateBinOp(Opc, LHS, RHS, Name);
  if (Opc == Instruction::And)
    return Builder.CreateLogicalAnd(LHS, RHS, Name);
  if (Opc == Instruction::Or)
    return Builder.CreateLogicalOr(LHS, RHS, Name);
  llvm_unreachable("Invalid logical opcode");
}

/// Return true if either PBI or BI has branch weight available, and store
/// the weights in {Pred|Succ}{True|False}Weight. If one of PBI and BI does
/// not have branch weight, use 1:1 as its weight.
static bool extractPredSuccWeights(CondBrInst *PBI, CondBrInst *BI,
                                   uint64_t &PredTrueWeight,
                                   uint64_t &PredFalseWeight,
                                   uint64_t &SuccTrueWeight,
                                   uint64_t &SuccFalseWeight) {
  bool PredHasWeights =
      extractBranchWeights(*PBI, PredTrueWeight, PredFalseWeight);
  bool SuccHasWeights =
      extractBranchWeights(*BI, SuccTrueWeight, SuccFalseWeight);
  if (PredHasWeights || SuccHasWeights) {
    if (!PredHasWeights)
      PredTrueWeight = PredFalseWeight = 1;
    if (!SuccHasWeights)
      SuccTrueWeight = SuccFalseWeight = 1;
    return true;
  } else {
    return false;
  }
}

/// Determine if the two branches share a common destination and deduce a glue
/// that joins the branches' conditions to arrive at the common destination if
/// that would be profitable.
static std::optional<std::tuple<BasicBlock *, Instruction::BinaryOps, bool>>
shouldFoldCondBranchesToCommonDestination(CondBrInst *BI, CondBrInst *PBI,
                                          const TargetTransformInfo *TTI) {
  assert(BI && PBI && "Both blocks must end with a conditional branches.");
  assert(is_contained(predecessors(BI->getParent()), PBI->getParent()) &&
         "PredBB must be a predecessor of BB.");

  // We have the potential to fold the conditions together, but if the
  // predecessor branch is predictable, we may not want to merge them.
  uint64_t PTWeight, PFWeight;
  BranchProbability PBITrueProb, Likely;
  if (TTI && !PBI->getMetadata(LLVMContext::MD_unpredictable) &&
      extractBranchWeights(*PBI, PTWeight, PFWeight) &&
      (PTWeight + PFWeight) != 0) {
    PBITrueProb =
        BranchProbability::getBranchProbability(PTWeight, PTWeight + PFWeight);
    Likely = TTI->getPredictableBranchThreshold();
  }

  if (PBI->getSuccessor(0) == BI->getSuccessor(0)) {
    // Speculate the 2nd condition unless the 1st is probably true.
    if (PBITrueProb.isUnknown() || PBITrueProb < Likely)
      return {{BI->getSuccessor(0), Instruction::Or, false}};
  } else if (PBI->getSuccessor(1) == BI->getSuccessor(1)) {
    // Speculate the 2nd condition unless the 1st is probably false.
    if (PBITrueProb.isUnknown() || PBITrueProb.getCompl() < Likely)
      return {{BI->getSuccessor(1), Instruction::And, false}};
  } else if (PBI->getSuccessor(0) == BI->getSuccessor(1)) {
    // Speculate the 2nd condition unless the 1st is probably true.
    if (PBITrueProb.isUnknown() || PBITrueProb < Likely)
      return {{BI->getSuccessor(1), Instruction::And, true}};
  } else if (PBI->getSuccessor(1) == BI->getSuccessor(0)) {
    // Speculate the 2nd condition unless the 1st is probably false.
    if (PBITrueProb.isUnknown() || PBITrueProb.getCompl() < Likely)
      return {{BI->getSuccessor(0), Instruction::Or, true}};
  }
  return std::nullopt;
}

static bool performBranchToCommonDestFolding(CondBrInst *BI, CondBrInst *PBI,
                                             DomTreeUpdater *DTU,
                                             MemorySSAUpdater *MSSAU,
                                             const TargetTransformInfo *TTI) {
  BasicBlock *BB = BI->getParent();
  BasicBlock *PredBlock = PBI->getParent();

  // Determine if the two branches share a common destination.
  BasicBlock *CommonSucc;
  Instruction::BinaryOps Opc;
  bool InvertPredCond;
  std::tie(CommonSucc, Opc, InvertPredCond) =
      *shouldFoldCondBranchesToCommonDestination(BI, PBI, TTI);

  LLVM_DEBUG(dbgs() << "FOLDING BRANCH TO COMMON DEST:\n" << *PBI << *BB);

  IRBuilder<ConstantFolder, IRBuilderCallbackInserter> Builder(
      *BB->getModule(), ConstantFolder{},
      IRBuilderCallbackInserter([&BB](Instruction *I) {
        // The builder is used to create instructions to eliminate the branch in
        // BB. If BB's terminator has !annotation metadata, add it to the new
        // instructions.
        I->copyMetadata(*BB->getTerminator(), LLVMContext::MD_annotation);
      }));
  Builder.SetInsertPoint(PBI);

  // If we need to invert the condition in the pred block to match, do so now.
  if (InvertPredCond) {
    InvertBranch(PBI, Builder);
  }

  BasicBlock *UniqueSucc =
      PBI->getSuccessor(0) == BB ? BI->getSuccessor(0) : BI->getSuccessor(1);

  // Before cloning instructions, notify the successor basic block that it
  // is about to have a new predecessor. This will update PHI nodes,
  // which will allow us to update live-out uses of bonus instructions.
  addPredecessorToBlock(UniqueSucc, PredBlock, BB, MSSAU);

  // Try to update branch weights.
  uint64_t PredTrueWeight, PredFalseWeight, SuccTrueWeight, SuccFalseWeight;
  SmallVector<uint64_t, 2> MDWeights;
  if (extractPredSuccWeights(PBI, BI, PredTrueWeight, PredFalseWeight,
                             SuccTrueWeight, SuccFalseWeight)) {

    if (PBI->getSuccessor(0) == BB) {
      // PBI: br i1 %x, BB, FalseDest
      // BI:  br i1 %y, UniqueSucc, FalseDest
      // TrueWeight is TrueWeight for PBI * TrueWeight for BI.
      MDWeights.push_back(PredTrueWeight * SuccTrueWeight);
      // FalseWeight is FalseWeight for PBI * TotalWeight for BI +
      //               TrueWeight for PBI * FalseWeight for BI.
      // We assume that total weights of a CondBrInst can fit into 32 bits.
      // Therefore, we will not have overflow using 64-bit arithmetic.
      MDWeights.push_back(PredFalseWeight * (SuccFalseWeight + SuccTrueWeight) +
                          PredTrueWeight * SuccFalseWeight);
    } else {
      // PBI: br i1 %x, TrueDest, BB
      // BI:  br i1 %y, TrueDest, UniqueSucc
      // TrueWeight is TrueWeight for PBI * TotalWeight for BI +
      //              FalseWeight for PBI * TrueWeight for BI.
      MDWeights.push_back(PredTrueWeight * (SuccFalseWeight + SuccTrueWeight) +
                          PredFalseWeight * SuccTrueWeight);
      // FalseWeight is FalseWeight for PBI * FalseWeight for BI.
      MDWeights.push_back(PredFalseWeight * SuccFalseWeight);
    }

    setFittedBranchWeights(*PBI, MDWeights, /*IsExpected=*/false,
                           /*ElideAllZero=*/true);

    // TODO: If BB is reachable from all paths through PredBlock, then we
    // could replace PBI's branch probabilities with BI's.
  } else {
    PBI->setMetadata(LLVMContext::MD_prof, nullptr);
    setExplicitlyUnknownBranchWeightsIfProfiled(*PBI, DEBUG_TYPE);
  }

  // Now, update the CFG.
  PBI->setSuccessor(PBI->getSuccessor(0) != BB, UniqueSucc);

  if (DTU)
    DTU->applyUpdates({{DominatorTree::Insert, PredBlock, UniqueSucc},
                       {DominatorTree::Delete, PredBlock, BB}});

  // If BI was a loop latch, it may have had associated loop metadata.
  // We need to copy it to the new latch, that is, PBI.
  if (MDNode *LoopMD = BI->getMetadata(LLVMContext::MD_loop))
    PBI->setMetadata(LLVMContext::MD_loop, LoopMD);

  ValueToValueMapTy VMap; // maps original values to cloned values
  cloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(BB, PredBlock, VMap);

  Module *M = BB->getModule();

  PredBlock->getTerminator()->cloneDebugInfoFrom(BB->getTerminator());
  for (DbgVariableRecord &DVR :
       filterDbgVars(PredBlock->getTerminator()->getDbgRecordRange())) {
    RemapDbgRecord(M, &DVR, VMap,
                   RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
  }

  // Now that the Cond was cloned into the predecessor basic block,
  // or/and the two conditions together.
  Value *BICond = VMap[BI->getCondition()];
  PBI->setCondition(
      createLogicalOp(Builder, Opc, PBI->getCondition(), BICond, "or.cond"));
  if (auto *SI = dyn_cast<SelectInst>(PBI->getCondition())) {
    if (!MDWeights.empty()) {
      assert(isSelectInRoleOfConjunctionOrDisjunction(SI));
      setFittedBranchWeights(*SI, {MDWeights[0], MDWeights[1]},
                             /*IsExpected=*/false, /*ElideAllZero=*/true);
    } else {
      setExplicitlyUnknownBranchWeightsIfProfiled(*SI, DEBUG_TYPE);
    }
  }

  ++NumFoldBranchToCommonDest;
  return true;
}

/// Return if an instruction's type or any of its operands' types are a vector
/// type.
static bool isVectorOp(Instruction &I) {
  return I.getType()->isVectorTy() || any_of(I.operands(), [](Use &U) {
           return U->getType()->isVectorTy();
         });
}

/// If this basic block is simple enough, and if a predecessor branches to us
/// and one of our successors, fold the block into the predecessor and use
/// logical operations to pick the right destination.
bool llvm::foldBranchToCommonDest(CondBrInst *BI, DomTreeUpdater *DTU,
                                  MemorySSAUpdater *MSSAU,
                                  const TargetTransformInfo *TTI,
                                  AssumptionCache *AC,
                                  unsigned BonusInstThreshold) {
  BasicBlock *BB = BI->getParent();
  TargetTransformInfo::TargetCostKind CostKind =
    BB->getParent()->hasMinSize() ? TargetTransformInfo::TCK_CodeSize
                                  : TargetTransformInfo::TCK_SizeAndLatency;

  Instruction *Cond = dyn_cast<Instruction>(BI->getCondition());

  if (!Cond || !isa<CmpInst, BinaryOperator, SelectInst, TruncInst>(Cond) ||
      Cond->getParent() != BB || !Cond->hasOneUse())
    return false;

  // Finally, don't infinitely unroll conditional loops.
  if (is_contained(successors(BB), BB))
    return false;

  // With which predecessors will we want to deal with?
  SmallVector<BasicBlock *, 8> Preds;
  for (BasicBlock *PredBlock : predecessors(BB)) {
    CondBrInst *PBI = dyn_cast<CondBrInst>(PredBlock->getTerminator());

    // Check that we have two conditional branches.  If there is a PHI node in
    // the common successor, verify that the same value flows in from both
    // blocks.
    if (!PBI || !safeToMergeTerminators(BI, PBI))
      continue;

    // Determine if the two branches share a common destination.
    BasicBlock *CommonSucc;
    Instruction::BinaryOps Opc;
    bool InvertPredCond;
    if (auto Recipe = shouldFoldCondBranchesToCommonDestination(BI, PBI, TTI))
      std::tie(CommonSucc, Opc, InvertPredCond) = *Recipe;
    else
      continue;

    // Check the cost of inserting the necessary logic before performing the
    // transformation.
    if (TTI) {
      Type *Ty = BI->getCondition()->getType();
      InstructionCost Cost = TTI->getArithmeticInstrCost(Opc, Ty, CostKind);
      if (InvertPredCond && (!PBI->getCondition()->hasOneUse() ||
                             !isa<CmpInst>(PBI->getCondition())))
        Cost += TTI->getArithmeticInstrCost(Instruction::Xor, Ty, CostKind);

      if (Cost > BranchFoldThreshold)
        continue;
    }

    // Ok, we do want to deal with this predecessor. Record it.
    Preds.emplace_back(PredBlock);
  }

  // If there aren't any predecessors into which we can fold,
  // don't bother checking the cost.
  if (Preds.empty())
    return false;

  // Only allow this transformation if computing the condition doesn't involve
  // too many instructions and these involved instructions can be executed
  // unconditionally. We denote all involved instructions except the condition
  // as "bonus instructions", and only allow this transformation when the
  // number of the bonus instructions we'll need to create when cloning into
  // each predecessor does not exceed a certain threshold.
  unsigned NumBonusInsts = 0;
  bool SawVectorOp = false;
  const unsigned PredCount = Preds.size();
  // Speculated instructions will be inserted before the terminator of the
  // predecessor. Only handle the simple case of one predecessor.
  const Instruction *CtxI =
      PredCount == 1 ? Preds[0]->getTerminator() : nullptr;
  for (Instruction &I : *BB) {
    // Don't check the branch condition comparison itself.
    if (&I == Cond)
      continue;
    // Ignore the terminator.
    if (isa<UncondBrInst, CondBrInst>(I))
      continue;
    // Pseudo probes aren't speculatable but can be dropped on fold.
    if (isa<PseudoProbeInst>(I))
      continue;
    // I must be safe to execute unconditionally.
    if (!isSafeToSpeculativelyExecute(&I, CtxI, AC))
      return false;
    SawVectorOp |= isVectorOp(I);

    // Account for the cost of duplicating this instruction into each
    // predecessor. Ignore free instructions.
    if (!TTI || TTI->getInstructionCost(&I, CostKind) !=
                    TargetTransformInfo::TCC_Free) {
      NumBonusInsts += PredCount;

      // Early exits once we reach the limit.
      if (NumBonusInsts >
          BonusInstThreshold * BranchFoldToCommonDestVectorMultiplier)
        return false;
    }

    auto IsBCSSAUse = [BB, &I](Use &U) {
      auto *UI = cast<Instruction>(U.getUser());
      if (auto *PN = dyn_cast<PHINode>(UI))
        return PN->getIncomingBlock(U) == BB;
      return UI->getParent() == BB && I.comesBefore(UI);
    };

    // Does this instruction require rewriting of uses?
    if (!all_of(I.uses(), IsBCSSAUse))
      return false;
  }
  if (NumBonusInsts >
      BonusInstThreshold *
          (SawVectorOp ? BranchFoldToCommonDestVectorMultiplier : 1))
    return false;

  // Ok, we have the budget. Perform the transformation.
  for (BasicBlock *PredBlock : Preds) {
    auto *PBI = cast<CondBrInst>(PredBlock->getTerminator());
    return performBranchToCommonDestFolding(BI, PBI, DTU, MSSAU, TTI);
  }
  return false;
}

// If there is only one store in BB1 and BB2, return it, otherwise return
// nullptr.
static StoreInst *findUniqueStoreInBlocks(BasicBlock *BB1, BasicBlock *BB2) {
  StoreInst *S = nullptr;
  for (auto *BB : {BB1, BB2}) {
    if (!BB)
      continue;
    for (auto &I : *BB)
      if (auto *SI = dyn_cast<StoreInst>(&I)) {
        if (S)
          // Multiple stores seen.
          return nullptr;
        else
          S = SI;
      }
  }
  return S;
}

static Value *ensureValueAvailableInSuccessor(Value *V, BasicBlock *BB,
                                              Value *AlternativeV = nullptr) {
  // PHI is going to be a PHI node that allows the value V that is defined in
  // BB to be referenced in BB's only successor.
  //
  // If AlternativeV is nullptr, the only value we care about in PHI is V. It
  // doesn't matter to us what the other operand is (it'll never get used). We
  // could just create a new PHI with an undef incoming value, but that could
  // increase register pressure if EarlyCSE/InstCombine can't fold it with some
  // other PHI. So here we directly look for some PHI in BB's successor with V
  // as an incoming operand. If we find one, we use it, else we create a new
  // one.
  //
  // If AlternativeV is not nullptr, we care about both incoming values in PHI.
  // PHI must be exactly: phi <ty> [ %BB, %V ], [ %OtherBB, %AlternativeV]
  // where OtherBB is the single other predecessor of BB's only successor.
  PHINode *PHI = nullptr;
  BasicBlock *Succ = BB->getSingleSuccessor();

  for (auto I = Succ->begin(); isa<PHINode>(I); ++I)
    if (cast<PHINode>(I)->getIncomingValueForBlock(BB) == V) {
      PHI = cast<PHINode>(I);
      if (!AlternativeV)
        break;

      assert(Succ->hasNPredecessors(2));
      auto PredI = pred_begin(Succ);
      BasicBlock *OtherPredBB = *PredI == BB ? *++PredI : *PredI;
      if (PHI->getIncomingValueForBlock(OtherPredBB) == AlternativeV)
        break;
      PHI = nullptr;
    }
  if (PHI)
    return PHI;

  // If V is not an instruction defined in BB, just return it.
  if (!AlternativeV &&
      (!isa<Instruction>(V) || cast<Instruction>(V)->getParent() != BB))
    return V;

  PHI = PHINode::Create(V->getType(), 2, "simplifycfg.merge");
  PHI->insertBefore(Succ->begin());
  PHI->addIncoming(V, BB);
  for (BasicBlock *PredBB : predecessors(Succ))
    if (PredBB != BB)
      PHI->addIncoming(
          AlternativeV ? AlternativeV : PoisonValue::get(V->getType()), PredBB);
  return PHI;
}

static bool mergeConditionalStoreToAddress(
    BasicBlock *PTB, BasicBlock *PFB, BasicBlock *QTB, BasicBlock *QFB,
    BasicBlock *PostBB, Value *Address, bool InvertPCond, bool InvertQCond,
    DomTreeUpdater *DTU, const DataLayout &DL, const TargetTransformInfo &TTI) {
  // For every pointer, there must be exactly two stores, one coming from
  // PTB or PFB, and the other from QTB or QFB. We don't support more than one
  // store (to any address) in PTB,PFB or QTB,QFB.
  // FIXME: We could relax this restriction with a bit more work and performance
  // testing.
  StoreInst *PStore = findUniqueStoreInBlocks(PTB, PFB);
  StoreInst *QStore = findUniqueStoreInBlocks(QTB, QFB);
  if (!PStore || !QStore)
    return false;

  // Now check the stores are compatible.
  if (!QStore->isUnordered() || !PStore->isUnordered() ||
      PStore->getOrdering() != QStore->getOrdering() ||
      PStore->getSyncScopeID() != QStore->getSyncScopeID() ||
      PStore->getValueOperand()->getType() !=
          QStore->getValueOperand()->getType())
    return false;

  // Check that sinking the store won't cause program behavior changes. Sinking
  // the store out of the Q blocks won't change any behavior as we're sinking
  // from a block to its unconditional successor. But we're moving a store from
  // the P blocks down through the middle block (QBI) and past both QFB and QTB.
  // So we need to check that there are no aliasing loads or stores in
  // QBI, QTB and QFB. We also need to check there are no conflicting memory
  // operations between PStore and the end of its parent block.
  //
  // The ideal way to do this is to query AliasAnalysis, but we don't
  // preserve AA currently so that is dangerous. Be super safe and just
  // check there are no other memory operations at all.
  for (auto &I : *QFB->getSinglePredecessor())
    if (I.mayReadOrWriteMemory())
      return false;
  for (auto &I : *QFB)
    if (&I != QStore && I.mayReadOrWriteMemory())
      return false;
  if (QTB)
    for (auto &I : *QTB)
      if (&I != QStore && I.mayReadOrWriteMemory())
        return false;
  for (auto I = BasicBlock::iterator(PStore), E = PStore->getParent()->end();
       I != E; ++I)
    if (&*I != PStore && I->mayReadOrWriteMemory())
      return false;

  // If we're not in aggressive mode, we only optimize if we have some
  // confidence that by optimizing we'll allow P and/or Q to be if-converted.
  auto IsWorthwhile = [&](BasicBlock *BB, ArrayRef<StoreInst *> FreeStores) {
    if (!BB)
      return true;
    // Heuristic: if the block can be if-converted/phi-folded and the
    // instructions inside are all cheap (arithmetic/GEPs), it's worthwhile to
    // thread this store.
    InstructionCost Cost = 0;
    InstructionCost Budget =
        PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic;
    for (auto &I : *BB) {
      // Consider terminator instruction to be free.
      if (I.isTerminator())
        continue;
      // If this is one the stores that we want to speculate out of this BB,
      // then don't count it's cost, consider it to be free.
      if (auto *S = dyn_cast<StoreInst>(&I))
        if (llvm::find(FreeStores, S))
          continue;
      // Else, we have a white-list of instructions that we are ak speculating.
      if (!isa<BinaryOperator>(I) && !isa<GetElementPtrInst>(I))
        return false; // Not in white-list - not worthwhile folding.
      // And finally, if this is a non-free instruction that we are okay
      // speculating, ensure that we consider the speculation budget.
      Cost +=
          TTI.getInstructionCost(&I, TargetTransformInfo::TCK_SizeAndLatency);
      if (Cost > Budget)
        return false; // Eagerly refuse to fold as soon as we're out of budget.
    }
    assert(Cost <= Budget &&
           "When we run out of budget we will eagerly return from within the "
           "per-instruction loop.");
    return true;
  };

  const std::array<StoreInst *, 2> FreeStores = {PStore, QStore};
  if (!MergeCondStoresAggressively &&
      (!IsWorthwhile(PTB, FreeStores) || !IsWorthwhile(PFB, FreeStores) ||
       !IsWorthwhile(QTB, FreeStores) || !IsWorthwhile(QFB, FreeStores)))
    return false;

  // If PostBB has more than two predecessors, we need to split it so we can
  // sink the store.
  if (std::next(pred_begin(PostBB), 2) != pred_end(PostBB)) {
    // We know that QFB's only successor is PostBB. And QFB has a single
    // predecessor. If QTB exists, then its only successor is also PostBB.
    // If QTB does not exist, then QFB's only predecessor has a conditional
    // branch to QFB and PostBB.
    BasicBlock *TruePred = QTB ? QTB : QFB->getSinglePredecessor();
    BasicBlock *NewBB =
        SplitBlockPredecessors(PostBB, {QFB, TruePred}, "condstore.split", DTU);
    if (!NewBB)
      return false;
    PostBB = NewBB;
  }

  // OK, we're going to sink the stores to PostBB. The store has to be
  // conditional though, so first create the predicate.
  CondBrInst *PBranch =
      cast<CondBrInst>(PFB->getSinglePredecessor()->getTerminator());
  CondBrInst *QBranch =
      cast<CondBrInst>(QFB->getSinglePredecessor()->getTerminator());
  Value *PCond = PBranch->getCondition();
  Value *QCond = QBranch->getCondition();

  Value *PPHI = ensureValueAvailableInSuccessor(PStore->getValueOperand(),
                                                PStore->getParent());
  Value *QPHI = ensureValueAvailableInSuccessor(QStore->getValueOperand(),
                                                QStore->getParent(), PPHI);

  IRBuilder<> QB(PostBB->getFirstInsertionPt());

  InvertPCond ^= (PStore->getParent() != PTB);
  InvertQCond ^= (QStore->getParent() != QTB);
  Value *PPred = InvertPCond ? QB.CreateNot(PCond) : PCond;
  Value *QPred = InvertQCond ? QB.CreateNot(QCond) : QCond;

  Value *CombinedPred = QB.CreateOr(PPred, QPred);

  BasicBlock::iterator InsertPt = QB.GetInsertPoint();
  auto *T = SplitBlockAndInsertIfThen(CombinedPred, InsertPt,
                                      /*Unreachable=*/false,
                                      /*BranchWeights=*/nullptr, DTU);
  if (hasBranchWeightMD(*PBranch) && hasBranchWeightMD(*QBranch)) {
    SmallVector<uint32_t, 2> PWeights, QWeights;
    extractBranchWeights(*PBranch, PWeights);
    extractBranchWeights(*QBranch, QWeights);
    if (InvertPCond)
      std::swap(PWeights[0], PWeights[1]);
    if (InvertQCond)
      std::swap(QWeights[0], QWeights[1]);
    auto CombinedWeights = getDisjunctionWeights(PWeights, QWeights);
    setFittedBranchWeights(*PostBB->getTerminator(),
                           {CombinedWeights[0], CombinedWeights[1]},
                           /*IsExpected=*/false, /*ElideAllZero=*/true);
  }

  QB.SetInsertPoint(T);
  StoreInst *SI = cast<StoreInst>(QB.CreateStore(QPHI, Address));
  combineMetadataForCSE(QStore, PStore, true);
  SI->copyMetadata(*QStore);
  // Update any dbg.assign intrinsics to track the merged value (QPHI) instead
  // of the original constant values, likely making these identical.
  for (auto *DbgAssign : at::getDVRAssignmentMarkers(SI)) {
    if (llvm::is_contained(DbgAssign->location_ops(),
                           PStore->getValueOperand()))
      DbgAssign->replaceVariableLocationOp(PStore->getValueOperand(), QPHI);
    if (llvm::is_contained(DbgAssign->location_ops(),
                           QStore->getValueOperand()))
      DbgAssign->replaceVariableLocationOp(QStore->getValueOperand(), QPHI);
  }

  // Choose the minimum alignment. If we could prove both stores execute, we
  // could use biggest one.  In this case, though, we only know that one of the
  // stores executes.  And we don't know it's safe to take the alignment from a
  // store that doesn't execute.
  SI->setAlignment(std::min(PStore->getAlign(), QStore->getAlign()));

  if (QStore->isAtomic())
    SI->setAtomic(QStore->getOrdering(), QStore->getSyncScopeID());

  QStore->eraseFromParent();
  PStore->eraseFromParent();

  return true;
}

static bool mergeConditionalStores(CondBrInst *PBI, CondBrInst *QBI,
                                   DomTreeUpdater *DTU, const DataLayout &DL,
                                   const TargetTransformInfo &TTI) {
  // The intention here is to find diamonds or triangles (see below) where each
  // conditional block contains a store to the same address. Both of these
  // stores are conditional, so they can't be unconditionally sunk. But it may
  // be profitable to speculatively sink the stores into one merged store at the
  // end, and predicate the merged store on the union of the two conditions of
  // PBI and QBI.
  //
  // This can reduce the number of stores executed if both of the conditions are
  // true, and can allow the blocks to become small enough to be if-converted.
  // This optimization will also chain, so that ladders of test-and-set
  // sequences can be if-converted away.
  //
  // We only deal with simple diamonds or triangles:
  //
  //     PBI       or      PBI        or a combination of the two
  //    /   \               | \
  //   PTB  PFB             |  PFB
  //    \   /               | /
  //     QBI                QBI
  //    /  \                | \
  //   QTB  QFB             |  QFB
  //    \  /                | /
  //    PostBB            PostBB
  //
  // We model triangles as a type of diamond with a nullptr "true" block.
  // Triangles are canonicalized so that the fallthrough edge is represented by
  // a true condition, as in the diagram above.
  BasicBlock *PTB = PBI->getSuccessor(0);
  BasicBlock *PFB = PBI->getSuccessor(1);
  BasicBlock *QTB = QBI->getSuccessor(0);
  BasicBlock *QFB = QBI->getSuccessor(1);
  BasicBlock *PostBB = QFB->getSingleSuccessor();

  // Make sure we have a good guess for PostBB. If QTB's only successor is
  // QFB, then QFB is a better PostBB.
  if (QTB->getSingleSuccessor() == QFB)
    PostBB = QFB;

  // If we couldn't find a good PostBB, stop.
  if (!PostBB)
    return false;

  bool InvertPCond = false, InvertQCond = false;
  // Canonicalize fallthroughs to the true branches.
  if (PFB == QBI->getParent()) {
    std::swap(PFB, PTB);
    InvertPCond = true;
  }
  if (QFB == PostBB) {
    std::swap(QFB, QTB);
    InvertQCond = true;
  }

  // From this point on we can assume PTB or QTB may be fallthroughs but PFB
  // and QFB may not. Model fallthroughs as a nullptr block.
  if (PTB == QBI->getParent())
    PTB = nullptr;
  if (QTB == PostBB)
    QTB = nullptr;

  // Legality bailouts. We must have at least the non-fallthrough blocks and
  // the post-dominating block, and the non-fallthroughs must only have one
  // predecessor.
  auto HasOnePredAndOneSucc = [](BasicBlock *BB, BasicBlock *P, BasicBlock *S) {
    return BB->getSinglePredecessor() == P && BB->getSingleSuccessor() == S;
  };
  if (!HasOnePredAndOneSucc(PFB, PBI->getParent(), QBI->getParent()) ||
      !HasOnePredAndOneSucc(QFB, QBI->getParent(), PostBB))
    return false;
  if ((PTB && !HasOnePredAndOneSucc(PTB, PBI->getParent(), QBI->getParent())) ||
      (QTB && !HasOnePredAndOneSucc(QTB, QBI->getParent(), PostBB)))
    return false;
  if (!QBI->getParent()->hasNUses(2))
    return false;

  // OK, this is a sequence of two diamonds or triangles.
  // Check if there are stores in PTB or PFB that are repeated in QTB or QFB.
  SmallPtrSet<Value *, 4> PStoreAddresses, QStoreAddresses;
  for (auto *BB : {PTB, PFB}) {
    if (!BB)
      continue;
    for (auto &I : *BB)
      if (StoreInst *SI = dyn_cast<StoreInst>(&I))
        PStoreAddresses.insert(SI->getPointerOperand());
  }
  for (auto *BB : {QTB, QFB}) {
    if (!BB)
      continue;
    for (auto &I : *BB)
      if (StoreInst *SI = dyn_cast<StoreInst>(&I))
        QStoreAddresses.insert(SI->getPointerOperand());
  }

  set_intersect(PStoreAddresses, QStoreAddresses);
  // set_intersect mutates PStoreAddresses in place. Rename it here to make it
  // clear what it contains.
  auto &CommonAddresses = PStoreAddresses;

  bool Changed = false;
  for (auto *Address : CommonAddresses)
    Changed |=
        mergeConditionalStoreToAddress(PTB, PFB, QTB, QFB, PostBB, Address,
                                       InvertPCond, InvertQCond, DTU, DL, TTI);
  return Changed;
}

/// If the previous block ended with a widenable branch, determine if reusing
/// the target block is profitable and legal.  This will have the effect of
/// "widening" PBI, but doesn't require us to reason about hosting safety.
static bool tryWidenCondBranchToCondBranch(CondBrInst *PBI, CondBrInst *BI,
                                           DomTreeUpdater *DTU) {
  // TODO: This can be generalized in two important ways:
  // 1) We can allow phi nodes in IfFalseBB and simply reuse all the input
  //    values from the PBI edge.
  // 2) We can sink side effecting instructions into BI's fallthrough
  //    successor provided they doesn't contribute to computation of
  //    BI's condition.
  BasicBlock *IfTrueBB = PBI->getSuccessor(0);
  BasicBlock *IfFalseBB = PBI->getSuccessor(1);
  if (!isWidenableBranch(PBI) || IfTrueBB != BI->getParent() ||
      !BI->getParent()->getSinglePredecessor())
    return false;
  if (!IfFalseBB->phis().empty())
    return false; // TODO
  // This helps avoid infinite loop with SimplifyCondBranchToCondBranch which
  // may undo the transform done here.
  // TODO: There might be a more fine-grained solution to this.
  if (!llvm::succ_empty(IfFalseBB))
    return false;
  // Use lambda to lazily compute expensive condition after cheap ones.
  auto NoSideEffects = [](BasicBlock &BB) {
    return llvm::none_of(BB, [](const Instruction &I) {
        return I.mayWriteToMemory() || I.mayHaveSideEffects();
      });
  };
  if (BI->getSuccessor(1) != IfFalseBB && // no inf looping
      BI->getSuccessor(1)->getTerminatingDeoptimizeCall() && // profitability
      NoSideEffects(*BI->getParent())) {
    auto *OldSuccessor = BI->getSuccessor(1);
    OldSuccessor->removePredecessor(BI->getParent());
    BI->setSuccessor(1, IfFalseBB);
    if (DTU)
      DTU->applyUpdates(
          {{DominatorTree::Insert, BI->getParent(), IfFalseBB},
           {DominatorTree::Delete, BI->getParent(), OldSuccessor}});
    return true;
  }
  if (BI->getSuccessor(0) != IfFalseBB && // no inf looping
      BI->getSuccessor(0)->getTerminatingDeoptimizeCall() && // profitability
      NoSideEffects(*BI->getParent())) {
    auto *OldSuccessor = BI->getSuccessor(0);
    OldSuccessor->removePredecessor(BI->getParent());
    BI->setSuccessor(0, IfFalseBB);
    if (DTU)
      DTU->applyUpdates(
          {{DominatorTree::Insert, BI->getParent(), IfFalseBB},
           {DominatorTree::Delete, BI->getParent(), OldSuccessor}});
    return true;
  }
  return false;
}

/// If we have a conditional branch as a predecessor of another block,
/// this function tries to simplify it.  We know
/// that PBI and BI are both conditional branches, and BI is in one of the
/// successor blocks of PBI - PBI branches to BI.
static bool SimplifyCondBranchToCondBranch(CondBrInst *PBI, CondBrInst *BI,
                                           DomTreeUpdater *DTU,
                                           const DataLayout &DL,
                                           const TargetTransformInfo &TTI) {
  BasicBlock *BB = BI->getParent();

  // If this block ends with a branch instruction, and if there is a
  // predecessor that ends on a branch of the same condition, make
  // this conditional branch redundant.
  if (PBI->getCondition() == BI->getCondition() &&
      PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
    // Okay, the outcome of this conditional branch is statically
    // knowable.  If this block had a single pred, handle specially, otherwise
    // foldCondBranchOnValueKnownInPredecessor() will handle it.
    if (BB->getSinglePredecessor()) {
      // Turn this into a branch on constant.
      bool CondIsTrue = PBI->getSuccessor(0) == BB;
      BI->setCondition(
          ConstantInt::get(Type::getInt1Ty(BB->getContext()), CondIsTrue));
      return true; // Nuke the branch on constant.
    }
  }

  // If the previous block ended with a widenable branch, determine if reusing
  // the target block is profitable and legal.  This will have the effect of
  // "widening" PBI, but doesn't require us to reason about hosting safety.
  if (tryWidenCondBranchToCondBranch(PBI, BI, DTU))
    return true;

  // If both branches are conditional and both contain stores to the same
  // address, remove the stores from the conditionals and create a conditional
  // merged store at the end.
  if (MergeCondStores && mergeConditionalStores(PBI, BI, DTU, DL, TTI))
    return true;

  // If this is a conditional branch in an empty block, and if any
  // predecessors are a conditional branch to one of our destinations,
  // fold the conditions into logical ops and one cond br.

  // Ignore dbg intrinsics.
  if (&*BB->begin() != BI)
    return false;

  int PBIOp, BIOp;
  if (PBI->getSuccessor(0) == BI->getSuccessor(0)) {
    PBIOp = 0;
    BIOp = 0;
  } else if (PBI->getSuccessor(0) == BI->getSuccessor(1)) {
    PBIOp = 0;
    BIOp = 1;
  } else if (PBI->getSuccessor(1) == BI->getSuccessor(0)) {
    PBIOp = 1;
    BIOp = 0;
  } else if (PBI->getSuccessor(1) == BI->getSuccessor(1)) {
    PBIOp = 1;
    BIOp = 1;
  } else {
    return false;
  }

  // Check to make sure that the other destination of this branch
  // isn't BB itself.  If so, this is an infinite loop that will
  // keep getting unwound.
  if (PBI->getSuccessor(PBIOp) == BB)
    return false;

  // If predecessor's branch probability to BB is too low don't merge branches.
  SmallVector<uint32_t, 2> PredWeights;
  if (!PBI->getMetadata(LLVMContext::MD_unpredictable) &&
      extractBranchWeights(*PBI, PredWeights) &&
      (static_cast<uint64_t>(PredWeights[0]) + PredWeights[1]) != 0) {

    BranchProbability CommonDestProb = BranchProbability::getBranchProbability(
        PredWeights[PBIOp],
        static_cast<uint64_t>(PredWeights[0]) + PredWeights[1]);

    BranchProbability Likely = TTI.getPredictableBranchThreshold();
    if (CommonDestProb >= Likely)
      return false;
  }

  // Do not perform this transformation if it would require
  // insertion of a large number of select instructions. For targets
  // without predication/cmovs, this is a big pessimization.

  BasicBlock *CommonDest = PBI->getSuccessor(PBIOp);
  BasicBlock *RemovedDest = PBI->getSuccessor(PBIOp ^ 1);
  unsigned NumPhis = 0;
  for (BasicBlock::iterator II = CommonDest->begin(); isa<PHINode>(II);
       ++II, ++NumPhis) {
    if (NumPhis > 2) // Disable this xform.
      return false;
  }

  // Finally, if everything is ok, fold the branches to logical ops.
  BasicBlock *OtherDest = BI->getSuccessor(BIOp ^ 1);

  LLVM_DEBUG(dbgs() << "FOLDING BRs:" << *PBI->getParent()
                    << "AND: " << *BI->getParent());

  SmallVector<DominatorTree::UpdateType, 5> Updates;

  // If OtherDest *is* BB, then BB is a basic block with a single conditional
  // branch in it, where one edge (OtherDest) goes back to itself but the other
  // exits.  We don't *know* that the program avoids the infinite loop
  // (even though that seems likely).  If we do this xform naively, we'll end up
  // recursively unpeeling the loop.  Since we know that (after the xform is
  // done) that the block *is* infinite if reached, we just make it an obviously
  // infinite loop with no cond branch.
  if (OtherDest == BB) {
    // Insert it at the end of the function, because it's either code,
    // or it won't matter if it's hot. :)
    BasicBlock *InfLoopBlock =
        BasicBlock::Create(BB->getContext(), "infloop", BB->getParent());
    UncondBrInst::Create(InfLoopBlock, InfLoopBlock);
    if (DTU)
      Updates.push_back({DominatorTree::Insert, InfLoopBlock, InfLoopBlock});
    OtherDest = InfLoopBlock;
  }

  LLVM_DEBUG(dbgs() << *PBI->getParent()->getParent());

  // BI may have other predecessors.  Because of this, we leave
  // it alone, but modify PBI.

  // Make sure we get to CommonDest on True&True directions.
  Value *PBICond = PBI->getCondition();
  IRBuilder<NoFolder> Builder(PBI);
  if (PBIOp)
    PBICond = Builder.CreateNot(PBICond, PBICond->getName() + ".not");

  Value *BICond = BI->getCondition();
  if (BIOp)
    BICond = Builder.CreateNot(BICond, BICond->getName() + ".not");

  // Merge the conditions.
  Value *Cond =
      createLogicalOp(Builder, Instruction::Or, PBICond, BICond, "brmerge");

  // Modify PBI to branch on the new condition to the new dests.
  PBI->setCondition(Cond);
  PBI->setSuccessor(0, CommonDest);
  PBI->setSuccessor(1, OtherDest);

  if (DTU) {
    Updates.push_back({DominatorTree::Insert, PBI->getParent(), OtherDest});
    Updates.push_back({DominatorTree::Delete, PBI->getParent(), RemovedDest});

    DTU->applyUpdates(Updates);
  }

  // Update branch weight for PBI.
  uint64_t PredTrueWeight, PredFalseWeight, SuccTrueWeight, SuccFalseWeight;
  uint64_t PredCommon, PredOther, SuccCommon, SuccOther;
  bool HasWeights =
      extractPredSuccWeights(PBI, BI, PredTrueWeight, PredFalseWeight,
                             SuccTrueWeight, SuccFalseWeight);
  if (HasWeights) {
    PredCommon = PBIOp ? PredFalseWeight : PredTrueWeight;
    PredOther = PBIOp ? PredTrueWeight : PredFalseWeight;
    SuccCommon = BIOp ? SuccFalseWeight : SuccTrueWeight;
    SuccOther = BIOp ? SuccTrueWeight : SuccFalseWeight;
    // The weight to CommonDest should be PredCommon * SuccTotal +
    //                                    PredOther * SuccCommon.
    // The weight to OtherDest should be PredOther * SuccOther.
    uint64_t NewWeights[2] = {PredCommon * (SuccCommon + SuccOther) +
                                  PredOther * SuccCommon,
                              PredOther * SuccOther};

    setFittedBranchWeights(*PBI, NewWeights, /*IsExpected=*/false,
                           /*ElideAllZero=*/true);
    // Cond may be a select instruction with the first operand set to "true", or
    // the second to "false" (see how createLogicalOp works for `and` and `or`)
    if (auto *SI = dyn_cast<SelectInst>(Cond)) {
      assert(isSelectInRoleOfConjunctionOrDisjunction(SI));
      // The select is predicated on PBICond
      assert(SI->getCondition() == PBICond);
      // The corresponding probabilities are what was referred to above as
      // PredCommon and PredOther.
      setFittedBranchWeights(*SI, {PredCommon, PredOther},
                             /*IsExpected=*/false, /*ElideAllZero=*/true);
    }
  }

  // OtherDest may have phi nodes.  If so, add an entry from PBI's
  // block that are identical to the entries for BI's block.
  addPredecessorToBlock(OtherDest, PBI->getParent(), BB);

  // We know that the CommonDest already had an edge from PBI to
  // it.  If it has PHIs though, the PHIs may have different
  // entries for BB and PBI's BB.  If so, insert a select to make
  // them agree.
  for (PHINode &PN : CommonDest->phis()) {
    Value *BIV = PN.getIncomingValueForBlock(BB);
    unsigned PBBIdx = PN.getBasicBlockIndex(PBI->getParent());
    Value *PBIV = PN.getIncomingValue(PBBIdx);
    if (BIV != PBIV) {
      // Insert a select in PBI to pick the right value.
      SelectInst *NV = cast<SelectInst>(
          Builder.CreateSelect(PBICond, PBIV, BIV, PBIV->getName() + ".mux"));
      PN.setIncomingValue(PBBIdx, NV);
      // The select has the same condition as PBI, in the same BB. The
      // probabilities don't change.
      if (HasWeights) {
        uint64_t TrueWeight = PBIOp ? PredFalseWeight : PredTrueWeight;
        uint64_t FalseWeight = PBIOp ? PredTrueWeight : PredFalseWeight;
        setFittedBranchWeights(*NV, {TrueWeight, FalseWeight},
                               /*IsExpected=*/false, /*ElideAllZero=*/true);
      }
    }
  }

  LLVM_DEBUG(dbgs() << "INTO: " << *PBI->getParent());
  LLVM_DEBUG(dbgs() << *PBI->getParent()->getParent());

  // This basic block is probably dead.  We know it has at least
  // one fewer predecessor.
  return true;
}

// Simplifies a terminator by replacing it with a branch to TrueBB if Cond is
// true or to FalseBB if Cond is false.
// Takes care of updating the successors and removing the old terminator.
// Also makes sure not to introduce new successors by assuming that edges to
// non-successor TrueBBs and FalseBBs aren't reachable.
bool SimplifyCFGOpt::simplifyTerminatorOnSelect(Instruction *OldTerm,
                                                Value *Cond, BasicBlock *TrueBB,
                                                BasicBlock *FalseBB,
                                                uint32_t TrueWeight,
                                                uint32_t FalseWeight) {
  auto *BB = OldTerm->getParent();
  // Remove any superfluous successor edges from the CFG.
  // First, figure out which successors to preserve.
  // If TrueBB and FalseBB are equal, only try to preserve one copy of that
  // successor.
  BasicBlock *KeepEdge1 = TrueBB;
  BasicBlock *KeepEdge2 = TrueBB != FalseBB ? FalseBB : nullptr;

  SmallSetVector<BasicBlock *, 2> RemovedSuccessors;

  // Then remove the rest.
  for (BasicBlock *Succ : successors(OldTerm)) {
    // Make sure only to keep exactly one copy of each edge.
    if (Succ == KeepEdge1)
      KeepEdge1 = nullptr;
    else if (Succ == KeepEdge2)
      KeepEdge2 = nullptr;
    else {
      Succ->removePredecessor(BB,
                              /*KeepOneInputPHIs=*/true);

      if (Succ != TrueBB && Succ != FalseBB)
        RemovedSuccessors.insert(Succ);
    }
  }

  IRBuilder<> Builder(OldTerm);
  Builder.SetCurrentDebugLocation(OldTerm->getDebugLoc());

  // Insert an appropriate new terminator.
  if (!KeepEdge1 && !KeepEdge2) {
    if (TrueBB == FalseBB) {
      // We were only looking for one successor, and it was present.
      // Create an unconditional branch to it.
      Builder.CreateBr(TrueBB);
    } else {
      // We found both of the successors we were looking for.
      // Create a conditional branch sharing the condition of the select.
      CondBrInst *NewBI = Builder.CreateCondBr(Cond, TrueBB, FalseBB);
      setBranchWeights(*NewBI, {TrueWeight, FalseWeight},
                       /*IsExpected=*/false, /*ElideAllZero=*/true);
    }
  } else if (KeepEdge1 && (KeepEdge2 || TrueBB == FalseBB)) {
    // Neither of the selected blocks were successors, so this
    // terminator must be unreachable.
    new UnreachableInst(OldTerm->getContext(), OldTerm->getIterator());
  } else {
    // One of the selected values was a successor, but the other wasn't.
    // Insert an unconditional branch to the one that was found;
    // the edge to the one that wasn't must be unreachable.
    if (!KeepEdge1) {
      // Only TrueBB was found.
      Builder.CreateBr(TrueBB);
    } else {
      // Only FalseBB was found.
      Builder.CreateBr(FalseBB);
    }
  }

  eraseTerminatorAndDCECond(OldTerm);

  if (DTU) {
    SmallVector<DominatorTree::UpdateType, 2> Updates;
    Updates.reserve(RemovedSuccessors.size());
    for (auto *RemovedSuccessor : RemovedSuccessors)
      Updates.push_back({DominatorTree::Delete, BB, RemovedSuccessor});
    DTU->applyUpdates(Updates);
  }

  return true;
}

// Folds switch(select(icmp eq X, C, K, X)) into switch(X), retargeting
// (or adding) the case for C to wherever K currently dispatches to:
//   %cmp = icmp eq T %x, C
//   %key = select i1 %cmp, T K, T %x
//   switch T %key, label %default [ T K, label %case_k ... ]
// becomes
//   switch T %x, label %default [ T C, label %case_k
//                                  T K, label %case_k ... ]
bool SimplifyCFGOpt::simplifySwitchOnSelectRemap(SwitchInst *SI,
                                                 SelectInst *Select, Value *X,
                                                 ConstantInt *C, bool Negate) {
  Value *TrueVal = Select->getTrueValue();
  Value *FalseVal = Select->getFalseValue();
  if (Negate)
    std::swap(TrueVal, FalseVal);
  if (FalseVal != X)
    return false;
  auto *K = dyn_cast<ConstantInt>(TrueVal);
  if (!K)
    return false;

  BasicBlock *DestFork = SI->findCaseValue(K)->getCaseSuccessor();
  auto CaseC = SI->findCaseValue(C);
  bool IsDefault = CaseC == SI->case_default();
  // Save before setSuccessor()/addCase() change it.
  BasicBlock *OldDest = CaseC->getCaseSuccessor();
  BasicBlock *BB = SI->getParent();

  // Switch on X first: removePredecessor() below may fold X away if it is a
  // PHI in OldDest, and the RAUW must update the switch condition too.
  SI->setCondition(X);

  if (OldDest != DestFork) {
    if (!IsDefault)
      OldDest->removePredecessor(BB);
    if (IsDefault)
      SI->addCase(C, DestFork);
    else
      CaseC->setSuccessor(DestFork);
    // Not a new edge (BB->DestFork exists via K), just adding the PHI
    // entry.
    addPredecessorToBlock(DestFork, BB, BB);

    if (!IsDefault) {
      // Edge to OldDest is gone only if nothing else still uses it.
      bool OldDestStillTargeted = any_of(
          successors(SI), [&](BasicBlock *Succ) { return Succ == OldDest; });
      if (DTU && !OldDestStillTargeted)
        DTU->applyUpdates({{DominatorTree::Delete, BB, OldDest}});
    }

    // Update the profile information on the switch if we had a profile
    // for both it and the select instruction.
    SmallVector<uint32_t> SwitchWeights;
    bool SwitchHasBranchWeights = extractBranchWeights(*SI, SwitchWeights);
    // If we add a case, ensure the length of the branch weights list matches
    // to make iterating over them easier later.
    if (IsDefault)
      SwitchWeights.push_back(0);
    uint64_t SelectTrueWeight;
    uint64_t SelectFalseWeight;
    bool SelectHasBranchWeights =
        extractBranchWeights(*Select, SelectTrueWeight, SelectFalseWeight);
    uint64_t SelectTotalWeight = SelectTrueWeight + SelectFalseWeight;
    if (Negate)
      std::swap(SelectTrueWeight, SelectFalseWeight);
    if (SwitchHasBranchWeights && SelectHasBranchWeights &&
        !ProfcheckDisableMetadataFixes) {
      // We update the branch weights by subtracting P(x=C) from the probability
      // of case K in the switch (what C redirect to before the transformation),
      // plugging the probability for case C into the switch (which we derive
      // from the select), and ensuring everything is scaled to have a common
      // denominator.
      uint64_t SwitchTotalWeight = sum_of(SwitchWeights, uint64_t{0});
      SmallVector<uint64_t> NewSwitchWeights;
      NewSwitchWeights.reserve(SwitchWeights.size());
      NewSwitchWeights.push_back(SwitchWeights[0] * SelectTotalWeight);
      for (const auto &[SwitchCase, SwitchWeight] :
           zip(SI->cases(), drop_begin(SwitchWeights))) {
        if (SwitchCase.getCaseValue() == C) {
          NewSwitchWeights.push_back(SwitchTotalWeight * SelectTrueWeight);
        } else if (SwitchCase.getCaseValue() == K) {
          // In reality, P(key=K) > P(x=C) should always hold, but explicitly
          // guard against bad profiles here to prevent underflow by saturating
          // to zero.
          uint64_t ProbabilityKeyEqualsK = SwitchWeight * SelectTotalWeight;
          uint64_t ProbabilityXEqualsC = SelectTrueWeight * SwitchTotalWeight;
          uint64_t ProbabilityXEqualsK =
              ProbabilityKeyEqualsK > ProbabilityXEqualsC
                  ? ProbabilityKeyEqualsK - ProbabilityXEqualsC
                  : 0;
          NewSwitchWeights.push_back(ProbabilityXEqualsK);
        } else {
          NewSwitchWeights.push_back(SwitchWeight * SelectTotalWeight);
        }
      }
      setFittedBranchWeights(*SI, NewSwitchWeights, /*IsExpected=*/false);
    } else if (SwitchHasBranchWeights) {
      // If we only have branch weights on the switch, we cannot reconstruct
      // branch weights correctly, so mark them as unknown if the function has
      // a profile count. Reset the branch weights first to ensure we remove
      // the now invalid branch weights if the function is not otherwise
      // profiled.
      SI->setMetadata(LLVMContext::MD_prof, nullptr);
      setExplicitlyUnknownBranchWeightsIfProfiled(*SI, DEBUG_TYPE);
    }
  }

  // The compare/select are now dead.
  RecursivelyDeleteTriviallyDeadInstructions(Select);
  return true;
}

// Replaces
//   (switch (select cond, X, Y)) on constant X, Y
// with a branch - conditional if X and Y lead to distinct BBs,
// unconditional otherwise.
bool SimplifyCFGOpt::simplifySwitchOnSelect(SwitchInst *SI,
                                            SelectInst *Select) {
  CmpPredicate Pred;
  Value *X;
  ConstantInt *C;
  if (Select->hasOneUse() &&
      match(Select->getCondition(),
            m_ICmp(Pred, m_Value(X), m_ConstantInt(C))) &&
      ICmpInst::isEquality(Pred) &&
      simplifySwitchOnSelectRemap(SI, Select, X, C, Pred == ICmpInst::ICMP_NE))
    return true;

  // Check for constant integer values in the select.
  ConstantInt *TrueVal = dyn_cast<ConstantInt>(Select->getTrueValue());
  ConstantInt *FalseVal = dyn_cast<ConstantInt>(Select->getFalseValue());
  if (!TrueVal || !FalseVal)
    return false;

  // Find the relevant condition and destinations.
  Value *Condition = Select->getCondition();
  BasicBlock *TrueBB = SI->findCaseValue(TrueVal)->getCaseSuccessor();
  BasicBlock *FalseBB = SI->findCaseValue(FalseVal)->getCaseSuccessor();

  // Get weight for TrueBB and FalseBB.
  uint32_t TrueWeight = 0, FalseWeight = 0;
  SmallVector<uint64_t, 8> Weights;
  bool HasWeights = hasBranchWeightMD(*SI);
  if (HasWeights) {
    getBranchWeights(SI, Weights);
    if (Weights.size() == 1 + SI->getNumCases()) {
      TrueWeight =
          (uint32_t)Weights[SI->findCaseValue(TrueVal)->getSuccessorIndex()];
      FalseWeight =
          (uint32_t)Weights[SI->findCaseValue(FalseVal)->getSuccessorIndex()];
    }
  }

  // Perform the actual simplification.
  return simplifyTerminatorOnSelect(SI, Condition, TrueBB, FalseBB, TrueWeight,
                                    FalseWeight);
}

// Replaces
//   (indirectbr (select cond, blockaddress(@fn, BlockA),
//                             blockaddress(@fn, BlockB)))
// with
//   (br cond, BlockA, BlockB).
bool SimplifyCFGOpt::simplifyIndirectBrOnSelect(IndirectBrInst *IBI,
                                                SelectInst *SI) {
  // Check that both operands of the select are block addresses.
  BlockAddress *TBA = dyn_cast<BlockAddress>(SI->getTrueValue());
  BlockAddress *FBA = dyn_cast<BlockAddress>(SI->getFalseValue());
  if (!TBA || !FBA)
    return false;

  // Extract the actual blocks.
  BasicBlock *TrueBB = TBA->getBasicBlock();
  BasicBlock *FalseBB = FBA->getBasicBlock();

  // The select's profile becomes the profile of the conditional branch that
  // replaces the indirect branch.
  SmallVector<uint32_t> SelectBranchWeights(2);
  extractBranchWeights(*SI, SelectBranchWeights);
  // Perform the actual simplification.
  return simplifyTerminatorOnSelect(IBI, SI->getCondition(), TrueBB, FalseBB,
                                    SelectBranchWeights[0],
                                    SelectBranchWeights[1]);
}

/// This is called when we find an icmp instruction
/// (a seteq/setne with a constant) as the only instruction in a
/// block that ends with an uncond branch.  We are looking for a very specific
/// pattern that occurs when "A == 1 || A == 2 || A == 3" gets simplified.  In
/// this case, we merge the first two "or's of icmp" into a switch, but then the
/// default value goes to an uncond block with a seteq in it, we get something
/// like:
///
///   switch i8 %A, label %DEFAULT [ i8 1, label %end    i8 2, label %end ]
/// DEFAULT:
///   %tmp = icmp eq i8 %A, 92
///   br label %end
/// end:
///   ... = phi i1 [ true, %entry ], [ %tmp, %DEFAULT ], [ true, %entry ]
///
/// We prefer to split the edge to 'end' so that there is a true/false entry to
/// the PHI, merging the third icmp into the switch.
bool SimplifyCFGOpt::tryToSimplifyUncondBranchWithICmpInIt(
    ICmpInst *ICI, IRBuilder<> &Builder) {
  // Select == nullptr means we assume that there is a hidden no-op select
  // instruction of `_ = select %icmp, true, false` after `%icmp = icmp ...`
  return tryToSimplifyUncondBranchWithICmpSelectInIt(ICI, nullptr, Builder);
}

/// Similar to tryToSimplifyUncondBranchWithICmpInIt, but handle a more generic
/// case. This is called when we find an icmp instruction (a seteq/setne with a
/// constant) and its following select instruction as the only TWO instructions
/// in a block that ends with an uncond branch.  We are looking for a very
/// specific pattern that occurs when "
///    if (A == 1) return C1;
///    if (A == 2) return C2;
///    if (A < 3) return C3;
///    return C4;
/// " gets simplified.  In this case, we merge the first two "branches of icmp"
/// into a switch, but then the default value goes to an uncond block with a lt
/// icmp and select in it, as InstCombine can not simplify "A < 3" as "A == 2".
/// After SimplifyCFG and other subsequent optimizations (e.g., SCCP), we might
/// get something like:
///
/// case1:
///   switch i8 %A, label %DEFAULT [ i8 0, label %end    i8 1, label %case2 ]
/// case2:
///   br label %end
/// DEFAULT:
///   %tmp = icmp eq i8 %A, 2
///   %val = select i1 %tmp, i8 C3, i8 C4
///   br label %end
/// end:
///   _ = phi i8 [ C1, %case1 ], [ C2, %case2 ], [ %val, %DEFAULT ]
///
/// We prefer to split the edge to 'end' so that there are TWO entries of V3/V4
/// to the PHI, merging the icmp & select into the switch, as follows:
///
/// case1:
///   switch i8 %A, label %DEFAULT [
///     i8 0, label %end
///     i8 1, label %case2
///     i8 2, label %case3
///   ]
/// case2:
///   br label %end
/// case3:
///   br label %end
/// DEFAULT:
///   br label %end
/// end:
///   _ = phi i8 [ C1, %case1 ], [ C2, %case2 ], [ C3, %case2 ], [ C4, %DEFAULT]
bool SimplifyCFGOpt::tryToSimplifyUncondBranchWithICmpSelectInIt(
    ICmpInst *ICI, SelectInst *Select, IRBuilder<> &Builder) {
  BasicBlock *BB = ICI->getParent();

  // If the block has any PHIs in it or the icmp/select has multiple uses, it is
  // too complex.
  /// TODO: support multi-phis in succ BB of select's BB.
  if (isa<PHINode>(BB->begin()) || !ICI->hasOneUse() ||
      (Select && !Select->hasOneUse()))
    return false;

  // The pattern we're looking for is where our only predecessor is a switch on
  // 'V' and this block is the default case for the switch.  In this case we can
  // fold the compared value into the switch to simplify things.
  BasicBlock *Pred = BB->getSinglePredecessor();
  if (!Pred || !isa<SwitchInst>(Pred->getTerminator()))
    return false;

  Value *IcmpCond;
  ConstantInt *NewCaseVal;
  CmpPredicate Predicate;

  // Match icmp X, C
  if (!match(ICI,
             m_ICmp(Predicate, m_Value(IcmpCond), m_ConstantInt(NewCaseVal))))
    return false;

  Value *SelectCond, *SelectTrueVal, *SelectFalseVal;
  Instruction *User;
  if (!Select) {
    // If Select == nullptr, we can assume that there is a hidden no-op select
    // just after icmp
    SelectCond = ICI;
    SelectTrueVal = Builder.getTrue();
    SelectFalseVal = Builder.getFalse();
    User = ICI->user_back();
  } else {
    SelectCond = Select->getCondition();
    // Check if the select condition is the same as the icmp condition.
    if (SelectCond != ICI)
      return false;
    SelectTrueVal = Select->getTrueValue();
    SelectFalseVal = Select->getFalseValue();
    User = Select->user_back();
  }

  SwitchInst *SI = cast<SwitchInst>(Pred->getTerminator());
  if (SI->getCondition() != IcmpCond)
    return false;

  // If BB is reachable on a non-default case, then we simply know the value of
  // V in this block.  Substitute it and constant fold the icmp instruction
  // away.
  if (SI->getDefaultDest() != BB) {
    ConstantInt *VVal = SI->findCaseDest(BB);
    assert(VVal && "Should have a unique destination value");
    ICI->setOperand(0, VVal);

    if (Value *V = simplifyInstruction(ICI, {DL, ICI})) {
      ICI->replaceAllUsesWith(V);
      ICI->eraseFromParent();
    }
    // BB is now empty, so it is likely to simplify away.
    return requestResimplify();
  }

  // Ok, the block is reachable from the default dest.  If the constant we're
  // comparing exists in one of the other edges, then we can constant fold ICI
  // and zap it.
  if (SI->findCaseValue(NewCaseVal) != SI->case_default()) {
    Value *V;
    if (Predicate == ICmpInst::ICMP_EQ)
      V = ConstantInt::getFalse(BB->getContext());
    else
      V = ConstantInt::getTrue(BB->getContext());

    ICI->replaceAllUsesWith(V);
    ICI->eraseFromParent();
    // BB is now empty, so it is likely to simplify away.
    return requestResimplify();
  }

  // The use of the select has to be in the 'end' block, by the only PHI node in
  // the block.
  BasicBlock *SuccBlock = BB->getTerminator()->getSuccessor(0);
  PHINode *PHIUse = dyn_cast<PHINode>(User);
  if (PHIUse == nullptr || PHIUse != &SuccBlock->front() ||
      isa<PHINode>(++BasicBlock::iterator(PHIUse)))
    return false;

  // If the icmp is a SETEQ, then the default dest gets SelectFalseVal, the new
  // edge gets SelectTrueVal in the PHI.
  Value *DefaultCst = SelectFalseVal;
  Value *NewCst = SelectTrueVal;

  if (ICI->getPredicate() == ICmpInst::ICMP_NE)
    std::swap(DefaultCst, NewCst);

  // Replace Select (which is used by the PHI for the default value) with
  // SelectFalseVal or SelectTrueVal depending on if ICI is EQ or NE.
  if (Select) {
    Select->replaceAllUsesWith(DefaultCst);
    Select->eraseFromParent();
  } else {
    ICI->replaceAllUsesWith(DefaultCst);
  }
  ICI->eraseFromParent();

  SmallVector<DominatorTree::UpdateType, 2> Updates;

  // Okay, the switch goes to this block on a default value.  Add an edge from
  // the switch to the merge point on the compared value.
  BasicBlock *NewBB =
      BasicBlock::Create(BB->getContext(), "switch.edge", BB->getParent(), BB);
  {
    SwitchInstProfUpdateWrapper SIW(*SI);
    auto W0 = SIW.getSuccessorWeight(0);
    SwitchInstProfUpdateWrapper::CaseWeightOpt NewW;
    if (W0) {
      NewW = ((uint64_t(*W0) + 1) >> 1);
      SIW.setSuccessorWeight(0, *NewW);
    }
    SIW.addCase(NewCaseVal, NewBB, NewW);
    if (DTU)
      Updates.push_back({DominatorTree::Insert, Pred, NewBB});
  }

  // NewBB branches to the phi block, add the uncond branch and the phi entry.
  Builder.SetInsertPoint(NewBB);
  Builder.SetCurrentDebugLocation(SI->getDebugLoc());
  Builder.CreateBr(SuccBlock);
  PHIUse->addIncoming(NewCst, NewBB);
  if (DTU) {
    Updates.push_back({DominatorTree::Insert, NewBB, SuccBlock});
    DTU->applyUpdates(Updates);
  }
  return true;
}

/// Check to see if it is branching on an or/and chain of icmp instructions, and
/// fold it into a switch instruction if so.
bool SimplifyCFGOpt::simplifyBranchOnICmpChain(CondBrInst *BI,
                                               IRBuilder<> &Builder,
                                               const DataLayout &DL) {
  Instruction *Cond = dyn_cast<Instruction>(BI->getCondition());
  if (!Cond)
    return false;

  // Change br (X == 0 | X == 1), T, F into a switch instruction.
  // If this is a bunch of seteq's or'd together, or if it's a bunch of
  // 'setne's and'ed together, collect them.

  // Try to gather values from a chain of and/or to be turned into a switch
  ConstantComparesGatherer ConstantCompare(Cond, DL);
  // Unpack the result
  SmallVectorImpl<ConstantInt *> &Values = ConstantCompare.Vals;
  Value *CompVal = ConstantCompare.CompValue;
  unsigned UsedICmps = ConstantCompare.UsedICmps;
  Value *ExtraCase = ConstantCompare.Extra;
  bool TrueWhenEqual = ConstantCompare.IsEq;

  // If we didn't have a multiply compared value, fail.
  if (!CompVal)
    return false;

  // Avoid turning single icmps into a switch.
  if (UsedICmps <= 1)
    return false;

  // There might be duplicate constants in the list, which the switch
  // instruction can't handle, remove them now.
  array_pod_sort(Values.begin(), Values.end(), constantIntSortPredicate);
  Values.erase(llvm::unique(Values), Values.end());

  // If Extra was used, we require at least two switch values to do the
  // transformation.  A switch with one value is just a conditional branch.
  if (ExtraCase && Values.size() < 2)
    return false;

  SmallVector<uint32_t> BranchWeights;
  const bool HasProfile = extractBranchWeights(*BI, BranchWeights);

  // Figure out which block is which destination.
  BasicBlock *DefaultBB = BI->getSuccessor(1);
  BasicBlock *EdgeBB = BI->getSuccessor(0);
  if (!TrueWhenEqual) {
    std::swap(DefaultBB, EdgeBB);
    if (HasProfile)
      std::swap(BranchWeights[0], BranchWeights[1]);
  }

  BasicBlock *BB = BI->getParent();

  LLVM_DEBUG(dbgs() << "Converting 'icmp' chain with " << Values.size()
                    << " cases into SWITCH.  BB is:\n"
                    << *BB);

  SmallVector<DominatorTree::UpdateType, 2> Updates;

  // If there are any extra values that couldn't be folded into the switch
  // then we evaluate them with an explicit branch first. Split the block
  // right before the condbr to handle it.
  if (ExtraCase) {
    BasicBlock *NewBB = SplitBlock(BB, BI, DTU, /*LI=*/nullptr,
                                   /*MSSAU=*/nullptr, "switch.early.test");

    // Remove the uncond branch added to the old block.
    Instruction *OldTI = BB->getTerminator();
    Builder.SetInsertPoint(OldTI);

    // There can be an unintended UB if extra values are Poison. Before the
    // transformation, extra values may not be evaluated according to the
    // condition, and it will not raise UB. But after transformation, we are
    // evaluating extra values before checking the condition, and it will raise
    // UB. It can be solved by adding freeze instruction to extra values.
    AssumptionCache *AC = Options.AC;

    if (!isGuaranteedNotToBeUndefOrPoison(ExtraCase, AC, BI, nullptr))
      ExtraCase = Builder.CreateFreeze(ExtraCase);

    // We don't have any info about this condition.
    auto *Br = TrueWhenEqual ? Builder.CreateCondBr(ExtraCase, EdgeBB, NewBB)
                             : Builder.CreateCondBr(ExtraCase, NewBB, EdgeBB);
    setExplicitlyUnknownBranchWeightsIfProfiled(*Br, DEBUG_TYPE);

    OldTI->eraseFromParent();

    if (DTU)
      Updates.push_back({DominatorTree::Insert, BB, EdgeBB});

    // If there are PHI nodes in EdgeBB, then we need to add a new entry to them
    // for the edge we just added.
    addPredecessorToBlock(EdgeBB, BB, NewBB);

    LLVM_DEBUG(dbgs() << "  ** 'icmp' chain unhandled condition: " << *ExtraCase
                      << "\nEXTRABB = " << *BB);
    BB = NewBB;
  }

  Builder.SetInsertPoint(BI);
  // Convert pointer to int before we switch.
  if (CompVal->getType()->isPointerTy()) {
    assert(!DL.hasUnstableRepresentation(CompVal->getType()) &&
           "Should not end up here with unstable pointers");
    CompVal = Builder.CreatePtrToInt(
        CompVal, DL.getIntPtrType(CompVal->getType()), "magicptr");
  }

  // Check if we can represent the values as a contiguous range. If so, we use a
  // range check + conditional branch instead of a switch.
  if (Values.front()->getValue() - Values.back()->getValue() ==
      Values.size() - 1) {
    ConstantRange RangeToCheck = ConstantRange::getNonEmpty(
        Values.back()->getValue(), Values.front()->getValue() + 1);
    APInt Offset, RHS;
    ICmpInst::Predicate Pred;
    RangeToCheck.getEquivalentICmp(Pred, RHS, Offset);
    Value *X = CompVal;
    if (!Offset.isZero())
      X = Builder.CreateAdd(X, ConstantInt::get(CompVal->getType(), Offset));
    Value *Cond =
        Builder.CreateICmp(Pred, X, ConstantInt::get(CompVal->getType(), RHS));
    CondBrInst *NewBI = Builder.CreateCondBr(Cond, EdgeBB, DefaultBB);
    if (HasProfile)
      setBranchWeights(*NewBI, BranchWeights, /*IsExpected=*/false);
    else
      setExplicitlyUnknownBranchWeightsIfProfiled(*NewBI, DEBUG_TYPE);
    if (MDNode *Unpredictable = BI->getMetadata(LLVMContext::MD_unpredictable))
      NewBI->setMetadata(LLVMContext::MD_unpredictable, Unpredictable);
    // We don't need to update PHI nodes since we don't add any new edges.
  } else {
    // Create the new switch instruction now.
    SwitchInst *New = Builder.CreateSwitch(CompVal, DefaultBB, Values.size());
    if (MDNode *Unpredictable = BI->getMetadata(LLVMContext::MD_unpredictable))
      New->setMetadata(LLVMContext::MD_unpredictable, Unpredictable);
    if (HasProfile) {
      // We know the weight of the default case. We don't know the weight of the
      // other cases, but rather than completely lose profiling info, we split
      // the remaining probability equally over them.
      SmallVector<uint32_t> NewWeights(Values.size() + 1);
      NewWeights[0] = BranchWeights[1]; // this is the default, and we swapped
                                        // if TrueWhenEqual.
      for (auto &V : drop_begin(NewWeights))
        V = BranchWeights[0] / Values.size();
      setBranchWeights(*New, NewWeights, /*IsExpected=*/false);
    } else {
      setExplicitlyUnknownBranchWeightsIfProfiled(*New, DEBUG_TYPE);
    }

    // Add all of the 'cases' to the switch instruction.
    for (ConstantInt *Val : Values)
      New->addCase(Val, EdgeBB);

    // We added edges from PI to the EdgeBB.  As such, if there were any
    // PHI nodes in EdgeBB, they need entries to be added corresponding to
    // the number of edges added.
    for (BasicBlock::iterator BBI = EdgeBB->begin(); isa<PHINode>(BBI); ++BBI) {
      PHINode *PN = cast<PHINode>(BBI);
      Value *InVal = PN->getIncomingValueForBlock(BB);
      for (unsigned i = 0, e = Values.size() - 1; i != e; ++i)
        PN->addIncoming(InVal, BB);
    }
  }

  // Erase the old branch instruction.
  eraseTerminatorAndDCECond(BI);
  if (DTU)
    DTU->applyUpdates(Updates);

  LLVM_DEBUG(dbgs() << "  ** 'icmp' chain result is:\n" << *BB << '\n');
  return true;
}

bool SimplifyCFGOpt::simplifyResume(ResumeInst *RI, IRBuilder<> &Builder) {
  if (isa<PHINode>(RI->getValue()))
    return simplifyCommonResume(RI);
  else if (isa<LandingPadInst>(RI->getParent()->getFirstNonPHIIt()) &&
           RI->getValue() == &*RI->getParent()->getFirstNonPHIIt())
    // The resume must unwind the exception that caused control to branch here.
    return simplifySingleResume(RI);

  return false;
}

// Check if cleanup block is empty
static bool isCleanupBlockEmpty(iterator_range<BasicBlock::iterator> R) {
  for (Instruction &I : R) {
    auto *II = dyn_cast<IntrinsicInst>(&I);
    if (!II || II->getIntrinsicID() != Intrinsic::lifetime_end)
      return false;
  }
  return true;
}

// Simplify resume that is shared by several landing pads (phi of landing pad).
bool SimplifyCFGOpt::simplifyCommonResume(ResumeInst *RI) {
  BasicBlock *BB = RI->getParent();

  // Check that there are no other instructions except for debug and lifetime
  // intrinsics between the phi's and resume instruction.
  if (!isCleanupBlockEmpty(make_range(RI->getParent()->getFirstNonPHIIt(),
                                      BB->getTerminator()->getIterator())))
    return false;

  SmallSetVector<BasicBlock *, 4> TrivialUnwindBlocks;
  auto *PhiLPInst = cast<PHINode>(RI->getValue());

  // Check incoming blocks to see if any of them are trivial.
  for (unsigned Idx = 0, End = PhiLPInst->getNumIncomingValues(); Idx != End;
       Idx++) {
    auto *IncomingBB = PhiLPInst->getIncomingBlock(Idx);
    auto *IncomingValue = PhiLPInst->getIncomingValue(Idx);

    // If the block has other successors, we can not delete it because
    // it has other dependents.
    if (IncomingBB->getUniqueSuccessor() != BB)
      continue;

    auto *LandingPad = dyn_cast<LandingPadInst>(IncomingBB->getFirstNonPHIIt());
    // Not the landing pad that caused the control to branch here.
    if (IncomingValue != LandingPad)
      continue;

    if (isCleanupBlockEmpty(
            make_range(LandingPad->getNextNode(), IncomingBB->getTerminator())))
      TrivialUnwindBlocks.insert(IncomingBB);
  }

  // If no trivial unwind blocks, don't do any simplifications.
  if (TrivialUnwindBlocks.empty())
    return false;

  // Turn all invokes that unwind here into calls.
  for (auto *TrivialBB : TrivialUnwindBlocks) {
    // Blocks that will be simplified should be removed from the phi node.
    // Note there could be multiple edges to the resume block, and we need
    // to remove them all.
    while (PhiLPInst->getBasicBlockIndex(TrivialBB) != -1)
      BB->removePredecessor(TrivialBB, true);

    for (BasicBlock *Pred :
         llvm::make_early_inc_range(predecessors(TrivialBB))) {
      removeUnwindEdge(Pred, DTU);
      ++NumInvokes;
    }

    // In each SimplifyCFG run, only the current processed block can be erased.
    // Otherwise, it will break the iteration of SimplifyCFG pass. So instead
    // of erasing TrivialBB, we only remove the branch to the common resume
    // block so that we can later erase the resume block since it has no
    // predecessors.
    TrivialBB->getTerminator()->eraseFromParent();
    new UnreachableInst(RI->getContext(), TrivialBB);
    if (DTU)
      DTU->applyUpdates({{DominatorTree::Delete, TrivialBB, BB}});
  }

  // Delete the resume block if all its predecessors have been removed.
  if (pred_empty(BB))
    DeleteDeadBlock(BB, DTU);

  return !TrivialUnwindBlocks.empty();
}

// Simplify resume that is only used by a single (non-phi) landing pad.
bool SimplifyCFGOpt::simplifySingleResume(ResumeInst *RI) {
  BasicBlock *BB = RI->getParent();
  auto *LPInst = cast<LandingPadInst>(BB->getFirstNonPHIIt());
  assert(RI->getValue() == LPInst &&
         "Resume must unwind the exception that caused control to here");

  // Check that there are no other instructions except for debug intrinsics.
  if (!isCleanupBlockEmpty(
          make_range<Instruction *>(LPInst->getNextNode(), RI)))
    return false;

  // Turn all invokes that unwind here into calls and delete the basic block.
  for (BasicBlock *Pred : llvm::make_early_inc_range(predecessors(BB))) {
    removeUnwindEdge(Pred, DTU);
    ++NumInvokes;
  }

  // The landingpad is now unreachable.  Zap it.
  DeleteDeadBlock(BB, DTU);
  return true;
}

static bool removeEmptyCleanup(CleanupReturnInst *RI, DomTreeUpdater *DTU) {
  // If this is a trivial cleanup pad that executes no instructions, it can be
  // eliminated.  If the cleanup pad continues to the caller, any predecessor
  // that is an EH pad will be updated to continue to the caller and any
  // predecessor that terminates with an invoke instruction will have its invoke
  // instruction converted to a call instruction.  If the cleanup pad being
  // simplified does not continue to the caller, each predecessor will be
  // updated to continue to the unwind destination of the cleanup pad being
  // simplified.
  BasicBlock *BB = RI->getParent();
  CleanupPadInst *CPInst = RI->getCleanupPad();
  if (CPInst->getParent() != BB)
    // This isn't an empty cleanup.
    return false;

  // We cannot kill the pad if it has multiple uses.  This typically arises
  // from unreachable basic blocks.
  if (!CPInst->hasOneUse())
    return false;

  // Check that there are no other instructions except for benign intrinsics.
  if (!isCleanupBlockEmpty(
          make_range<Instruction *>(CPInst->getNextNode(), RI)))
    return false;

  // If the cleanup return we are simplifying unwinds to the caller, this will
  // set UnwindDest to nullptr.
  BasicBlock *UnwindDest = RI->getUnwindDest();

  // We're about to remove BB from the control flow.  Before we do, sink any
  // PHINodes into the unwind destination.  Doing this before changing the
  // control flow avoids some potentially slow checks, since we can currently
  // be certain that UnwindDest and BB have no common predecessors (since they
  // are both EH pads).
  if (UnwindDest) {
    // First, go through the PHI nodes in UnwindDest and update any nodes that
    // reference the block we are removing
    for (PHINode &DestPN : UnwindDest->phis()) {
      int Idx = DestPN.getBasicBlockIndex(BB);
      // Since BB unwinds to UnwindDest, it has to be in the PHI node.
      assert(Idx != -1);
      // This PHI node has an incoming value that corresponds to a control
      // path through the cleanup pad we are removing.  If the incoming
      // value is in the cleanup pad, it must be a PHINode (because we
      // verified above that the block is otherwise empty).  Otherwise, the
      // value is either a constant or a value that dominates the cleanup
      // pad being removed.
      //
      // Because BB and UnwindDest are both EH pads, all of their
      // predecessors must unwind to these blocks, and since no instruction
      // can have multiple unwind destinations, there will be no overlap in
      // incoming blocks between SrcPN and DestPN.
      Value *SrcVal = DestPN.getIncomingValue(Idx);
      PHINode *SrcPN = dyn_cast<PHINode>(SrcVal);

      bool NeedPHITranslation = SrcPN && SrcPN->getParent() == BB;
      for (auto *Pred : predecessors(BB)) {
        Value *Incoming =
            NeedPHITranslation ? SrcPN->getIncomingValueForBlock(Pred) : SrcVal;
        DestPN.addIncoming(Incoming, Pred);
      }
    }

    // Sink any remaining PHI nodes directly into UnwindDest.
    BasicBlock::iterator InsertPt = UnwindDest->getFirstNonPHIIt();
    for (PHINode &PN : make_early_inc_range(BB->phis())) {
      if (PN.use_empty() || !PN.isUsedOutsideOfBlock(BB))
        // If the PHI node has no uses or all of its uses are in this basic
        // block (meaning they are debug or lifetime intrinsics), just leave
        // it.  It will be erased when we erase BB below.
        continue;

      // Otherwise, sink this PHI node into UnwindDest.
      // Any predecessors to UnwindDest which are not already represented
      // must be back edges which inherit the value from the path through
      // BB.  In this case, the PHI value must reference itself.
      for (auto *pred : predecessors(UnwindDest))
        if (pred != BB)
          PN.addIncoming(&PN, pred);
      PN.moveBefore(InsertPt);
      // Also, add a dummy incoming value for the original BB itself,
      // so that the PHI is well-formed until we drop said predecessor.
      PN.addIncoming(PoisonValue::get(PN.getType()), BB);
    }
  }

  std::vector<DominatorTree::UpdateType> Updates;

  // We use make_early_inc_range here because we will remove all predecessors.
  for (BasicBlock *PredBB : llvm::make_early_inc_range(predecessors(BB))) {
    if (UnwindDest == nullptr) {
      if (DTU) {
        DTU->applyUpdates(Updates);
        Updates.clear();
      }
      removeUnwindEdge(PredBB, DTU);
      ++NumInvokes;
    } else {
      BB->removePredecessor(PredBB);
      Instruction *TI = PredBB->getTerminator();
      TI->replaceUsesOfWith(BB, UnwindDest);
      if (DTU) {
        Updates.push_back({DominatorTree::Insert, PredBB, UnwindDest});
        Updates.push_back({DominatorTree::Delete, PredBB, BB});
      }
    }
  }

  if (DTU)
    DTU->applyUpdates(Updates);

  DeleteDeadBlock(BB, DTU);

  return true;
}

// Try to merge two cleanuppads together.
static bool mergeCleanupPad(CleanupReturnInst *RI) {
  // Skip any cleanuprets which unwind to caller, there is nothing to merge
  // with.
  BasicBlock *UnwindDest = RI->getUnwindDest();
  if (!UnwindDest)
    return false;

  // This cleanupret isn't the only predecessor of this cleanuppad, it wouldn't
  // be safe to merge without code duplication.
  if (UnwindDest->getSinglePredecessor() != RI->getParent())
    return false;

  // Verify that our cleanuppad's unwind destination is another cleanuppad.
  auto *SuccessorCleanupPad = dyn_cast<CleanupPadInst>(&UnwindDest->front());
  if (!SuccessorCleanupPad)
    return false;

  CleanupPadInst *PredecessorCleanupPad = RI->getCleanupPad();
  // Replace any uses of the successor cleanupad with the predecessor pad
  // The only cleanuppad uses should be this cleanupret, it's cleanupret and
  // funclet bundle operands.
  SuccessorCleanupPad->replaceAllUsesWith(PredecessorCleanupPad);
  // Remove the old cleanuppad.
  SuccessorCleanupPad->eraseFromParent();
  // Now, we simply replace the cleanupret with a branch to the unwind
  // destination.
  UncondBrInst::Create(UnwindDest, RI->getParent());
  RI->eraseFromParent();

  return true;
}

bool SimplifyCFGOpt::simplifyCleanupReturn(CleanupReturnInst *RI) {
  // It is possible to transiantly have an undef cleanuppad operand because we
  // have deleted some, but not all, dead blocks.
  // Eventually, this block will be deleted.
  if (isa<UndefValue>(RI->getOperand(0)))
    return false;

  if (mergeCleanupPad(RI))
    return true;

  if (removeEmptyCleanup(RI, DTU))
    return true;

  return false;
}

// WARNING: keep in sync with InstCombinerImpl::visitUnreachableInst()!
bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
  BasicBlock *BB = UI->getParent();

  bool Changed = false;

  // Ensure that any debug-info records that used to occur after the Unreachable
  // are moved to in front of it -- otherwise they'll "dangle" at the end of
  // the block.
  BB->flushTerminatorDbgRecords();

  // Debug-info records on the unreachable inst itself should be deleted, as
  // below we delete everything past the final executable instruction.
  UI->dropDbgRecords();

  // If there are any instructions immediately before the unreachable that can
  // be removed, do so.
  while (UI->getIterator() != BB->begin()) {
    BasicBlock::iterator BBI = UI->getIterator();
    --BBI;

    if (!isGuaranteedToTransferExecutionToSuccessor(&*BBI))
      break; // Can not drop any more instructions. We're done here.
    // Otherwise, this instruction can be freely erased,
    // even if it is not side-effect free.

    // Note that deleting EH's here is in fact okay, although it involves a bit
    // of subtle reasoning. If this inst is an EH, all the predecessors of this
    // block will be the unwind edges of Invoke/CatchSwitch/CleanupReturn,
    // and we can therefore guarantee this block will be erased.

    // If we're deleting this, we're deleting any subsequent debug info, so
    // delete DbgRecords.
    BBI->dropDbgRecords();

    // Delete this instruction (any uses are guaranteed to be dead)
    BBI->replaceAllUsesWith(PoisonValue::get(BBI->getType()));
    BBI->eraseFromParent();
    Changed = true;
  }

  // If the unreachable instruction is the first in the block, take a gander
  // at all of the predecessors of this instruction, and simplify them.
  if (&BB->front() != UI)
    return Changed;

  std::vector<DominatorTree::UpdateType> Updates;

  SmallSetVector<BasicBlock *, 8> Preds(pred_begin(BB), pred_end(BB));
  for (BasicBlock *Predecessor : Preds) {
    Instruction *TI = Predecessor->getTerminator();
    IRBuilder<> Builder(TI);
    if (isa<UncondBrInst>(TI)) {
      new UnreachableInst(TI->getContext(), TI->getIterator());
      TI->eraseFromParent();
      Changed = true;
      if (DTU)
        Updates.push_back({DominatorTree::Delete, Predecessor, BB});
    } else if (auto *BI = dyn_cast<CondBrInst>(TI)) {
      // We could either have a proper unconditional branch,
      // or a degenerate conditional branch with matching destinations.
      if (BI->getSuccessor(0) == BI->getSuccessor(1)) {
        new UnreachableInst(TI->getContext(), TI->getIterator());
        TI->eraseFromParent();
        Changed = true;
      } else {
        Value* Cond = BI->getCondition();
        assert(BI->getSuccessor(0) != BI->getSuccessor(1) &&
               "The destinations are guaranteed to be different here.");
        CallInst *Assumption;
        if (BI->getSuccessor(0) == BB) {
          Assumption = Builder.CreateAssumption(Builder.CreateNot(Cond));
          Builder.CreateBr(BI->getSuccessor(1));
        } else {
          assert(BI->getSuccessor(1) == BB && "Incorrect CFG");
          Assumption = Builder.CreateAssumption(Cond);
          Builder.CreateBr(BI->getSuccessor(0));
        }
        if (Options.AC)
          Options.AC->registerAssumption(cast<AssumeInst>(Assumption));

        eraseTerminatorAndDCECond(BI);
        Changed = true;
      }
      if (DTU)
        Updates.push_back({DominatorTree::Delete, Predecessor, BB});
    } else if (auto *SI = dyn_cast<SwitchInst>(TI)) {
      SwitchInstProfUpdateWrapper SU(*SI);
      for (auto i = SU->case_begin(), e = SU->case_end(); i != e;) {
        if (i->getCaseSuccessor() != BB) {
          ++i;
          continue;
        }
        BB->removePredecessor(SU->getParent());
        i = SU.removeCase(i);
        e = SU->case_end();
        Changed = true;
      }
      // Note that the default destination can't be removed!
      if (DTU && SI->getDefaultDest() != BB)
        Updates.push_back({DominatorTree::Delete, Predecessor, BB});
    } else if (auto *II = dyn_cast<InvokeInst>(TI)) {
      if (II->getUnwindDest() == BB) {
        if (DTU) {
          DTU->applyUpdates(Updates);
          Updates.clear();
        }
        auto *CI = cast<CallInst>(removeUnwindEdge(TI->getParent(), DTU));
        if (!CI->doesNotThrow())
          CI->setDoesNotThrow();
        Changed = true;
      }
    } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) {
      if (CSI->getUnwindDest() == BB) {
        if (DTU) {
          DTU->applyUpdates(Updates);
          Updates.clear();
        }
        removeUnwindEdge(TI->getParent(), DTU);
        Changed = true;
        continue;
      }

      for (CatchSwitchInst::handler_iterator I = CSI->handler_begin(),
                                             E = CSI->handler_end();
           I != E; ++I) {
        if (*I == BB) {
          CSI->removeHandler(I);
          --I;
          --E;
          Changed = true;
        }
      }
      if (DTU)
        Updates.push_back({DominatorTree::Delete, Predecessor, BB});
      if (CSI->getNumHandlers() == 0) {
        if (CSI->hasUnwindDest()) {
          // Redirect all predecessors of the block containing CatchSwitchInst
          // to instead branch to the CatchSwitchInst's unwind destination.
          if (DTU) {
            for (auto *PredecessorOfPredecessor : predecessors(Predecessor)) {
              Updates.push_back({DominatorTree::Insert,
                                 PredecessorOfPredecessor,
                                 CSI->getUnwindDest()});
              Updates.push_back({DominatorTree::Delete,
                                 PredecessorOfPredecessor, Predecessor});
            }
          }
          Predecessor->replaceAllUsesWith(CSI->getUnwindDest());
        } else {
          // Rewrite all preds to unwind to caller (or from invoke to call).
          if (DTU) {
            DTU->applyUpdates(Updates);
            Updates.clear();
          }
          SmallVector<BasicBlock *, 8> EHPreds(predecessors(Predecessor));
          for (BasicBlock *EHPred : EHPreds)
            removeUnwindEdge(EHPred, DTU);
        }
        // The catchswitch is no longer reachable.
        new UnreachableInst(CSI->getContext(), CSI->getIterator());
        CSI->eraseFromParent();
        Changed = true;
      }
    } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
      (void)CRI;
      assert(CRI->hasUnwindDest() && CRI->getUnwindDest() == BB &&
             "Expected to always have an unwind to BB.");
      if (DTU)
        Updates.push_back({DominatorTree::Delete, Predecessor, BB});
      new UnreachableInst(TI->getContext(), TI->getIterator());
      TI->eraseFromParent();
      Changed = true;
    }
  }

  if (DTU)
    DTU->applyUpdates(Updates);

  // If this block is now dead, remove it.
  if (pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) {
    DeleteDeadBlock(BB, DTU);
    return true;
  }

  return Changed;
}

struct ContiguousCasesResult {
  ConstantInt *Min;
  ConstantInt *Max;
  BasicBlock *Dest;
  BasicBlock *OtherDest;
  SmallVectorImpl<ConstantInt *> *Cases;
  SmallVectorImpl<ConstantInt *> *OtherCases;
};

static std::optional<ContiguousCasesResult>
findContiguousCases(Value *Condition, SmallVectorImpl<ConstantInt *> &Cases,
                    SmallVectorImpl<ConstantInt *> &OtherCases,
                    BasicBlock *Dest, BasicBlock *OtherDest) {
  assert(Cases.size() >= 1);

  array_pod_sort(Cases.begin(), Cases.end(), constantIntSortPredicate);
  const APInt &Min = Cases.back()->getValue();
  const APInt &Max = Cases.front()->getValue();
  APInt Offset = Max - Min;
  size_t ContiguousOffset = Cases.size() - 1;
  if (Offset == ContiguousOffset) {
    return ContiguousCasesResult{
        /*Min=*/Cases.back(),
        /*Max=*/Cases.front(),
        /*Dest=*/Dest,
        /*OtherDest=*/OtherDest,
        /*Cases=*/&Cases,
        /*OtherCases=*/&OtherCases,
    };
  }
  ConstantRange CR = computeConstantRange(Condition, /*ForSigned=*/false,
                                          SimplifyQuery(Dest->getDataLayout()));
  // If this is a wrapping contiguous range, that is, [Min, OtherMin] +
  // [OtherMax, Max] (also [OtherMax, OtherMin]), [OtherMin+1, OtherMax-1] is a
  // contiguous range for the other destination. N.B. If CR is not a full range,
  // Max+1 is not equal to Min. It's not continuous in arithmetic.
  if (Max == CR.getUnsignedMax() && Min == CR.getUnsignedMin()) {
    assert(Cases.size() >= 2);
    auto *It =
        std::adjacent_find(Cases.begin(), Cases.end(), [](auto L, auto R) {
          return L->getValue() != R->getValue() + 1;
        });
    if (It == Cases.end())
      return std::nullopt;
    auto [OtherMax, OtherMin] = std::make_pair(*It, *std::next(It));
    if ((Max - OtherMax->getValue()) + (OtherMin->getValue() - Min) ==
        Cases.size() - 2) {
      return ContiguousCasesResult{
          /*Min=*/cast<ConstantInt>(
              ConstantInt::get(OtherMin->getType(), OtherMin->getValue() + 1)),
          /*Max=*/
          cast<ConstantInt>(
              ConstantInt::get(OtherMax->getType(), OtherMax->getValue() - 1)),
          /*Dest=*/OtherDest,
          /*OtherDest=*/Dest,
          /*Cases=*/&OtherCases,
          /*OtherCases=*/&Cases,
      };
    }
  }
  return std::nullopt;
}

static void createUnreachableSwitchDefault(SwitchInst *Switch,
                                           DomTreeUpdater *DTU,
                                           bool RemoveOrigDefaultBlock = true) {
  LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
  auto *BB = Switch->getParent();
  auto *OrigDefaultBlock = Switch->getDefaultDest();
  if (RemoveOrigDefaultBlock)
    OrigDefaultBlock->removePredecessor(BB);
  BasicBlock *NewDefaultBlock = BasicBlock::Create(
      BB->getContext(), BB->getName() + ".unreachabledefault", BB->getParent(),
      OrigDefaultBlock);
  auto *UI = new UnreachableInst(Switch->getContext(), NewDefaultBlock);
  UI->setDebugLoc(DebugLoc::getTemporary());
  Switch->setDefaultDest(&*NewDefaultBlock);
  if (DTU) {
    SmallVector<DominatorTree::UpdateType, 2> Updates;
    Updates.push_back({DominatorTree::Insert, BB, &*NewDefaultBlock});
    if (RemoveOrigDefaultBlock &&
        !is_contained(successors(BB), OrigDefaultBlock))
      Updates.push_back({DominatorTree::Delete, BB, &*OrigDefaultBlock});
    DTU->applyUpdates(Updates);
  }
}

/// Turn a switch into an integer range comparison and branch.
/// Switches with more than 2 destinations are ignored.
/// Switches with 1 destination are also ignored.
bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
                                             IRBuilder<> &Builder) {
  assert(SI->getNumCases() > 1 && "Degenerate switch?");

  bool HasDefault = !SI->defaultDestUnreachable();

  auto *BB = SI->getParent();
  // Partition the cases into two sets with different destinations.
  BasicBlock *DestA = HasDefault ? SI->getDefaultDest() : nullptr;
  BasicBlock *DestB = nullptr;
  SmallVector<ConstantInt *, 16> CasesA;
  SmallVector<ConstantInt *, 16> CasesB;

  for (auto Case : SI->cases()) {
    BasicBlock *Dest = Case.getCaseSuccessor();
    if (!DestA)
      DestA = Dest;
    if (Dest == DestA) {
      CasesA.push_back(Case.getCaseValue());
      continue;
    }
    if (!DestB)
      DestB = Dest;
    if (Dest == DestB) {
      CasesB.push_back(Case.getCaseValue());
      continue;
    }
    return false; // More than two destinations.
  }
  if (!DestB)
    return false; // All destinations are the same and the default is unreachable

  assert(DestA && DestB &&
         "Single-destination switch should have been folded.");
  assert(DestA != DestB);
  assert(DestB != SI->getDefaultDest());
  assert(!CasesB.empty() && "There must be non-default cases.");
  assert(!CasesA.empty() || HasDefault);

  // Figure out if one of the sets of cases form a contiguous range.
  std::optional<ContiguousCasesResult> ContiguousCases;

  // Only one icmp is needed when there is only one case.
  if (!HasDefault && CasesA.size() == 1)
    ContiguousCases = ContiguousCasesResult{
        /*Min=*/CasesA[0],
        /*Max=*/CasesA[0],
        /*Dest=*/DestA,
        /*OtherDest=*/DestB,
        /*Cases=*/&CasesA,
        /*OtherCases=*/&CasesB,
    };
  else if (CasesB.size() == 1)
    ContiguousCases = ContiguousCasesResult{
        /*Min=*/CasesB[0],
        /*Max=*/CasesB[0],
        /*Dest=*/DestB,
        /*OtherDest=*/DestA,
        /*Cases=*/&CasesB,
        /*OtherCases=*/&CasesA,
    };
  // Correctness: Cases to the default destination cannot be contiguous cases.
  else if (!HasDefault)
    ContiguousCases =
        findContiguousCases(SI->getCondition(), CasesA, CasesB, DestA, DestB);

  if (!ContiguousCases)
    ContiguousCases =
        findContiguousCases(SI->getCondition(), CasesB, CasesA, DestB, DestA);

  if (!ContiguousCases)
    return false;

  auto [Min, Max, Dest, OtherDest, Cases, OtherCases] = *ContiguousCases;

  // Start building the compare and branch.

  Constant *Offset = ConstantExpr::getNeg(Min);
  Constant *NumCases = ConstantInt::get(Offset->getType(),
                                        Max->getValue() - Min->getValue() + 1);
  Instruction *NewBI;
  if (NumCases->isOneValue()) {
    assert(Max->getValue() == Min->getValue());
    Value *Cmp = Builder.CreateICmpEQ(SI->getCondition(), Min);
    NewBI = Builder.CreateCondBr(Cmp, Dest, OtherDest);
  }
  // If NumCases overflowed, then all possible values jump to the successor.
  else if (NumCases->isNullValue() && !Cases->empty()) {
    NewBI = Builder.CreateBr(Dest);
  } else {
    Value *Sub = SI->getCondition();
    if (!Offset->isNullValue())
      Sub = Builder.CreateAdd(Sub, Offset, Sub->getName() + ".off");
    Value *Cmp = Builder.CreateICmpULT(Sub, NumCases, "switch");
    NewBI = Builder.CreateCondBr(Cmp, Dest, OtherDest);
  }

  // Update weight for the newly-created conditional branch.
  if (hasBranchWeightMD(*SI) && isa<CondBrInst>(NewBI)) {
    SmallVector<uint64_t, 8> Weights;
    getBranchWeights(SI, Weights);
    if (Weights.size() == 1 + SI->getNumCases()) {
      uint64_t TrueWeight = 0;
      uint64_t FalseWeight = 0;
      for (size_t I = 0, E = Weights.size(); I != E; ++I) {
        if (SI->getSuccessor(I) == Dest)
          TrueWeight += Weights[I];
        else
          FalseWeight += Weights[I];
      }
      while (TrueWeight > UINT32_MAX || FalseWeight > UINT32_MAX) {
        TrueWeight /= 2;
        FalseWeight /= 2;
      }
      setFittedBranchWeights(*NewBI, {TrueWeight, FalseWeight},
                             /*IsExpected=*/false, /*ElideAllZero=*/true);
    }
  }

  // Prune obsolete incoming values off the successors' PHI nodes.
  for (auto &PHI : make_early_inc_range(Dest->phis())) {
    unsigned PreviousEdges = Cases->size();
    if (Dest == SI->getDefaultDest())
      ++PreviousEdges;
    for (unsigned I = 0, E = PreviousEdges - 1; I != E; ++I)
      PHI.removeIncomingValue(SI->getParent());
  }
  for (auto &PHI : make_early_inc_range(OtherDest->phis())) {
    unsigned PreviousEdges = OtherCases->size();
    if (OtherDest == SI->getDefaultDest())
      ++PreviousEdges;
    unsigned E = PreviousEdges - 1;
    // Remove all incoming values from OtherDest if OtherDest is unreachable.
    if (isa<UncondBrInst>(NewBI))
      ++E;
    for (unsigned I = 0; I != E; ++I)
      PHI.removeIncomingValue(SI->getParent());
  }

  // Clean up the default block.
  SmallVector<DominatorTree::UpdateType, 2> Updates;
  if (!HasDefault) {
    BasicBlock *OrigDefaultBlock = SI->getDefaultDest();
    OrigDefaultBlock->removePredecessor(BB);
    Updates.push_back({DominatorTree::Delete, BB, OrigDefaultBlock});
  }

  // Drop the switch.
  SI->eraseFromParent();

  if (isa<UncondBrInst>(NewBI))
    Updates.push_back({DominatorTree::Delete, BB, OtherDest});

  if (DTU)
    DTU->applyUpdates(Updates);
  return true;
}

/// Compute masked bits for the condition of a switch
/// and use it to remove dead cases.
static bool eliminateDeadSwitchCases(SwitchInst *SI, DomTreeUpdater *DTU,
                                     AssumptionCache *AC,
                                     const DataLayout &DL) {
  Value *Cond = SI->getCondition();
  KnownBits Known = computeKnownBits(Cond, DL, AC, SI);
  SmallPtrSet<const Constant *, 4> KnownValues;
  bool IsKnownValuesValid = collectPossibleValues(Cond, KnownValues, 4);

  // We can also eliminate cases by determining that their values are outside of
  // the limited range of the condition based on how many significant (non-sign)
  // bits are in the condition value.
  unsigned MaxSignificantBitsInCond =
      ComputeMaxSignificantBits(Cond, DL, AC, SI);

  // Gather dead cases.
  SmallVector<ConstantInt *, 8> DeadCases;
  SmallDenseMap<BasicBlock *, int, 8> NumPerSuccessorCases;
  SmallVector<BasicBlock *, 8> UniqueSuccessors;
  for (const auto &Case : SI->cases()) {
    auto *Successor = Case.getCaseSuccessor();
    if (DTU) {
      auto [It, Inserted] = NumPerSuccessorCases.try_emplace(Successor);
      if (Inserted)
        UniqueSuccessors.push_back(Successor);
      ++It->second;
    }
    ConstantInt *CaseC = Case.getCaseValue();
    const APInt &CaseVal = CaseC->getValue();
    if (Known.Zero.intersects(CaseVal) || !Known.One.isSubsetOf(CaseVal) ||
        (CaseVal.getSignificantBits() > MaxSignificantBitsInCond) ||
        (IsKnownValuesValid && !KnownValues.contains(CaseC))) {
      DeadCases.push_back(CaseC);
      if (DTU)
        --NumPerSuccessorCases[Successor];
      LLVM_DEBUG(dbgs() << "SimplifyCFG: switch case " << CaseVal
                        << " is dead.\n");
    } else if (IsKnownValuesValid)
      KnownValues.erase(CaseC);
  }

  // If we can prove that the cases must cover all possible values, the
  // default destination becomes dead and we can remove it.  If we know some
  // of the bits in the value, we can use that to more precisely compute the
  // number of possible unique case values.
  bool HasDefault = !SI->defaultDestUnreachable();
  const unsigned NumUnknownBits =
      Known.getBitWidth() - (Known.Zero | Known.One).popcount();
  assert(NumUnknownBits <= Known.getBitWidth());
  if (HasDefault && DeadCases.empty()) {
    if (IsKnownValuesValid && all_of(KnownValues, IsaPred<UndefValue>)) {
      createUnreachableSwitchDefault(SI, DTU);
      return true;
    }

    if (NumUnknownBits < 64 /* avoid overflow */) {
      uint64_t AllNumCases = 1ULL << NumUnknownBits;
      if (SI->getNumCases() == AllNumCases) {
        createUnreachableSwitchDefault(SI, DTU);
        return true;
      }
      // When only one case value is missing, replace default with that case.
      // Eliminating the default branch will provide more opportunities for
      // optimization, such as lookup tables.
      if (SI->getNumCases() == AllNumCases - 1) {
        assert(NumUnknownBits > 1 && "Should be canonicalized to a branch");
        IntegerType *CondTy = cast<IntegerType>(Cond->getType());
        if (CondTy->getIntegerBitWidth() > 64 ||
            !DL.fitsInLegalInteger(CondTy->getIntegerBitWidth()))
          return false;

        uint64_t MissingCaseVal = 0;
        for (const auto &Case : SI->cases())
          MissingCaseVal ^= Case.getCaseValue()->getValue().getLimitedValue();
        auto *MissingCase = cast<ConstantInt>(
            ConstantInt::get(Cond->getType(), MissingCaseVal));
        SwitchInstProfUpdateWrapper SIW(*SI);
        SIW.addCase(MissingCase, SI->getDefaultDest(),
                    SIW.getSuccessorWeight(0));
        createUnreachableSwitchDefault(SI, DTU,
                                       /*RemoveOrigDefaultBlock*/ false);
        SIW.setSuccessorWeight(0, 0);
        return true;
      }
    }
  }

  if (DeadCases.empty())
    return false;

  SwitchInstProfUpdateWrapper SIW(*SI);
  for (ConstantInt *DeadCase : DeadCases) {
    SwitchInst::CaseIt CaseI = SI->findCaseValue(DeadCase);
    assert(CaseI != SI->case_default() &&
           "Case was not found. Probably mistake in DeadCases forming.");
    // Prune unused values from PHI nodes.
    CaseI->getCaseSuccessor()->removePredecessor(SI->getParent());
    SIW.removeCase(CaseI);
  }

  if (DTU) {
    std::vector<DominatorTree::UpdateType> Updates;
    for (auto *Successor : UniqueSuccessors)
      if (NumPerSuccessorCases[Successor] == 0)
        Updates.push_back({DominatorTree::Delete, SI->getParent(), Successor});
    DTU->applyUpdates(Updates);
  }

  return true;
}

/// If BB would be eligible for simplification by
/// TryToSimplifyUncondBranchFromEmptyBlock (i.e. it is empty and terminated
/// by an unconditional branch), look at the phi node for BB in the successor
/// block and see if the incoming value is equal to CaseValue. If so, return
/// the phi node, and set PhiIndex to BB's index in the phi node.
static PHINode *findPHIForConditionForwarding(ConstantInt *CaseValue,
                                              BasicBlock *BB, int *PhiIndex) {
  if (&*BB->getFirstNonPHIIt() != BB->getTerminator())
    return nullptr; // BB must be empty to be a candidate for simplification.
  if (!BB->getSinglePredecessor())
    return nullptr; // BB must be dominated by the switch.

  UncondBrInst *Branch = dyn_cast<UncondBrInst>(BB->getTerminator());
  if (!Branch)
    return nullptr; // Terminator must be unconditional branch.

  BasicBlock *Succ = Branch->getSuccessor();

  for (PHINode &PHI : Succ->phis()) {
    int Idx = PHI.getBasicBlockIndex(BB);
    assert(Idx >= 0 && "PHI has no entry for predecessor?");

    Value *InValue = PHI.getIncomingValue(Idx);
    if (InValue != CaseValue)
      continue;

    *PhiIndex = Idx;
    return &PHI;
  }

  return nullptr;
}

/// Try to forward the condition of a switch instruction to a phi node
/// dominated by the switch, if that would mean that some of the destination
/// blocks of the switch can be folded away. Return true if a change is made.
static bool forwardSwitchConditionToPHI(SwitchInst *SI) {
  using ForwardingNodesMap = DenseMap<PHINode *, SmallVector<int, 4>>;

  ForwardingNodesMap ForwardingNodes;
  BasicBlock *SwitchBlock = SI->getParent();
  bool Changed = false;
  for (const auto &Case : SI->cases()) {
    ConstantInt *CaseValue = Case.getCaseValue();
    BasicBlock *CaseDest = Case.getCaseSuccessor();

    // Replace phi operands in successor blocks that are using the constant case
    // value rather than the switch condition variable:
    //   switchbb:
    //   switch i32 %x, label %default [
    //     i32 17, label %succ
    //   ...
    //   succ:
    //     %r = phi i32 ... [ 17, %switchbb ] ...
    // -->
    //     %r = phi i32 ... [ %x, %switchbb ] ...

    for (PHINode &Phi : CaseDest->phis()) {
      // This only works if there is exactly 1 incoming edge from the switch to
      // a phi. If there is >1, that means multiple cases of the switch map to 1
      // value in the phi, and that phi value is not the switch condition. Thus,
      // this transform would not make sense (the phi would be invalid because
      // a phi can't have different incoming values from the same block).
      int SwitchBBIdx = Phi.getBasicBlockIndex(SwitchBlock);
      if (Phi.getIncomingValue(SwitchBBIdx) == CaseValue &&
          count(Phi.blocks(), SwitchBlock) == 1) {
        Phi.setIncomingValue(SwitchBBIdx, SI->getCondition());
        Changed = true;
      }
    }

    // Collect phi nodes that are indirectly using this switch's case constants.
    int PhiIdx;
    if (auto *Phi = findPHIForConditionForwarding(CaseValue, CaseDest, &PhiIdx))
      ForwardingNodes[Phi].push_back(PhiIdx);
  }

  for (auto &ForwardingNode : ForwardingNodes) {
    PHINode *Phi = ForwardingNode.first;
    SmallVectorImpl<int> &Indexes = ForwardingNode.second;
    // Check if it helps to fold PHI.
    if (Indexes.size() < 2 && !llvm::is_contained(Phi->incoming_values(), SI->getCondition()))
      continue;

    for (int Index : Indexes)
      Phi->setIncomingValue(Index, SI->getCondition());
    Changed = true;
  }

  return Changed;
}

/// Return true if the backend will be able to handle
/// initializing an array of constants like C.
static bool validLookupTableConstant(Constant *C, const TargetTransformInfo &TTI) {
  if (C->isThreadDependent())
    return false;
  if (C->isDLLImportDependent())
    return false;

  if (!isa<ConstantDataVector, ConstantExpr, ConstantFP, ConstantInt,
           ConstantPointerNull, GlobalValue, UndefValue>(C))
    return false;

  // Globals cannot contain scalable types.
  if (C->getType()->isScalableTy())
    return false;

  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
    // Pointer casts and in-bounds GEPs will not prohibit the backend from
    // materializing the array of constants.
    Constant *StrippedC = cast<Constant>(CE->stripInBoundsConstantOffsets());
    if (StrippedC == C || !validLookupTableConstant(StrippedC, TTI))
      return false;
  }

  if (!TTI.shouldBuildLookupTablesForConstant(C))
    return false;

  return true;
}

/// If V is a Constant, return it. Otherwise, try to look up
/// its constant value in ConstantPool, returning 0 if it's not there.
static Constant *
lookupConstant(Value *V,
               const SmallDenseMap<Value *, Constant *> &ConstantPool) {
  if (Constant *C = dyn_cast<Constant>(V))
    return C;
  return ConstantPool.lookup(V);
}

/// Try to fold instruction I into a constant. This works for
/// simple instructions such as binary operations where both operands are
/// constant or can be replaced by constants from the ConstantPool. Returns the
/// resulting constant on success, 0 otherwise.
static Constant *
constantFold(Instruction *I, const DataLayout &DL,
             const SmallDenseMap<Value *, Constant *> &ConstantPool) {
  if (SelectInst *Select = dyn_cast<SelectInst>(I)) {
    Constant *A = lookupConstant(Select->getCondition(), ConstantPool);
    if (!A)
      return nullptr;
    if (A->isAllOnesValue())
      return lookupConstant(Select->getTrueValue(), ConstantPool);
    if (A->isNullValue())
      return lookupConstant(Select->getFalseValue(), ConstantPool);
    return nullptr;
  }

  SmallVector<Constant *, 4> COps;
  for (unsigned N = 0, E = I->getNumOperands(); N != E; ++N) {
    if (Constant *A = lookupConstant(I->getOperand(N), ConstantPool))
      COps.push_back(A);
    else
      return nullptr;
  }

  return ConstantFoldInstOperands(I, COps, DL);
}

/// Try to determine the resulting constant values in phi nodes
/// at the common destination basic block, *CommonDest, for one of the case
/// destinations CaseDest corresponding to value CaseVal (nullptr for the
/// default case), of a switch instruction SI.
static bool
getCaseResults(SwitchInst *SI, ConstantInt *CaseVal, BasicBlock *CaseDest,
               BasicBlock **CommonDest,
               SmallVectorImpl<std::pair<PHINode *, Constant *>> &Res,
               const DataLayout &DL) {
  // The block from which we enter the common destination.
  BasicBlock *Pred = SI->getParent();

  // If CaseDest is empty except for some side-effect free instructions through
  // which we can constant-propagate the CaseVal, continue to its successor.
  SmallDenseMap<Value *, Constant *> ConstantPool;
  ConstantPool.insert(std::make_pair(SI->getCondition(), CaseVal));
  for (Instruction &I : *CaseDest) {
    if (I.isTerminator()) {
      // If the terminator is a simple branch, continue to the next block.
      if (I.getNumSuccessors() != 1 || I.isSpecialTerminator())
        return false;
      Pred = CaseDest;
      CaseDest = I.getSuccessor(0);
    } else if (Constant *C = constantFold(&I, DL, ConstantPool)) {
      // Instruction is side-effect free and constant.

      // If the instruction has uses outside this block or a phi node slot for
      // the block, it is not safe to bypass the instruction since it would then
      // no longer dominate all its uses.
      for (auto &Use : I.uses()) {
        User *User = Use.getUser();
        if (Instruction *I = dyn_cast<Instruction>(User))
          if (I->getParent() == CaseDest)
            continue;
        if (PHINode *Phi = dyn_cast<PHINode>(User))
          if (Phi->getIncomingBlock(Use) == CaseDest)
            continue;
        return false;
      }

      ConstantPool.insert(std::make_pair(&I, C));
    } else {
      break;
    }
  }

  // If we did not have a CommonDest before, use the current one.
  if (!*CommonDest)
    *CommonDest = CaseDest;
  // If the destination isn't the common one, abort.
  if (CaseDest != *CommonDest)
    return false;

  // Get the values for this case from phi nodes in the destination block.
  for (PHINode &PHI : (*CommonDest)->phis()) {
    int Idx = PHI.getBasicBlockIndex(Pred);
    if (Idx == -1)
      continue;

    Constant *ConstVal =
        lookupConstant(PHI.getIncomingValue(Idx), ConstantPool);
    if (!ConstVal)
      return false;

    Res.push_back(std::make_pair(&PHI, ConstVal));
  }

  return Res.size() > 0;
}

// Helper function used to add CaseVal to the list of cases that generate
// Result. Returns the updated number of cases that generate this result.
static size_t mapCaseToResult(ConstantInt *CaseVal,
                              SwitchCaseResultVectorTy &UniqueResults,
                              Constant *Result) {
  for (auto &I : UniqueResults) {
    if (I.first == Result) {
      I.second.push_back(CaseVal);
      return I.second.size();
    }
  }
  UniqueResults.push_back(
      std::make_pair(Result, SmallVector<ConstantInt *, 4>(1, CaseVal)));
  return 1;
}

// Helper function that initializes a map containing
// results for the PHI node of the common destination block for a switch
// instruction. Returns false if multiple PHI nodes have been found or if
// there is not a common destination block for the switch.
static bool initializeUniqueCases(SwitchInst *SI, PHINode *&PHI,
                                  BasicBlock *&CommonDest,
                                  SwitchCaseResultVectorTy &UniqueResults,
                                  Constant *&DefaultResult,
                                  const DataLayout &DL,
                                  uintptr_t MaxUniqueResults) {
  for (const auto &I : SI->cases()) {
    ConstantInt *CaseVal = I.getCaseValue();

    // Resulting value at phi nodes for this case value.
    SwitchCaseResultsTy Results;
    if (!getCaseResults(SI, CaseVal, I.getCaseSuccessor(), &CommonDest, Results,
                        DL))
      return false;

    // Only one value per case is permitted.
    if (Results.size() > 1)
      return false;

    // Add the case->result mapping to UniqueResults.
    const size_t NumCasesForResult =
        mapCaseToResult(CaseVal, UniqueResults, Results.begin()->second);

    // Early out if there are too many cases for this result.
    if (NumCasesForResult > MaxSwitchCasesPerResult)
      return false;

    // Early out if there are too many unique results.
    if (UniqueResults.size() > MaxUniqueResults)
      return false;

    // Check the PHI consistency.
    if (!PHI)
      PHI = Results[0].first;
    else if (PHI != Results[0].first)
      return false;
  }
  // Find the default result value.
  SmallVector<std::pair<PHINode *, Constant *>, 1> DefaultResults;
  getCaseResults(SI, nullptr, SI->getDefaultDest(), &CommonDest, DefaultResults,
                 DL);
  // If the default value is not found abort unless the default destination
  // is unreachable.
  DefaultResult =
      DefaultResults.size() == 1 ? DefaultResults.begin()->second : nullptr;

  return DefaultResult || SI->defaultDestUnreachable();
}

// Helper function that checks if it is possible to transform a switch with only
// two cases (or two cases + default) that produces a result into a select.
// TODO: Handle switches with more than 2 cases that map to the same result.
// The branch weights correspond to the provided Condition (i.e. if Condition is
// modified from the original SwitchInst, the caller must adjust the weights)
static Value *foldSwitchToSelect(const SwitchCaseResultVectorTy &ResultVector,
                                 Constant *DefaultResult, Value *Condition,
                                 IRBuilder<> &Builder, const DataLayout &DL,
                                 ArrayRef<uint32_t> BranchWeights) {
  // If we are selecting between only two cases transform into a simple
  // select or a two-way select if default is possible.
  // Example:
  // switch (a) {                  %0 = icmp eq i32 %a, 10
  //   case 10: return 42;         %1 = select i1 %0, i32 42, i32 4
  //   case 20: return 2;   ---->  %2 = icmp eq i32 %a, 20
  //   default: return 4;          %3 = select i1 %2, i32 2, i32 %1
  // }

  const bool HasBranchWeights = !BranchWeights.empty();

  if (ResultVector.size() == 2 && ResultVector[0].second.size() == 1 &&
      ResultVector[1].second.size() == 1) {
    ConstantInt *FirstCase = ResultVector[0].second[0];
    ConstantInt *SecondCase = ResultVector[1].second[0];
    Value *SelectValue = ResultVector[1].first;
    if (DefaultResult) {
      Value *ValueCompare =
          Builder.CreateICmpEQ(Condition, SecondCase, "switch.selectcmp");
      SelectValue = Builder.CreateSelect(ValueCompare, ResultVector[1].first,
                                         DefaultResult, "switch.select");
      if (auto *SI = dyn_cast<SelectInst>(SelectValue);
          SI && HasBranchWeights) {
        // We start with 3 probabilities, where the numerator is the
        // corresponding BranchWeights[i], and the denominator is the sum over
        // BranchWeights. We want the probability and negative probability of
        // Condition == SecondCase.
        assert(BranchWeights.size() == 3);
        setBranchWeights(
            *SI, {BranchWeights[2], BranchWeights[0] + BranchWeights[1]},
            /*IsExpected=*/false, /*ElideAllZero=*/true);
      }
    }
    Value *ValueCompare =
        Builder.CreateICmpEQ(Condition, FirstCase, "switch.selectcmp");
    Value *Ret = Builder.CreateSelect(ValueCompare, ResultVector[0].first,
                                      SelectValue, "switch.select");
    if (auto *SI = dyn_cast<SelectInst>(Ret); SI && HasBranchWeights) {
      // We may have had a DefaultResult. Base the position of the first and
      // second's branch weights accordingly. Also the proability that Condition
      // != FirstCase needs to take that into account.
      assert(BranchWeights.size() >= 2);
      size_t FirstCasePos = (Condition != nullptr);
      size_t SecondCasePos = FirstCasePos + 1;
      uint32_t DefaultCase = (Condition != nullptr) ? BranchWeights[0] : 0;
      setBranchWeights(*SI,
                       {BranchWeights[FirstCasePos],
                        DefaultCase + BranchWeights[SecondCasePos]},
                       /*IsExpected=*/false, /*ElideAllZero=*/true);
    }
    return Ret;
  }

  // Handle the degenerate case where two cases have the same result value.
  if (ResultVector.size() == 1 && DefaultResult) {
    ArrayRef<ConstantInt *> CaseValues = ResultVector[0].second;
    unsigned CaseCount = CaseValues.size();
    // n bits group cases map to the same result:
    // case 0,4      -> Cond & 0b1..1011 == 0 ? result : default
    // case 0,2,4,6  -> Cond & 0b1..1001 == 0 ? result : default
    // case 0,2,8,10 -> Cond & 0b1..0101 == 0 ? result : default
    if (isPowerOf2_32(CaseCount)) {
      ConstantInt *MinCaseVal = CaseValues[0];
      // If there are bits that are set exclusively by CaseValues, we
      // can transform the switch into a select if the conjunction of
      // all the values uniquely identify CaseValues.
      APInt AndMask = APInt::getAllOnes(MinCaseVal->getBitWidth());

      // Find the minimum value and compute the and of all the case values.
      for (auto *Case : CaseValues) {
        if (Case->getValue().slt(MinCaseVal->getValue()))
          MinCaseVal = Case;
        AndMask &= Case->getValue();
      }
      KnownBits Known = computeKnownBits(Condition, DL);

      if (!AndMask.isZero() && Known.getMaxValue().uge(AndMask)) {
        // Compute the number of bits that are free to vary.
        unsigned FreeBits = Known.countMaxActiveBits() - AndMask.popcount();

        // Check if the number of values covered by the mask is equal
        // to the number of cases.
        if (FreeBits == Log2_32(CaseCount)) {
          Value *And = Builder.CreateAnd(Condition, AndMask);
          Value *Cmp = Builder.CreateICmpEQ(
              And, Constant::getIntegerValue(And->getType(), AndMask));
          Value *Ret =
              Builder.CreateSelect(Cmp, ResultVector[0].first, DefaultResult);
          if (auto *SI = dyn_cast<SelectInst>(Ret); SI && HasBranchWeights) {
            // We know there's a Default case. We base the resulting branch
            // weights off its probability.
            assert(BranchWeights.size() >= 2);
            setBranchWeights(
                *SI,
                {accumulate(drop_begin(BranchWeights), 0U), BranchWeights[0]},
                /*IsExpected=*/false, /*ElideAllZero=*/true);
          }
          return Ret;
        }
      }

      // Mark the bits case number touched.
      APInt BitMask = APInt::getZero(MinCaseVal->getBitWidth());
      for (auto *Case : CaseValues)
        BitMask |= (Case->getValue() - MinCaseVal->getValue());

      // Check if cases with the same result can cover all number
      // in touched bits.
      if (BitMask.popcount() == Log2_32(CaseCount)) {
        if (!MinCaseVal->isNullValue())
          Condition = Builder.CreateSub(Condition, MinCaseVal);
        Value *And = Builder.CreateAnd(Condition, ~BitMask, "switch.and");
        Value *Cmp = Builder.CreateICmpEQ(
            And, Constant::getNullValue(And->getType()), "switch.selectcmp");
        Value *Ret =
            Builder.CreateSelect(Cmp, ResultVector[0].first, DefaultResult);
        if (auto *SI = dyn_cast<SelectInst>(Ret); SI && HasBranchWeights) {
          assert(BranchWeights.size() >= 2);
          setBranchWeights(
              *SI,
              {accumulate(drop_begin(BranchWeights), 0U), BranchWeights[0]},
              /*IsExpected=*/false, /*ElideAllZero=*/true);
        }
        return Ret;
      }
    }

    // Handle the degenerate case where two cases have the same value.
    if (CaseValues.size() == 2) {
      Value *Cmp1 = Builder.CreateICmpEQ(Condition, CaseValues[0],
                                         "switch.selectcmp.case1");
      Value *Cmp2 = Builder.CreateICmpEQ(Condition, CaseValues[1],
                                         "switch.selectcmp.case2");
      Value *Cmp = Builder.CreateOr(Cmp1, Cmp2, "switch.selectcmp");
      Value *Ret =
          Builder.CreateSelect(Cmp, ResultVector[0].first, DefaultResult);
      if (auto *SI = dyn_cast<SelectInst>(Ret); SI && HasBranchWeights) {
        assert(BranchWeights.size() >= 2);
        setBranchWeights(
            *SI, {accumulate(drop_begin(BranchWeights), 0U), BranchWeights[0]},
            /*IsExpected=*/false, /*ElideAllZero=*/true);
      }
      return Ret;
    }
  }

  return nullptr;
}

// Helper function to cleanup a switch instruction that has been converted into
// a select, fixing up PHI nodes and basic blocks.
static void removeSwitchAfterSelectFold(SwitchInst *SI, PHINode *PHI,
                                        Value *SelectValue,
                                        IRBuilder<> &Builder,
                                        DomTreeUpdater *DTU) {
  std::vector<DominatorTree::UpdateType> Updates;

  BasicBlock *SelectBB = SI->getParent();
  BasicBlock *DestBB = PHI->getParent();

  if (DTU && !is_contained(predecessors(DestBB), SelectBB))
    Updates.push_back({DominatorTree::Insert, SelectBB, DestBB});
  Builder.CreateBr(DestBB);

  // Remove the switch.

  PHI->removeIncomingValueIf(
      [&](unsigned Idx) { return PHI->getIncomingBlock(Idx) == SelectBB; });
  PHI->addIncoming(SelectValue, SelectBB);

  SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
  for (unsigned i = 0, e = SI->getNumSuccessors(); i < e; ++i) {
    BasicBlock *Succ = SI->getSuccessor(i);

    if (Succ == DestBB)
      continue;
    Succ->removePredecessor(SelectBB);
    if (DTU && RemovedSuccessors.insert(Succ).second)
      Updates.push_back({DominatorTree::Delete, SelectBB, Succ});
  }
  SI->eraseFromParent();
  if (DTU)
    DTU->applyUpdates(Updates);
}

/// If a switch is only used to initialize one or more phi nodes in a common
/// successor block with only two different constant values, try to replace the
/// switch with a select. Returns true if the fold was made.
static bool trySwitchToSelect(SwitchInst *SI, IRBuilder<> &Builder,
                              DomTreeUpdater *DTU, const DataLayout &DL) {
  Value *const Cond = SI->getCondition();
  PHINode *PHI = nullptr;
  BasicBlock *CommonDest = nullptr;
  Constant *DefaultResult;
  SwitchCaseResultVectorTy UniqueResults;
  // Collect all the cases that will deliver the same value from the switch.
  if (!initializeUniqueCases(SI, PHI, CommonDest, UniqueResults, DefaultResult,
                             DL, /*MaxUniqueResults*/ 2))
    return false;

  assert(PHI != nullptr && "PHI for value select not found");
  Builder.SetInsertPoint(SI);
  SmallVector<uint32_t, 4> BranchWeights;
  [[maybe_unused]] auto HasWeights =
      extractBranchWeights(getBranchWeightMDNode(*SI), BranchWeights);
  assert(!HasWeights == (BranchWeights.empty()));
  assert(BranchWeights.empty() ||
         (BranchWeights.size() >=
          UniqueResults.size() + (DefaultResult != nullptr)));

  Value *SelectValue = foldSwitchToSelect(UniqueResults, DefaultResult, Cond,
                                          Builder, DL, BranchWeights);
  if (!SelectValue)
    return false;

  removeSwitchAfterSelectFold(SI, PHI, SelectValue, Builder, DTU);
  return true;
}

namespace {

/// This class finds alternatives for switches to ultimately
/// replace the switch.
class SwitchReplacement {
public:
  /// Create a helper for optimizations to use as a switch replacement.
  /// Find a better representation for the content of Values,
  /// using DefaultValue to fill any holes in the table.
  /// If no representation is possible, isValid() returns false.
  SwitchReplacement(
      Module &M, uint64_t TableSize, ConstantInt *Offset,
      const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
      Constant *DefaultValue, const DataLayout &DL,
      const TargetTransformInfo &TTI, const StringRef &FuncName);

  /// Build instructions with Builder to retrieve values using Index
  /// and replace the switch.
  Value *replaceSwitch(Value *Index, IRBuilder<> &Builder, const DataLayout &DL,
                       Function *Func);

  /// Return true if a table with TableSize elements of
  /// type ElementType would fit in a target-legal register.
  static bool wouldFitInRegister(const DataLayout &DL, uint64_t TableSize,
                                 Type *ElementType);

  /// Return the default value of the switch.
  Constant *getDefaultValue();

  /// Return true if the replacement is a lookup table.
  bool isLookupTable();

  /// Return true if the replacement is a bit map.
  bool isBitMap();

  /// Return true if a suitable switch replacement was found.
  bool isValid() const { return Kind != InvalidKind; }

private:
  // Depending on the switch, there are different alternatives.
  enum {
    // No suitable replacement was found.
    InvalidKind,

    // For switches where each case contains the same value, we just have to
    // store that single value and return it for each lookup.
    SingleValueKind,

    // For switches where there is a linear relationship between table index
    // and values. We calculate the result with a simple multiplication
    // and addition instead of a table lookup.
    LinearMapKind,

    // For small tables with integer elements, we can pack them into a bitmap
    // that fits into a target-legal register. Values are retrieved by
    // shift and mask operations.
    BitMapKind,

    // The table is stored as an array of values. Values are retrieved by load
    // instructions from the table.
    LookupTableKind
  } Kind;

  // The default value of the switch.
  Constant *DefaultValue;

  // The type of the output values.
  Type *ValueType;

  // For SingleValueKind, this is the single value.
  Constant *SingleValue = nullptr;

  // For BitMapKind, this is the bitmap.
  ConstantInt *BitMap = nullptr;
  IntegerType *BitMapElementTy = nullptr;

  // For LinearMapKind, these are the constants used to derive the value.
  ConstantInt *LinearOffset = nullptr;
  ConstantInt *LinearMultiplier = nullptr;
  bool LinearMapValWrapped = false;

  // For LookupTableKind, this is the table.
  Constant *Initializer = nullptr;
};

} // end anonymous namespace

SwitchReplacement::SwitchReplacement(
    Module &M, uint64_t TableSize, ConstantInt *Offset,
    const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
    Constant *DefaultValue, const DataLayout &DL,
    const TargetTransformInfo &TTI, const StringRef &FuncName)
    : DefaultValue(DefaultValue) {
  assert(Values.size() && "Can't build lookup table without values!");
  assert(TableSize >= Values.size() && "Can't fit values in table!");

  // If all values in the table are equal, this is that value.
  SingleValue = Values.begin()->second;

  ValueType = Values.begin()->second->getType();

  // Build up the table contents.
  SmallVector<Constant *, 64> TableContents(TableSize);
  for (const auto &[CaseVal, CaseRes] : Values) {
    assert(CaseRes->getType() == ValueType);

    uint64_t Idx = (CaseVal->getValue() - Offset->getValue()).getLimitedValue();
    TableContents[Idx] = CaseRes;

    if (SingleValue && !isa<PoisonValue>(CaseRes) && CaseRes != SingleValue)
      SingleValue = isa<PoisonValue>(SingleValue) ? CaseRes : nullptr;
  }

  // Fill in any holes in the table with the default result.
  if (Values.size() < TableSize) {
    assert(DefaultValue &&
           "Need a default value to fill the lookup table holes.");
    assert(DefaultValue->getType() == ValueType);
    for (uint64_t I = 0; I < TableSize; ++I) {
      if (!TableContents[I])
        TableContents[I] = DefaultValue;
    }

    // If the default value is poison, all the holes are poison.
    bool DefaultValueIsPoison = isa<PoisonValue>(DefaultValue);

    if (DefaultValue != SingleValue && !DefaultValueIsPoison)
      SingleValue = nullptr;
  }

  // If each element in the table contains the same value, we only need to store
  // that single value.
  if (SingleValue) {
    Kind = SingleValueKind;
    return;
  }

  // Check if we can derive the value with a linear transformation from the
  // table index.
  if (isa<IntegerType>(ValueType)) {
    bool LinearMappingPossible = true;
    APInt PrevVal;
    APInt DistToPrev;
    // When linear map is monotonic and signed overflow doesn't happen on
    // maximum index, we can attach nsw on Add and Mul.
    bool NonMonotonic = false;
    assert(TableSize >= 2 && "Should be a SingleValue table.");
    // Check if there is the same distance between two consecutive values.
    for (uint64_t I = 0; I < TableSize; ++I) {
      ConstantInt *ConstVal = dyn_cast<ConstantInt>(TableContents[I]);

      if (!ConstVal && isa<PoisonValue>(TableContents[I])) {
        // This is an poison, so it's (probably) a lookup table hole.
        // To prevent any regressions from before we switched to using poison as
        // the default value, holes will fall back to using the first value.
        // This can be removed once we add proper handling for poisons in lookup
        // tables.
        ConstVal = dyn_cast<ConstantInt>(Values[0].second);
      }

      if (!ConstVal) {
        // We only handle literal integers when checking for a linear mapping.
        LinearMappingPossible = false;
        break;
      }
      const APInt &Val = ConstVal->getValue();
      if (I != 0) {
        APInt Dist = Val - PrevVal;
        if (I == 1) {
          DistToPrev = Dist;
        } else if (Dist != DistToPrev) {
          LinearMappingPossible = false;
          break;
        }
        NonMonotonic |=
            Dist.isStrictlyPositive() ? Val.sle(PrevVal) : Val.sgt(PrevVal);
      }
      PrevVal = Val;
    }
    if (LinearMappingPossible) {
      LinearOffset = cast<ConstantInt>(TableContents[0]);
      LinearMultiplier = ConstantInt::get(M.getContext(), DistToPrev);
      APInt M = LinearMultiplier->getValue();
      bool MayWrap = true;
      if (isIntN(M.getBitWidth(), TableSize - 1))
        (void)M.smul_ov(APInt(M.getBitWidth(), TableSize - 1), MayWrap);
      LinearMapValWrapped = NonMonotonic || MayWrap;
      Kind = LinearMapKind;
      return;
    }
  }

  // If the values are integer constants and the table fits in a register,
  // build a bitmap.
  if (wouldFitInRegister(DL, TableSize, ValueType) &&
      all_of(TableContents, IsaPred<ConstantInt, UndefValue>)) {
    IntegerType *IT = cast<IntegerType>(ValueType);
    APInt TableInt(TableSize * IT->getBitWidth(), 0);
    for (uint64_t I = TableSize; I > 0; --I) {
      TableInt <<= IT->getBitWidth();
      // Insert values into the bitmap. Undef values are set to zero.
      if (!isa<UndefValue>(TableContents[I - 1])) {
        ConstantInt *Val = cast<ConstantInt>(TableContents[I - 1]);
        TableInt |= Val->getValue().zext(TableInt.getBitWidth());
      }
    }
    BitMap = ConstantInt::get(M.getContext(), TableInt);
    BitMapElementTy = IT;
    Kind = BitMapKind;
    return;
  }

  // The remaining representation needs a global initializer.
  if (!all_of(TableContents,
              [&](Constant *C) { return validLookupTableConstant(C, TTI); })) {
    Kind = InvalidKind;
    return;
  }

  if (auto *IT = dyn_cast<IntegerType>(ValueType)) {
    ConstantRange Range(IT->getBitWidth(), false);
    for (Constant *Value : TableContents)
      if (!isa<UndefValue>(Value))
        Range = Range.unionWith(cast<ConstantInt>(Value)->getValue());
    // TODO: handle sign extension as well?
    unsigned NeededBitWidth =
        std::max(TTI.getMinimumLookupTableEntryBitWidth(),
                 unsigned(PowerOf2Ceil(Range.getActiveBits())));
    if (NeededBitWidth < IT->getBitWidth()) {
      IntegerType *DstTy = IntegerType::get(IT->getContext(), NeededBitWidth);
      for (Constant *&Value : TableContents)
        Value = ConstantFoldCastInstruction(Instruction::Trunc, Value, DstTy);
    }
  }

  // Store the table in an array.
  auto *TableTy = ArrayType::get(TableContents[0]->getType(), TableSize);
  Initializer = ConstantArray::get(TableTy, TableContents);

  Kind = LookupTableKind;
}

Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder,
                                        const DataLayout &DL, Function *Func) {
  switch (Kind) {
  case InvalidKind:
    llvm_unreachable("Cannot use an invalid switch replacement");
  case SingleValueKind:
    return SingleValue;
  case LinearMapKind: {
    ++NumLinearMaps;
    // Derive the result value from the input value.
    Value *Result = Builder.CreateIntCast(Index, LinearMultiplier->getType(),
                                          false, "switch.idx.cast");
    if (!LinearMultiplier->isOne())
      Result = Builder.CreateMul(Result, LinearMultiplier, "switch.idx.mult",
                                 /*HasNUW = */ false,
                                 /*HasNSW = */ !LinearMapValWrapped);

    if (!LinearOffset->isZero())
      Result = Builder.CreateAdd(Result, LinearOffset, "switch.offset",
                                 /*HasNUW = */ false,
                                 /*HasNSW = */ !LinearMapValWrapped);
    return Result;
  }
  case BitMapKind: {
    ++NumBitMaps;
    // Type of the bitmap (e.g. i59).
    IntegerType *MapTy = BitMap->getIntegerType();

    // Cast Index to the same type as the bitmap.
    // Note: The Index is <= the number of elements in the table, so
    // truncating it to the width of the bitmask is safe.
    Value *ShiftAmt = Builder.CreateZExtOrTrunc(Index, MapTy, "switch.cast");

    // Multiply the shift amount by the element width. NUW/NSW can always be
    // set, because wouldFitInRegister guarantees Index * ShiftAmt is in
    // BitMap's bit width.
    ShiftAmt = Builder.CreateMul(
        ShiftAmt, ConstantInt::get(MapTy, BitMapElementTy->getBitWidth()),
        "switch.shiftamt",/*HasNUW =*/true,/*HasNSW =*/true);

    // Shift down.
    Value *DownShifted =
        Builder.CreateLShr(BitMap, ShiftAmt, "switch.downshift");
    // Mask off.
    return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
  }
  case LookupTableKind: {
    ++NumLookupTables;
    auto *Table =
        new GlobalVariable(*Func->getParent(), Initializer->getType(),
                           /*isConstant=*/true, GlobalVariable::PrivateLinkage,
                           Initializer, "switch.table." + Func->getName());
    Table->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
    // Set the alignment to that of an array items. We will be only loading one
    // value out of it.
    Table->setAlignment(DL.getPrefTypeAlign(ValueType));
    Type *IndexTy = DL.getIndexType(Table->getType());
    auto *ArrayTy = cast<ArrayType>(Table->getValueType());

    if (Index->getType() != IndexTy) {
      unsigned OldBitWidth = Index->getType()->getIntegerBitWidth();
      Index = Builder.CreateZExtOrTrunc(Index, IndexTy);
      if (auto *Zext = dyn_cast<ZExtInst>(Index))
        Zext->setNonNeg(
            isUIntN(OldBitWidth - 1, ArrayTy->getNumElements() - 1));
    }

    Value *GEPIndices[] = {ConstantInt::get(IndexTy, 0), Index};
    Value *GEP =
        Builder.CreateInBoundsGEP(ArrayTy, Table, GEPIndices, "switch.gep");
    Value *Load =
        Builder.CreateLoad(ArrayTy->getElementType(), GEP, "switch.load");
    if (Load->getType() == ValueType)
      return Load;
    return Builder.CreateZExt(Load, ValueType, "switch.ext");
  }
  }
  llvm_unreachable("Unknown helper kind!");
}

bool SwitchReplacement::wouldFitInRegister(const DataLayout &DL,
                                           uint64_t TableSize,
                                           Type *ElementType) {
  auto *IT = dyn_cast<IntegerType>(ElementType);
  if (!IT)
    return false;
  // FIXME: If the type is wider than it needs to be, e.g. i8 but all values
  // are <= 15, we could try to narrow the type.

  // Avoid overflow, fitsInLegalInteger uses unsigned int for the width.
  if (TableSize >= UINT_MAX / IT->getBitWidth())
    return false;
  return DL.fitsInLegalInteger(TableSize * IT->getBitWidth());
}

static bool isTypeLegalForLookupTable(Type *Ty, const TargetTransformInfo &TTI,
                                      const DataLayout &DL) {
  // Allow any legal type.
  if (TTI.isTypeLegal(Ty))
    return true;

  auto *IT = dyn_cast<IntegerType>(Ty);
  if (!IT)
    return false;

  // Also allow power of 2 integer types that have at least 8 bits and fit in
  // a register. These types are common in frontend languages and targets
  // usually support loads of these types.
  // TODO: We could relax this to any integer that fits in a register and rely
  // on ABI alignment and padding in the table to allow the load to be widened.
  // Or we could widen the constants and truncate the load.
  unsigned BitWidth = IT->getBitWidth();
  return BitWidth >= 8 && isPowerOf2_32(BitWidth) &&
         DL.fitsInLegalInteger(IT->getBitWidth());
}

Constant *SwitchReplacement::getDefaultValue() { return DefaultValue; }

bool SwitchReplacement::isLookupTable() { return Kind == LookupTableKind; }

bool SwitchReplacement::isBitMap() { return Kind == BitMapKind; }

static bool isSwitchDense(uint64_t NumCases, uint64_t CaseRange, bool OptSize) {
  // 40% is the default density for building a jump table in optsize/minsize
  // mode, 10% is the default density for jump tables. See also
  // TargetLoweringBase::isSuitableForJumpTable(), which this function was based
  // on.
  const uint64_t MinDensity = OptSize ? 40 : 10;

  if (CaseRange >= UINT64_MAX / 100)
    return false; // Avoid multiplication overflows below.

  return NumCases * 100 >= CaseRange * MinDensity;
}

static bool isSwitchDense(ArrayRef<int64_t> Values, bool OptSize) {
  uint64_t Diff = (uint64_t)Values.back() - (uint64_t)Values.front();
  uint64_t Range = Diff + 1;
  if (Range < Diff)
    return false; // Overflow.

  return isSwitchDense(Values.size(), Range, OptSize);
}

static std::optional<unsigned>
getDenseSwitchRangeReductionShift(ArrayRef<int64_t> Values, int64_t Base,
                                  bool OptSize) {
  assert(Values.size() > 1 && "expected multiple switch cases");
  if (!llvm::all_of(Values, [Base](int64_t V) { return V >= Base; }))
    return std::nullopt;

  // First, transform the values by subtracting Base.
  SmallVector<int64_t, 4> ReducedValues(Values);
  uint64_t ReducedValuesOr = 0;
  for (auto &V : ReducedValues) {
    uint64_t Reduced = (uint64_t)V - (uint64_t)Base;
    ReducedValuesOr |= Reduced;
    V = (int64_t)Reduced;
  }

  // Conceptually, the reduced values are non-negative distances from Base.
  // Since the rest of the transform is bitwise only, treat them as unsigned
  // bit patterns from here.

  // countr_zero(0) returns 64. As Values is guaranteed to have more than
  // one element and LLVM disallows duplicate cases, ReducedValuesOr will
  // have at least one bit set, so Shift will be less than 64.
  unsigned Shift = llvm::countr_zero(ReducedValuesOr);
  assert(Shift < 64);
  if (Shift > 0)
    for (auto &V : ReducedValues)
      V = (int64_t)((uint64_t)V >> Shift);

  if (!isSwitchDense(ReducedValues, OptSize))
    return std::nullopt;

  return Shift;
}

/// Determine whether a lookup table should be built for this switch, based on
/// the number of cases, size of the table, and the types of the results.
// TODO: We could support larger than legal types by limiting based on the
// number of loads required and/or table size. If the constants are small we
// could use smaller table entries and extend after the load.
static bool shouldBuildLookupTable(SwitchInst *SI, uint64_t TableSize,
                                   const TargetTransformInfo &TTI,
                                   const DataLayout &DL,
                                   const SmallVector<Type *> &ResultTypes) {
  if (SI->getNumCases() > TableSize)
    return false; // TableSize overflowed.

  bool AllTablesFitInRegister = true;
  bool HasIllegalType = false;
  for (const auto &Ty : ResultTypes) {
    // Saturate this flag to true.
    HasIllegalType = HasIllegalType || !isTypeLegalForLookupTable(Ty, TTI, DL);

    // Saturate this flag to false.
    AllTablesFitInRegister =
        AllTablesFitInRegister &&
        SwitchReplacement::wouldFitInRegister(DL, TableSize, Ty);

    // If both flags saturate, we're done. NOTE: This *only* works with
    // saturating flags, and all flags have to saturate first due to the
    // non-deterministic behavior of iterating over a dense map.
    if (HasIllegalType && !AllTablesFitInRegister)
      break;
  }

  // If each table would fit in a register, we should build it anyway.
  if (AllTablesFitInRegister)
    return true;

  // Don't build a table that doesn't fit in-register if it has illegal types.
  if (HasIllegalType)
    return false;

  return isSwitchDense(SI->getNumCases(), TableSize,
                       SI->getFunction()->hasOptSize());
}

static bool shouldUseSwitchConditionAsTableIndex(
    ConstantInt &MinCaseVal, const ConstantInt &MaxCaseVal,
    bool HasDefaultResults, const SmallVector<Type *> &ResultTypes,
    const DataLayout &DL, const TargetTransformInfo &TTI) {
  if (MinCaseVal.isNullValue())
    return true;
  if (MinCaseVal.isNegative() ||
      MaxCaseVal.getLimitedValue() == std::numeric_limits<uint64_t>::max() ||
      !HasDefaultResults)
    return false;
  return all_of(ResultTypes, [&](const auto &ResultType) {
    return SwitchReplacement::wouldFitInRegister(
        DL, MaxCaseVal.getLimitedValue() + 1 /* TableSize */, ResultType);
  });
}

/// Try to reuse the switch table index compare. Following pattern:
/// \code
///     if (idx < tablesize)
///        r = table[idx]; // table does not contain default_value
///     else
///        r = default_value;
///     if (r != default_value)
///        ...
/// \endcode
/// Is optimized to:
/// \code
///     cond = idx < tablesize;
///     if (cond)
///        r = table[idx];
///     else
///        r = default_value;
///     if (cond)
///        ...
/// \endcode
/// Jump threading will then eliminate the second if(cond).
static void reuseTableCompare(
    User *PhiUser, BasicBlock *PhiBlock, CondBrInst *RangeCheckBranch,
    Constant *DefaultValue,
    const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values) {
  ICmpInst *CmpInst = dyn_cast<ICmpInst>(PhiUser);
  if (!CmpInst)
    return;

  // We require that the compare is in the same block as the phi so that jump
  // threading can do its work afterwards.
  if (CmpInst->getParent() != PhiBlock)
    return;

  Constant *CmpOp1 = dyn_cast<Constant>(CmpInst->getOperand(1));
  if (!CmpOp1)
    return;

  Value *RangeCmp = RangeCheckBranch->getCondition();
  Constant *TrueConst = ConstantInt::getTrue(RangeCmp->getType());
  Constant *FalseConst = ConstantInt::getFalse(RangeCmp->getType());

  // Check if the compare with the default value is constant true or false.
  const DataLayout &DL = PhiBlock->getDataLayout();
  Constant *DefaultConst = ConstantFoldCompareInstOperands(
      CmpInst->getPredicate(), DefaultValue, CmpOp1, DL);
  if (DefaultConst != TrueConst && DefaultConst != FalseConst)
    return;

  // Check if the compare with the case values is distinct from the default
  // compare result.
  for (auto ValuePair : Values) {
    Constant *CaseConst = ConstantFoldCompareInstOperands(
        CmpInst->getPredicate(), ValuePair.second, CmpOp1, DL);
    if (!CaseConst || CaseConst == DefaultConst ||
        (CaseConst != TrueConst && CaseConst != FalseConst))
      return;
  }

  // Check if the branch instruction dominates the phi node. It's a simple
  // dominance check, but sufficient for our needs.
  // Although this check is invariant in the calling loops, it's better to do it
  // at this late stage. Practically we do it at most once for a switch.
  BasicBlock *BranchBlock = RangeCheckBranch->getParent();
  for (BasicBlock *Pred : predecessors(PhiBlock)) {
    if (Pred != BranchBlock && Pred->getUniquePredecessor() != BranchBlock)
      return;
  }

  if (DefaultConst == FalseConst) {
    // The compare yields the same result. We can replace it.
    CmpInst->replaceAllUsesWith(RangeCmp);
    ++NumTableCmpReuses;
  } else {
    // The compare yields the same result, just inverted. We can replace it.
    Value *InvertedTableCmp = BinaryOperator::CreateXor(
        RangeCmp, ConstantInt::get(RangeCmp->getType(), 1), "inverted.cmp",
        RangeCheckBranch->getIterator());
    CmpInst->replaceAllUsesWith(InvertedTableCmp);
    ++NumTableCmpReuses;
  }
}

/// If the switch is only used to initialize one or more phi nodes in a common
/// successor block with different constant values, replace the switch with
/// lookup tables.
static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
                                 DomTreeUpdater *DTU, const DataLayout &DL,
                                 const TargetTransformInfo &TTI,
                                 bool ConvertSwitchToLookupTable) {
  assert(SI->getNumCases() > 1 && "Degenerate switch?");

  BasicBlock *BB = SI->getParent();
  Function *Fn = BB->getParent();

  // FIXME: If the switch is too sparse for a lookup table, perhaps we could
  // split off a dense part and build a lookup table for that.

  // FIXME: This creates arrays of GEPs to constant strings, which means each
  // GEP needs a runtime relocation in PIC code. We should just build one big
  // string and lookup indices into that.

  // Ignore switches with less than three cases. Lookup tables will not make
  // them faster, so we don't analyze them.
  if (SI->getNumCases() < 3)
    return false;

  // Figure out the corresponding result for each case value and phi node in the
  // common destination, as well as the min and max case values.
  assert(!SI->cases().empty());
  SwitchInst::CaseIt CI = SI->case_begin();
  ConstantInt *MinCaseVal = CI->getCaseValue();
  ConstantInt *MaxCaseVal = CI->getCaseValue();

  BasicBlock *CommonDest = nullptr;

  using ResultListTy = SmallVector<std::pair<ConstantInt *, Constant *>, 4>;
  SmallDenseMap<PHINode *, ResultListTy> ResultLists;

  SmallDenseMap<PHINode *, Constant *> DefaultResults;
  SmallVector<Type *> ResultTypes;
  SmallVector<PHINode *, 4> PHIs;

  for (SwitchInst::CaseIt E = SI->case_end(); CI != E; ++CI) {
    ConstantInt *CaseVal = CI->getCaseValue();
    if (CaseVal->getValue().slt(MinCaseVal->getValue()))
      MinCaseVal = CaseVal;
    if (CaseVal->getValue().sgt(MaxCaseVal->getValue()))
      MaxCaseVal = CaseVal;

    // Resulting value at phi nodes for this case value.
    using ResultsTy = SmallVector<std::pair<PHINode *, Constant *>, 4>;
    ResultsTy Results;
    if (!getCaseResults(SI, CaseVal, CI->getCaseSuccessor(), &CommonDest,
                        Results, DL))
      return false;

    // Append the result and result types from this case to the list for each
    // phi.
    for (const auto &I : Results) {
      PHINode *PHI = I.first;
      Constant *Value = I.second;
      auto [It, Inserted] = ResultLists.try_emplace(PHI);
      if (Inserted)
        PHIs.push_back(PHI);
      It->second.push_back(std::make_pair(CaseVal, Value));
      ResultTypes.push_back(PHI->getType());
    }
  }

  // If the table has holes, we need a constant result for the default case
  // or a bitmask that fits in a register.
  SmallVector<std::pair<PHINode *, Constant *>, 4> DefaultResultsList;
  bool HasDefaultResults = getCaseResults(SI, nullptr, SI->getDefaultDest(),
                                          &CommonDest, DefaultResultsList, DL);
  for (const auto &I : DefaultResultsList) {
    PHINode *PHI = I.first;
    Constant *Result = I.second;
    DefaultResults[PHI] = Result;
  }

  bool UseSwitchConditionAsTableIndex = shouldUseSwitchConditionAsTableIndex(
      *MinCaseVal, *MaxCaseVal, HasDefaultResults, ResultTypes, DL, TTI);
  uint64_t TableSize;
  ConstantInt *TableIndexOffset;
  if (UseSwitchConditionAsTableIndex) {
    TableSize = MaxCaseVal->getLimitedValue() + 1;
    TableIndexOffset = ConstantInt::get(MaxCaseVal->getIntegerType(), 0);
  } else {
    TableSize =
        (MaxCaseVal->getValue() - MinCaseVal->getValue()).getLimitedValue() + 1;

    TableIndexOffset = MinCaseVal;
  }

  // If the default destination is unreachable, or if the lookup table covers
  // all values of the conditional variable, branch directly to the lookup table
  // BB. Otherwise, check that the condition is within the case range.
  uint64_t NumResults = ResultLists[PHIs[0]].size();
  bool DefaultIsReachable = !SI->defaultDestUnreachable();

  bool TableHasHoles = (NumResults < TableSize);

  // If the table has holes but the default destination doesn't produce any
  // constant results, the lookup table entries corresponding to the holes will
  // contain poison.
  bool AllHolesArePoison = TableHasHoles && !HasDefaultResults;

  // If the default destination doesn't produce a constant result but is still
  // reachable, and the lookup table has holes, we need to use a mask to
  // determine if the current index should load from the lookup table or jump
  // to the default case.
  // The mask is unnecessary if the table has holes but the default destination
  // is unreachable, as in that case the holes must also be unreachable.
  bool NeedMask = AllHolesArePoison && DefaultIsReachable;
  if (NeedMask) {
    // As an extra penalty for the validity test we require more cases.
    if (SI->getNumCases() < 4) // FIXME: Find best threshold value (benchmark).
      return false;
    if (!DL.fitsInLegalInteger(TableSize))
      return false;
  }

  if (!shouldBuildLookupTable(SI, TableSize, TTI, DL, ResultTypes))
    return false;

  // Compute the table index value.
  Value *TableIndex;
  if (UseSwitchConditionAsTableIndex) {
    TableIndex = SI->getCondition();
    if (HasDefaultResults) {
      // Grow the table to cover all possible index values to avoid the range
      // check. It will use the default result to fill in the table hole later,
      // so make sure it exist.
      ConstantRange CR = computeConstantRange(TableIndex, /*ForSigned=*/false,
                                              SimplifyQuery(DL));
      // Grow the table shouldn't have any size impact by checking
      // wouldFitInRegister.
      // TODO: Consider growing the table also when it doesn't fit in a register
      // if no optsize is specified.
      const uint64_t UpperBound = CR.getUpper().getLimitedValue();
      if (!CR.isUpperWrapped() &&
          all_of(ResultTypes, [&](const auto &ResultType) {
            return SwitchReplacement::wouldFitInRegister(DL, UpperBound,
                                                         ResultType);
          })) {
        // There may be some case index larger than the UpperBound (unreachable
        // case), so make sure the table size does not get smaller.
        TableSize = std::max(UpperBound, TableSize);
        // The default branch is unreachable after we enlarge the lookup table.
        // Adjust DefaultIsReachable to reuse code path.
        DefaultIsReachable = false;
      }
    }
  }

  // Keep track of the switch replacement for each phi
  SmallDenseMap<PHINode *, SwitchReplacement> PhiToReplacementMap;
  for (PHINode *PHI : PHIs) {
    const auto &ResultList = ResultLists[PHI];

    Type *ResultType = ResultList.begin()->second->getType();
    // Use any value to fill the lookup table holes.
    Constant *DefaultVal =
        AllHolesArePoison ? PoisonValue::get(ResultType) : DefaultResults[PHI];
    StringRef FuncName = Fn->getName();
    SwitchReplacement Replacement(*Fn->getParent(), TableSize, TableIndexOffset,
                                  ResultList, DefaultVal, DL, TTI, FuncName);
    if (!Replacement.isValid())
      return false;
    PhiToReplacementMap.insert({PHI, Replacement});
  }

  bool AnyLookupTables = any_of(
      PhiToReplacementMap, [](auto &KV) { return KV.second.isLookupTable(); });
  bool AnyBitMaps = any_of(PhiToReplacementMap,
                           [](auto &KV) { return KV.second.isBitMap(); });

  // A few conditions prevent the generation of lookup tables:
  //     1. The target does not support lookup tables.
  //     2. The "no-jump-tables" function attribute is set.
  // However, these objections do not apply to other switch replacements, like
  // the bitmap, so we only stop here if any of these conditions are met and we
  // want to create a LUT. Otherwise, continue with the switch replacement.
  if (AnyLookupTables &&
      (!TTI.shouldBuildLookupTables() ||
       Fn->getFnAttribute("no-jump-tables").getValueAsBool()))
    return false;

  // In the early optimization pipeline, disable formation of lookup tables,
  // bit maps and mask checks, as they may inhibit further optimization.
  if (!ConvertSwitchToLookupTable &&
      (AnyLookupTables || AnyBitMaps || NeedMask))
    return false;

  Builder.SetInsertPoint(SI);
  // TableIndex is the switch condition - TableIndexOffset if we don't
  // use the condition directly
  if (!UseSwitchConditionAsTableIndex) {
    // If the default is unreachable, all case values are s>= MinCaseVal. Then
    // we can try to attach nsw.
    bool MayWrap = true;
    if (!DefaultIsReachable) {
      APInt Res =
          MaxCaseVal->getValue().ssub_ov(MinCaseVal->getValue(), MayWrap);
      (void)Res;
    }
    TableIndex = Builder.CreateSub(SI->getCondition(), TableIndexOffset,
                                   "switch.tableidx", /*HasNUW =*/false,
                                   /*HasNSW =*/!MayWrap);
  }

  std::vector<DominatorTree::UpdateType> Updates;

  // Compute the maximum table size representable by the integer type we are
  // switching upon.
  unsigned CaseSize = MinCaseVal->getType()->getPrimitiveSizeInBits();
  uint64_t MaxTableSize = CaseSize > 63 ? UINT64_MAX : 1ULL << CaseSize;
  assert(MaxTableSize >= TableSize &&
         "It is impossible for a switch to have more entries than the max "
         "representable value of its input integer type's size.");

  // Create the BB that does the lookups.
  Module &Mod = *CommonDest->getParent()->getParent();
  BasicBlock *LookupBB = BasicBlock::Create(
      Mod.getContext(), "switch.lookup", CommonDest->getParent(), CommonDest);

  CondBrInst *RangeCheckBranch = nullptr;
  CondBrInst *CondBranch = nullptr;

  Builder.SetInsertPoint(SI);
  const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize);
  const bool IsFullyCoveredLookupTable =
      !DefaultIsReachable || GeneratingCoveredLookupTable;
  if (IsFullyCoveredLookupTable) {
    Builder.CreateBr(LookupBB);
    if (DTU)
      Updates.push_back({DominatorTree::Insert, BB, LookupBB});
    // Note: We call removeProdecessor later since we need to be able to get the
    // PHI value for the default case in case we're using a bit mask.
  } else {
    Value *Cmp = Builder.CreateICmpULT(
        TableIndex, ConstantInt::get(MinCaseVal->getType(), TableSize));
    RangeCheckBranch =
        Builder.CreateCondBr(Cmp, LookupBB, SI->getDefaultDest());
    CondBranch = RangeCheckBranch;
    if (DTU)
      Updates.push_back({DominatorTree::Insert, BB, LookupBB});
  }

  // Populate the BB that does the lookups.
  Builder.SetInsertPoint(LookupBB);

  if (NeedMask) {
    // Before doing the lookup, we do the hole check. The LookupBB is therefore
    // re-purposed to do the hole check, and we create a new LookupBB.
    BasicBlock *MaskBB = LookupBB;
    MaskBB->setName("switch.hole_check");
    LookupBB = BasicBlock::Create(Mod.getContext(), "switch.lookup",
                                  CommonDest->getParent(), CommonDest);

    // Make the mask's bitwidth at least 8-bit and a power-of-2 to avoid
    // unnecessary illegal types.
    uint64_t TableSizePowOf2 = NextPowerOf2(std::max(7ULL, TableSize - 1ULL));
    APInt MaskInt(TableSizePowOf2, 0);
    APInt One(TableSizePowOf2, 1);
    // Build bitmask; fill in a 1 bit for every case.
    const ResultListTy &ResultList = ResultLists[PHIs[0]];
    for (const auto &Result : ResultList) {
      uint64_t Idx = (Result.first->getValue() - TableIndexOffset->getValue())
                         .getLimitedValue();
      MaskInt |= One << Idx;
    }
    ConstantInt *TableMask = ConstantInt::get(Mod.getContext(), MaskInt);

    // Get the TableIndex'th bit of the bitmask.
    // If this bit is 0 (meaning hole) jump to the default destination,
    // else continue with table lookup.
    IntegerType *MapTy = TableMask->getIntegerType();
    Value *MaskIndex =
        Builder.CreateZExtOrTrunc(TableIndex, MapTy, "switch.maskindex");
    Value *Shifted = Builder.CreateLShr(TableMask, MaskIndex, "switch.shifted");
    Value *LoBit = Builder.CreateTrunc(
        Shifted, Type::getInt1Ty(Mod.getContext()), "switch.lobit");
    if (!IsFullyCoveredLookupTable)
      setExplicitlyUnknownBranchWeightsIfProfiled(*CondBranch, DEBUG_TYPE);
    CondBranch = Builder.CreateCondBr(LoBit, LookupBB, SI->getDefaultDest());
    if (DTU) {
      Updates.push_back({DominatorTree::Insert, MaskBB, LookupBB});
      Updates.push_back({DominatorTree::Insert, MaskBB, SI->getDefaultDest()});
    }
    Builder.SetInsertPoint(LookupBB);
    addPredecessorToBlock(SI->getDefaultDest(), MaskBB, BB);
  }

  if (!DefaultIsReachable || GeneratingCoveredLookupTable) {
    // We cached PHINodes in PHIs. To avoid accessing deleted PHINodes later,
    // do not delete PHINodes here.
    SI->getDefaultDest()->removePredecessor(BB,
                                            /*KeepOneInputPHIs=*/true);
    if (DTU)
      Updates.push_back({DominatorTree::Delete, BB, SI->getDefaultDest()});
  }

  for (PHINode *PHI : PHIs) {
    const ResultListTy &ResultList = ResultLists[PHI];
    auto Replacement = PhiToReplacementMap.at(PHI);
    auto *Result = Replacement.replaceSwitch(TableIndex, Builder, DL, Fn);
    // Do a small peephole optimization: re-use the switch table compare if
    // possible.
    if (!TableHasHoles && HasDefaultResults && RangeCheckBranch) {
      BasicBlock *PhiBlock = PHI->getParent();
      // Search for compare instructions which use the phi.
      for (auto *User : PHI->users()) {
        reuseTableCompare(User, PhiBlock, RangeCheckBranch,
                          Replacement.getDefaultValue(), ResultList);
      }
    }

    PHI->addIncoming(Result, LookupBB);
  }

  Builder.CreateBr(CommonDest);
  if (DTU)
    Updates.push_back({DominatorTree::Insert, LookupBB, CommonDest});

  SmallVector<uint32_t> BranchWeights;
  const bool HasBranchWeights =
      CondBranch && extractBranchWeights(*SI, BranchWeights);
  uint64_t ToLookupWeight = 0;
  uint64_t ToDefaultWeight = 0;

  // Remove the switch.
  SmallPtrSet<BasicBlock *, 8> RemovedSuccessors;
  for (unsigned I = 0, E = SI->getNumSuccessors(); I < E; ++I) {
    BasicBlock *Succ = SI->getSuccessor(I);

    if (Succ == SI->getDefaultDest()) {
      if (HasBranchWeights)
        ToDefaultWeight += BranchWeights[I];
      continue;
    }
    Succ->removePredecessor(BB);
    if (DTU && RemovedSuccessors.insert(Succ).second)
      Updates.push_back({DominatorTree::Delete, BB, Succ});
    if (HasBranchWeights)
      ToLookupWeight += BranchWeights[I];
  }
  SI->eraseFromParent();
  // In the case where we do not have a fully covered lookup table (i.e., we
  // need a range check), and we need a mask check, we split the default case
  // into two different cases for which we cannot infer branch weights.
  // Otherwise we have a single branch for which we can infer branch weights.
  if ((NeedMask && !IsFullyCoveredLookupTable) &&
      !ProfcheckDisableMetadataFixes)
    setExplicitlyUnknownBranchWeightsIfProfiled(*CondBranch, DEBUG_TYPE);
  else if (HasBranchWeights)
    setFittedBranchWeights(*CondBranch, {ToLookupWeight, ToDefaultWeight},
                           /*IsExpected=*/false);
  if (DTU)
    DTU->applyUpdates(Updates);

  if (NeedMask)
    ++NumLookupTablesHoles;
  return true;
}

/// Try to transform a switch that has "holes" in it to a contiguous sequence
/// of cases.
///
/// A switch such as: switch(i) {case 5: case 9: case 13: case 17:} can be
/// range-reduced to: switch ((i-5) / 4) {case 0: case 1: case 2: case 3:}.
///
/// This converts a sparse switch into a dense switch which allows better
/// lowering and could also allow transforming into a lookup table.
static bool reduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder,
                              const DataLayout &DL,
                              const TargetTransformInfo &TTI) {
  auto *CondTy = cast<IntegerType>(SI->getCondition()->getType());
  if (CondTy->getIntegerBitWidth() > 64 ||
      !DL.fitsInLegalInteger(CondTy->getIntegerBitWidth()))
    return false;
  // Only bother with this optimization if there are more than 3 switch cases;
  // SDAG will only bother creating jump tables for 4 or more cases.
  if (SI->getNumCases() < 4)
    return false;

  // This transform is agnostic to the signedness of the input or case values. We
  // can treat the case values as signed or unsigned. We can optimize more common
  // cases such as a sequence crossing zero {-4,0,4,8} if we interpret case values
  // as signed.
  SmallVector<int64_t,4> Values;
  for (const auto &C : SI->cases())
    Values.push_back(C.getCaseValue()->getValue().getSExtValue());
  llvm::sort(Values);

  // If the switch is already dense, there's nothing useful to do here.
  bool OptSize = SI->getFunction()->hasOptSize();
  if (isSwitchDense(Values, OptSize))
    return false;

  // Find a Base and corresponding Shift that results in a dense switch range.
  // Values[0] is the local minimum.
  int64_t Base = Values[0];
  std::optional<unsigned> Shift;
  // Prefer Base=0 when shifting out common low zero bits still produces a dense
  // range, as this avoids an unnecessary `(condition - local_min)` expression.
  // However, avoiding the subtract can leave a wider reduced range than using
  // the local minimum, so require Base=0 to satisfy the stricter optsize
  // density threshold before falling back to the normal density policy for
  // local-min.
  if ((Shift = getDenseSwitchRangeReductionShift(Values, /*Base=*/0,
                                                 /*OptSize=*/true)))
    Base = 0;
  else if (Base != 0)
    Shift = getDenseSwitchRangeReductionShift(Values, Base, OptSize);

  if (!Shift)
    return false;

  // The obvious transform is to shift the switch condition right and emit a
  // check that the condition actually cleanly divided by GCD, i.e.
  //   C & (1 << Shift - 1) == 0
  // inserting a new CFG edge to handle the case where it didn't divide cleanly.
  //
  // A cheaper way of doing this is a simple ROTR(C, Shift). This performs the
  // shift and puts the shifted-off bits in the uppermost bits. If any of these
  // are nonzero then the switch condition will be very large and will hit the
  // default case.
  //
  // This transform can be done speculatively because it is so cheap - it
  // results in a single rotate operation being inserted.

  auto *Ty = cast<IntegerType>(SI->getCondition()->getType());
  Builder.SetInsertPoint(SI);
  Value *Sub = SI->getCondition();
  if (Base != 0)
    Sub = Builder.CreateSub(Sub, ConstantInt::getSigned(Ty, Base));
  Value *Rot = Builder.CreateIntrinsic(
      Ty, Intrinsic::fshl,
      {Sub, Sub, ConstantInt::get(Ty, Ty->getBitWidth() - *Shift)});
  SI->replaceUsesOfWith(SI->getCondition(), Rot);

  for (auto Case : SI->cases()) {
    auto *Orig = Case.getCaseValue();
    auto Sub = Orig->getValue() - APInt(Ty->getBitWidth(), Base, true);
    Case.setValue(cast<ConstantInt>(ConstantInt::get(Ty, Sub.lshr(*Shift))));
  }
  return true;
}

/// Tries to transform the switch when the condition is umin with a constant.
/// In that case, the default branch can be replaced by the constant's branch.
/// This method also removes dead cases when the simplification cannot replace
/// the default branch.
///
/// For example:
/// switch(umin(a, 3)) {
/// case 0:
/// case 1:
/// case 2:
/// case 3:
/// case 4:
///   // ...
/// default:
///   unreachable
/// }
///
/// Transforms into:
///
/// switch(a) {
/// case 0:
/// case 1:
/// case 2:
/// default:
///   // This is case 3
/// }
static bool simplifySwitchWhenUMin(SwitchInst *SI, DomTreeUpdater *DTU) {
  Value *A;
  ConstantInt *Constant;

  if (!match(SI->getCondition(), m_UMin(m_Value(A), m_ConstantInt(Constant))))
    return false;

  SmallVector<DominatorTree::UpdateType> Updates;
  SwitchInstProfUpdateWrapper SIW(*SI);
  BasicBlock *BB = SIW->getParent();

  // Dead cases are removed even when the simplification fails.
  // A case is dead when its value is higher than the Constant.
  for (auto I = SI->case_begin(), E = SI->case_end(); I != E;) {
    if (!I->getCaseValue()->getValue().ugt(Constant->getValue())) {
      ++I;
      continue;
    }
    BasicBlock *DeadCaseBB = I->getCaseSuccessor();
    DeadCaseBB->removePredecessor(BB);
    I = SIW.removeCase(I);
    E = SIW->case_end();
    if (!is_contained(successors(BB), DeadCaseBB))
      Updates.push_back({DominatorTree::Delete, BB, DeadCaseBB});
  }

  auto Case = SI->findCaseValue(Constant);
  // If the case value is not found, `findCaseValue` returns the default case.
  // In this scenario, since there is no explicit `case 3:`, the simplification
  // fails. The simplification also fails when the switch’s default destination
  // is reachable.
  if (!SI->defaultDestUnreachable() || Case == SI->case_default()) {
    if (DTU)
      DTU->applyUpdates(Updates);
    return !Updates.empty();
  }

  BasicBlock *Unreachable = SI->getDefaultDest();
  SIW.replaceDefaultDest(Case);
  SIW.removeCase(Case);
  SIW->setCondition(A);

  Updates.push_back({DominatorTree::Delete, BB, Unreachable});

  if (DTU)
    DTU->applyUpdates(Updates);

  return true;
}

static bool simplifySwitchDefaultBranch(SwitchInst *SI, DomTreeUpdater *DTU,
                                        const DataLayout &DL,
                                        AssumptionCache *AC) {
  assert(SI);
  if (SI->defaultDestUnreachable())
    return false;

  // If it can be proved that the switch condition takes some concrete value
  // in the default block, we can make some nice simplifications to the
  // switch.
  BasicBlock *Default = SI->getDefaultDest();
  const Instruction *CtxI = &*Default->getFirstNonPHIIt();
  const KnownBits Known = computeKnownBits(
      SI->getCondition(),
      SimplifyQuery(DL, /*DT=*/nullptr, AC, CtxI).allowEphemerals(true));
  if (!Known.isConstant())
    return false;

  // At this point, we know that only one value can be mapped to the
  // default block. So, if a case doesn't exist for it already, we
  // can create one pointing to the default block.
  ConstantInt *CaseVal =
      ConstantInt::get(SI->getContext(), Known.getConstant());
  const llvm::SwitchInst::CaseIt CaseIt = SI->findCaseValue(CaseVal);
  if (CaseIt == SI->case_default()) {
    SwitchInstProfUpdateWrapper SIW(*SI);
    SIW.addCase(CaseVal, Default, SIW.getSuccessorWeight(0));
    SIW.setSuccessorWeight(0, 0);
  }
  // If there is a pre-existing case for the constant, the default branch
  // will be removed rather than being moved. Thus, we are removing an edge
  // in the CFG, and need to update any PHIs in the default block.
  createUnreachableSwitchDefault(SI, DTU, /*RemoveOrigDefaultBlock=*/CaseIt !=
                                              SI->case_default());

  assert(SI->getNumCases() > 0 && "Switch should have at least one case");
  assert(SI->findCaseValue(CaseVal) != SI->case_default() &&
         "Proven value should have a dedicated case");
  assert(SI->defaultDestUnreachable());
  return true;
}

/// Tries to transform switch of powers of two to reduce switch range.
/// For example, switch like:
/// switch (C) { case 1: case 2: case 64: case 128: }
/// will be transformed to:
/// switch (count_trailing_zeros(C)) { case 0: case 1: case 6: case 7: }
///
/// This transformation allows better lowering and may transform the switch
/// instruction into a sequence of bit manipulation and a smaller
/// log2(C)-indexed value table (instead of traditionally emitting a load of the
/// address of the jump target, and indirectly jump to it).
static bool simplifySwitchOfPowersOfTwo(SwitchInst *SI, IRBuilder<> &Builder,
                                        DomTreeUpdater *DTU,
                                        const DataLayout &DL,
                                        const TargetTransformInfo &TTI) {
  Value *Condition = SI->getCondition();
  LLVMContext &Context = SI->getContext();
  auto *CondTy = cast<IntegerType>(Condition->getType());

  if (CondTy->getIntegerBitWidth() > 64 ||
      !DL.fitsInLegalInteger(CondTy->getIntegerBitWidth()))
    return false;

  // Ensure trailing zeroes count intrinsic emission is not too expensive.
  IntrinsicCostAttributes Attrs(Intrinsic::cttz, CondTy,
                                {Condition, ConstantInt::getTrue(Context)});
  if (TTI.getIntrinsicInstrCost(Attrs, TTI::TCK_SizeAndLatency) >
      TTI::TCC_Basic * 2)
    return false;

  // Only bother with this optimization if there are more than 3 switch cases.
  // SDAG will start emitting jump tables for 4 or more cases.
  if (SI->getNumCases() < 4)
    return false;

  // Check that switch cases are powers of two.
  SmallVector<uint64_t, 4> Values;
  for (const auto &Case : SI->cases()) {
    uint64_t CaseValue = Case.getCaseValue()->getValue().getZExtValue();
    if (llvm::has_single_bit(CaseValue))
      Values.push_back(CaseValue);
    else
      return false;
  }

  // isSwichDense requires case values to be sorted.
  llvm::sort(Values);
  if (!isSwitchDense(Values.size(),
                     llvm::countr_zero(Values.back()) -
                         llvm::countr_zero(Values.front()) + 1,
                     SI->getFunction()->hasOptSize()))
    // Transform is unable to generate dense switch.
    return false;

  Builder.SetInsertPoint(SI);

  if (!SI->defaultDestUnreachable()) {
    // Let non-power-of-two inputs jump to the default case, when the latter is
    // reachable.
    auto *PopC = Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, Condition);
    auto *IsPow2 = Builder.CreateICmpEQ(PopC, ConstantInt::get(CondTy, 1));

    auto *OrigBB = SI->getParent();
    auto *DefaultCaseBB = SI->getDefaultDest();
    BasicBlock *SplitBB = SplitBlock(OrigBB, SI, DTU);
    auto It = OrigBB->getTerminator()->getIterator();
    SmallVector<uint32_t> Weights;
    auto HasWeights = extractBranchWeights(*SI, Weights);
    auto *BI = CondBrInst::Create(IsPow2, SplitBB, DefaultCaseBB, It);
    if (HasWeights && any_of(Weights, not_equal_to(0))) {
      // IsPow2 covers a subset of the cases in which we'd go to the default
      // label. The other is those powers of 2 that don't appear in the case
      // statement. We don't know the distribution of the values coming in, so
      // the safest is to split 50-50 the original probability to `default`.
      uint64_t OrigDenominator =
          sum_of(map_range(Weights, StaticCastTo<uint64_t>));
      SmallVector<uint64_t> NewWeights(2);
      NewWeights[1] = Weights[0] / 2;
      NewWeights[0] = OrigDenominator - NewWeights[1];
      setFittedBranchWeights(*BI, NewWeights, /*IsExpected=*/false);
      // The probability of executing the default block stays constant. It was
      //  p_d = Weights[0] / OrigDenominator
      //  we rewrite as W/D
      // We want to find the probability of the default branch of the switch
      // statement. Let's call it X. We have W/D = W/2D + X * (1-W/2D)
      // i.e. the original probability is the probability we go to the default
      // branch from the BI branch, or we take the default branch on the SI.
      // Meaning X = W / (2D - W), or (W/2) / (D - W/2)
      // This matches using W/2 for the default branch probability numerator and
      // D-W/2 as the denominator.
      Weights[0] = NewWeights[1];
      uint64_t CasesDenominator = OrigDenominator - Weights[0];
      for (auto &W : drop_begin(Weights))
        W = NewWeights[0] * static_cast<double>(W) / CasesDenominator;

      setBranchWeights(*SI, Weights, /*IsExpected=*/false);
    }
    // BI is handling the default case for SI, and so should share its DebugLoc.
    BI->setDebugLoc(SI->getDebugLoc());
    It->eraseFromParent();

    addPredecessorToBlock(DefaultCaseBB, OrigBB, SplitBB);
    if (DTU)
      DTU->applyUpdates({{DominatorTree::Insert, OrigBB, DefaultCaseBB}});
  }

  // Replace each case with its trailing zeros number.
  for (auto &Case : SI->cases()) {
    auto *OrigValue = Case.getCaseValue();
    Case.setValue(ConstantInt::get(OrigValue->getIntegerType(),
                                   OrigValue->getValue().countr_zero()));
  }

  // Replace condition with its trailing zeros number.
  auto *ConditionTrailingZeros = Builder.CreateIntrinsic(
      Intrinsic::cttz, {CondTy}, {Condition, ConstantInt::getTrue(Context)});

  SI->setCondition(ConditionTrailingZeros);

  return true;
}

/// Fold switch over ucmp/scmp intrinsic to br if two of the switch arms have
/// the same destination.
static bool simplifySwitchOfCmpIntrinsic(SwitchInst *SI, IRBuilderBase &Builder,
                                         DomTreeUpdater *DTU) {
  auto *Cmp = dyn_cast<CmpIntrinsic>(SI->getCondition());
  if (!Cmp || !Cmp->hasOneUse())
    return false;

  SmallVector<uint32_t, 4> Weights;
  bool HasWeights = extractBranchWeights(getBranchWeightMDNode(*SI), Weights);
  if (!HasWeights)
    Weights.resize(4); // Avoid checking HasWeights everywhere.

  // Normalize to [us]cmp == Res ? Succ : OtherSucc.
  int64_t Res;
  BasicBlock *Succ, *OtherSucc;
  uint32_t SuccWeight = 0, OtherSuccWeight = 0;
  BasicBlock *Unreachable = nullptr;

  if (SI->getNumCases() == 2) {
    // Find which of 1, 0 or -1 is missing (handled by default dest).
    SmallSet<int64_t, 3> Missing;
    Missing.insert(1);
    Missing.insert(0);
    Missing.insert(-1);

    Succ = SI->getDefaultDest();
    SuccWeight = Weights[0];
    OtherSucc = nullptr;
    for (auto &Case : SI->cases()) {
      std::optional<int64_t> Val =
          Case.getCaseValue()->getValue().trySExtValue();
      if (!Val)
        return false;
      if (!Missing.erase(*Val))
        return false;
      if (OtherSucc && OtherSucc != Case.getCaseSuccessor())
        return false;
      OtherSucc = Case.getCaseSuccessor();
      OtherSuccWeight += Weights[Case.getSuccessorIndex()];
    }

    assert(Missing.size() == 1 && "Should have one case left");
    Res = *Missing.begin();
  } else if (SI->getNumCases() == 3 && SI->defaultDestUnreachable()) {
    // Normalize so that Succ is taken once and OtherSucc twice.
    Unreachable = SI->getDefaultDest();
    Succ = OtherSucc = nullptr;
    for (auto &Case : SI->cases()) {
      BasicBlock *NewSucc = Case.getCaseSuccessor();
      uint32_t Weight = Weights[Case.getSuccessorIndex()];
      if (!OtherSucc || OtherSucc == NewSucc) {
        OtherSucc = NewSucc;
        OtherSuccWeight += Weight;
      } else if (!Succ) {
        Succ = NewSucc;
        SuccWeight = Weight;
      } else if (Succ == NewSucc) {
        std::swap(Succ, OtherSucc);
        std::swap(SuccWeight, OtherSuccWeight);
      } else
        return false;
    }
    for (auto &Case : SI->cases()) {
      std::optional<int64_t> Val =
          Case.getCaseValue()->getValue().trySExtValue();
      if (!Val || (Val != 1 && Val != 0 && Val != -1))
        return false;
      if (Case.getCaseSuccessor() == Succ) {
        Res = *Val;
        break;
      }
    }
  } else {
    return false;
  }

  // Determine predicate for the missing case.
  ICmpInst::Predicate Pred;
  switch (Res) {
  case 1:
    Pred = ICmpInst::ICMP_UGT;
    break;
  case 0:
    Pred = ICmpInst::ICMP_EQ;
    break;
  case -1:
    Pred = ICmpInst::ICMP_ULT;
    break;
  }
  if (Cmp->isSigned())
    Pred = ICmpInst::getSignedPredicate(Pred);

  MDNode *NewWeights = nullptr;
  if (HasWeights)
    NewWeights = MDBuilder(SI->getContext())
                     .createBranchWeights(SuccWeight, OtherSuccWeight);

  BasicBlock *BB = SI->getParent();
  Builder.SetInsertPoint(SI->getIterator());
  Value *ICmp = Builder.CreateICmp(Pred, Cmp->getLHS(), Cmp->getRHS());
  Builder.CreateCondBr(ICmp, Succ, OtherSucc, NewWeights,
                       SI->getMetadata(LLVMContext::MD_unpredictable));
  OtherSucc->removePredecessor(BB);
  if (Unreachable)
    Unreachable->removePredecessor(BB);
  SI->eraseFromParent();
  Cmp->eraseFromParent();
  if (DTU && Unreachable)
    DTU->applyUpdates({{DominatorTree::Delete, BB, Unreachable}});
  return true;
}

/// Checking whether two BBs are equal depends on the contents of the
/// BasicBlock and the incoming values of their successor PHINodes.
/// PHINode::getIncomingValueForBlock is O(|Preds|), so we'd like to avoid
/// calling this function on each BasicBlock every time isEqual is called,
/// especially since the same BasicBlock may be passed as an argument multiple
/// times. To do this, we can precompute a map of PHINode -> Pred BasicBlock ->
/// IncomingValue and add it in the Wrapper so isEqual can do O(1) checking
/// of the incoming values.
struct EqualBBWrapper {
  BasicBlock *BB;

  // One Phi usually has < 8 incoming values.
  using BB2ValueMap = SmallDenseMap<BasicBlock *, Value *, 8>;
  using Phi2IVsMap = DenseMap<PHINode *, BB2ValueMap>;
  Phi2IVsMap *PhiPredIVs;

  // We only merge the identical non-entry BBs with
  // - terminator unconditional br to Succ (pending relaxation),
  // - does not have address taken / weird control.
  static bool canBeMerged(const BasicBlock *BB) {
    assert(BB && "Expected non-null BB");
    // Entry block cannot be eliminated or have predecessors.
    if (BB->isEntryBlock())
      return false;

    // Single successor and must be Succ.
    // FIXME: Relax that the terminator is a BranchInst by checking for equality
    // on other kinds of terminators. We decide to only support unconditional
    // branches for now for compile time reasons.
    auto *BI = dyn_cast<UncondBrInst>(BB->getTerminator());
    if (!BI)
      return false;

    // Avoid blocks that are "address-taken" (blockaddress) or have unusual
    // uses.
    if (BB->hasAddressTaken() || BB->isEHPad())
      return false;

    // TODO: relax this condition to merge equal blocks with >1 instructions?
    // Here, we use a O(1) form of the O(n) comparison of `size() != 1`.
    if (&BB->front() != &BB->back())
      return false;

    // The BB must have at least one predecessor.
    if (pred_empty(BB))
      return false;

    return true;
  }
};

template <> struct llvm::DenseMapInfo<const EqualBBWrapper *> {
  static unsigned getHashValue(const EqualBBWrapper *EBW) {
    BasicBlock *BB = EBW->BB;
    UncondBrInst *BI = cast<UncondBrInst>(BB->getTerminator());
    assert(BB->size() == 1 && "Expected just a single branch in the BB");

    // Since we assume the BB is just a single UncondBrInst with a single
    // successor, we hash as the BB and the incoming Values of its successor
    // PHIs. Initially, we tried to just use the successor BB as the hash, but
    // including the incoming PHI values leads to better performance.
    // We also tried to build a map from BB -> Succs.IncomingValues ahead of
    // time and passing it in EqualBBWrapper, but this slowed down the average
    // compile time without having any impact on the worst case compile time.
    BasicBlock *Succ = BI->getSuccessor();
    auto PhiValsForBB = map_range(Succ->phis(), [&](PHINode &Phi) {
      return (*EBW->PhiPredIVs)[&Phi][BB];
    });
    return hash_combine(Succ, hash_combine_range(PhiValsForBB));
  }
  static bool isEqual(const EqualBBWrapper *LHS, const EqualBBWrapper *RHS) {
    BasicBlock *A = LHS->BB;
    BasicBlock *B = RHS->BB;

    // FIXME: we checked that the size of A and B are both 1 in
    // mergeIdenticalUncondBBs to make the Case list smaller to
    // improve performance. If we decide to support BasicBlocks with more
    // than just a single instruction, we need to check that A.size() ==
    // B.size() here, and we need to check more than just the BranchInsts
    // for equality.

    UncondBrInst *ABI = cast<UncondBrInst>(A->getTerminator());
    UncondBrInst *BBI = cast<UncondBrInst>(B->getTerminator());
    if (ABI->getSuccessor() != BBI->getSuccessor())
      return false;

    // Need to check that PHIs in successor have matching values.
    BasicBlock *Succ = ABI->getSuccessor();
    auto IfPhiIVMatch = [&](PHINode &Phi) {
      // Replace O(|Pred|) Phi.getIncomingValueForBlock with this O(1) hashmap
      // query.
      auto &PredIVs = (*LHS->PhiPredIVs)[&Phi];
      return PredIVs[A] == PredIVs[B];
    };
    return all_of(Succ->phis(), IfPhiIVMatch);
  }
};

// Merge identical BBs into one of them.
static bool mergeIdenticalBBs(ArrayRef<BasicBlock *> Candidates,
                              DomTreeUpdater *DTU) {
  if (Candidates.size() < 2)
    return false;

  // Build Cases. Skip BBs that are not candidates for simplification. Mark
  // PHINodes which need to be processed into PhiPredIVs. We decide to process
  // an entire PHI at once after the loop, opposed to calling
  // getIncomingValueForBlock inside this loop, since each call to
  // getIncomingValueForBlock is O(|Preds|).
  EqualBBWrapper::Phi2IVsMap PhiPredIVs;
  SmallVector<EqualBBWrapper> BBs2Merge;
  BBs2Merge.reserve(Candidates.size());
  SmallSetVector<PHINode *, 8> Phis;

  for (BasicBlock *BB : Candidates) {
    BasicBlock *Succ = BB->getSingleSuccessor();
    assert(Succ && "Expected unconditional BB");
    BBs2Merge.emplace_back(EqualBBWrapper{BB, &PhiPredIVs});
    Phis.insert_range(make_pointer_range(Succ->phis()));
  }

  // Precompute a data structure to improve performance of isEqual for
  // EqualBBWrapper.
  PhiPredIVs.reserve(Phis.size());
  for (PHINode *Phi : Phis) {
    auto &IVs =
        PhiPredIVs.try_emplace(Phi, Phi->getNumIncomingValues()).first->second;
    // Pre-fill all incoming for O(1) lookup as Phi.getIncomingValueForBlock is
    // O(|Pred|).
    for (auto &IV : Phi->incoming_values())
      IVs.insert({Phi->getIncomingBlock(IV), IV.get()});
  }

  // Group duplicates using DenseSet with custom equality/hashing.
  // Build a set such that if the EqualBBWrapper exists in the set and another
  // EqualBBWrapper isEqual, then the equivalent EqualBBWrapper which is not in
  // the set should be replaced with the one in the set. If the EqualBBWrapper
  // is not in the set, then it should be added to the set so other
  // EqualBBWrapper can check against it in the same manner. We use
  // EqualBBWrapper instead of just BasicBlock because we'd like to pass around
  // information to isEquality, getHashValue, and when doing the replacement
  // with better performance.
  DenseSet<const EqualBBWrapper *> Keep;
  Keep.reserve(BBs2Merge.size());

  SmallVector<DominatorTree::UpdateType> Updates;
  Updates.reserve(BBs2Merge.size() * 2);

  bool MadeChange = false;

  // Helper: redirect all edges X -> DeadPred to X -> LivePred.
  auto RedirectIncomingEdges = [&](BasicBlock *Dead, BasicBlock *Live) {
    SmallSetVector<BasicBlock *, 8> DeadPreds(llvm::from_range,
                                              predecessors(Dead));
    if (DTU) {
      // All predecessors of DeadPred (except the common predecessor) will be
      // moved to LivePred.
      Updates.reserve(Updates.size() + DeadPreds.size() * 2);
      SmallPtrSet<BasicBlock *, 16> LivePreds(llvm::from_range,
                                              predecessors(Live));
      for (BasicBlock *PredOfDead : DeadPreds) {
        // Do not modify those common predecessors of DeadPred and LivePred.
        if (!LivePreds.contains(PredOfDead))
          Updates.push_back({DominatorTree::Insert, PredOfDead, Live});
        Updates.push_back({DominatorTree::Delete, PredOfDead, Dead});
      }
    }
    LLVM_DEBUG(dbgs() << "Replacing duplicate pred BB ";
               Dead->printAsOperand(dbgs()); dbgs() << " with pred ";
               Live->printAsOperand(dbgs()); dbgs() << " for ";
               Live->getSingleSuccessor()->printAsOperand(dbgs());
               dbgs() << "\n");
    // Replace successors in all predecessors of DeadPred.
    for (BasicBlock *PredOfDead : DeadPreds) {
      Instruction *T = PredOfDead->getTerminator();
      T->replaceSuccessorWith(Dead, Live);
    }
  };

  // Try to eliminate duplicate predecessors.
  for (const auto &EBW : BBs2Merge) {
    // EBW is a candidate for simplification. If we find a duplicate BB,
    // replace it.
    const auto &[It, Inserted] = Keep.insert(&EBW);
    if (Inserted)
      continue;

    // Found duplicate: merge P into canonical predecessor It->Pred.
    BasicBlock *KeepBB = (*It)->BB;
    BasicBlock *DeadBB = EBW.BB;

    // Avoid merging a BB with itself.
    if (KeepBB == DeadBB)
      continue;

    // Redirect all edges into DeadPred to KeepPred.
    RedirectIncomingEdges(DeadBB, KeepBB);

    // Now DeadBB should become unreachable; leave DCE to later,
    // but we can try to simplify it if it only branches to Succ.
    // (We won't erase here to keep the routine simple and DT-safe.)
    assert(pred_empty(DeadBB) && "DeadBB should be unreachable.");
    MadeChange = true;
  }

  if (DTU && !Updates.empty())
    DTU->applyUpdates(Updates);

  return MadeChange;
}

bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
                                                 DomTreeUpdater *DTU) {
  // Collect candidate switch-arms top-down.
  SmallSetVector<BasicBlock *, 16> FilteredArms(
      llvm::from_range,
      make_filter_range(successors(SI), EqualBBWrapper::canBeMerged));
  return mergeIdenticalBBs(FilteredArms.getArrayRef(), DTU);
}

bool SimplifyCFGOpt::simplifyDuplicatePredecessors(BasicBlock *BB,
                                                   DomTreeUpdater *DTU) {
  // Need at least 2 predecessors to do anything.
  if (!BB || !BB->hasNPredecessorsOrMore(2))
    return false;

  // Compilation time consideration: retain the canonical loop, otherwise, we
  // require more time in the later loop canonicalization.
  if (Options.NeedCanonicalLoop && is_contained(LoopHeaders, BB))
    return false;

  // Collect candidate predecessors bottom-up.
  SmallSetVector<BasicBlock *, 8> FilteredPreds(
      llvm::from_range,
      make_filter_range(predecessors(BB), EqualBBWrapper::canBeMerged));
  return mergeIdenticalBBs(FilteredPreds.getArrayRef(), DTU);
}

bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
  BasicBlock *BB = SI->getParent();

  if (isValueEqualityComparison(SI)) {
    // If we only have one predecessor, and if it is a branch on this value,
    // see if that predecessor totally determines the outcome of this switch.
    if (BasicBlock *OnlyPred = BB->getSinglePredecessor())
      if (simplifyEqualityComparisonWithOnlyPredecessor(SI, OnlyPred, Builder))
        return requestResimplify();

    Value *Cond = SI->getCondition();
    if (SelectInst *Select = dyn_cast<SelectInst>(Cond))
      if (simplifySwitchOnSelect(SI, Select))
        return requestResimplify();

    // If the block only contains the switch, see if we can fold the block
    // away into any preds.
    if (SI == &*BB->begin())
      if (foldValueComparisonIntoPredecessors(SI, Builder))
        return requestResimplify();
  }

  // Try to transform the switch into an icmp and a branch.
  // The conversion from switch to comparison may lose information on
  // impossible switch values, so disable it early in the pipeline.
  if (Options.ConvertSwitchRangeToICmp && turnSwitchRangeIntoICmp(SI, Builder))
    return requestResimplify();

  // Remove unreachable cases.
  if (eliminateDeadSwitchCases(SI, DTU, Options.AC, DL))
    return requestResimplify();

  if (simplifySwitchOfCmpIntrinsic(SI, Builder, DTU))
    return requestResimplify();

  if (trySwitchToSelect(SI, Builder, DTU, DL))
    return requestResimplify();

  if (Options.ForwardSwitchCondToPhi && forwardSwitchConditionToPHI(SI))
    return requestResimplify();

  // The conversion of switches to arithmetic or lookup table is disabled in
  // the early optimization pipeline, as it may lose information or make the
  // resulting code harder to analyze.
  if (Options.ConvertSwitchToArithmetic || Options.ConvertSwitchToLookupTable)
    if (simplifySwitchLookup(SI, Builder, DTU, DL, TTI,
                             Options.ConvertSwitchToLookupTable))
      return requestResimplify();

  if (simplifySwitchOfPowersOfTwo(SI, Builder, DTU, DL, TTI))
    return requestResimplify();

  if (reduceSwitchRange(SI, Builder, DL, TTI))
    return requestResimplify();

  if (HoistCommon &&
      hoistCommonCodeFromSuccessors(SI, !Options.HoistCommonInsts))
    return requestResimplify();

  // We can merge identical switch arms early to enhance more aggressive
  // optimization on switch.
  if (simplifyDuplicateSwitchArms(SI, DTU))
    return requestResimplify();

  if (simplifySwitchWhenUMin(SI, DTU))
    return requestResimplify();

  if (simplifySwitchDefaultBranch(SI, DTU, DL, Options.AC))
    return requestResimplify();

  return false;
}

bool SimplifyCFGOpt::simplifyIndirectBr(IndirectBrInst *IBI) {
  BasicBlock *BB = IBI->getParent();
  bool Changed = false;
  SmallVector<uint32_t> BranchWeights;
  const bool HasBranchWeights = extractBranchWeights(*IBI, BranchWeights);

  DenseMap<const BasicBlock *, uint64_t> TargetWeight;
  if (HasBranchWeights)
    for (size_t I = 0, E = IBI->getNumDestinations(); I < E; ++I)
      TargetWeight[IBI->getDestination(I)] += BranchWeights[I];

  // Eliminate redundant destinations.
  SmallPtrSet<Value *, 8> Succs;
  SmallSetVector<BasicBlock *, 8> RemovedSuccs;
  for (unsigned I = 0, E = IBI->getNumDestinations(); I != E; ++I) {
    BasicBlock *Dest = IBI->getDestination(I);
    if (!Dest->hasAddressTaken() || !Succs.insert(Dest).second) {
      if (!Dest->hasAddressTaken())
        RemovedSuccs.insert(Dest);
      Dest->removePredecessor(BB);
      IBI->removeDestination(I);
      --I;
      --E;
      Changed = true;
    }
  }

  if (DTU) {
    std::vector<DominatorTree::UpdateType> Updates;
    Updates.reserve(RemovedSuccs.size());
    for (auto *RemovedSucc : RemovedSuccs)
      Updates.push_back({DominatorTree::Delete, BB, RemovedSucc});
    DTU->applyUpdates(Updates);
  }

  if (IBI->getNumDestinations() == 0) {
    // If the indirectbr has no successors, change it to unreachable.
    new UnreachableInst(IBI->getContext(), IBI->getIterator());
    eraseTerminatorAndDCECond(IBI);
    return true;
  }

  if (IBI->getNumDestinations() == 1) {
    // If the indirectbr has one successor, change it to a direct branch.
    UncondBrInst::Create(IBI->getDestination(0), IBI->getIterator());
    eraseTerminatorAndDCECond(IBI);
    return true;
  }
  if (HasBranchWeights) {
    SmallVector<uint64_t> NewBranchWeights(IBI->getNumDestinations());
    for (size_t I = 0, E = IBI->getNumDestinations(); I < E; ++I)
      NewBranchWeights[I] += TargetWeight.find(IBI->getDestination(I))->second;
    setFittedBranchWeights(*IBI, NewBranchWeights, /*IsExpected=*/false);
  }
  if (SelectInst *SI = dyn_cast<SelectInst>(IBI->getAddress())) {
    if (simplifyIndirectBrOnSelect(IBI, SI))
      return requestResimplify();
  }
  return Changed;
}

/// Given an block with only a single landing pad and a unconditional branch
/// try to find another basic block which this one can be merged with.  This
/// handles cases where we have multiple invokes with unique landing pads, but
/// a shared handler.
///
/// We specifically choose to not worry about merging non-empty blocks
/// here.  That is a PRE/scheduling problem and is best solved elsewhere.  In
/// practice, the optimizer produces empty landing pad blocks quite frequently
/// when dealing with exception dense code.  (see: instcombine, gvn, if-else
/// sinking in this file)
///
/// This is primarily a code size optimization.  We need to avoid performing
/// any transform which might inhibit optimization (such as our ability to
/// specialize a particular handler via tail commoning).  We do this by not
/// merging any blocks which require us to introduce a phi.  Since the same
/// values are flowing through both blocks, we don't lose any ability to
/// specialize.  If anything, we make such specialization more likely.
///
/// Phis in the successor are allowed if both blocks pass the same value, or
/// each passes its own landing pad value and that is its only use: the merged
/// block's landing pad then carries the value for both edges.
static bool tryToMergeLandingPad(LandingPadInst *LPad, UncondBrInst *BI,
                                 BasicBlock *BB, DomTreeUpdater *DTU) {
  auto Succ = BB->getUniqueSuccessor();
  assert(Succ);

  for (BasicBlock *OtherPred : predecessors(Succ)) {
    if (BB == OtherPred)
      continue;
    BasicBlock::iterator I = OtherPred->begin();
    LandingPadInst *LPad2 = dyn_cast<LandingPadInst>(I);
    if (!LPad2 || !LPad2->isIdenticalTo(LPad))
      continue;
    ++I;
    UncondBrInst *BI2 = dyn_cast<UncondBrInst>(I);
    if (!BI2 || !BI2->isIdenticalTo(BI))
      continue;

    // Merging must not require a new phi in the merged landing pad block.
    if (!all_of(Succ->phis(), [&](PHINode &PN) {
          Value *V = PN.getIncomingValueForBlock(BB);
          Value *V2 = PN.getIncomingValueForBlock(OtherPred);
          return V == V2 || (V == LPad && V2 == LPad2);
        }))
      continue;

    // Those phis must be the only uses of the landing pads. Otherwise, with a
    // loop through Succ, a use would be clobbered when the merged pad is
    // re-entered.
    unsigned NumLPadPhis = count_if(Succ->phis(), [&](PHINode &PN) {
      return PN.getIncomingValueForBlock(BB) == LPad;
    });
    if (!LPad->hasNUses(NumLPadPhis) || !LPad2->hasNUses(NumLPadPhis))
      continue;

    std::vector<DominatorTree::UpdateType> Updates;

    // We've found an identical block.  Update our predecessors to take that
    // path instead and make ourselves dead.
    SmallSetVector<BasicBlock *, 16> UniquePreds(pred_begin(BB), pred_end(BB));
    for (BasicBlock *Pred : UniquePreds) {
      InvokeInst *II = cast<InvokeInst>(Pred->getTerminator());
      assert(II->getNormalDest() != BB && II->getUnwindDest() == BB &&
             "unexpected successor");
      II->setUnwindDest(OtherPred);
      if (DTU) {
        Updates.push_back({DominatorTree::Insert, Pred, OtherPred});
        Updates.push_back({DominatorTree::Delete, Pred, BB});
      }
    }

    SmallSetVector<BasicBlock *, 16> UniqueSuccs(succ_begin(BB), succ_end(BB));
    for (BasicBlock *Succ : UniqueSuccs) {
      Succ->removePredecessor(BB);
      if (DTU)
        Updates.push_back({DominatorTree::Delete, BB, Succ});
    }

    IRBuilder<> Builder(BI);
    Builder.CreateUnreachable();
    BI->eraseFromParent();
    if (DTU)
      DTU->applyUpdates(Updates);
    return true;
  }
  return false;
}

bool SimplifyCFGOpt::simplifyUncondBranch(UncondBrInst *BI,
                                          IRBuilder<> &Builder) {
  BasicBlock *BB = BI->getParent();
  BasicBlock *Succ = BI->getSuccessor(0);

  // If the Terminator is the only non-phi instruction, simplify the block.
  // If LoopHeader is provided, check if the block or its successor is a loop
  // header. (This is for early invocations before loop simplify and
  // vectorization to keep canonical loop forms for nested loops. These blocks
  // can be eliminated when the pass is invoked later in the back-end.)
  // Note that if BB has only one predecessor then we do not introduce new
  // backedge, so we can eliminate BB.
  bool NeedCanonicalLoop =
      Options.NeedCanonicalLoop &&
      (!LoopHeaders.empty() && BB->hasNPredecessorsOrMore(2) &&
       (is_contained(LoopHeaders, BB) || is_contained(LoopHeaders, Succ)));
  BasicBlock::iterator I = BB->getFirstNonPHIOrPseudoProbe();
  if (I->isTerminator() && BB != &BB->getParent()->getEntryBlock() &&
      !NeedCanonicalLoop && TryToSimplifyUncondBranchFromEmptyBlock(BB, DTU))
    return true;

  // If the only instruction in the block is a seteq/setne comparison against a
  // constant, try to simplify the block.
  if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) {
    if (ICI->isEquality() && isa<ConstantInt>(ICI->getOperand(1))) {
      ++I;
      if (I->isTerminator() &&
          tryToSimplifyUncondBranchWithICmpInIt(ICI, Builder))
        return true;
      if (isa<SelectInst>(I) && I->getNextNode()->isTerminator() &&
          tryToSimplifyUncondBranchWithICmpSelectInIt(ICI, cast<SelectInst>(I),
                                                      Builder))
        return true;
    }
  }

  // See if we can merge an empty landing pad block with another which is
  // equivalent.
  if (LandingPadInst *LPad = dyn_cast<LandingPadInst>(I)) {
    ++I;
    if (I->isTerminator() && tryToMergeLandingPad(LPad, BI, BB, DTU))
      return true;
  }

  return false;
}

static BasicBlock *allPredecessorsComeFromSameSource(BasicBlock *BB) {
  BasicBlock *PredPred = nullptr;
  for (auto *P : predecessors(BB)) {
    BasicBlock *PPred = P->getSinglePredecessor();
    if (!PPred || (PredPred && PredPred != PPred))
      return nullptr;
    PredPred = PPred;
  }
  return PredPred;
}

/// Fold the following pattern:
/// bb0:
///   br i1 %cond1, label %bb1, label %bb2
/// bb1:
///   br i1 %cond2, label %bb3, label %bb4
/// bb2:
///   br i1 %cond2, label %bb4, label %bb3
/// bb3:
///   ...
/// bb4:
///   ...
/// into
/// bb0:
///   %cond = xor i1 %cond1, %cond2
///   br i1 %cond, label %bb4, label %bb3
/// bb3:
///   ...
/// bb4:
///   ...
/// NOTE: %cond2 always dominates the terminator of bb0.
static bool mergeNestedCondBranch(CondBrInst *BI, DomTreeUpdater *DTU) {
  BasicBlock *BB = BI->getParent();
  BasicBlock *BB1 = BI->getSuccessor(0);
  BasicBlock *BB2 = BI->getSuccessor(1);
  auto IsSimpleSuccessor = [BB](BasicBlock *Succ, CondBrInst *&SuccBI) {
    if (Succ == BB)
      return false;
    if (&Succ->front() != Succ->getTerminator())
      return false;
    SuccBI = dyn_cast<CondBrInst>(Succ->getTerminator());
    if (!SuccBI)
      return false;
    BasicBlock *Succ1 = SuccBI->getSuccessor(0);
    BasicBlock *Succ2 = SuccBI->getSuccessor(1);
    return Succ1 != Succ && Succ2 != Succ && Succ1 != BB && Succ2 != BB &&
           !isa<PHINode>(Succ1->front()) && !isa<PHINode>(Succ2->front());
  };
  CondBrInst *BB1BI, *BB2BI;
  if (!IsSimpleSuccessor(BB1, BB1BI) || !IsSimpleSuccessor(BB2, BB2BI))
    return false;

  if (BB1BI->getCondition() != BB2BI->getCondition() ||
      BB1BI->getSuccessor(0) != BB2BI->getSuccessor(1) ||
      BB1BI->getSuccessor(1) != BB2BI->getSuccessor(0))
    return false;

  BasicBlock *BB3 = BB1BI->getSuccessor(0);
  BasicBlock *BB4 = BB1BI->getSuccessor(1);
  // Bail out on trivial cases to avoid bothering to handle the special case in
  // the code below.
  if (BB3 == BB4)
    return false;
  IRBuilder<> Builder(BI);
  BI->setCondition(
      Builder.CreateXor(BI->getCondition(), BB1BI->getCondition()));
  BB1->removePredecessor(BB);
  BI->setSuccessor(0, BB4);
  BB2->removePredecessor(BB);
  BI->setSuccessor(1, BB3);
  if (DTU) {
    SmallVector<DominatorTree::UpdateType, 4> Updates;
    Updates.push_back({DominatorTree::Delete, BB, BB1});
    Updates.push_back({DominatorTree::Insert, BB, BB4});
    Updates.push_back({DominatorTree::Delete, BB, BB2});
    Updates.push_back({DominatorTree::Insert, BB, BB3});

    DTU->applyUpdates(Updates);
  }
  bool HasWeight = false;
  uint64_t BBTWeight, BBFWeight;
  if (extractBranchWeights(*BI, BBTWeight, BBFWeight))
    HasWeight = true;
  else
    BBTWeight = BBFWeight = 1;
  uint64_t BB1TWeight, BB1FWeight;
  if (extractBranchWeights(*BB1BI, BB1TWeight, BB1FWeight))
    HasWeight = true;
  else
    BB1TWeight = BB1FWeight = 1;
  uint64_t BB2TWeight, BB2FWeight;
  if (extractBranchWeights(*BB2BI, BB2TWeight, BB2FWeight))
    HasWeight = true;
  else
    BB2TWeight = BB2FWeight = 1;
  if (HasWeight) {
    uint64_t Weights[2] = {BBTWeight * BB1FWeight + BBFWeight * BB2TWeight,
                           BBTWeight * BB1TWeight + BBFWeight * BB2FWeight};
    setFittedBranchWeights(*BI, Weights, /*IsExpected=*/false,
                           /*ElideAllZero=*/true);
  }
  return true;
}

bool SimplifyCFGOpt::simplifyCondBranch(CondBrInst *BI, IRBuilder<> &Builder) {
  assert(
      !isa<ConstantInt>(BI->getCondition()) &&
      BI->getSuccessor(0) != BI->getSuccessor(1) &&
      "Tautological conditional branch should have been eliminated already.");

  BasicBlock *BB = BI->getParent();
  if (!Options.SimplifyCondBranch ||
      BI->getFunction()->hasFnAttribute(Attribute::OptForFuzzing))
    return false;

  // Conditional branch
  if (isValueEqualityComparison(BI)) {
    // If we only have one predecessor, and if it is a branch on this value,
    // see if that predecessor totally determines the outcome of this
    // switch.
    if (BasicBlock *OnlyPred = BB->getSinglePredecessor())
      if (simplifyEqualityComparisonWithOnlyPredecessor(BI, OnlyPred, Builder))
        return requestResimplify();

    // This block must be empty, except for the setcond inst, if it exists.
    // Ignore pseudo intrinsics.
    for (auto &I : *BB) {
      if (isa<PseudoProbeInst>(I) ||
          &I == cast<Instruction>(BI->getCondition()))
        continue;
      if (&I == BI)
        if (foldValueComparisonIntoPredecessors(BI, Builder))
          return requestResimplify();
      break;
    }
  }

  // Try to turn "br (X == 0 | X == 1), T, F" into a switch instruction.
  if (simplifyBranchOnICmpChain(BI, Builder, DL))
    return true;

  // If this basic block has dominating predecessor blocks and the dominating
  // blocks' conditions imply BI's condition, we know the direction of BI.
  std::optional<bool> Imp = isImpliedByDomCondition(BI->getCondition(), BI, DL);
  if (Imp) {
    // Turn this into a branch on constant.
    auto *OldCond = BI->getCondition();
    ConstantInt *TorF = *Imp ? ConstantInt::getTrue(BB->getContext())
                             : ConstantInt::getFalse(BB->getContext());
    BI->setCondition(TorF);
    RecursivelyDeleteTriviallyDeadInstructions(OldCond);
    return requestResimplify();
  }

  // If this basic block is ONLY a compare and a branch, and if a predecessor
  // branches to us and one of our successors, fold the comparison into the
  // predecessor and use logical operations to pick the right destination.
  if (Options.SpeculateBlocks &&
      foldBranchToCommonDest(BI, DTU, /*MSSAU=*/nullptr, &TTI, Options.AC,
                             Options.BonusInstThreshold))
    return requestResimplify();

  // We have a conditional branch to two blocks that are only reachable
  // from BI.  We know that the condbr dominates the two blocks, so see if
  // there is any identical code in the "then" and "else" blocks.  If so, we
  // can hoist it up to the branching block.
  if (BI->getSuccessor(0)->getSinglePredecessor()) {
    if (BI->getSuccessor(1)->getSinglePredecessor()) {
      if (HoistCommon &&
          hoistCommonCodeFromSuccessors(BI, !Options.HoistCommonInsts))
        return requestResimplify();

      if (BI && Options.HoistLoadsStoresWithCondFaulting &&
          isProfitableToSpeculate(BI, std::nullopt, TTI)) {
        SmallVector<Instruction *, 2> SpeculatedConditionalLoadsStores;
        auto CanSpeculateConditionalLoadsStores = [&]() {
          for (auto *Succ : successors(BB)) {
            for (Instruction &I : *Succ) {
              if (I.isTerminator()) {
                if (I.getNumSuccessors() > 1)
                  return false;
                continue;
              } else if (!isSafeCheapLoadStore(&I, TTI) ||
                         SpeculatedConditionalLoadsStores.size() ==
                             HoistLoadsStoresWithCondFaultingThreshold) {
                return false;
              }
              SpeculatedConditionalLoadsStores.push_back(&I);
            }
          }
          return !SpeculatedConditionalLoadsStores.empty();
        };

        if (CanSpeculateConditionalLoadsStores()) {
          hoistConditionalLoadsStores(BI, SpeculatedConditionalLoadsStores,
                                      std::nullopt, nullptr);
          return requestResimplify();
        }
      }
    } else {
      // If Successor #1 has multiple preds, we may be able to conditionally
      // execute Successor #0 if it branches to Successor #1.
      Instruction *Succ0TI = BI->getSuccessor(0)->getTerminator();
      if (Succ0TI->getNumSuccessors() == 1 &&
          Succ0TI->getSuccessor(0) == BI->getSuccessor(1))
        if (speculativelyExecuteBB(BI, BI->getSuccessor(0)))
          return requestResimplify();
    }
  } else if (BI->getSuccessor(1)->getSinglePredecessor()) {
    // If Successor #0 has multiple preds, we may be able to conditionally
    // execute Successor #1 if it branches to Successor #0.
    Instruction *Succ1TI = BI->getSuccessor(1)->getTerminator();
    if (Succ1TI->getNumSuccessors() == 1 &&
        Succ1TI->getSuccessor(0) == BI->getSuccessor(0))
      if (speculativelyExecuteBB(BI, BI->getSuccessor(1)))
        return requestResimplify();
  }

  // If this is a branch on something for which we know the constant value in
  // predecessors (e.g. a phi node in the current block), thread control
  // through this block.
  if (foldCondBranchOnValueKnownInPredecessor(BI))
    return requestResimplify();

  // Scan predecessor blocks for conditional branches.
  for (BasicBlock *Pred : predecessors(BB))
    if (CondBrInst *PBI = dyn_cast<CondBrInst>(Pred->getTerminator()))
      if (PBI != BI)
        if (SimplifyCondBranchToCondBranch(PBI, BI, DTU, DL, TTI))
          return requestResimplify();

  // Look for diamond patterns.
  if (MergeCondStores)
    if (BasicBlock *PrevBB = allPredecessorsComeFromSameSource(BB))
      if (CondBrInst *PBI = dyn_cast<CondBrInst>(PrevBB->getTerminator()))
        if (PBI != BI)
          if (mergeConditionalStores(PBI, BI, DTU, DL, TTI))
            return requestResimplify();

  // Look for nested conditional branches.
  if (mergeNestedCondBranch(BI, DTU))
    return requestResimplify();

  return false;
}

/// Check if passing a value to an instruction will cause undefined behavior.
static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified) {
  assert(V->getType() == I->getType() && "Mismatched types");
  Constant *C = dyn_cast<Constant>(V);
  if (!C)
    return false;

  if (I->use_empty())
    return false;

  if (C->isNullValue() || isa<UndefValue>(C)) {
    // Find the first same-block use with a UB-triggering opcode, skipping
    // cross-block or before-I uses.
    auto FindUse = llvm::find_if(I->uses(), [I](auto &U) {
      auto *Use = cast<Instruction>(U.getUser());
      // Only same-block uses after I can witness UB at I's program point.
      // Self-uses and before-I uses can occur when I is a PHI node.
      if (Use->getParent() != I->getParent() || Use == I || Use->comesBefore(I))
        return false;
      // Change this list when we want to add new instructions.
      switch (Use->getOpcode()) {
      default:
        return false;
      case Instruction::GetElementPtr:
      case Instruction::Ret:
      case Instruction::BitCast:
      case Instruction::Load:
      case Instruction::Store:
      case Instruction::Call:
      case Instruction::CallBr:
      case Instruction::Invoke:
      case Instruction::UDiv:
      case Instruction::URem:
        // Note: signed div/rem of INT_MIN / -1 is also immediate UB, not
        // implemented to avoid code complexity as it is unclear how useful such
        // logic is.
      case Instruction::SDiv:
      case Instruction::SRem:
        return true;
      }
    });
    if (FindUse == I->use_end())
      return false;
    auto &Use = *FindUse;
    auto *User = cast<Instruction>(Use.getUser());

    // Now make sure that there are no instructions in between that can alter
    // control flow (eg. calls)
    auto InstrRange =
        make_range(std::next(I->getIterator()), User->getIterator());
    if (any_of(InstrRange, [](Instruction &I) {
          return !isGuaranteedToTransferExecutionToSuccessor(&I);
        }))
      return false;

    // Look through GEPs. A load from a GEP derived from NULL is still undefined
    if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User))
      if (GEP->getPointerOperand() == I) {
        // The type of GEP may differ from the type of base pointer.
        // Bail out on vector GEPs, as they are not handled by other checks.
        if (GEP->getType()->isVectorTy())
          return false;
        // The current base address is null, there are four cases to consider:
        // getelementptr (TY, null, 0)                 -> null
        // getelementptr (TY, null, not zero)          -> may be modified
        // getelementptr inbounds (TY, null, 0)        -> null
        // getelementptr inbounds (TY, null, not zero) -> poison iff null is
        // undefined?
        if (!GEP->hasAllZeroIndices() &&
            (!GEP->isInBounds() ||
             NullPointerIsDefined(GEP->getFunction(),
                                  GEP->getPointerAddressSpace())))
          PtrValueMayBeModified = true;
        return passingValueIsAlwaysUndefined(V, GEP, PtrValueMayBeModified);
      }

    // Look through return.
    if (ReturnInst *Ret = dyn_cast<ReturnInst>(User)) {
      bool HasNoUndefAttr =
          Ret->getFunction()->hasRetAttribute(Attribute::NoUndef);
      // Return undefined to a noundef return value is undefined.
      if (isa<UndefValue>(C) && HasNoUndefAttr)
        return true;
      // Return null to a nonnull+noundef return value is undefined.
      if (C->isNullValue() && HasNoUndefAttr &&
          Ret->getFunction()->hasRetAttribute(Attribute::NonNull)) {
        return !PtrValueMayBeModified;
      }
    }

    // Load from null is undefined.
    if (LoadInst *LI = dyn_cast<LoadInst>(User))
      if (!LI->isVolatile())
        return !NullPointerIsDefined(LI->getFunction(),
                                     LI->getPointerAddressSpace());

    // Store to null is undefined.
    if (StoreInst *SI = dyn_cast<StoreInst>(User))
      if (!SI->isVolatile())
        return (!NullPointerIsDefined(SI->getFunction(),
                                      SI->getPointerAddressSpace())) &&
               SI->getPointerOperand() == I;

    // llvm.assume(false/undef) always triggers immediate UB.
    if (auto *Assume = dyn_cast<AssumeInst>(User)) {
      // Ignore assume operand bundles.
      if (I == Assume->getArgOperand(0))
        return true;
    }

    if (auto *CB = dyn_cast<CallBase>(User)) {
      if (C->isNullValue() && NullPointerIsDefined(CB->getFunction()))
        return false;
      // A call to null is undefined.
      if (CB->getCalledOperand() == I)
        return true;

      if (CB->isArgOperand(&Use)) {
        unsigned ArgIdx = CB->getArgOperandNo(&Use);
        // Passing null to a nonnnull+noundef argument is undefined.
        if (isa<ConstantPointerNull>(C) && C->getType()->isPointerTy() &&
            CB->paramHasNonNullAttr(ArgIdx, /*AllowUndefOrPoison=*/false))
          return !PtrValueMayBeModified;
        // Passing undef to a noundef argument is undefined.
        if (isa<UndefValue>(C) && CB->isPassingUndefUB(ArgIdx))
          return true;
      }
    }
    // Div/Rem by zero is immediate UB
    if (match(User, m_BinOp(m_Value(), m_Specific(I))) && User->isIntDivRem())
      return true;
  }
  return false;
}

/// If BB has an incoming value that will always trigger undefined behavior
/// (eg. null pointer dereference), remove the branch leading here.
static bool removeUndefIntroducingPredecessor(BasicBlock *BB,
                                              DomTreeUpdater *DTU,
                                              AssumptionCache *AC) {
  for (PHINode &PHI : BB->phis())
    for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i)
      if (passingValueIsAlwaysUndefined(PHI.getIncomingValue(i), &PHI)) {
        BasicBlock *Predecessor = PHI.getIncomingBlock(i);
        Instruction *T = Predecessor->getTerminator();
        IRBuilder<> Builder(T);
        if (isa<UncondBrInst>(T)) {
          BB->removePredecessor(Predecessor);
          // Turn unconditional branches into unreachables.
          Builder.CreateUnreachable();
          T->eraseFromParent();
          if (DTU)
            DTU->applyUpdates({{DominatorTree::Delete, Predecessor, BB}});
          return true;
        } else if (CondBrInst *BI = dyn_cast<CondBrInst>(T)) {
          BB->removePredecessor(Predecessor);
          // Handle degenerate conditional branches.
          if (BI->getSuccessor(0) == BI->getSuccessor(1)) {
            // The only difference from the UncondBrInst path above is that it
            // has two edges in CFG.
            BB->removePredecessor(Predecessor);
            // Turn unconditional branches into unreachables.
            Builder.CreateUnreachable();
          } else {
            // Preserve guarding condition in assume, because it might not be
            // inferrable from any dominating condition.
            Value *Cond = BI->getCondition();
            CallInst *Assumption;
            if (BI->getSuccessor(0) == BB)
              Assumption = Builder.CreateAssumption(Builder.CreateNot(Cond));
            else
              Assumption = Builder.CreateAssumption(Cond);
            if (AC)
              AC->registerAssumption(cast<AssumeInst>(Assumption));
            Builder.CreateBr(BI->getSuccessor(0) == BB ? BI->getSuccessor(1)
                                                       : BI->getSuccessor(0));
          }
          BI->eraseFromParent();
          if (DTU)
            DTU->applyUpdates({{DominatorTree::Delete, Predecessor, BB}});
          return true;
        } else if (SwitchInst *SI = dyn_cast<SwitchInst>(T)) {
          // Redirect all branches leading to UB into
          // a newly created unreachable block.
          BasicBlock *Unreachable = BasicBlock::Create(
              Predecessor->getContext(), "unreachable", BB->getParent(), BB);
          Builder.SetInsertPoint(Unreachable);
          // The new block contains only one instruction: Unreachable
          Builder.CreateUnreachable();
          for (const auto &Case : SI->cases())
            if (Case.getCaseSuccessor() == BB) {
              BB->removePredecessor(Predecessor);
              Case.setSuccessor(Unreachable);
            }
          if (SI->getDefaultDest() == BB) {
            BB->removePredecessor(Predecessor);
            SI->setDefaultDest(Unreachable);
          }

          if (DTU)
            DTU->applyUpdates(
                { { DominatorTree::Insert, Predecessor, Unreachable },
                  { DominatorTree::Delete, Predecessor, BB } });
          return true;
        }
      }

  return false;
}

bool SimplifyCFGOpt::simplifyOnce(BasicBlock *BB) {
  bool Changed = false;

  assert(BB && BB->getParent() && "Block not embedded in function!");
  assert(BB->hasTerminator() && "Degenerate basic block encountered!");

  // Remove basic blocks that have no predecessors (except the entry block)...
  // or that just have themself as a predecessor.  These are unreachable.
  if ((pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) ||
      BB->getSinglePredecessor() == BB) {
    LLVM_DEBUG(dbgs() << "Removing BB: \n" << *BB);
    DeleteDeadBlock(BB, DTU);
    return true;
  }

  // Check to see if we can constant propagate this terminator instruction
  // away...
  Changed |= ConstantFoldTerminator(BB, /*DeleteDeadConditions=*/true,
                                    /*TLI=*/nullptr, DTU);

  // Check for and eliminate duplicate PHI nodes in this block.
  Changed |= EliminateDuplicatePHINodes(BB);

  // Check for and remove branches that will always cause undefined behavior.
  if (removeUndefIntroducingPredecessor(BB, DTU, Options.AC))
    return requestResimplify();

  // Merge basic blocks into their predecessor if there is only one distinct
  // pred, and if there is only one distinct successor of the predecessor, and
  // if there are no PHI nodes.
  if (MergeBlockIntoPredecessor(BB, DTU))
    return true;

  if (SinkCommon && Options.SinkCommonInsts) {
    if (sinkCommonCodeFromPredecessors(BB, DTU) ||
        mergeCompatibleInvokes(BB, DTU)) {
      // sinkCommonCodeFromPredecessors() does not automatically CSE PHI's,
      // so we may now how duplicate PHI's.
      // Let's rerun EliminateDuplicatePHINodes() first,
      // before foldTwoEntryPHINode() potentially converts them into select's,
      // after which we'd need a whole EarlyCSE pass run to cleanup them.
      return true;
    }
    // Merge identical predecessors of this block.
    if (simplifyDuplicatePredecessors(BB, DTU))
      return true;
  }

  if (Options.SpeculateBlocks &&
      !BB->getParent()->hasFnAttribute(Attribute::OptForFuzzing)) {
    // If there is a trivial two-entry PHI node in this basic block, and we can
    // eliminate it, do so now.
    if (auto *PN = dyn_cast<PHINode>(BB->begin()))
      if (PN->getNumIncomingValues() == 2)
        if (foldTwoEntryPHINode(PN, TTI, DTU, Options.AC, DL,
                                Options.SpeculateUnpredictables))
          return true;
  }

  IRBuilder<> Builder(BB);
  Instruction *Terminator = BB->getTerminator();
  Builder.SetInsertPoint(Terminator);
  switch (Terminator->getOpcode()) {
  case Instruction::UncondBr:
    Changed |= simplifyUncondBranch(cast<UncondBrInst>(Terminator), Builder);
    break;
  case Instruction::CondBr:
    Changed |= simplifyCondBranch(cast<CondBrInst>(Terminator), Builder);
    break;
  case Instruction::Resume:
    Changed |= simplifyResume(cast<ResumeInst>(Terminator), Builder);
    break;
  case Instruction::CleanupRet:
    Changed |= simplifyCleanupReturn(cast<CleanupReturnInst>(Terminator));
    break;
  case Instruction::Switch:
    Changed |= simplifySwitch(cast<SwitchInst>(Terminator), Builder);
    break;
  case Instruction::Unreachable:
    Changed |= simplifyUnreachable(cast<UnreachableInst>(Terminator));
    break;
  case Instruction::IndirectBr:
    Changed |= simplifyIndirectBr(cast<IndirectBrInst>(Terminator));
    break;
  }

  return Changed;
}

bool SimplifyCFGOpt::run(BasicBlock *BB) {
  bool Changed = false;

  // Repeated simplify BB as long as resimplification is requested.
  do {
    Resimplify = false;

    // Perform one round of simplifcation. Resimplify flag will be set if
    // another iteration is requested.
    Changed |= simplifyOnce(BB);
  } while (Resimplify);

  return Changed;
}

bool llvm::simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
                       DomTreeUpdater *DTU, const SimplifyCFGOptions &Options,
                       ArrayRef<WeakVH> LoopHeaders) {
  return SimplifyCFGOpt(TTI, DTU, BB->getDataLayout(), LoopHeaders,
                        Options)
      .run(BB);
}
