//===- CodeGenPrepare.cpp - Prepare a function for code generation --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This pass munges the code in the input function to better prepare it for
// SelectionDAG-based code generation. This works around limitations in it's
// basic-block-at-a-time approach. It should eventually be removed.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsAArch64.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Statepoint.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/IR/ValueMap.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/BypassSlowDivision.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SimplifyLibCalls.h"
#include "llvm/Transforms/Utils/SizeOpts.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <utility>
#include <vector>

using namespace llvm;
using namespace llvm::PatternMatch;

#define DEBUG_TYPE "codegenprepare"

STATISTIC(NumBlocksElim, "Number of blocks eliminated");
STATISTIC(NumPHIsElim, "Number of trivial PHIs eliminated");
STATISTIC(NumGEPsElim, "Number of GEPs converted to casts");
STATISTIC(NumCmpUses, "Number of uses of Cmp expressions replaced with uses of "
                      "sunken Cmps");
STATISTIC(NumCastUses, "Number of uses of Cast expressions replaced with uses "
                       "of sunken Casts");
STATISTIC(NumMemoryInsts, "Number of memory instructions whose address "
                          "computations were sunk");
STATISTIC(NumMemoryInstsPhiCreated,
          "Number of phis created when address "
          "computations were sunk to memory instructions");
STATISTIC(NumMemoryInstsSelectCreated,
          "Number of select created when address "
          "computations were sunk to memory instructions");
STATISTIC(NumExtsMoved, "Number of [s|z]ext instructions combined with loads");
STATISTIC(NumExtUses, "Number of uses of [s|z]ext instructions optimized");
STATISTIC(NumAndsAdded,
          "Number of and mask instructions added to form ext loads");
STATISTIC(NumAndUses, "Number of uses of and mask instructions optimized");
STATISTIC(NumRetsDup, "Number of return instructions duplicated");
STATISTIC(NumDbgValueMoved, "Number of debug value instructions moved");
STATISTIC(NumSelectsExpanded, "Number of selects turned into branches");
STATISTIC(NumStoreExtractExposed, "Number of store(extractelement) exposed");

static cl::opt<bool> DisableBranchOpts(
    "disable-cgp-branch-opts", cl::Hidden, cl::init(false),
    cl::desc("Disable branch optimizations in CodeGenPrepare"));

static cl::opt<bool>
    DisableGCOpts("disable-cgp-gc-opts", cl::Hidden, cl::init(false),
                  cl::desc("Disable GC optimizations in CodeGenPrepare"));

static cl::opt<bool>
    DisableSelectToBranch("disable-cgp-select2branch", cl::Hidden,
                          cl::init(false),
                          cl::desc("Disable select to branch conversion."));

static cl::opt<bool>
    AddrSinkUsingGEPs("addr-sink-using-gep", cl::Hidden, cl::init(true),
                      cl::desc("Address sinking in CGP using GEPs."));

static cl::opt<bool>
    EnableAndCmpSinking("enable-andcmp-sinking", cl::Hidden, cl::init(true),
                        cl::desc("Enable sinkinig and/cmp into branches."));

static cl::opt<bool> DisableStoreExtract(
    "disable-cgp-store-extract", cl::Hidden, cl::init(false),
    cl::desc("Disable store(extract) optimizations in CodeGenPrepare"));

static cl::opt<bool> StressStoreExtract(
    "stress-cgp-store-extract", cl::Hidden, cl::init(false),
    cl::desc("Stress test store(extract) optimizations in CodeGenPrepare"));

static cl::opt<bool> DisableExtLdPromotion(
    "disable-cgp-ext-ld-promotion", cl::Hidden, cl::init(false),
    cl::desc("Disable ext(promotable(ld)) -> promoted(ext(ld)) optimization in "
             "CodeGenPrepare"));

static cl::opt<bool> StressExtLdPromotion(
    "stress-cgp-ext-ld-promotion", cl::Hidden, cl::init(false),
    cl::desc("Stress test ext(promotable(ld)) -> promoted(ext(ld)) "
             "optimization in CodeGenPrepare"));

static cl::opt<bool> DisablePreheaderProtect(
    "disable-preheader-prot", cl::Hidden, cl::init(false),
    cl::desc("Disable protection against removing loop preheaders"));

static cl::opt<bool> ProfileGuidedSectionPrefix(
    "profile-guided-section-prefix", cl::Hidden, cl::init(true),
    cl::desc("Use profile info to add section prefix for hot/cold functions"));

static cl::opt<bool> ProfileUnknownInSpecialSection(
    "profile-unknown-in-special-section", cl::Hidden,
    cl::desc("In profiling mode like sampleFDO, if a function doesn't have "
             "profile, we cannot tell the function is cold for sure because "
             "it may be a function newly added without ever being sampled. "
             "With the flag enabled, compiler can put such profile unknown "
             "functions into a special section, so runtime system can choose "
             "to handle it in a different way than .text section, to save "
             "RAM for example. "));

static cl::opt<bool> BBSectionsGuidedSectionPrefix(
    "bbsections-guided-section-prefix", cl::Hidden, cl::init(true),
    cl::desc("Use the basic-block-sections profile to determine the text "
             "section prefix for hot functions. Functions with "
             "basic-block-sections profile will be placed in `.text.hot` "
             "regardless of their FDO profile info. Other functions won't be "
             "impacted, i.e., their prefixes will be decided by FDO/sampleFDO "
             "profiles."));

static cl::opt<unsigned> FreqRatioToSkipMerge(
    "cgp-freq-ratio-to-skip-merge", cl::Hidden, cl::init(2),
    cl::desc("Skip merging empty blocks if (frequency of empty block) / "
             "(frequency of destination block) is greater than this ratio"));

static cl::opt<bool> ForceSplitStore(
    "force-split-store", cl::Hidden, cl::init(false),
    cl::desc("Force store splitting no matter what the target query says."));

static cl::opt<bool> EnableTypePromotionMerge(
    "cgp-type-promotion-merge", cl::Hidden,
    cl::desc("Enable merging of redundant sexts when one is dominating"
             " the other."),
    cl::init(true));

static cl::opt<bool> DisableComplexAddrModes(
    "disable-complex-addr-modes", cl::Hidden, cl::init(false),
    cl::desc("Disables combining addressing modes with different parts "
             "in optimizeMemoryInst."));

static cl::opt<bool>
    AddrSinkNewPhis("addr-sink-new-phis", cl::Hidden, cl::init(false),
                    cl::desc("Allow creation of Phis in Address sinking."));

static cl::opt<bool> AddrSinkNewSelects(
    "addr-sink-new-select", cl::Hidden, cl::init(true),
    cl::desc("Allow creation of selects in Address sinking."));

static cl::opt<bool> AddrSinkCombineBaseReg(
    "addr-sink-combine-base-reg", cl::Hidden, cl::init(true),
    cl::desc("Allow combining of BaseReg field in Address sinking."));

static cl::opt<bool> AddrSinkCombineBaseGV(
    "addr-sink-combine-base-gv", cl::Hidden, cl::init(true),
    cl::desc("Allow combining of BaseGV field in Address sinking."));

static cl::opt<bool> AddrSinkCombineBaseOffs(
    "addr-sink-combine-base-offs", cl::Hidden, cl::init(true),
    cl::desc("Allow combining of BaseOffs field in Address sinking."));

static cl::opt<bool> AddrSinkCombineScaledReg(
    "addr-sink-combine-scaled-reg", cl::Hidden, cl::init(true),
    cl::desc("Allow combining of ScaledReg field in Address sinking."));

static cl::opt<bool>
    EnableGEPOffsetSplit("cgp-split-large-offset-gep", cl::Hidden,
                         cl::init(true),
                         cl::desc("Enable splitting large offset of GEP."));

static cl::opt<bool> EnableICMP_EQToICMP_ST(
    "cgp-icmp-eq2icmp-st", cl::Hidden, cl::init(false),
    cl::desc("Enable ICMP_EQ to ICMP_S(L|G)T conversion."));

static cl::opt<bool>
    VerifyBFIUpdates("cgp-verify-bfi-updates", cl::Hidden, cl::init(false),
                     cl::desc("Enable BFI update verification for "
                              "CodeGenPrepare."));

static cl::opt<bool>
    OptimizePhiTypes("cgp-optimize-phi-types", cl::Hidden, cl::init(false),
                     cl::desc("Enable converting phi types in CodeGenPrepare"));

static cl::opt<unsigned>
    HugeFuncThresholdInCGPP("cgpp-huge-func", cl::init(10000), cl::Hidden,
                            cl::desc("Least BB number of huge function."));

static cl::opt<unsigned>
    MaxAddressUsersToScan("cgp-max-address-users-to-scan", cl::init(100),
                          cl::Hidden,
                          cl::desc("Max number of address users to look at"));
namespace {

enum ExtType {
  ZeroExtension, // Zero extension has been seen.
  SignExtension, // Sign extension has been seen.
  BothExtension  // This extension type is used if we saw sext after
                 // ZeroExtension had been set, or if we saw zext after
                 // SignExtension had been set. It makes the type
                 // information of a promoted instruction invalid.
};

enum ModifyDT {
  NotModifyDT, // Not Modify any DT.
  ModifyBBDT,  // Modify the Basic Block Dominator Tree.
  ModifyInstDT // Modify the Instruction Dominator in a Basic Block,
               // This usually means we move/delete/insert instruction
               // in a Basic Block. So we should re-iterate instructions
               // in such Basic Block.
};

using SetOfInstrs = SmallPtrSet<Instruction *, 16>;
using TypeIsSExt = PointerIntPair<Type *, 2, ExtType>;
using InstrToOrigTy = DenseMap<Instruction *, TypeIsSExt>;
using SExts = SmallVector<Instruction *, 16>;
using ValueToSExts = MapVector<Value *, SExts>;

class TypePromotionTransaction;

class CodeGenPrepare : public FunctionPass {
  const TargetMachine *TM = nullptr;
  const TargetSubtargetInfo *SubtargetInfo = nullptr;
  const TargetLowering *TLI = nullptr;
  const TargetRegisterInfo *TRI = nullptr;
  const TargetTransformInfo *TTI = nullptr;
  const BasicBlockSectionsProfileReader *BBSectionsProfileReader = nullptr;
  const TargetLibraryInfo *TLInfo = nullptr;
  LoopInfo *LI = nullptr;
  std::unique_ptr<BlockFrequencyInfo> BFI;
  std::unique_ptr<BranchProbabilityInfo> BPI;
  ProfileSummaryInfo *PSI = nullptr;

  /// As we scan instructions optimizing them, this is the next instruction
  /// to optimize. Transforms that can invalidate this should update it.
  BasicBlock::iterator CurInstIterator;

  /// Keeps track of non-local addresses that have been sunk into a block.
  /// This allows us to avoid inserting duplicate code for blocks with
  /// multiple load/stores of the same address. The usage of WeakTrackingVH
  /// enables SunkAddrs to be treated as a cache whose entries can be
  /// invalidated if a sunken address computation has been erased.
  ValueMap<Value *, WeakTrackingVH> SunkAddrs;

  /// Keeps track of all instructions inserted for the current function.
  SetOfInstrs InsertedInsts;

  /// Keeps track of the type of the related instruction before their
  /// promotion for the current function.
  InstrToOrigTy PromotedInsts;

  /// Keep track of instructions removed during promotion.
  SetOfInstrs RemovedInsts;

  /// Keep track of sext chains based on their initial value.
  DenseMap<Value *, Instruction *> SeenChainsForSExt;

  /// Keep track of GEPs accessing the same data structures such as structs or
  /// arrays that are candidates to be split later because of their large
  /// size.
  MapVector<AssertingVH<Value>,
            SmallVector<std::pair<AssertingVH<GetElementPtrInst>, int64_t>, 32>>
      LargeOffsetGEPMap;

  /// Keep track of new GEP base after splitting the GEPs having large offset.
  SmallSet<AssertingVH<Value>, 2> NewGEPBases;

  /// Map serial numbers to Large offset GEPs.
  DenseMap<AssertingVH<GetElementPtrInst>, int> LargeOffsetGEPID;

  /// Keep track of SExt promoted.
  ValueToSExts ValToSExtendedUses;

  /// True if the function has the OptSize attribute.
  bool OptSize;

  /// DataLayout for the Function being processed.
  const DataLayout *DL = nullptr;

  /// Building the dominator tree can be expensive, so we only build it
  /// lazily and update it when required.
  std::unique_ptr<DominatorTree> DT;

public:
  /// If encounter huge function, we need to limit the build time.
  bool IsHugeFunc = false;

  /// FreshBBs is like worklist, it collected the updated BBs which need
  /// to be optimized again.
  /// Note: Consider building time in this pass, when a BB updated, we need
  /// to insert such BB into FreshBBs for huge function.
  SmallSet<BasicBlock *, 32> FreshBBs;

  static char ID; // Pass identification, replacement for typeid

  CodeGenPrepare() : FunctionPass(ID) {
    initializeCodeGenPreparePass(*PassRegistry::getPassRegistry());
  }

  bool runOnFunction(Function &F) override;

  void releaseMemory() override {
    // Clear per function information.
    InsertedInsts.clear();
    PromotedInsts.clear();
    FreshBBs.clear();
    BPI.reset();
    BFI.reset();
  }

  StringRef getPassName() const override { return "CodeGen Prepare"; }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    // FIXME: When we can selectively preserve passes, preserve the domtree.
    AU.addRequired<ProfileSummaryInfoWrapperPass>();
    AU.addRequired<TargetLibraryInfoWrapperPass>();
    AU.addRequired<TargetPassConfig>();
    AU.addRequired<TargetTransformInfoWrapperPass>();
    AU.addRequired<LoopInfoWrapperPass>();
    AU.addUsedIfAvailable<BasicBlockSectionsProfileReader>();
  }

private:
  template <typename F>
  void resetIteratorIfInvalidatedWhileCalling(BasicBlock *BB, F f) {
    // Substituting can cause recursive simplifications, which can invalidate
    // our iterator.  Use a WeakTrackingVH to hold onto it in case this
    // happens.
    Value *CurValue = &*CurInstIterator;
    WeakTrackingVH IterHandle(CurValue);

    f();

    // If the iterator instruction was recursively deleted, start over at the
    // start of the block.
    if (IterHandle != CurValue) {
      CurInstIterator = BB->begin();
      SunkAddrs.clear();
    }
  }

  // Get the DominatorTree, building if necessary.
  DominatorTree &getDT(Function &F) {
    if (!DT)
      DT = std::make_unique<DominatorTree>(F);
    return *DT;
  }

  void removeAllAssertingVHReferences(Value *V);
  bool eliminateAssumptions(Function &F);
  bool eliminateFallThrough(Function &F, DominatorTree *DT = nullptr);
  bool eliminateMostlyEmptyBlocks(Function &F);
  BasicBlock *findDestBlockOfMergeableEmptyBlock(BasicBlock *BB);
  bool canMergeBlocks(const BasicBlock *BB, const BasicBlock *DestBB) const;
  void eliminateMostlyEmptyBlock(BasicBlock *BB);
  bool isMergingEmptyBlockProfitable(BasicBlock *BB, BasicBlock *DestBB,
                                     bool isPreheader);
  bool makeBitReverse(Instruction &I);
  bool optimizeBlock(BasicBlock &BB, ModifyDT &ModifiedDT);
  bool optimizeInst(Instruction *I, ModifyDT &ModifiedDT);
  bool optimizeMemoryInst(Instruction *MemoryInst, Value *Addr, Type *AccessTy,
                          unsigned AddrSpace);
  bool optimizeGatherScatterInst(Instruction *MemoryInst, Value *Ptr);
  bool optimizeInlineAsmInst(CallInst *CS);
  bool optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT);
  bool optimizeExt(Instruction *&I);
  bool optimizeExtUses(Instruction *I);
  bool optimizeLoadExt(LoadInst *Load);
  bool optimizeShiftInst(BinaryOperator *BO);
  bool optimizeFunnelShift(IntrinsicInst *Fsh);
  bool optimizeSelectInst(SelectInst *SI);
  bool optimizeShuffleVectorInst(ShuffleVectorInst *SVI);
  bool optimizeSwitchType(SwitchInst *SI);
  bool optimizeSwitchPhiConstants(SwitchInst *SI);
  bool optimizeSwitchInst(SwitchInst *SI);
  bool optimizeExtractElementInst(Instruction *Inst);
  bool dupRetToEnableTailCallOpts(BasicBlock *BB, ModifyDT &ModifiedDT);
  bool fixupDbgValue(Instruction *I);
  bool placeDbgValues(Function &F);
  bool placePseudoProbes(Function &F);
  bool canFormExtLd(const SmallVectorImpl<Instruction *> &MovedExts,
                    LoadInst *&LI, Instruction *&Inst, bool HasPromoted);
  bool tryToPromoteExts(TypePromotionTransaction &TPT,
                        const SmallVectorImpl<Instruction *> &Exts,
                        SmallVectorImpl<Instruction *> &ProfitablyMovedExts,
                        unsigned CreatedInstsCost = 0);
  bool mergeSExts(Function &F);
  bool splitLargeGEPOffsets();
  bool optimizePhiType(PHINode *Inst, SmallPtrSetImpl<PHINode *> &Visited,
                       SmallPtrSetImpl<Instruction *> &DeletedInstrs);
  bool optimizePhiTypes(Function &F);
  bool performAddressTypePromotion(
      Instruction *&Inst, bool AllowPromotionWithoutCommonHeader,
      bool HasPromoted, TypePromotionTransaction &TPT,
      SmallVectorImpl<Instruction *> &SpeculativelyMovedExts);
  bool splitBranchCondition(Function &F, ModifyDT &ModifiedDT);
  bool simplifyOffsetableRelocate(GCStatepointInst &I);

  bool tryToSinkFreeOperands(Instruction *I);
  bool replaceMathCmpWithIntrinsic(BinaryOperator *BO, Value *Arg0, Value *Arg1,
                                   CmpInst *Cmp, Intrinsic::ID IID);
  bool optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT);
  bool combineToUSubWithOverflow(CmpInst *Cmp, ModifyDT &ModifiedDT);
  bool combineToUAddWithOverflow(CmpInst *Cmp, ModifyDT &ModifiedDT);
  void verifyBFIUpdates(Function &F);
};

} // end anonymous namespace

char CodeGenPrepare::ID = 0;

INITIALIZE_PASS_BEGIN(CodeGenPrepare, DEBUG_TYPE,
                      "Optimize for code generation", false, false)
INITIALIZE_PASS_DEPENDENCY(BasicBlockSectionsProfileReader)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_END(CodeGenPrepare, DEBUG_TYPE, "Optimize for code generation",
                    false, false)

FunctionPass *llvm::createCodeGenPreparePass() { return new CodeGenPrepare(); }

bool CodeGenPrepare::runOnFunction(Function &F) {
  if (skipFunction(F))
    return false;

  DL = &F.getParent()->getDataLayout();

  bool EverMadeChange = false;

  TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
  SubtargetInfo = TM->getSubtargetImpl(F);
  TLI = SubtargetInfo->getTargetLowering();
  TRI = SubtargetInfo->getRegisterInfo();
  TLInfo = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
  TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
  LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
  BPI.reset(new BranchProbabilityInfo(F, *LI));
  BFI.reset(new BlockFrequencyInfo(F, *BPI, *LI));
  PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
  BBSectionsProfileReader =
      getAnalysisIfAvailable<BasicBlockSectionsProfileReader>();
  OptSize = F.hasOptSize();
  // Use the basic-block-sections profile to promote hot functions to .text.hot
  // if requested.
  if (BBSectionsGuidedSectionPrefix && BBSectionsProfileReader &&
      BBSectionsProfileReader->isFunctionHot(F.getName())) {
    F.setSectionPrefix("hot");
  } else if (ProfileGuidedSectionPrefix) {
    // The hot attribute overwrites profile count based hotness while profile
    // counts based hotness overwrite the cold attribute.
    // This is a conservative behabvior.
    if (F.hasFnAttribute(Attribute::Hot) ||
        PSI->isFunctionHotInCallGraph(&F, *BFI))
      F.setSectionPrefix("hot");
    // If PSI shows this function is not hot, we will placed the function
    // into unlikely section if (1) PSI shows this is a cold function, or
    // (2) the function has a attribute of cold.
    else if (PSI->isFunctionColdInCallGraph(&F, *BFI) ||
             F.hasFnAttribute(Attribute::Cold))
      F.setSectionPrefix("unlikely");
    else if (ProfileUnknownInSpecialSection && PSI->hasPartialSampleProfile() &&
             PSI->isFunctionHotnessUnknown(F))
      F.setSectionPrefix("unknown");
  }

  /// This optimization identifies DIV instructions that can be
  /// profitably bypassed and carried out with a shorter, faster divide.
  if (!OptSize && !PSI->hasHugeWorkingSetSize() && TLI->isSlowDivBypassed()) {
    const DenseMap<unsigned int, unsigned int> &BypassWidths =
        TLI->getBypassSlowDivWidths();
    BasicBlock *BB = &*F.begin();
    while (BB != nullptr) {
      // bypassSlowDivision may create new BBs, but we don't want to reapply the
      // optimization to those blocks.
      BasicBlock *Next = BB->getNextNode();
      // F.hasOptSize is already checked in the outer if statement.
      if (!llvm::shouldOptimizeForSize(BB, PSI, BFI.get()))
        EverMadeChange |= bypassSlowDivision(BB, BypassWidths);
      BB = Next;
    }
  }

  // Get rid of @llvm.assume builtins before attempting to eliminate empty
  // blocks, since there might be blocks that only contain @llvm.assume calls
  // (plus arguments that we can get rid of).
  EverMadeChange |= eliminateAssumptions(F);

  // Eliminate blocks that contain only PHI nodes and an
  // unconditional branch.
  EverMadeChange |= eliminateMostlyEmptyBlocks(F);

  ModifyDT ModifiedDT = ModifyDT::NotModifyDT;
  if (!DisableBranchOpts)
    EverMadeChange |= splitBranchCondition(F, ModifiedDT);

  // Split some critical edges where one of the sources is an indirect branch,
  // to help generate sane code for PHIs involving such edges.
  EverMadeChange |=
      SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/true);

  // If we are optimzing huge function, we need to consider the build time.
  // Because the basic algorithm's complex is near O(N!).
  IsHugeFunc = F.size() > HugeFuncThresholdInCGPP;

  // Transformations above may invalidate dominator tree and/or loop info.
  DT.reset();
  LI->releaseMemory();
  LI->analyze(getDT(F));

  bool MadeChange = true;
  bool FuncIterated = false;
  while (MadeChange) {
    MadeChange = false;

    for (BasicBlock &BB : llvm::make_early_inc_range(F)) {
      if (FuncIterated && !FreshBBs.contains(&BB))
        continue;

      ModifyDT ModifiedDTOnIteration = ModifyDT::NotModifyDT;
      bool Changed = optimizeBlock(BB, ModifiedDTOnIteration);

      if (ModifiedDTOnIteration == ModifyDT::ModifyBBDT)
        DT.reset();

      MadeChange |= Changed;
      if (IsHugeFunc) {
        // If the BB is updated, it may still has chance to be optimized.
        // This usually happen at sink optimization.
        // For example:
        //
        // bb0：
        // %and = and i32 %a, 4
        // %cmp = icmp eq i32 %and, 0
        //
        // If the %cmp sink to other BB, the %and will has chance to sink.
        if (Changed)
          FreshBBs.insert(&BB);
        else if (FuncIterated)
          FreshBBs.erase(&BB);
      } else {
        // For small/normal functions, we restart BB iteration if the dominator
        // tree of the Function was changed.
        if (ModifiedDTOnIteration != ModifyDT::NotModifyDT)
          break;
      }
    }
    // We have iterated all the BB in the (only work for huge) function.
    FuncIterated = IsHugeFunc;

    if (EnableTypePromotionMerge && !ValToSExtendedUses.empty())
      MadeChange |= mergeSExts(F);
    if (!LargeOffsetGEPMap.empty())
      MadeChange |= splitLargeGEPOffsets();
    MadeChange |= optimizePhiTypes(F);

    if (MadeChange)
      eliminateFallThrough(F, DT.get());

#ifndef NDEBUG
    if (MadeChange && VerifyLoopInfo)
      LI->verify(getDT(F));
#endif

    // Really free removed instructions during promotion.
    for (Instruction *I : RemovedInsts)
      I->deleteValue();

    EverMadeChange |= MadeChange;
    SeenChainsForSExt.clear();
    ValToSExtendedUses.clear();
    RemovedInsts.clear();
    LargeOffsetGEPMap.clear();
    LargeOffsetGEPID.clear();
  }

  NewGEPBases.clear();
  SunkAddrs.clear();

  if (!DisableBranchOpts) {
    MadeChange = false;
    // Use a set vector to get deterministic iteration order. The order the
    // blocks are removed may affect whether or not PHI nodes in successors
    // are removed.
    SmallSetVector<BasicBlock *, 8> WorkList;
    for (BasicBlock &BB : F) {
      SmallVector<BasicBlock *, 2> Successors(successors(&BB));
      MadeChange |= ConstantFoldTerminator(&BB, true);
      if (!MadeChange)
        continue;

      for (BasicBlock *Succ : Successors)
        if (pred_empty(Succ))
          WorkList.insert(Succ);
    }

    // Delete the dead blocks and any of their dead successors.
    MadeChange |= !WorkList.empty();
    while (!WorkList.empty()) {
      BasicBlock *BB = WorkList.pop_back_val();
      SmallVector<BasicBlock *, 2> Successors(successors(BB));

      DeleteDeadBlock(BB);

      for (BasicBlock *Succ : Successors)
        if (pred_empty(Succ))
          WorkList.insert(Succ);
    }

    // Merge pairs of basic blocks with unconditional branches, connected by
    // a single edge.
    if (EverMadeChange || MadeChange)
      MadeChange |= eliminateFallThrough(F);

    EverMadeChange |= MadeChange;
  }

  if (!DisableGCOpts) {
    SmallVector<GCStatepointInst *, 2> Statepoints;
    for (BasicBlock &BB : F)
      for (Instruction &I : BB)
        if (auto *SP = dyn_cast<GCStatepointInst>(&I))
          Statepoints.push_back(SP);
    for (auto &I : Statepoints)
      EverMadeChange |= simplifyOffsetableRelocate(*I);
  }

  // Do this last to clean up use-before-def scenarios introduced by other
  // preparatory transforms.
  EverMadeChange |= placeDbgValues(F);
  EverMadeChange |= placePseudoProbes(F);

#ifndef NDEBUG
  if (VerifyBFIUpdates)
    verifyBFIUpdates(F);
#endif

  return EverMadeChange;
}

bool CodeGenPrepare::eliminateAssumptions(Function &F) {
  bool MadeChange = false;
  for (BasicBlock &BB : F) {
    CurInstIterator = BB.begin();
    while (CurInstIterator != BB.end()) {
      Instruction *I = &*(CurInstIterator++);
      if (auto *Assume = dyn_cast<AssumeInst>(I)) {
        MadeChange = true;
        Value *Operand = Assume->getOperand(0);
        Assume->eraseFromParent();

        resetIteratorIfInvalidatedWhileCalling(&BB, [&]() {
          RecursivelyDeleteTriviallyDeadInstructions(Operand, TLInfo, nullptr);
        });
      }
    }
  }
  return MadeChange;
}

/// An instruction is about to be deleted, so remove all references to it in our
/// GEP-tracking data strcutures.
void CodeGenPrepare::removeAllAssertingVHReferences(Value *V) {
  LargeOffsetGEPMap.erase(V);
  NewGEPBases.erase(V);

  auto GEP = dyn_cast<GetElementPtrInst>(V);
  if (!GEP)
    return;

  LargeOffsetGEPID.erase(GEP);

  auto VecI = LargeOffsetGEPMap.find(GEP->getPointerOperand());
  if (VecI == LargeOffsetGEPMap.end())
    return;

  auto &GEPVector = VecI->second;
  llvm::erase_if(GEPVector, [=](auto &Elt) { return Elt.first == GEP; });

  if (GEPVector.empty())
    LargeOffsetGEPMap.erase(VecI);
}

// Verify BFI has been updated correctly by recomputing BFI and comparing them.
void LLVM_ATTRIBUTE_UNUSED CodeGenPrepare::verifyBFIUpdates(Function &F) {
  DominatorTree NewDT(F);
  LoopInfo NewLI(NewDT);
  BranchProbabilityInfo NewBPI(F, NewLI, TLInfo);
  BlockFrequencyInfo NewBFI(F, NewBPI, NewLI);
  NewBFI.verifyMatch(*BFI);
}

/// Merge basic blocks which are connected by a single edge, where one of the
/// basic blocks has a single successor pointing to the other basic block,
/// which has a single predecessor.
bool CodeGenPrepare::eliminateFallThrough(Function &F, DominatorTree *DT) {
  bool Changed = false;
  // Scan all of the blocks in the function, except for the entry block.
  // Use a temporary array to avoid iterator being invalidated when
  // deleting blocks.
  SmallVector<WeakTrackingVH, 16> Blocks;
  for (auto &Block : llvm::drop_begin(F))
    Blocks.push_back(&Block);

  SmallSet<WeakTrackingVH, 16> Preds;
  for (auto &Block : Blocks) {
    auto *BB = cast_or_null<BasicBlock>(Block);
    if (!BB)
      continue;
    // If the destination block has a single pred, then this is a trivial
    // edge, just collapse it.
    BasicBlock *SinglePred = BB->getSinglePredecessor();

    // Don't merge if BB's address is taken.
    if (!SinglePred || SinglePred == BB || BB->hasAddressTaken())
      continue;

    // Make an effort to skip unreachable blocks.
    if (DT && !DT->isReachableFromEntry(BB))
      continue;

    BranchInst *Term = dyn_cast<BranchInst>(SinglePred->getTerminator());
    if (Term && !Term->isConditional()) {
      Changed = true;
      LLVM_DEBUG(dbgs() << "To merge:\n" << *BB << "\n\n\n");

      // Merge BB into SinglePred and delete it.
      MergeBlockIntoPredecessor(BB, /* DTU */ nullptr, LI, /* MSSAU */ nullptr,
                                /* MemDep */ nullptr,
                                /* PredecessorWithTwoSuccessors */ false, DT);
      Preds.insert(SinglePred);

      if (IsHugeFunc) {
        // Update FreshBBs to optimize the merged BB.
        FreshBBs.insert(SinglePred);
        FreshBBs.erase(BB);
      }
    }
  }

  // (Repeatedly) merging blocks into their predecessors can create redundant
  // debug intrinsics.
  for (const auto &Pred : Preds)
    if (auto *BB = cast_or_null<BasicBlock>(Pred))
      RemoveRedundantDbgInstrs(BB);

  return Changed;
}

/// Find a destination block from BB if BB is mergeable empty block.
BasicBlock *CodeGenPrepare::findDestBlockOfMergeableEmptyBlock(BasicBlock *BB) {
  // If this block doesn't end with an uncond branch, ignore it.
  BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator());
  if (!BI || !BI->isUnconditional())
    return nullptr;

  // If the instruction before the branch (skipping debug info) isn't a phi
  // node, then other stuff is happening here.
  BasicBlock::iterator BBI = BI->getIterator();
  if (BBI != BB->begin()) {
    --BBI;
    while (isa<DbgInfoIntrinsic>(BBI)) {
      if (BBI == BB->begin())
        break;
      --BBI;
    }
    if (!isa<DbgInfoIntrinsic>(BBI) && !isa<PHINode>(BBI))
      return nullptr;
  }

  // Do not break infinite loops.
  BasicBlock *DestBB = BI->getSuccessor(0);
  if (DestBB == BB)
    return nullptr;

  if (!canMergeBlocks(BB, DestBB))
    DestBB = nullptr;

  return DestBB;
}

/// Eliminate blocks that contain only PHI nodes, debug info directives, and an
/// unconditional branch. Passes before isel (e.g. LSR/loopsimplify) often split
/// edges in ways that are non-optimal for isel. Start by eliminating these
/// blocks so we can split them the way we want them.
bool CodeGenPrepare::eliminateMostlyEmptyBlocks(Function &F) {
  SmallPtrSet<BasicBlock *, 16> Preheaders;
  SmallVector<Loop *, 16> LoopList(LI->begin(), LI->end());
  while (!LoopList.empty()) {
    Loop *L = LoopList.pop_back_val();
    llvm::append_range(LoopList, *L);
    if (BasicBlock *Preheader = L->getLoopPreheader())
      Preheaders.insert(Preheader);
  }

  bool MadeChange = false;
  // Copy blocks into a temporary array to avoid iterator invalidation issues
  // as we remove them.
  // Note that this intentionally skips the entry block.
  SmallVector<WeakTrackingVH, 16> Blocks;
  for (auto &Block : llvm::drop_begin(F))
    Blocks.push_back(&Block);

  for (auto &Block : Blocks) {
    BasicBlock *BB = cast_or_null<BasicBlock>(Block);
    if (!BB)
      continue;
    BasicBlock *DestBB = findDestBlockOfMergeableEmptyBlock(BB);
    if (!DestBB ||
        !isMergingEmptyBlockProfitable(BB, DestBB, Preheaders.count(BB)))
      continue;

    eliminateMostlyEmptyBlock(BB);
    MadeChange = true;
  }
  return MadeChange;
}

bool CodeGenPrepare::isMergingEmptyBlockProfitable(BasicBlock *BB,
                                                   BasicBlock *DestBB,
                                                   bool isPreheader) {
  // Do not delete loop preheaders if doing so would create a critical edge.
  // Loop preheaders can be good locations to spill registers. If the
  // preheader is deleted and we create a critical edge, registers may be
  // spilled in the loop body instead.
  if (!DisablePreheaderProtect && isPreheader &&
      !(BB->getSinglePredecessor() &&
        BB->getSinglePredecessor()->getSingleSuccessor()))
    return false;

  // Skip merging if the block's successor is also a successor to any callbr
  // that leads to this block.
  // FIXME: Is this really needed? Is this a correctness issue?
  for (BasicBlock *Pred : predecessors(BB)) {
    if (auto *CBI = dyn_cast<CallBrInst>((Pred)->getTerminator()))
      for (unsigned i = 0, e = CBI->getNumSuccessors(); i != e; ++i)
        if (DestBB == CBI->getSuccessor(i))
          return false;
  }

  // Try to skip merging if the unique predecessor of BB is terminated by a
  // switch or indirect branch instruction, and BB is used as an incoming block
  // of PHIs in DestBB. In such case, merging BB and DestBB would cause ISel to
  // add COPY instructions in the predecessor of BB instead of BB (if it is not
  // merged). Note that the critical edge created by merging such blocks wont be
  // split in MachineSink because the jump table is not analyzable. By keeping
  // such empty block (BB), ISel will place COPY instructions in BB, not in the
  // predecessor of BB.
  BasicBlock *Pred = BB->getUniquePredecessor();
  if (!Pred || !(isa<SwitchInst>(Pred->getTerminator()) ||
                 isa<IndirectBrInst>(Pred->getTerminator())))
    return true;

  if (BB->getTerminator() != BB->getFirstNonPHIOrDbg())
    return true;

  // We use a simple cost heuristic which determine skipping merging is
  // profitable if the cost of skipping merging is less than the cost of
  // merging : Cost(skipping merging) < Cost(merging BB), where the
  // Cost(skipping merging) is Freq(BB) * (Cost(Copy) + Cost(Branch)), and
  // the Cost(merging BB) is Freq(Pred) * Cost(Copy).
  // Assuming Cost(Copy) == Cost(Branch), we could simplify it to :
  //   Freq(Pred) / Freq(BB) > 2.
  // Note that if there are multiple empty blocks sharing the same incoming
  // value for the PHIs in the DestBB, we consider them together. In such
  // case, Cost(merging BB) will be the sum of their frequencies.

  if (!isa<PHINode>(DestBB->begin()))
    return true;

  SmallPtrSet<BasicBlock *, 16> SameIncomingValueBBs;

  // Find all other incoming blocks from which incoming values of all PHIs in
  // DestBB are the same as the ones from BB.
  for (BasicBlock *DestBBPred : predecessors(DestBB)) {
    if (DestBBPred == BB)
      continue;

    if (llvm::all_of(DestBB->phis(), [&](const PHINode &DestPN) {
          return DestPN.getIncomingValueForBlock(BB) ==
                 DestPN.getIncomingValueForBlock(DestBBPred);
        }))
      SameIncomingValueBBs.insert(DestBBPred);
  }

  // See if all BB's incoming values are same as the value from Pred. In this
  // case, no reason to skip merging because COPYs are expected to be place in
  // Pred already.
  if (SameIncomingValueBBs.count(Pred))
    return true;

  BlockFrequency PredFreq = BFI->getBlockFreq(Pred);
  BlockFrequency BBFreq = BFI->getBlockFreq(BB);

  for (auto *SameValueBB : SameIncomingValueBBs)
    if (SameValueBB->getUniquePredecessor() == Pred &&
        DestBB == findDestBlockOfMergeableEmptyBlock(SameValueBB))
      BBFreq += BFI->getBlockFreq(SameValueBB);

  return PredFreq.getFrequency() <=
         BBFreq.getFrequency() * FreqRatioToSkipMerge;
}

/// Return true if we can merge BB into DestBB if there is a single
/// unconditional branch between them, and BB contains no other non-phi
/// instructions.
bool CodeGenPrepare::canMergeBlocks(const BasicBlock *BB,
                                    const BasicBlock *DestBB) const {
  // We only want to eliminate blocks whose phi nodes are used by phi nodes in
  // the successor.  If there are more complex condition (e.g. preheaders),
  // don't mess around with them.
  for (const PHINode &PN : BB->phis()) {
    for (const User *U : PN.users()) {
      const Instruction *UI = cast<Instruction>(U);
      if (UI->getParent() != DestBB || !isa<PHINode>(UI))
        return false;
      // If User is inside DestBB block and it is a PHINode then check
      // incoming value. If incoming value is not from BB then this is
      // a complex condition (e.g. preheaders) we want to avoid here.
      if (UI->getParent() == DestBB) {
        if (const PHINode *UPN = dyn_cast<PHINode>(UI))
          for (unsigned I = 0, E = UPN->getNumIncomingValues(); I != E; ++I) {
            Instruction *Insn = dyn_cast<Instruction>(UPN->getIncomingValue(I));
            if (Insn && Insn->getParent() == BB &&
                Insn->getParent() != UPN->getIncomingBlock(I))
              return false;
          }
      }
    }
  }

  // If BB and DestBB contain any common predecessors, then the phi nodes in BB
  // and DestBB may have conflicting incoming values for the block.  If so, we
  // can't merge the block.
  const PHINode *DestBBPN = dyn_cast<PHINode>(DestBB->begin());
  if (!DestBBPN)
    return true; // no conflict.

  // Collect the preds of BB.
  SmallPtrSet<const BasicBlock *, 16> BBPreds;
  if (const PHINode *BBPN = dyn_cast<PHINode>(BB->begin())) {
    // It is faster to get preds from a PHI than with pred_iterator.
    for (unsigned i = 0, e = BBPN->getNumIncomingValues(); i != e; ++i)
      BBPreds.insert(BBPN->getIncomingBlock(i));
  } else {
    BBPreds.insert(pred_begin(BB), pred_end(BB));
  }

  // Walk the preds of DestBB.
  for (unsigned i = 0, e = DestBBPN->getNumIncomingValues(); i != e; ++i) {
    BasicBlock *Pred = DestBBPN->getIncomingBlock(i);
    if (BBPreds.count(Pred)) { // Common predecessor?
      for (const PHINode &PN : DestBB->phis()) {
        const Value *V1 = PN.getIncomingValueForBlock(Pred);
        const Value *V2 = PN.getIncomingValueForBlock(BB);

        // If V2 is a phi node in BB, look up what the mapped value will be.
        if (const PHINode *V2PN = dyn_cast<PHINode>(V2))
          if (V2PN->getParent() == BB)
            V2 = V2PN->getIncomingValueForBlock(Pred);

        // If there is a conflict, bail out.
        if (V1 != V2)
          return false;
      }
    }
  }

  return true;
}

/// Replace all old uses with new ones, and push the updated BBs into FreshBBs.
static void replaceAllUsesWith(Value *Old, Value *New,
                               SmallSet<BasicBlock *, 32> &FreshBBs,
                               bool IsHuge) {
  auto *OldI = dyn_cast<Instruction>(Old);
  if (OldI) {
    for (Value::user_iterator UI = OldI->user_begin(), E = OldI->user_end();
         UI != E; ++UI) {
      Instruction *User = cast<Instruction>(*UI);
      if (IsHuge)
        FreshBBs.insert(User->getParent());
    }
  }
  Old->replaceAllUsesWith(New);
}

/// Eliminate a basic block that has only phi's and an unconditional branch in
/// it.
void CodeGenPrepare::eliminateMostlyEmptyBlock(BasicBlock *BB) {
  BranchInst *BI = cast<BranchInst>(BB->getTerminator());
  BasicBlock *DestBB = BI->getSuccessor(0);

  LLVM_DEBUG(dbgs() << "MERGING MOSTLY EMPTY BLOCKS - BEFORE:\n"
                    << *BB << *DestBB);

  // If the destination block has a single pred, then this is a trivial edge,
  // just collapse it.
  if (BasicBlock *SinglePred = DestBB->getSinglePredecessor()) {
    if (SinglePred != DestBB) {
      assert(SinglePred == BB &&
             "Single predecessor not the same as predecessor");
      // Merge DestBB into SinglePred/BB and delete it.
      MergeBlockIntoPredecessor(DestBB);
      // Note: BB(=SinglePred) will not be deleted on this path.
      // DestBB(=its single successor) is the one that was deleted.
      LLVM_DEBUG(dbgs() << "AFTER:\n" << *SinglePred << "\n\n\n");

      if (IsHugeFunc) {
        // Update FreshBBs to optimize the merged BB.
        FreshBBs.insert(SinglePred);
        FreshBBs.erase(DestBB);
      }
      return;
    }
  }

  // Otherwise, we have multiple predecessors of BB.  Update the PHIs in DestBB
  // to handle the new incoming edges it is about to have.
  for (PHINode &PN : DestBB->phis()) {
    // Remove the incoming value for BB, and remember it.
    Value *InVal = PN.removeIncomingValue(BB, false);

    // Two options: either the InVal is a phi node defined in BB or it is some
    // value that dominates BB.
    PHINode *InValPhi = dyn_cast<PHINode>(InVal);
    if (InValPhi && InValPhi->getParent() == BB) {
      // Add all of the input values of the input PHI as inputs of this phi.
      for (unsigned i = 0, e = InValPhi->getNumIncomingValues(); i != e; ++i)
        PN.addIncoming(InValPhi->getIncomingValue(i),
                       InValPhi->getIncomingBlock(i));
    } else {
      // Otherwise, add one instance of the dominating value for each edge that
      // we will be adding.
      if (PHINode *BBPN = dyn_cast<PHINode>(BB->begin())) {
        for (unsigned i = 0, e = BBPN->getNumIncomingValues(); i != e; ++i)
          PN.addIncoming(InVal, BBPN->getIncomingBlock(i));
      } else {
        for (BasicBlock *Pred : predecessors(BB))
          PN.addIncoming(InVal, Pred);
      }
    }
  }

  // The PHIs are now updated, change everything that refers to BB to use
  // DestBB and remove BB.
  BB->replaceAllUsesWith(DestBB);
  BB->eraseFromParent();
  ++NumBlocksElim;

  LLVM_DEBUG(dbgs() << "AFTER:\n" << *DestBB << "\n\n\n");
}

// Computes a map of base pointer relocation instructions to corresponding
// derived pointer relocation instructions given a vector of all relocate calls
static void computeBaseDerivedRelocateMap(
    const SmallVectorImpl<GCRelocateInst *> &AllRelocateCalls,
    DenseMap<GCRelocateInst *, SmallVector<GCRelocateInst *, 2>>
        &RelocateInstMap) {
  // Collect information in two maps: one primarily for locating the base object
  // while filling the second map; the second map is the final structure holding
  // a mapping between Base and corresponding Derived relocate calls
  DenseMap<std::pair<unsigned, unsigned>, GCRelocateInst *> RelocateIdxMap;
  for (auto *ThisRelocate : AllRelocateCalls) {
    auto K = std::make_pair(ThisRelocate->getBasePtrIndex(),
                            ThisRelocate->getDerivedPtrIndex());
    RelocateIdxMap.insert(std::make_pair(K, ThisRelocate));
  }
  for (auto &Item : RelocateIdxMap) {
    std::pair<unsigned, unsigned> Key = Item.first;
    if (Key.first == Key.second)
      // Base relocation: nothing to insert
      continue;

    GCRelocateInst *I = Item.second;
    auto BaseKey = std::make_pair(Key.first, Key.first);

    // We're iterating over RelocateIdxMap so we cannot modify it.
    auto MaybeBase = RelocateIdxMap.find(BaseKey);
    if (MaybeBase == RelocateIdxMap.end())
      // TODO: We might want to insert a new base object relocate and gep off
      // that, if there are enough derived object relocates.
      continue;

    RelocateInstMap[MaybeBase->second].push_back(I);
  }
}

// Accepts a GEP and extracts the operands into a vector provided they're all
// small integer constants
static bool getGEPSmallConstantIntOffsetV(GetElementPtrInst *GEP,
                                          SmallVectorImpl<Value *> &OffsetV) {
  for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
    // Only accept small constant integer operands
    auto *Op = dyn_cast<ConstantInt>(GEP->getOperand(i));
    if (!Op || Op->getZExtValue() > 20)
      return false;
  }

  for (unsigned i = 1; i < GEP->getNumOperands(); i++)
    OffsetV.push_back(GEP->getOperand(i));
  return true;
}

// Takes a RelocatedBase (base pointer relocation instruction) and Targets to
// replace, computes a replacement, and affects it.
static bool
simplifyRelocatesOffABase(GCRelocateInst *RelocatedBase,
                          const SmallVectorImpl<GCRelocateInst *> &Targets) {
  bool MadeChange = false;
  // We must ensure the relocation of derived pointer is defined after
  // relocation of base pointer. If we find a relocation corresponding to base
  // defined earlier than relocation of base then we move relocation of base
  // right before found relocation. We consider only relocation in the same
  // basic block as relocation of base. Relocations from other basic block will
  // be skipped by optimization and we do not care about them.
  for (auto R = RelocatedBase->getParent()->getFirstInsertionPt();
       &*R != RelocatedBase; ++R)
    if (auto *RI = dyn_cast<GCRelocateInst>(R))
      if (RI->getStatepoint() == RelocatedBase->getStatepoint())
        if (RI->getBasePtrIndex() == RelocatedBase->getBasePtrIndex()) {
          RelocatedBase->moveBefore(RI);
          break;
        }

  for (GCRelocateInst *ToReplace : Targets) {
    assert(ToReplace->getBasePtrIndex() == RelocatedBase->getBasePtrIndex() &&
           "Not relocating a derived object of the original base object");
    if (ToReplace->getBasePtrIndex() == ToReplace->getDerivedPtrIndex()) {
      // A duplicate relocate call. TODO: coalesce duplicates.
      continue;
    }

    if (RelocatedBase->getParent() != ToReplace->getParent()) {
      // Base and derived relocates are in different basic blocks.
      // In this case transform is only valid when base dominates derived
      // relocate. However it would be too expensive to check dominance
      // for each such relocate, so we skip the whole transformation.
      continue;
    }

    Value *Base = ToReplace->getBasePtr();
    auto *Derived = dyn_cast<GetElementPtrInst>(ToReplace->getDerivedPtr());
    if (!Derived || Derived->getPointerOperand() != Base)
      continue;

    SmallVector<Value *, 2> OffsetV;
    if (!getGEPSmallConstantIntOffsetV(Derived, OffsetV))
      continue;

    // Create a Builder and replace the target callsite with a gep
    assert(RelocatedBase->getNextNode() &&
           "Should always have one since it's not a terminator");

    // Insert after RelocatedBase
    IRBuilder<> Builder(RelocatedBase->getNextNode());
    Builder.SetCurrentDebugLocation(ToReplace->getDebugLoc());

    // If gc_relocate does not match the actual type, cast it to the right type.
    // In theory, there must be a bitcast after gc_relocate if the type does not
    // match, and we should reuse it to get the derived pointer. But it could be
    // cases like this:
    // bb1:
    //  ...
    //  %g1 = call coldcc i8 addrspace(1)*
    //  @llvm.experimental.gc.relocate.p1i8(...) br label %merge
    //
    // bb2:
    //  ...
    //  %g2 = call coldcc i8 addrspace(1)*
    //  @llvm.experimental.gc.relocate.p1i8(...) br label %merge
    //
    // merge:
    //  %p1 = phi i8 addrspace(1)* [ %g1, %bb1 ], [ %g2, %bb2 ]
    //  %cast = bitcast i8 addrspace(1)* %p1 in to i32 addrspace(1)*
    //
    // In this case, we can not find the bitcast any more. So we insert a new
    // bitcast no matter there is already one or not. In this way, we can handle
    // all cases, and the extra bitcast should be optimized away in later
    // passes.
    Value *ActualRelocatedBase = RelocatedBase;
    if (RelocatedBase->getType() != Base->getType()) {
      ActualRelocatedBase =
          Builder.CreateBitCast(RelocatedBase, Base->getType());
    }
    Value *Replacement =
        Builder.CreateGEP(Derived->getSourceElementType(), ActualRelocatedBase,
                          ArrayRef(OffsetV));
    Replacement->takeName(ToReplace);
    // If the newly generated derived pointer's type does not match the original
    // derived pointer's type, cast the new derived pointer to match it. Same
    // reasoning as above.
    Value *ActualReplacement = Replacement;
    if (Replacement->getType() != ToReplace->getType()) {
      ActualReplacement =
          Builder.CreateBitCast(Replacement, ToReplace->getType());
    }
    ToReplace->replaceAllUsesWith(ActualReplacement);
    ToReplace->eraseFromParent();

    MadeChange = true;
  }
  return MadeChange;
}

// Turns this:
//
// %base = ...
// %ptr = gep %base + 15
// %tok = statepoint (%fun, i32 0, i32 0, i32 0, %base, %ptr)
// %base' = relocate(%tok, i32 4, i32 4)
// %ptr' = relocate(%tok, i32 4, i32 5)
// %val = load %ptr'
//
// into this:
//
// %base = ...
// %ptr = gep %base + 15
// %tok = statepoint (%fun, i32 0, i32 0, i32 0, %base, %ptr)
// %base' = gc.relocate(%tok, i32 4, i32 4)
// %ptr' = gep %base' + 15
// %val = load %ptr'
bool CodeGenPrepare::simplifyOffsetableRelocate(GCStatepointInst &I) {
  bool MadeChange = false;
  SmallVector<GCRelocateInst *, 2> AllRelocateCalls;
  for (auto *U : I.users())
    if (GCRelocateInst *Relocate = dyn_cast<GCRelocateInst>(U))
      // Collect all the relocate calls associated with a statepoint
      AllRelocateCalls.push_back(Relocate);

  // We need at least one base pointer relocation + one derived pointer
  // relocation to mangle
  if (AllRelocateCalls.size() < 2)
    return false;

  // RelocateInstMap is a mapping from the base relocate instruction to the
  // corresponding derived relocate instructions
  DenseMap<GCRelocateInst *, SmallVector<GCRelocateInst *, 2>> RelocateInstMap;
  computeBaseDerivedRelocateMap(AllRelocateCalls, RelocateInstMap);
  if (RelocateInstMap.empty())
    return false;

  for (auto &Item : RelocateInstMap)
    // Item.first is the RelocatedBase to offset against
    // Item.second is the vector of Targets to replace
    MadeChange = simplifyRelocatesOffABase(Item.first, Item.second);
  return MadeChange;
}

/// Sink the specified cast instruction into its user blocks.
static bool SinkCast(CastInst *CI) {
  BasicBlock *DefBB = CI->getParent();

  /// InsertedCasts - Only insert a cast in each block once.
  DenseMap<BasicBlock *, CastInst *> InsertedCasts;

  bool MadeChange = false;
  for (Value::user_iterator UI = CI->user_begin(), E = CI->user_end();
       UI != E;) {
    Use &TheUse = UI.getUse();
    Instruction *User = cast<Instruction>(*UI);

    // Figure out which BB this cast is used in.  For PHI's this is the
    // appropriate predecessor block.
    BasicBlock *UserBB = User->getParent();
    if (PHINode *PN = dyn_cast<PHINode>(User)) {
      UserBB = PN->getIncomingBlock(TheUse);
    }

    // Preincrement use iterator so we don't invalidate it.
    ++UI;

    // The first insertion point of a block containing an EH pad is after the
    // pad.  If the pad is the user, we cannot sink the cast past the pad.
    if (User->isEHPad())
      continue;

    // If the block selected to receive the cast is an EH pad that does not
    // allow non-PHI instructions before the terminator, we can't sink the
    // cast.
    if (UserBB->getTerminator()->isEHPad())
      continue;

    // If this user is in the same block as the cast, don't change the cast.
    if (UserBB == DefBB)
      continue;

    // If we have already inserted a cast into this block, use it.
    CastInst *&InsertedCast = InsertedCasts[UserBB];

    if (!InsertedCast) {
      BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
      assert(InsertPt != UserBB->end());
      InsertedCast = CastInst::Create(CI->getOpcode(), CI->getOperand(0),
                                      CI->getType(), "", &*InsertPt);
      InsertedCast->setDebugLoc(CI->getDebugLoc());
    }

    // Replace a use of the cast with a use of the new cast.
    TheUse = InsertedCast;
    MadeChange = true;
    ++NumCastUses;
  }

  // If we removed all uses, nuke the cast.
  if (CI->use_empty()) {
    salvageDebugInfo(*CI);
    CI->eraseFromParent();
    MadeChange = true;
  }

  return MadeChange;
}

/// If the specified cast instruction is a noop copy (e.g. it's casting from
/// one pointer type to another, i32->i8 on PPC), sink it into user blocks to
/// reduce the number of virtual registers that must be created and coalesced.
///
/// Return true if any changes are made.
static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI,
                                       const DataLayout &DL) {
  // Sink only "cheap" (or nop) address-space casts.  This is a weaker condition
  // than sinking only nop casts, but is helpful on some platforms.
  if (auto *ASC = dyn_cast<AddrSpaceCastInst>(CI)) {
    if (!TLI.isFreeAddrSpaceCast(ASC->getSrcAddressSpace(),
                                 ASC->getDestAddressSpace()))
      return false;
  }

  // If this is a noop copy,
  EVT SrcVT = TLI.getValueType(DL, CI->getOperand(0)->getType());
  EVT DstVT = TLI.getValueType(DL, CI->getType());

  // This is an fp<->int conversion?
  if (SrcVT.isInteger() != DstVT.isInteger())
    return false;

  // If this is an extension, it will be a zero or sign extension, which
  // isn't a noop.
  if (SrcVT.bitsLT(DstVT))
    return false;

  // If these values will be promoted, find out what they will be promoted
  // to.  This helps us consider truncates on PPC as noop copies when they
  // are.
  if (TLI.getTypeAction(CI->getContext(), SrcVT) ==
      TargetLowering::TypePromoteInteger)
    SrcVT = TLI.getTypeToTransformTo(CI->getContext(), SrcVT);
  if (TLI.getTypeAction(CI->getContext(), DstVT) ==
      TargetLowering::TypePromoteInteger)
    DstVT = TLI.getTypeToTransformTo(CI->getContext(), DstVT);

  // If, after promotion, these are the same types, this is a noop copy.
  if (SrcVT != DstVT)
    return false;

  return SinkCast(CI);
}

// Match a simple increment by constant operation.  Note that if a sub is
// matched, the step is negated (as if the step had been canonicalized to
// an add, even though we leave the instruction alone.)
bool matchIncrement(const Instruction *IVInc, Instruction *&LHS,
                    Constant *&Step) {
  if (match(IVInc, m_Add(m_Instruction(LHS), m_Constant(Step))) ||
      match(IVInc, m_ExtractValue<0>(m_Intrinsic<Intrinsic::uadd_with_overflow>(
                       m_Instruction(LHS), m_Constant(Step)))))
    return true;
  if (match(IVInc, m_Sub(m_Instruction(LHS), m_Constant(Step))) ||
      match(IVInc, m_ExtractValue<0>(m_Intrinsic<Intrinsic::usub_with_overflow>(
                       m_Instruction(LHS), m_Constant(Step))))) {
    Step = ConstantExpr::getNeg(Step);
    return true;
  }
  return false;
}

/// If given \p PN is an inductive variable with value IVInc coming from the
/// backedge, and on each iteration it gets increased by Step, return pair
/// <IVInc, Step>. Otherwise, return std::nullopt.
static std::optional<std::pair<Instruction *, Constant *>>
getIVIncrement(const PHINode *PN, const LoopInfo *LI) {
  const Loop *L = LI->getLoopFor(PN->getParent());
  if (!L || L->getHeader() != PN->getParent() || !L->getLoopLatch())
    return std::nullopt;
  auto *IVInc =
      dyn_cast<Instruction>(PN->getIncomingValueForBlock(L->getLoopLatch()));
  if (!IVInc || LI->getLoopFor(IVInc->getParent()) != L)
    return std::nullopt;
  Instruction *LHS = nullptr;
  Constant *Step = nullptr;
  if (matchIncrement(IVInc, LHS, Step) && LHS == PN)
    return std::make_pair(IVInc, Step);
  return std::nullopt;
}

static bool isIVIncrement(const Value *V, const LoopInfo *LI) {
  auto *I = dyn_cast<Instruction>(V);
  if (!I)
    return false;
  Instruction *LHS = nullptr;
  Constant *Step = nullptr;
  if (!matchIncrement(I, LHS, Step))
    return false;
  if (auto *PN = dyn_cast<PHINode>(LHS))
    if (auto IVInc = getIVIncrement(PN, LI))
      return IVInc->first == I;
  return false;
}

bool CodeGenPrepare::replaceMathCmpWithIntrinsic(BinaryOperator *BO,
                                                 Value *Arg0, Value *Arg1,
                                                 CmpInst *Cmp,
                                                 Intrinsic::ID IID) {
  auto IsReplacableIVIncrement = [this, &Cmp](BinaryOperator *BO) {
    if (!isIVIncrement(BO, LI))
      return false;
    const Loop *L = LI->getLoopFor(BO->getParent());
    assert(L && "L should not be null after isIVIncrement()");
    // Do not risk on moving increment into a child loop.
    if (LI->getLoopFor(Cmp->getParent()) != L)
      return false;

    // Finally, we need to ensure that the insert point will dominate all
    // existing uses of the increment.

    auto &DT = getDT(*BO->getParent()->getParent());
    if (DT.dominates(Cmp->getParent(), BO->getParent()))
      // If we're moving up the dom tree, all uses are trivially dominated.
      // (This is the common case for code produced by LSR.)
      return true;

    // Otherwise, special case the single use in the phi recurrence.
    return BO->hasOneUse() && DT.dominates(Cmp->getParent(), L->getLoopLatch());
  };
  if (BO->getParent() != Cmp->getParent() && !IsReplacableIVIncrement(BO)) {
    // We used to use a dominator tree here to allow multi-block optimization.
    // But that was problematic because:
    // 1. It could cause a perf regression by hoisting the math op into the
    //    critical path.
    // 2. It could cause a perf regression by creating a value that was live
    //    across multiple blocks and increasing register pressure.
    // 3. Use of a dominator tree could cause large compile-time regression.
    //    This is because we recompute the DT on every change in the main CGP
    //    run-loop. The recomputing is probably unnecessary in many cases, so if
    //    that was fixed, using a DT here would be ok.
    //
    // There is one important particular case we still want to handle: if BO is
    // the IV increment. Important properties that make it profitable:
    // - We can speculate IV increment anywhere in the loop (as long as the
    //   indvar Phi is its only user);
    // - Upon computing Cmp, we effectively compute something equivalent to the
    //   IV increment (despite it loops differently in the IR). So moving it up
    //   to the cmp point does not really increase register pressure.
    return false;
  }

  // We allow matching the canonical IR (add X, C) back to (usubo X, -C).
  if (BO->getOpcode() == Instruction::Add &&
      IID == Intrinsic::usub_with_overflow) {
    assert(isa<Constant>(Arg1) && "Unexpected input for usubo");
    Arg1 = ConstantExpr::getNeg(cast<Constant>(Arg1));
  }

  // Insert at the first instruction of the pair.
  Instruction *InsertPt = nullptr;
  for (Instruction &Iter : *Cmp->getParent()) {
    // If BO is an XOR, it is not guaranteed that it comes after both inputs to
    // the overflow intrinsic are defined.
    if ((BO->getOpcode() != Instruction::Xor && &Iter == BO) || &Iter == Cmp) {
      InsertPt = &Iter;
      break;
    }
  }
  assert(InsertPt != nullptr && "Parent block did not contain cmp or binop");

  IRBuilder<> Builder(InsertPt);
  Value *MathOV = Builder.CreateBinaryIntrinsic(IID, Arg0, Arg1);
  if (BO->getOpcode() != Instruction::Xor) {
    Value *Math = Builder.CreateExtractValue(MathOV, 0, "math");
    replaceAllUsesWith(BO, Math, FreshBBs, IsHugeFunc);
  } else
    assert(BO->hasOneUse() &&
           "Patterns with XOr should use the BO only in the compare");
  Value *OV = Builder.CreateExtractValue(MathOV, 1, "ov");
  replaceAllUsesWith(Cmp, OV, FreshBBs, IsHugeFunc);
  Cmp->eraseFromParent();
  BO->eraseFromParent();
  return true;
}

/// Match special-case patterns that check for unsigned add overflow.
static bool matchUAddWithOverflowConstantEdgeCases(CmpInst *Cmp,
                                                   BinaryOperator *&Add) {
  // Add = add A, 1; Cmp = icmp eq A,-1 (overflow if A is max val)
  // Add = add A,-1; Cmp = icmp ne A, 0 (overflow if A is non-zero)
  Value *A = Cmp->getOperand(0), *B = Cmp->getOperand(1);

  // We are not expecting non-canonical/degenerate code. Just bail out.
  if (isa<Constant>(A))
    return false;

  ICmpInst::Predicate Pred = Cmp->getPredicate();
  if (Pred == ICmpInst::ICMP_EQ && match(B, m_AllOnes()))
    B = ConstantInt::get(B->getType(), 1);
  else if (Pred == ICmpInst::ICMP_NE && match(B, m_ZeroInt()))
    B = ConstantInt::get(B->getType(), -1);
  else
    return false;

  // Check the users of the variable operand of the compare looking for an add
  // with the adjusted constant.
  for (User *U : A->users()) {
    if (match(U, m_Add(m_Specific(A), m_Specific(B)))) {
      Add = cast<BinaryOperator>(U);
      return true;
    }
  }
  return false;
}

/// Try to combine the compare into a call to the llvm.uadd.with.overflow
/// intrinsic. Return true if any changes were made.
bool CodeGenPrepare::combineToUAddWithOverflow(CmpInst *Cmp,
                                               ModifyDT &ModifiedDT) {
  bool EdgeCase = false;
  Value *A, *B;
  BinaryOperator *Add;
  if (!match(Cmp, m_UAddWithOverflow(m_Value(A), m_Value(B), m_BinOp(Add)))) {
    if (!matchUAddWithOverflowConstantEdgeCases(Cmp, Add))
      return false;
    // Set A and B in case we match matchUAddWithOverflowConstantEdgeCases.
    A = Add->getOperand(0);
    B = Add->getOperand(1);
    EdgeCase = true;
  }

  if (!TLI->shouldFormOverflowOp(ISD::UADDO,
                                 TLI->getValueType(*DL, Add->getType()),
                                 Add->hasNUsesOrMore(EdgeCase ? 1 : 2)))
    return false;

  // We don't want to move around uses of condition values this late, so we
  // check if it is legal to create the call to the intrinsic in the basic
  // block containing the icmp.
  if (Add->getParent() != Cmp->getParent() && !Add->hasOneUse())
    return false;

  if (!replaceMathCmpWithIntrinsic(Add, A, B, Cmp,
                                   Intrinsic::uadd_with_overflow))
    return false;

  // Reset callers - do not crash by iterating over a dead instruction.
  ModifiedDT = ModifyDT::ModifyInstDT;
  return true;
}

bool CodeGenPrepare::combineToUSubWithOverflow(CmpInst *Cmp,
                                               ModifyDT &ModifiedDT) {
  // We are not expecting non-canonical/degenerate code. Just bail out.
  Value *A = Cmp->getOperand(0), *B = Cmp->getOperand(1);
  if (isa<Constant>(A) && isa<Constant>(B))
    return false;

  // Convert (A u> B) to (A u< B) to simplify pattern matching.
  ICmpInst::Predicate Pred = Cmp->getPredicate();
  if (Pred == ICmpInst::ICMP_UGT) {
    std::swap(A, B);
    Pred = ICmpInst::ICMP_ULT;
  }
  // Convert special-case: (A == 0) is the same as (A u< 1).
  if (Pred == ICmpInst::ICMP_EQ && match(B, m_ZeroInt())) {
    B = ConstantInt::get(B->getType(), 1);
    Pred = ICmpInst::ICMP_ULT;
  }
  // Convert special-case: (A != 0) is the same as (0 u< A).
  if (Pred == ICmpInst::ICMP_NE && match(B, m_ZeroInt())) {
    std::swap(A, B);
    Pred = ICmpInst::ICMP_ULT;
  }
  if (Pred != ICmpInst::ICMP_ULT)
    return false;

  // Walk the users of a variable operand of a compare looking for a subtract or
  // add with that same operand. Also match the 2nd operand of the compare to
  // the add/sub, but that may be a negated constant operand of an add.
  Value *CmpVariableOperand = isa<Constant>(A) ? B : A;
  BinaryOperator *Sub = nullptr;
  for (User *U : CmpVariableOperand->users()) {
    // A - B, A u< B --> usubo(A, B)
    if (match(U, m_Sub(m_Specific(A), m_Specific(B)))) {
      Sub = cast<BinaryOperator>(U);
      break;
    }

    // A + (-C), A u< C (canonicalized form of (sub A, C))
    const APInt *CmpC, *AddC;
    if (match(U, m_Add(m_Specific(A), m_APInt(AddC))) &&
        match(B, m_APInt(CmpC)) && *AddC == -(*CmpC)) {
      Sub = cast<BinaryOperator>(U);
      break;
    }
  }
  if (!Sub)
    return false;

  if (!TLI->shouldFormOverflowOp(ISD::USUBO,
                                 TLI->getValueType(*DL, Sub->getType()),
                                 Sub->hasNUsesOrMore(1)))
    return false;

  if (!replaceMathCmpWithIntrinsic(Sub, Sub->getOperand(0), Sub->getOperand(1),
                                   Cmp, Intrinsic::usub_with_overflow))
    return false;

  // Reset callers - do not crash by iterating over a dead instruction.
  ModifiedDT = ModifyDT::ModifyInstDT;
  return true;
}

/// Sink the given CmpInst into user blocks to reduce the number of virtual
/// registers that must be created and coalesced. This is a clear win except on
/// targets with multiple condition code registers (PowerPC), where it might
/// lose; some adjustment may be wanted there.
///
/// Return true if any changes are made.
static bool sinkCmpExpression(CmpInst *Cmp, const TargetLowering &TLI) {
  if (TLI.hasMultipleConditionRegisters())
    return false;

  // Avoid sinking soft-FP comparisons, since this can move them into a loop.
  if (TLI.useSoftFloat() && isa<FCmpInst>(Cmp))
    return false;

  // Only insert a cmp in each block once.
  DenseMap<BasicBlock *, CmpInst *> InsertedCmps;

  bool MadeChange = false;
  for (Value::user_iterator UI = Cmp->user_begin(), E = Cmp->user_end();
       UI != E;) {
    Use &TheUse = UI.getUse();
    Instruction *User = cast<Instruction>(*UI);

    // Preincrement use iterator so we don't invalidate it.
    ++UI;

    // Don't bother for PHI nodes.
    if (isa<PHINode>(User))
      continue;

    // Figure out which BB this cmp is used in.
    BasicBlock *UserBB = User->getParent();
    BasicBlock *DefBB = Cmp->getParent();

    // If this user is in the same block as the cmp, don't change the cmp.
    if (UserBB == DefBB)
      continue;

    // If we have already inserted a cmp into this block, use it.
    CmpInst *&InsertedCmp = InsertedCmps[UserBB];

    if (!InsertedCmp) {
      BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
      assert(InsertPt != UserBB->end());
      InsertedCmp = CmpInst::Create(Cmp->getOpcode(), Cmp->getPredicate(),
                                    Cmp->getOperand(0), Cmp->getOperand(1), "",
                                    &*InsertPt);
      // Propagate the debug info.
      InsertedCmp->setDebugLoc(Cmp->getDebugLoc());
    }

    // Replace a use of the cmp with a use of the new cmp.
    TheUse = InsertedCmp;
    MadeChange = true;
    ++NumCmpUses;
  }

  // If we removed all uses, nuke the cmp.
  if (Cmp->use_empty()) {
    Cmp->eraseFromParent();
    MadeChange = true;
  }

  return MadeChange;
}

/// For pattern like:
///
///   DomCond = icmp sgt/slt CmpOp0, CmpOp1 (might not be in DomBB)
///   ...
/// DomBB:
///   ...
///   br DomCond, TrueBB, CmpBB
/// CmpBB: (with DomBB being the single predecessor)
///   ...
///   Cmp = icmp eq CmpOp0, CmpOp1
///   ...
///
/// It would use two comparison on targets that lowering of icmp sgt/slt is
/// different from lowering of icmp eq (PowerPC). This function try to convert
/// 'Cmp = icmp eq CmpOp0, CmpOp1' to ' Cmp = icmp slt/sgt CmpOp0, CmpOp1'.
/// After that, DomCond and Cmp can use the same comparison so reduce one
/// comparison.
///
/// Return true if any changes are made.
static bool foldICmpWithDominatingICmp(CmpInst *Cmp,
                                       const TargetLowering &TLI) {
  if (!EnableICMP_EQToICMP_ST && TLI.isEqualityCmpFoldedWithSignedCmp())
    return false;

  ICmpInst::Predicate Pred = Cmp->getPredicate();
  if (Pred != ICmpInst::ICMP_EQ)
    return false;

  // If icmp eq has users other than BranchInst and SelectInst, converting it to
  // icmp slt/sgt would introduce more redundant LLVM IR.
  for (User *U : Cmp->users()) {
    if (isa<BranchInst>(U))
      continue;
    if (isa<SelectInst>(U) && cast<SelectInst>(U)->getCondition() == Cmp)
      continue;
    return false;
  }

  // This is a cheap/incomplete check for dominance - just match a single
  // predecessor with a conditional branch.
  BasicBlock *CmpBB = Cmp->getParent();
  BasicBlock *DomBB = CmpBB->getSinglePredecessor();
  if (!DomBB)
    return false;

  // We want to ensure that the only way control gets to the comparison of
  // interest is that a less/greater than comparison on the same operands is
  // false.
  Value *DomCond;
  BasicBlock *TrueBB, *FalseBB;
  if (!match(DomBB->getTerminator(), m_Br(m_Value(DomCond), TrueBB, FalseBB)))
    return false;
  if (CmpBB != FalseBB)
    return false;

  Value *CmpOp0 = Cmp->getOperand(0), *CmpOp1 = Cmp->getOperand(1);
  ICmpInst::Predicate DomPred;
  if (!match(DomCond, m_ICmp(DomPred, m_Specific(CmpOp0), m_Specific(CmpOp1))))
    return false;
  if (DomPred != ICmpInst::ICMP_SGT && DomPred != ICmpInst::ICMP_SLT)
    return false;

  // Convert the equality comparison to the opposite of the dominating
  // comparison and swap the direction for all branch/select users.
  // We have conceptually converted:
  // Res = (a < b) ? <LT_RES> : (a == b) ? <EQ_RES> : <GT_RES>;
  // to
  // Res = (a < b) ? <LT_RES> : (a > b)  ? <GT_RES> : <EQ_RES>;
  // And similarly for branches.
  for (User *U : Cmp->users()) {
    if (auto *BI = dyn_cast<BranchInst>(U)) {
      assert(BI->isConditional() && "Must be conditional");
      BI->swapSuccessors();
      continue;
    }
    if (auto *SI = dyn_cast<SelectInst>(U)) {
      // Swap operands
      SI->swapValues();
      SI->swapProfMetadata();
      continue;
    }
    llvm_unreachable("Must be a branch or a select");
  }
  Cmp->setPredicate(CmpInst::getSwappedPredicate(DomPred));
  return true;
}

/// Many architectures use the same instruction for both subtract and cmp. Try
/// to swap cmp operands to match subtract operations to allow for CSE.
static bool swapICmpOperandsToExposeCSEOpportunities(CmpInst *Cmp) {
  Value *Op0 = Cmp->getOperand(0);
  Value *Op1 = Cmp->getOperand(1);
  if (!Op0->getType()->isIntegerTy() || isa<Constant>(Op0) ||
      isa<Constant>(Op1) || Op0 == Op1)
    return false;

  // If a subtract already has the same operands as a compare, swapping would be
  // bad. If a subtract has the same operands as a compare but in reverse order,
  // then swapping is good.
  int GoodToSwap = 0;
  unsigned NumInspected = 0;
  for (const User *U : Op0->users()) {
    // Avoid walking many users.
    if (++NumInspected > 128)
      return false;
    if (match(U, m_Sub(m_Specific(Op1), m_Specific(Op0))))
      GoodToSwap++;
    else if (match(U, m_Sub(m_Specific(Op0), m_Specific(Op1))))
      GoodToSwap--;
  }

  if (GoodToSwap > 0) {
    Cmp->swapOperands();
    return true;
  }
  return false;
}

bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) {
  if (sinkCmpExpression(Cmp, *TLI))
    return true;

  if (combineToUAddWithOverflow(Cmp, ModifiedDT))
    return true;

  if (combineToUSubWithOverflow(Cmp, ModifiedDT))
    return true;

  if (foldICmpWithDominatingICmp(Cmp, *TLI))
    return true;

  if (swapICmpOperandsToExposeCSEOpportunities(Cmp))
    return true;

  return false;
}

/// Duplicate and sink the given 'and' instruction into user blocks where it is
/// used in a compare to allow isel to generate better code for targets where
/// this operation can be combined.
///
/// Return true if any changes are made.
static bool sinkAndCmp0Expression(Instruction *AndI, const TargetLowering &TLI,
                                  SetOfInstrs &InsertedInsts) {
  // Double-check that we're not trying to optimize an instruction that was
  // already optimized by some other part of this pass.
  assert(!InsertedInsts.count(AndI) &&
         "Attempting to optimize already optimized and instruction");
  (void)InsertedInsts;

  // Nothing to do for single use in same basic block.
  if (AndI->hasOneUse() &&
      AndI->getParent() == cast<Instruction>(*AndI->user_begin())->getParent())
    return false;

  // Try to avoid cases where sinking/duplicating is likely to increase register
  // pressure.
  if (!isa<ConstantInt>(AndI->getOperand(0)) &&
      !isa<ConstantInt>(AndI->getOperand(1)) &&
      AndI->getOperand(0)->hasOneUse() && AndI->getOperand(1)->hasOneUse())
    return false;

  for (auto *U : AndI->users()) {
    Instruction *User = cast<Instruction>(U);

    // Only sink 'and' feeding icmp with 0.
    if (!isa<ICmpInst>(User))
      return false;

    auto *CmpC = dyn_cast<ConstantInt>(User->getOperand(1));
    if (!CmpC || !CmpC->isZero())
      return false;
  }

  if (!TLI.isMaskAndCmp0FoldingBeneficial(*AndI))
    return false;

  LLVM_DEBUG(dbgs() << "found 'and' feeding only icmp 0;\n");
  LLVM_DEBUG(AndI->getParent()->dump());

  // Push the 'and' into the same block as the icmp 0.  There should only be
  // one (icmp (and, 0)) in each block, since CSE/GVN should have removed any
  // others, so we don't need to keep track of which BBs we insert into.
  for (Value::user_iterator UI = AndI->user_begin(), E = AndI->user_end();
       UI != E;) {
    Use &TheUse = UI.getUse();
    Instruction *User = cast<Instruction>(*UI);

    // Preincrement use iterator so we don't invalidate it.
    ++UI;

    LLVM_DEBUG(dbgs() << "sinking 'and' use: " << *User << "\n");

    // Keep the 'and' in the same place if the use is already in the same block.
    Instruction *InsertPt =
        User->getParent() == AndI->getParent() ? AndI : User;
    Instruction *InsertedAnd =
        BinaryOperator::Create(Instruction::And, AndI->getOperand(0),
                               AndI->getOperand(1), "", InsertPt);
    // Propagate the debug info.
    InsertedAnd->setDebugLoc(AndI->getDebugLoc());

    // Replace a use of the 'and' with a use of the new 'and'.
    TheUse = InsertedAnd;
    ++NumAndUses;
    LLVM_DEBUG(User->getParent()->dump());
  }

  // We removed all uses, nuke the and.
  AndI->eraseFromParent();
  return true;
}

/// Check if the candidates could be combined with a shift instruction, which
/// includes:
/// 1. Truncate instruction
/// 2. And instruction and the imm is a mask of the low bits:
/// imm & (imm+1) == 0
static bool isExtractBitsCandidateUse(Instruction *User) {
  if (!isa<TruncInst>(User)) {
    if (User->getOpcode() != Instruction::And ||
        !isa<ConstantInt>(User->getOperand(1)))
      return false;

    const APInt &Cimm = cast<ConstantInt>(User->getOperand(1))->getValue();

    if ((Cimm & (Cimm + 1)).getBoolValue())
      return false;
  }
  return true;
}

/// Sink both shift and truncate instruction to the use of truncate's BB.
static bool
SinkShiftAndTruncate(BinaryOperator *ShiftI, Instruction *User, ConstantInt *CI,
                     DenseMap<BasicBlock *, BinaryOperator *> &InsertedShifts,
                     const TargetLowering &TLI, const DataLayout &DL) {
  BasicBlock *UserBB = User->getParent();
  DenseMap<BasicBlock *, CastInst *> InsertedTruncs;
  auto *TruncI = cast<TruncInst>(User);
  bool MadeChange = false;

  for (Value::user_iterator TruncUI = TruncI->user_begin(),
                            TruncE = TruncI->user_end();
       TruncUI != TruncE;) {

    Use &TruncTheUse = TruncUI.getUse();
    Instruction *TruncUser = cast<Instruction>(*TruncUI);
    // Preincrement use iterator so we don't invalidate it.

    ++TruncUI;

    int ISDOpcode = TLI.InstructionOpcodeToISD(TruncUser->getOpcode());
    if (!ISDOpcode)
      continue;

    // If the use is actually a legal node, there will not be an
    // implicit truncate.
    // FIXME: always querying the result type is just an
    // approximation; some nodes' legality is determined by the
    // operand or other means. There's no good way to find out though.
    if (TLI.isOperationLegalOrCustom(
            ISDOpcode, TLI.getValueType(DL, TruncUser->getType(), true)))
      continue;

    // Don't bother for PHI nodes.
    if (isa<PHINode>(TruncUser))
      continue;

    BasicBlock *TruncUserBB = TruncUser->getParent();

    if (UserBB == TruncUserBB)
      continue;

    BinaryOperator *&InsertedShift = InsertedShifts[TruncUserBB];
    CastInst *&InsertedTrunc = InsertedTruncs[TruncUserBB];

    if (!InsertedShift && !InsertedTrunc) {
      BasicBlock::iterator InsertPt = TruncUserBB->getFirstInsertionPt();
      assert(InsertPt != TruncUserBB->end());
      // Sink the shift
      if (ShiftI->getOpcode() == Instruction::AShr)
        InsertedShift = BinaryOperator::CreateAShr(ShiftI->getOperand(0), CI,
                                                   "", &*InsertPt);
      else
        InsertedShift = BinaryOperator::CreateLShr(ShiftI->getOperand(0), CI,
                                                   "", &*InsertPt);
      InsertedShift->setDebugLoc(ShiftI->getDebugLoc());

      // Sink the trunc
      BasicBlock::iterator TruncInsertPt = TruncUserBB->getFirstInsertionPt();
      TruncInsertPt++;
      assert(TruncInsertPt != TruncUserBB->end());

      InsertedTrunc = CastInst::Create(TruncI->getOpcode(), InsertedShift,
                                       TruncI->getType(), "", &*TruncInsertPt);
      InsertedTrunc->setDebugLoc(TruncI->getDebugLoc());

      MadeChange = true;

      TruncTheUse = InsertedTrunc;
    }
  }
  return MadeChange;
}

/// Sink the shift *right* instruction into user blocks if the uses could
/// potentially be combined with this shift instruction and generate BitExtract
/// instruction. It will only be applied if the architecture supports BitExtract
/// instruction. Here is an example:
/// BB1:
///   %x.extract.shift = lshr i64 %arg1, 32
/// BB2:
///   %x.extract.trunc = trunc i64 %x.extract.shift to i16
/// ==>
///
/// BB2:
///   %x.extract.shift.1 = lshr i64 %arg1, 32
///   %x.extract.trunc = trunc i64 %x.extract.shift.1 to i16
///
/// CodeGen will recognize the pattern in BB2 and generate BitExtract
/// instruction.
/// Return true if any changes are made.
static bool OptimizeExtractBits(BinaryOperator *ShiftI, ConstantInt *CI,
                                const TargetLowering &TLI,
                                const DataLayout &DL) {
  BasicBlock *DefBB = ShiftI->getParent();

  /// Only insert instructions in each block once.
  DenseMap<BasicBlock *, BinaryOperator *> InsertedShifts;

  bool shiftIsLegal = TLI.isTypeLegal(TLI.getValueType(DL, ShiftI->getType()));

  bool MadeChange = false;
  for (Value::user_iterator UI = ShiftI->user_begin(), E = ShiftI->user_end();
       UI != E;) {
    Use &TheUse = UI.getUse();
    Instruction *User = cast<Instruction>(*UI);
    // Preincrement use iterator so we don't invalidate it.
    ++UI;

    // Don't bother for PHI nodes.
    if (isa<PHINode>(User))
      continue;

    if (!isExtractBitsCandidateUse(User))
      continue;

    BasicBlock *UserBB = User->getParent();

    if (UserBB == DefBB) {
      // If the shift and truncate instruction are in the same BB. The use of
      // the truncate(TruncUse) may still introduce another truncate if not
      // legal. In this case, we would like to sink both shift and truncate
      // instruction to the BB of TruncUse.
      // for example:
      // BB1:
      // i64 shift.result = lshr i64 opnd, imm
      // trunc.result = trunc shift.result to i16
      //
      // BB2:
      //   ----> We will have an implicit truncate here if the architecture does
      //   not have i16 compare.
      // cmp i16 trunc.result, opnd2
      //
      if (isa<TruncInst>(User) &&
          shiftIsLegal
          // If the type of the truncate is legal, no truncate will be
          // introduced in other basic blocks.
          && (!TLI.isTypeLegal(TLI.getValueType(DL, User->getType()))))
        MadeChange =
            SinkShiftAndTruncate(ShiftI, User, CI, InsertedShifts, TLI, DL);

      continue;
    }
    // If we have already inserted a shift into this block, use it.
    BinaryOperator *&InsertedShift = InsertedShifts[UserBB];

    if (!InsertedShift) {
      BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
      assert(InsertPt != UserBB->end());

      if (ShiftI->getOpcode() == Instruction::AShr)
        InsertedShift = BinaryOperator::CreateAShr(ShiftI->getOperand(0), CI,
                                                   "", &*InsertPt);
      else
        InsertedShift = BinaryOperator::CreateLShr(ShiftI->getOperand(0), CI,
                                                   "", &*InsertPt);
      InsertedShift->setDebugLoc(ShiftI->getDebugLoc());

      MadeChange = true;
    }

    // Replace a use of the shift with a use of the new shift.
    TheUse = InsertedShift;
  }

  // If we removed all uses, or there are none, nuke the shift.
  if (ShiftI->use_empty()) {
    salvageDebugInfo(*ShiftI);
    ShiftI->eraseFromParent();
    MadeChange = true;
  }

  return MadeChange;
}

/// If counting leading or trailing zeros is an expensive operation and a zero
/// input is defined, add a check for zero to avoid calling the intrinsic.
///
/// We want to transform:
///     %z = call i64 @llvm.cttz.i64(i64 %A, i1 false)
///
/// into:
///   entry:
///     %cmpz = icmp eq i64 %A, 0
///     br i1 %cmpz, label %cond.end, label %cond.false
///   cond.false:
///     %z = call i64 @llvm.cttz.i64(i64 %A, i1 true)
///     br label %cond.end
///   cond.end:
///     %ctz = phi i64 [ 64, %entry ], [ %z, %cond.false ]
///
/// If the transform is performed, return true and set ModifiedDT to true.
static bool despeculateCountZeros(IntrinsicInst *CountZeros,
                                  LoopInfo &LI,
                                  const TargetLowering *TLI,
                                  const DataLayout *DL, ModifyDT &ModifiedDT,
                                  SmallSet<BasicBlock *, 32> &FreshBBs,
                                  bool IsHugeFunc) {
  // If a zero input is undefined, it doesn't make sense to despeculate that.
  if (match(CountZeros->getOperand(1), m_One()))
    return false;

  // If it's cheap to speculate, there's nothing to do.
  Type *Ty = CountZeros->getType();
  auto IntrinsicID = CountZeros->getIntrinsicID();
  if ((IntrinsicID == Intrinsic::cttz && TLI->isCheapToSpeculateCttz(Ty)) ||
      (IntrinsicID == Intrinsic::ctlz && TLI->isCheapToSpeculateCtlz(Ty)))
    return false;

  // Only handle legal scalar cases. Anything else requires too much work.
  unsigned SizeInBits = Ty->getScalarSizeInBits();
  if (Ty->isVectorTy() || SizeInBits > DL->getLargestLegalIntTypeSizeInBits())
    return false;

  // Bail if the value is never zero.
  Use &Op = CountZeros->getOperandUse(0);
  if (isKnownNonZero(Op, *DL))
    return false;

  // The intrinsic will be sunk behind a compare against zero and branch.
  BasicBlock *StartBlock = CountZeros->getParent();
  BasicBlock *CallBlock = StartBlock->splitBasicBlock(CountZeros, "cond.false");
  if (IsHugeFunc)
    FreshBBs.insert(CallBlock);

  // Create another block after the count zero intrinsic. A PHI will be added
  // in this block to select the result of the intrinsic or the bit-width
  // constant if the input to the intrinsic is zero.
  BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(CountZeros));
  BasicBlock *EndBlock = CallBlock->splitBasicBlock(SplitPt, "cond.end");
  if (IsHugeFunc)
    FreshBBs.insert(EndBlock);

  // Update the LoopInfo. The new blocks are in the same loop as the start
  // block.
  if (Loop *L = LI.getLoopFor(StartBlock)) {
    L->addBasicBlockToLoop(CallBlock, LI);
    L->addBasicBlockToLoop(EndBlock, LI);
  }

  // Set up a builder to create a compare, conditional branch, and PHI.
  IRBuilder<> Builder(CountZeros->getContext());
  Builder.SetInsertPoint(StartBlock->getTerminator());
  Builder.SetCurrentDebugLocation(CountZeros->getDebugLoc());

  // Replace the unconditional branch that was created by the first split with
  // a compare against zero and a conditional branch.
  Value *Zero = Constant::getNullValue(Ty);
  // Avoid introducing branch on poison. This also replaces the ctz operand.
  if (!isGuaranteedNotToBeUndefOrPoison(Op))
    Op = Builder.CreateFreeze(Op, Op->getName() + ".fr");
  Value *Cmp = Builder.CreateICmpEQ(Op, Zero, "cmpz");
  Builder.CreateCondBr(Cmp, EndBlock, CallBlock);
  StartBlock->getTerminator()->eraseFromParent();

  // Create a PHI in the end block to select either the output of the intrinsic
  // or the bit width of the operand.
  Builder.SetInsertPoint(&EndBlock->front());
  PHINode *PN = Builder.CreatePHI(Ty, 2, "ctz");
  replaceAllUsesWith(CountZeros, PN, FreshBBs, IsHugeFunc);
  Value *BitWidth = Builder.getInt(APInt(SizeInBits, SizeInBits));
  PN->addIncoming(BitWidth, StartBlock);
  PN->addIncoming(CountZeros, CallBlock);

  // We are explicitly handling the zero case, so we can set the intrinsic's
  // undefined zero argument to 'true'. This will also prevent reprocessing the
  // intrinsic; we only despeculate when a zero input is defined.
  CountZeros->setArgOperand(1, Builder.getTrue());
  ModifiedDT = ModifyDT::ModifyBBDT;
  return true;
}

bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) {
  BasicBlock *BB = CI->getParent();

  // Lower inline assembly if we can.
  // If we found an inline asm expession, and if the target knows how to
  // lower it to normal LLVM code, do so now.
  if (CI->isInlineAsm()) {
    if (TLI->ExpandInlineAsm(CI)) {
      // Avoid invalidating the iterator.
      CurInstIterator = BB->begin();
      // Avoid processing instructions out of order, which could cause
      // reuse before a value is defined.
      SunkAddrs.clear();
      return true;
    }
    // Sink address computing for memory operands into the block.
    if (optimizeInlineAsmInst(CI))
      return true;
  }

  // Align the pointer arguments to this call if the target thinks it's a good
  // idea
  unsigned MinSize;
  Align PrefAlign;
  if (TLI->shouldAlignPointerArgs(CI, MinSize, PrefAlign)) {
    for (auto &Arg : CI->args()) {
      // We want to align both objects whose address is used directly and
      // objects whose address is used in casts and GEPs, though it only makes
      // sense for GEPs if the offset is a multiple of the desired alignment and
      // if size - offset meets the size threshold.
      if (!Arg->getType()->isPointerTy())
        continue;
      APInt Offset(DL->getIndexSizeInBits(
                       cast<PointerType>(Arg->getType())->getAddressSpace()),
                   0);
      Value *Val = Arg->stripAndAccumulateInBoundsConstantOffsets(*DL, Offset);
      uint64_t Offset2 = Offset.getLimitedValue();
      if (!isAligned(PrefAlign, Offset2))
        continue;
      AllocaInst *AI;
      if ((AI = dyn_cast<AllocaInst>(Val)) && AI->getAlign() < PrefAlign &&
          DL->getTypeAllocSize(AI->getAllocatedType()) >= MinSize + Offset2)
        AI->setAlignment(PrefAlign);
      // Global variables can only be aligned if they are defined in this
      // object (i.e. they are uniquely initialized in this object), and
      // over-aligning global variables that have an explicit section is
      // forbidden.
      GlobalVariable *GV;
      if ((GV = dyn_cast<GlobalVariable>(Val)) && GV->canIncreaseAlignment() &&
          GV->getPointerAlignment(*DL) < PrefAlign &&
          DL->getTypeAllocSize(GV->getValueType()) >= MinSize + Offset2)
        GV->setAlignment(PrefAlign);
    }
  }
  // If this is a memcpy (or similar) then we may be able to improve the
  // alignment.
  if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(CI)) {
    Align DestAlign = getKnownAlignment(MI->getDest(), *DL);
    MaybeAlign MIDestAlign = MI->getDestAlign();
    if (!MIDestAlign || DestAlign > *MIDestAlign)
      MI->setDestAlignment(DestAlign);
    if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) {
      MaybeAlign MTISrcAlign = MTI->getSourceAlign();
      Align SrcAlign = getKnownAlignment(MTI->getSource(), *DL);
      if (!MTISrcAlign || SrcAlign > *MTISrcAlign)
        MTI->setSourceAlignment(SrcAlign);
    }
  }

  // If we have a cold call site, try to sink addressing computation into the
  // cold block.  This interacts with our handling for loads and stores to
  // ensure that we can fold all uses of a potential addressing computation
  // into their uses.  TODO: generalize this to work over profiling data
  if (CI->hasFnAttr(Attribute::Cold) && !OptSize &&
      !llvm::shouldOptimizeForSize(BB, PSI, BFI.get()))
    for (auto &Arg : CI->args()) {
      if (!Arg->getType()->isPointerTy())
        continue;
      unsigned AS = Arg->getType()->getPointerAddressSpace();
      if (optimizeMemoryInst(CI, Arg, Arg->getType(), AS))
        return true;
    }

  IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI);
  if (II) {
    switch (II->getIntrinsicID()) {
    default:
      break;
    case Intrinsic::assume:
      llvm_unreachable("llvm.assume should have been removed already");
    case Intrinsic::experimental_widenable_condition: {
      // Give up on future widening oppurtunties so that we can fold away dead
      // paths and merge blocks before going into block-local instruction
      // selection.
      if (II->use_empty()) {
        II->eraseFromParent();
        return true;
      }
      Constant *RetVal = ConstantInt::getTrue(II->getContext());
      resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
        replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr);
      });
      return true;
    }
    case Intrinsic::objectsize:
      llvm_unreachable("llvm.objectsize.* should have been lowered already");
    case Intrinsic::is_constant:
      llvm_unreachable("llvm.is.constant.* should have been lowered already");
    case Intrinsic::aarch64_stlxr:
    case Intrinsic::aarch64_stxr: {
      ZExtInst *ExtVal = dyn_cast<ZExtInst>(CI->getArgOperand(0));
      if (!ExtVal || !ExtVal->hasOneUse() ||
          ExtVal->getParent() == CI->getParent())
        return false;
      // Sink a zext feeding stlxr/stxr before it, so it can be folded into it.
      ExtVal->moveBefore(CI);
      // Mark this instruction as "inserted by CGP", so that other
      // optimizations don't touch it.
      InsertedInsts.insert(ExtVal);
      return true;
    }

    case Intrinsic::launder_invariant_group:
    case Intrinsic::strip_invariant_group: {
      Value *ArgVal = II->getArgOperand(0);
      auto it = LargeOffsetGEPMap.find(II);
      if (it != LargeOffsetGEPMap.end()) {
        // Merge entries in LargeOffsetGEPMap to reflect the RAUW.
        // Make sure not to have to deal with iterator invalidation
        // after possibly adding ArgVal to LargeOffsetGEPMap.
        auto GEPs = std::move(it->second);
        LargeOffsetGEPMap[ArgVal].append(GEPs.begin(), GEPs.end());
        LargeOffsetGEPMap.erase(II);
      }

      replaceAllUsesWith(II, ArgVal, FreshBBs, IsHugeFunc);
      II->eraseFromParent();
      return true;
    }
    case Intrinsic::cttz:
    case Intrinsic::ctlz:
      // If counting zeros is expensive, try to avoid it.
      return despeculateCountZeros(II, *LI, TLI, DL, ModifiedDT, FreshBBs,
                                   IsHugeFunc);
    case Intrinsic::fshl:
    case Intrinsic::fshr:
      return optimizeFunnelShift(II);
    case Intrinsic::dbg_assign:
    case Intrinsic::dbg_value:
      return fixupDbgValue(II);
    case Intrinsic::masked_gather:
      return optimizeGatherScatterInst(II, II->getArgOperand(0));
    case Intrinsic::masked_scatter:
      return optimizeGatherScatterInst(II, II->getArgOperand(1));
    }

    SmallVector<Value *, 2> PtrOps;
    Type *AccessTy;
    if (TLI->getAddrModeArguments(II, PtrOps, AccessTy))
      while (!PtrOps.empty()) {
        Value *PtrVal = PtrOps.pop_back_val();
        unsigned AS = PtrVal->getType()->getPointerAddressSpace();
        if (optimizeMemoryInst(II, PtrVal, AccessTy, AS))
          return true;
      }
  }

  // From here on out we're working with named functions.
  if (!CI->getCalledFunction())
    return false;

  // Lower all default uses of _chk calls.  This is very similar
  // to what InstCombineCalls does, but here we are only lowering calls
  // to fortified library functions (e.g. __memcpy_chk) that have the default
  // "don't know" as the objectsize.  Anything else should be left alone.
  FortifiedLibCallSimplifier Simplifier(TLInfo, true);
  IRBuilder<> Builder(CI);
  if (Value *V = Simplifier.optimizeCall(CI, Builder)) {
    replaceAllUsesWith(CI, V, FreshBBs, IsHugeFunc);
    CI->eraseFromParent();
    return true;
  }

  return false;
}

/// Look for opportunities to duplicate return instructions to the predecessor
/// to enable tail call optimizations. The case it is currently looking for is:
/// @code
/// bb0:
///   %tmp0 = tail call i32 @f0()
///   br label %return
/// bb1:
///   %tmp1 = tail call i32 @f1()
///   br label %return
/// bb2:
///   %tmp2 = tail call i32 @f2()
///   br label %return
/// return:
///   %retval = phi i32 [ %tmp0, %bb0 ], [ %tmp1, %bb1 ], [ %tmp2, %bb2 ]
///   ret i32 %retval
/// @endcode
///
/// =>
///
/// @code
/// bb0:
///   %tmp0 = tail call i32 @f0()
///   ret i32 %tmp0
/// bb1:
///   %tmp1 = tail call i32 @f1()
///   ret i32 %tmp1
/// bb2:
///   %tmp2 = tail call i32 @f2()
///   ret i32 %tmp2
/// @endcode
bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB,
                                                ModifyDT &ModifiedDT) {
  if (!BB->getTerminator())
    return false;

  ReturnInst *RetI = dyn_cast<ReturnInst>(BB->getTerminator());
  if (!RetI)
    return false;

  assert(LI->getLoopFor(BB) == nullptr && "A return block cannot be in a loop");

  PHINode *PN = nullptr;
  ExtractValueInst *EVI = nullptr;
  BitCastInst *BCI = nullptr;
  Value *V = RetI->getReturnValue();
  if (V) {
    BCI = dyn_cast<BitCastInst>(V);
    if (BCI)
      V = BCI->getOperand(0);

    EVI = dyn_cast<ExtractValueInst>(V);
    if (EVI) {
      V = EVI->getOperand(0);
      if (!llvm::all_of(EVI->indices(), [](unsigned idx) { return idx == 0; }))
        return false;
    }

    PN = dyn_cast<PHINode>(V);
    if (!PN)
      return false;
  }

  if (PN && PN->getParent() != BB)
    return false;

  auto isLifetimeEndOrBitCastFor = [](const Instruction *Inst) {
    const BitCastInst *BC = dyn_cast<BitCastInst>(Inst);
    if (BC && BC->hasOneUse())
      Inst = BC->user_back();

    if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst))
      return II->getIntrinsicID() == Intrinsic::lifetime_end;
    return false;
  };

  // Make sure there are no instructions between the first instruction
  // and return.
  const Instruction *BI = BB->getFirstNonPHI();
  // Skip over debug and the bitcast.
  while (isa<DbgInfoIntrinsic>(BI) || BI == BCI || BI == EVI ||
         isa<PseudoProbeInst>(BI) || isLifetimeEndOrBitCastFor(BI))
    BI = BI->getNextNode();
  if (BI != RetI)
    return false;

  /// Only dup the ReturnInst if the CallInst is likely to be emitted as a tail
  /// call.
  const Function *F = BB->getParent();
  SmallVector<BasicBlock *, 4> TailCallBBs;
  if (PN) {
    for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) {
      // Look through bitcasts.
      Value *IncomingVal = PN->getIncomingValue(I)->stripPointerCasts();
      CallInst *CI = dyn_cast<CallInst>(IncomingVal);
      BasicBlock *PredBB = PN->getIncomingBlock(I);
      // Make sure the phi value is indeed produced by the tail call.
      if (CI && CI->hasOneUse() && CI->getParent() == PredBB &&
          TLI->mayBeEmittedAsTailCall(CI) &&
          attributesPermitTailCall(F, CI, RetI, *TLI))
        TailCallBBs.push_back(PredBB);
    }
  } else {
    SmallPtrSet<BasicBlock *, 4> VisitedBBs;
    for (BasicBlock *Pred : predecessors(BB)) {
      if (!VisitedBBs.insert(Pred).second)
        continue;
      if (Instruction *I = Pred->rbegin()->getPrevNonDebugInstruction(true)) {
        CallInst *CI = dyn_cast<CallInst>(I);
        if (CI && CI->use_empty() && TLI->mayBeEmittedAsTailCall(CI) &&
            attributesPermitTailCall(F, CI, RetI, *TLI))
          TailCallBBs.push_back(Pred);
      }
    }
  }

  bool Changed = false;
  for (auto const &TailCallBB : TailCallBBs) {
    // Make sure the call instruction is followed by an unconditional branch to
    // the return block.
    BranchInst *BI = dyn_cast<BranchInst>(TailCallBB->getTerminator());
    if (!BI || !BI->isUnconditional() || BI->getSuccessor(0) != BB)
      continue;

    // Duplicate the return into TailCallBB.
    (void)FoldReturnIntoUncondBranch(RetI, BB, TailCallBB);
    assert(!VerifyBFIUpdates ||
           BFI->getBlockFreq(BB) >= BFI->getBlockFreq(TailCallBB));
    BFI->setBlockFreq(
        BB,
        (BFI->getBlockFreq(BB) - BFI->getBlockFreq(TailCallBB)).getFrequency());
    ModifiedDT = ModifyDT::ModifyBBDT;
    Changed = true;
    ++NumRetsDup;
  }

  // If we eliminated all predecessors of the block, delete the block now.
  if (Changed && !BB->hasAddressTaken() && pred_empty(BB))
    BB->eraseFromParent();

  return Changed;
}

//===----------------------------------------------------------------------===//
// Memory Optimization
//===----------------------------------------------------------------------===//

namespace {

/// This is an extended version of TargetLowering::AddrMode
/// which holds actual Value*'s for register values.
struct ExtAddrMode : public TargetLowering::AddrMode {
  Value *BaseReg = nullptr;
  Value *ScaledReg = nullptr;
  Value *OriginalValue = nullptr;
  bool InBounds = true;

  enum FieldName {
    NoField = 0x00,
    BaseRegField = 0x01,
    BaseGVField = 0x02,
    BaseOffsField = 0x04,
    ScaledRegField = 0x08,
    ScaleField = 0x10,
    MultipleFields = 0xff
  };

  ExtAddrMode() = default;

  void print(raw_ostream &OS) const;
  void dump() const;

  FieldName compare(const ExtAddrMode &other) {
    // First check that the types are the same on each field, as differing types
    // is something we can't cope with later on.
    if (BaseReg && other.BaseReg &&
        BaseReg->getType() != other.BaseReg->getType())
      return MultipleFields;
    if (BaseGV && other.BaseGV && BaseGV->getType() != other.BaseGV->getType())
      return MultipleFields;
    if (ScaledReg && other.ScaledReg &&
        ScaledReg->getType() != other.ScaledReg->getType())
      return MultipleFields;

    // Conservatively reject 'inbounds' mismatches.
    if (InBounds != other.InBounds)
      return MultipleFields;

    // Check each field to see if it differs.
    unsigned Result = NoField;
    if (BaseReg != other.BaseReg)
      Result |= BaseRegField;
    if (BaseGV != other.BaseGV)
      Result |= BaseGVField;
    if (BaseOffs != other.BaseOffs)
      Result |= BaseOffsField;
    if (ScaledReg != other.ScaledReg)
      Result |= ScaledRegField;
    // Don't count 0 as being a different scale, because that actually means
    // unscaled (which will already be counted by having no ScaledReg).
    if (Scale && other.Scale && Scale != other.Scale)
      Result |= ScaleField;

    if (llvm::popcount(Result) > 1)
      return MultipleFields;
    else
      return static_cast<FieldName>(Result);
  }

  // An AddrMode is trivial if it involves no calculation i.e. it is just a base
  // with no offset.
  bool isTrivial() {
    // An AddrMode is (BaseGV + BaseReg + BaseOffs + ScaleReg * Scale) so it is
    // trivial if at most one of these terms is nonzero, except that BaseGV and
    // BaseReg both being zero actually means a null pointer value, which we
    // consider to be 'non-zero' here.
    return !BaseOffs && !Scale && !(BaseGV && BaseReg);
  }

  Value *GetFieldAsValue(FieldName Field, Type *IntPtrTy) {
    switch (Field) {
    default:
      return nullptr;
    case BaseRegField:
      return BaseReg;
    case BaseGVField:
      return BaseGV;
    case ScaledRegField:
      return ScaledReg;
    case BaseOffsField:
      return ConstantInt::get(IntPtrTy, BaseOffs);
    }
  }

  void SetCombinedField(FieldName Field, Value *V,
                        const SmallVectorImpl<ExtAddrMode> &AddrModes) {
    switch (Field) {
    default:
      llvm_unreachable("Unhandled fields are expected to be rejected earlier");
      break;
    case ExtAddrMode::BaseRegField:
      BaseReg = V;
      break;
    case ExtAddrMode::BaseGVField:
      // A combined BaseGV is an Instruction, not a GlobalValue, so it goes
      // in the BaseReg field.
      assert(BaseReg == nullptr);
      BaseReg = V;
      BaseGV = nullptr;
      break;
    case ExtAddrMode::ScaledRegField:
      ScaledReg = V;
      // If we have a mix of scaled and unscaled addrmodes then we want scale
      // to be the scale and not zero.
      if (!Scale)
        for (const ExtAddrMode &AM : AddrModes)
          if (AM.Scale) {
            Scale = AM.Scale;
            break;
          }
      break;
    case ExtAddrMode::BaseOffsField:
      // The offset is no longer a constant, so it goes in ScaledReg with a
      // scale of 1.
      assert(ScaledReg == nullptr);
      ScaledReg = V;
      Scale = 1;
      BaseOffs = 0;
      break;
    }
  }
};

#ifndef NDEBUG
static inline raw_ostream &operator<<(raw_ostream &OS, const ExtAddrMode &AM) {
  AM.print(OS);
  return OS;
}
#endif

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void ExtAddrMode::print(raw_ostream &OS) const {
  bool NeedPlus = false;
  OS << "[";
  if (InBounds)
    OS << "inbounds ";
  if (BaseGV) {
    OS << "GV:";
    BaseGV->printAsOperand(OS, /*PrintType=*/false);
    NeedPlus = true;
  }

  if (BaseOffs) {
    OS << (NeedPlus ? " + " : "") << BaseOffs;
    NeedPlus = true;
  }

  if (BaseReg) {
    OS << (NeedPlus ? " + " : "") << "Base:";
    BaseReg->printAsOperand(OS, /*PrintType=*/false);
    NeedPlus = true;
  }
  if (Scale) {
    OS << (NeedPlus ? " + " : "") << Scale << "*";
    ScaledReg->printAsOperand(OS, /*PrintType=*/false);
  }

  OS << ']';
}

LLVM_DUMP_METHOD void ExtAddrMode::dump() const {
  print(dbgs());
  dbgs() << '\n';
}
#endif

} // end anonymous namespace

namespace {

/// This class provides transaction based operation on the IR.
/// Every change made through this class is recorded in the internal state and
/// can be undone (rollback) until commit is called.
/// CGP does not check if instructions could be speculatively executed when
/// moved. Preserving the original location would pessimize the debugging
/// experience, as well as negatively impact the quality of sample PGO.
class TypePromotionTransaction {
  /// This represents the common interface of the individual transaction.
  /// Each class implements the logic for doing one specific modification on
  /// the IR via the TypePromotionTransaction.
  class TypePromotionAction {
  protected:
    /// The Instruction modified.
    Instruction *Inst;

  public:
    /// Constructor of the action.
    /// The constructor performs the related action on the IR.
    TypePromotionAction(Instruction *Inst) : Inst(Inst) {}

    virtual ~TypePromotionAction() = default;

    /// Undo the modification done by this action.
    /// When this method is called, the IR must be in the same state as it was
    /// before this action was applied.
    /// \pre Undoing the action works if and only if the IR is in the exact same
    /// state as it was directly after this action was applied.
    virtual void undo() = 0;

    /// Advocate every change made by this action.
    /// When the results on the IR of the action are to be kept, it is important
    /// to call this function, otherwise hidden information may be kept forever.
    virtual void commit() {
      // Nothing to be done, this action is not doing anything.
    }
  };

  /// Utility to remember the position of an instruction.
  class InsertionHandler {
    /// Position of an instruction.
    /// Either an instruction:
    /// - Is the first in a basic block: BB is used.
    /// - Has a previous instruction: PrevInst is used.
    union {
      Instruction *PrevInst;
      BasicBlock *BB;
    } Point;

    /// Remember whether or not the instruction had a previous instruction.
    bool HasPrevInstruction;

  public:
    /// Record the position of \p Inst.
    InsertionHandler(Instruction *Inst) {
      BasicBlock::iterator It = Inst->getIterator();
      HasPrevInstruction = (It != (Inst->getParent()->begin()));
      if (HasPrevInstruction)
        Point.PrevInst = &*--It;
      else
        Point.BB = Inst->getParent();
    }

    /// Insert \p Inst at the recorded position.
    void insert(Instruction *Inst) {
      if (HasPrevInstruction) {
        if (Inst->getParent())
          Inst->removeFromParent();
        Inst->insertAfter(Point.PrevInst);
      } else {
        Instruction *Position = &*Point.BB->getFirstInsertionPt();
        if (Inst->getParent())
          Inst->moveBefore(Position);
        else
          Inst->insertBefore(Position);
      }
    }
  };

  /// Move an instruction before another.
  class InstructionMoveBefore : public TypePromotionAction {
    /// Original position of the instruction.
    InsertionHandler Position;

  public:
    /// Move \p Inst before \p Before.
    InstructionMoveBefore(Instruction *Inst, Instruction *Before)
        : TypePromotionAction(Inst), Position(Inst) {
      LLVM_DEBUG(dbgs() << "Do: move: " << *Inst << "\nbefore: " << *Before
                        << "\n");
      Inst->moveBefore(Before);
    }

    /// Move the instruction back to its original position.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: moveBefore: " << *Inst << "\n");
      Position.insert(Inst);
    }
  };

  /// Set the operand of an instruction with a new value.
  class OperandSetter : public TypePromotionAction {
    /// Original operand of the instruction.
    Value *Origin;

    /// Index of the modified instruction.
    unsigned Idx;

  public:
    /// Set \p Idx operand of \p Inst with \p NewVal.
    OperandSetter(Instruction *Inst, unsigned Idx, Value *NewVal)
        : TypePromotionAction(Inst), Idx(Idx) {
      LLVM_DEBUG(dbgs() << "Do: setOperand: " << Idx << "\n"
                        << "for:" << *Inst << "\n"
                        << "with:" << *NewVal << "\n");
      Origin = Inst->getOperand(Idx);
      Inst->setOperand(Idx, NewVal);
    }

    /// Restore the original value of the instruction.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: setOperand:" << Idx << "\n"
                        << "for: " << *Inst << "\n"
                        << "with: " << *Origin << "\n");
      Inst->setOperand(Idx, Origin);
    }
  };

  /// Hide the operands of an instruction.
  /// Do as if this instruction was not using any of its operands.
  class OperandsHider : public TypePromotionAction {
    /// The list of original operands.
    SmallVector<Value *, 4> OriginalValues;

  public:
    /// Remove \p Inst from the uses of the operands of \p Inst.
    OperandsHider(Instruction *Inst) : TypePromotionAction(Inst) {
      LLVM_DEBUG(dbgs() << "Do: OperandsHider: " << *Inst << "\n");
      unsigned NumOpnds = Inst->getNumOperands();
      OriginalValues.reserve(NumOpnds);
      for (unsigned It = 0; It < NumOpnds; ++It) {
        // Save the current operand.
        Value *Val = Inst->getOperand(It);
        OriginalValues.push_back(Val);
        // Set a dummy one.
        // We could use OperandSetter here, but that would imply an overhead
        // that we are not willing to pay.
        Inst->setOperand(It, UndefValue::get(Val->getType()));
      }
    }

    /// Restore the original list of uses.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: OperandsHider: " << *Inst << "\n");
      for (unsigned It = 0, EndIt = OriginalValues.size(); It != EndIt; ++It)
        Inst->setOperand(It, OriginalValues[It]);
    }
  };

  /// Build a truncate instruction.
  class TruncBuilder : public TypePromotionAction {
    Value *Val;

  public:
    /// Build a truncate instruction of \p Opnd producing a \p Ty
    /// result.
    /// trunc Opnd to Ty.
    TruncBuilder(Instruction *Opnd, Type *Ty) : TypePromotionAction(Opnd) {
      IRBuilder<> Builder(Opnd);
      Builder.SetCurrentDebugLocation(DebugLoc());
      Val = Builder.CreateTrunc(Opnd, Ty, "promoted");
      LLVM_DEBUG(dbgs() << "Do: TruncBuilder: " << *Val << "\n");
    }

    /// Get the built value.
    Value *getBuiltValue() { return Val; }

    /// Remove the built instruction.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: TruncBuilder: " << *Val << "\n");
      if (Instruction *IVal = dyn_cast<Instruction>(Val))
        IVal->eraseFromParent();
    }
  };

  /// Build a sign extension instruction.
  class SExtBuilder : public TypePromotionAction {
    Value *Val;

  public:
    /// Build a sign extension instruction of \p Opnd producing a \p Ty
    /// result.
    /// sext Opnd to Ty.
    SExtBuilder(Instruction *InsertPt, Value *Opnd, Type *Ty)
        : TypePromotionAction(InsertPt) {
      IRBuilder<> Builder(InsertPt);
      Val = Builder.CreateSExt(Opnd, Ty, "promoted");
      LLVM_DEBUG(dbgs() << "Do: SExtBuilder: " << *Val << "\n");
    }

    /// Get the built value.
    Value *getBuiltValue() { return Val; }

    /// Remove the built instruction.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: SExtBuilder: " << *Val << "\n");
      if (Instruction *IVal = dyn_cast<Instruction>(Val))
        IVal->eraseFromParent();
    }
  };

  /// Build a zero extension instruction.
  class ZExtBuilder : public TypePromotionAction {
    Value *Val;

  public:
    /// Build a zero extension instruction of \p Opnd producing a \p Ty
    /// result.
    /// zext Opnd to Ty.
    ZExtBuilder(Instruction *InsertPt, Value *Opnd, Type *Ty)
        : TypePromotionAction(InsertPt) {
      IRBuilder<> Builder(InsertPt);
      Builder.SetCurrentDebugLocation(DebugLoc());
      Val = Builder.CreateZExt(Opnd, Ty, "promoted");
      LLVM_DEBUG(dbgs() << "Do: ZExtBuilder: " << *Val << "\n");
    }

    /// Get the built value.
    Value *getBuiltValue() { return Val; }

    /// Remove the built instruction.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: ZExtBuilder: " << *Val << "\n");
      if (Instruction *IVal = dyn_cast<Instruction>(Val))
        IVal->eraseFromParent();
    }
  };

  /// Mutate an instruction to another type.
  class TypeMutator : public TypePromotionAction {
    /// Record the original type.
    Type *OrigTy;

  public:
    /// Mutate the type of \p Inst into \p NewTy.
    TypeMutator(Instruction *Inst, Type *NewTy)
        : TypePromotionAction(Inst), OrigTy(Inst->getType()) {
      LLVM_DEBUG(dbgs() << "Do: MutateType: " << *Inst << " with " << *NewTy
                        << "\n");
      Inst->mutateType(NewTy);
    }

    /// Mutate the instruction back to its original type.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: MutateType: " << *Inst << " with " << *OrigTy
                        << "\n");
      Inst->mutateType(OrigTy);
    }
  };

  /// Replace the uses of an instruction by another instruction.
  class UsesReplacer : public TypePromotionAction {
    /// Helper structure to keep track of the replaced uses.
    struct InstructionAndIdx {
      /// The instruction using the instruction.
      Instruction *Inst;

      /// The index where this instruction is used for Inst.
      unsigned Idx;

      InstructionAndIdx(Instruction *Inst, unsigned Idx)
          : Inst(Inst), Idx(Idx) {}
    };

    /// Keep track of the original uses (pair Instruction, Index).
    SmallVector<InstructionAndIdx, 4> OriginalUses;
    /// Keep track of the debug users.
    SmallVector<DbgValueInst *, 1> DbgValues;

    /// Keep track of the new value so that we can undo it by replacing
    /// instances of the new value with the original value.
    Value *New;

    using use_iterator = SmallVectorImpl<InstructionAndIdx>::iterator;

  public:
    /// Replace all the use of \p Inst by \p New.
    UsesReplacer(Instruction *Inst, Value *New)
        : TypePromotionAction(Inst), New(New) {
      LLVM_DEBUG(dbgs() << "Do: UsersReplacer: " << *Inst << " with " << *New
                        << "\n");
      // Record the original uses.
      for (Use &U : Inst->uses()) {
        Instruction *UserI = cast<Instruction>(U.getUser());
        OriginalUses.push_back(InstructionAndIdx(UserI, U.getOperandNo()));
      }
      // Record the debug uses separately. They are not in the instruction's
      // use list, but they are replaced by RAUW.
      findDbgValues(DbgValues, Inst);

      // Now, we can replace the uses.
      Inst->replaceAllUsesWith(New);
    }

    /// Reassign the original uses of Inst to Inst.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: UsersReplacer: " << *Inst << "\n");
      for (InstructionAndIdx &Use : OriginalUses)
        Use.Inst->setOperand(Use.Idx, Inst);
      // RAUW has replaced all original uses with references to the new value,
      // including the debug uses. Since we are undoing the replacements,
      // the original debug uses must also be reinstated to maintain the
      // correctness and utility of debug value instructions.
      for (auto *DVI : DbgValues)
        DVI->replaceVariableLocationOp(New, Inst);
    }
  };

  /// Remove an instruction from the IR.
  class InstructionRemover : public TypePromotionAction {
    /// Original position of the instruction.
    InsertionHandler Inserter;

    /// Helper structure to hide all the link to the instruction. In other
    /// words, this helps to do as if the instruction was removed.
    OperandsHider Hider;

    /// Keep track of the uses replaced, if any.
    UsesReplacer *Replacer = nullptr;

    /// Keep track of instructions removed.
    SetOfInstrs &RemovedInsts;

  public:
    /// Remove all reference of \p Inst and optionally replace all its
    /// uses with New.
    /// \p RemovedInsts Keep track of the instructions removed by this Action.
    /// \pre If !Inst->use_empty(), then New != nullptr
    InstructionRemover(Instruction *Inst, SetOfInstrs &RemovedInsts,
                       Value *New = nullptr)
        : TypePromotionAction(Inst), Inserter(Inst), Hider(Inst),
          RemovedInsts(RemovedInsts) {
      if (New)
        Replacer = new UsesReplacer(Inst, New);
      LLVM_DEBUG(dbgs() << "Do: InstructionRemover: " << *Inst << "\n");
      RemovedInsts.insert(Inst);
      /// The instructions removed here will be freed after completing
      /// optimizeBlock() for all blocks as we need to keep track of the
      /// removed instructions during promotion.
      Inst->removeFromParent();
    }

    ~InstructionRemover() override { delete Replacer; }

    InstructionRemover &operator=(const InstructionRemover &other) = delete;
    InstructionRemover(const InstructionRemover &other) = delete;

    /// Resurrect the instruction and reassign it to the proper uses if
    /// new value was provided when build this action.
    void undo() override {
      LLVM_DEBUG(dbgs() << "Undo: InstructionRemover: " << *Inst << "\n");
      Inserter.insert(Inst);
      if (Replacer)
        Replacer->undo();
      Hider.undo();
      RemovedInsts.erase(Inst);
    }
  };

public:
  /// Restoration point.
  /// The restoration point is a pointer to an action instead of an iterator
  /// because the iterator may be invalidated but not the pointer.
  using ConstRestorationPt = const TypePromotionAction *;

  TypePromotionTransaction(SetOfInstrs &RemovedInsts)
      : RemovedInsts(RemovedInsts) {}

  /// Advocate every changes made in that transaction. Return true if any change
  /// happen.
  bool commit();

  /// Undo all the changes made after the given point.
  void rollback(ConstRestorationPt Point);

  /// Get the current restoration point.
  ConstRestorationPt getRestorationPoint() const;

  /// \name API for IR modification with state keeping to support rollback.
  /// @{
  /// Same as Instruction::setOperand.
  void setOperand(Instruction *Inst, unsigned Idx, Value *NewVal);

  /// Same as Instruction::eraseFromParent.
  void eraseInstruction(Instruction *Inst, Value *NewVal = nullptr);

  /// Same as Value::replaceAllUsesWith.
  void replaceAllUsesWith(Instruction *Inst, Value *New);

  /// Same as Value::mutateType.
  void mutateType(Instruction *Inst, Type *NewTy);

  /// Same as IRBuilder::createTrunc.
  Value *createTrunc(Instruction *Opnd, Type *Ty);

  /// Same as IRBuilder::createSExt.
  Value *createSExt(Instruction *Inst, Value *Opnd, Type *Ty);

  /// Same as IRBuilder::createZExt.
  Value *createZExt(Instruction *Inst, Value *Opnd, Type *Ty);

  /// Same as Instruction::moveBefore.
  void moveBefore(Instruction *Inst, Instruction *Before);
  /// @}

private:
  /// The ordered list of actions made so far.
  SmallVector<std::unique_ptr<TypePromotionAction>, 16> Actions;

  using CommitPt =
      SmallVectorImpl<std::unique_ptr<TypePromotionAction>>::iterator;

  SetOfInstrs &RemovedInsts;
};

} // end anonymous namespace

void TypePromotionTransaction::setOperand(Instruction *Inst, unsigned Idx,
                                          Value *NewVal) {
  Actions.push_back(std::make_unique<TypePromotionTransaction::OperandSetter>(
      Inst, Idx, NewVal));
}

void TypePromotionTransaction::eraseInstruction(Instruction *Inst,
                                                Value *NewVal) {
  Actions.push_back(
      std::make_unique<TypePromotionTransaction::InstructionRemover>(
          Inst, RemovedInsts, NewVal));
}

void TypePromotionTransaction::replaceAllUsesWith(Instruction *Inst,
                                                  Value *New) {
  Actions.push_back(
      std::make_unique<TypePromotionTransaction::UsesReplacer>(Inst, New));
}

void TypePromotionTransaction::mutateType(Instruction *Inst, Type *NewTy) {
  Actions.push_back(
      std::make_unique<TypePromotionTransaction::TypeMutator>(Inst, NewTy));
}

Value *TypePromotionTransaction::createTrunc(Instruction *Opnd, Type *Ty) {
  std::unique_ptr<TruncBuilder> Ptr(new TruncBuilder(Opnd, Ty));
  Value *Val = Ptr->getBuiltValue();
  Actions.push_back(std::move(Ptr));
  return Val;
}

Value *TypePromotionTransaction::createSExt(Instruction *Inst, Value *Opnd,
                                            Type *Ty) {
  std::unique_ptr<SExtBuilder> Ptr(new SExtBuilder(Inst, Opnd, Ty));
  Value *Val = Ptr->getBuiltValue();
  Actions.push_back(std::move(Ptr));
  return Val;
}

Value *TypePromotionTransaction::createZExt(Instruction *Inst, Value *Opnd,
                                            Type *Ty) {
  std::unique_ptr<ZExtBuilder> Ptr(new ZExtBuilder(Inst, Opnd, Ty));
  Value *Val = Ptr->getBuiltValue();
  Actions.push_back(std::move(Ptr));
  return Val;
}

void TypePromotionTransaction::moveBefore(Instruction *Inst,
                                          Instruction *Before) {
  Actions.push_back(
      std::make_unique<TypePromotionTransaction::InstructionMoveBefore>(
          Inst, Before));
}

TypePromotionTransaction::ConstRestorationPt
TypePromotionTransaction::getRestorationPoint() const {
  return !Actions.empty() ? Actions.back().get() : nullptr;
}

bool TypePromotionTransaction::commit() {
  for (std::unique_ptr<TypePromotionAction> &Action : Actions)
    Action->commit();
  bool Modified = !Actions.empty();
  Actions.clear();
  return Modified;
}

void TypePromotionTransaction::rollback(
    TypePromotionTransaction::ConstRestorationPt Point) {
  while (!Actions.empty() && Point != Actions.back().get()) {
    std::unique_ptr<TypePromotionAction> Curr = Actions.pop_back_val();
    Curr->undo();
  }
}

namespace {

/// A helper class for matching addressing modes.
///
/// This encapsulates the logic for matching the target-legal addressing modes.
class AddressingModeMatcher {
  SmallVectorImpl<Instruction *> &AddrModeInsts;
  const TargetLowering &TLI;
  const TargetRegisterInfo &TRI;
  const DataLayout &DL;
  const LoopInfo &LI;
  const std::function<const DominatorTree &()> getDTFn;

  /// AccessTy/MemoryInst - This is the type for the access (e.g. double) and
  /// the memory instruction that we're computing this address for.
  Type *AccessTy;
  unsigned AddrSpace;
  Instruction *MemoryInst;

  /// This is the addressing mode that we're building up. This is
  /// part of the return value of this addressing mode matching stuff.
  ExtAddrMode &AddrMode;

  /// The instructions inserted by other CodeGenPrepare optimizations.
  const SetOfInstrs &InsertedInsts;

  /// A map from the instructions to their type before promotion.
  InstrToOrigTy &PromotedInsts;

  /// The ongoing transaction where every action should be registered.
  TypePromotionTransaction &TPT;

  // A GEP which has too large offset to be folded into the addressing mode.
  std::pair<AssertingVH<GetElementPtrInst>, int64_t> &LargeOffsetGEP;

  /// This is set to true when we should not do profitability checks.
  /// When true, IsProfitableToFoldIntoAddressingMode always returns true.
  bool IgnoreProfitability;

  /// True if we are optimizing for size.
  bool OptSize = false;

  ProfileSummaryInfo *PSI;
  BlockFrequencyInfo *BFI;

  AddressingModeMatcher(
      SmallVectorImpl<Instruction *> &AMI, const TargetLowering &TLI,
      const TargetRegisterInfo &TRI, const LoopInfo &LI,
      const std::function<const DominatorTree &()> getDTFn, Type *AT,
      unsigned AS, Instruction *MI, ExtAddrMode &AM,
      const SetOfInstrs &InsertedInsts, InstrToOrigTy &PromotedInsts,
      TypePromotionTransaction &TPT,
      std::pair<AssertingVH<GetElementPtrInst>, int64_t> &LargeOffsetGEP,
      bool OptSize, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI)
      : AddrModeInsts(AMI), TLI(TLI), TRI(TRI),
        DL(MI->getModule()->getDataLayout()), LI(LI), getDTFn(getDTFn),
        AccessTy(AT), AddrSpace(AS), MemoryInst(MI), AddrMode(AM),
        InsertedInsts(InsertedInsts), PromotedInsts(PromotedInsts), TPT(TPT),
        LargeOffsetGEP(LargeOffsetGEP), OptSize(OptSize), PSI(PSI), BFI(BFI) {
    IgnoreProfitability = false;
  }

public:
  /// Find the maximal addressing mode that a load/store of V can fold,
  /// give an access type of AccessTy.  This returns a list of involved
  /// instructions in AddrModeInsts.
  /// \p InsertedInsts The instructions inserted by other CodeGenPrepare
  /// optimizations.
  /// \p PromotedInsts maps the instructions to their type before promotion.
  /// \p The ongoing transaction where every action should be registered.
  static ExtAddrMode
  Match(Value *V, Type *AccessTy, unsigned AS, Instruction *MemoryInst,
        SmallVectorImpl<Instruction *> &AddrModeInsts,
        const TargetLowering &TLI, const LoopInfo &LI,
        const std::function<const DominatorTree &()> getDTFn,
        const TargetRegisterInfo &TRI, const SetOfInstrs &InsertedInsts,
        InstrToOrigTy &PromotedInsts, TypePromotionTransaction &TPT,
        std::pair<AssertingVH<GetElementPtrInst>, int64_t> &LargeOffsetGEP,
        bool OptSize, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) {
    ExtAddrMode Result;

    bool Success = AddressingModeMatcher(AddrModeInsts, TLI, TRI, LI, getDTFn,
                                         AccessTy, AS, MemoryInst, Result,
                                         InsertedInsts, PromotedInsts, TPT,
                                         LargeOffsetGEP, OptSize, PSI, BFI)
                       .matchAddr(V, 0);
    (void)Success;
    assert(Success && "Couldn't select *anything*?");
    return Result;
  }

private:
  bool matchScaledValue(Value *ScaleReg, int64_t Scale, unsigned Depth);
  bool matchAddr(Value *Addr, unsigned Depth);
  bool matchOperationAddr(User *AddrInst, unsigned Opcode, unsigned Depth,
                          bool *MovedAway = nullptr);
  bool isProfitableToFoldIntoAddressingMode(Instruction *I,
                                            ExtAddrMode &AMBefore,
                                            ExtAddrMode &AMAfter);
  bool valueAlreadyLiveAtInst(Value *Val, Value *KnownLive1, Value *KnownLive2);
  bool isPromotionProfitable(unsigned NewCost, unsigned OldCost,
                             Value *PromotedOperand) const;
};

class PhiNodeSet;

/// An iterator for PhiNodeSet.
class PhiNodeSetIterator {
  PhiNodeSet *const Set;
  size_t CurrentIndex = 0;

public:
  /// The constructor. Start should point to either a valid element, or be equal
  /// to the size of the underlying SmallVector of the PhiNodeSet.
  PhiNodeSetIterator(PhiNodeSet *const Set, size_t Start);
  PHINode *operator*() const;
  PhiNodeSetIterator &operator++();
  bool operator==(const PhiNodeSetIterator &RHS) const;
  bool operator!=(const PhiNodeSetIterator &RHS) const;
};

/// Keeps a set of PHINodes.
///
/// This is a minimal set implementation for a specific use case:
/// It is very fast when there are very few elements, but also provides good
/// performance when there are many. It is similar to SmallPtrSet, but also
/// provides iteration by insertion order, which is deterministic and stable
/// across runs. It is also similar to SmallSetVector, but provides removing
/// elements in O(1) time. This is achieved by not actually removing the element
/// from the underlying vector, so comes at the cost of using more memory, but
/// that is fine, since PhiNodeSets are used as short lived objects.
class PhiNodeSet {
  friend class PhiNodeSetIterator;

  using MapType = SmallDenseMap<PHINode *, size_t, 32>;
  using iterator = PhiNodeSetIterator;

  /// Keeps the elements in the order of their insertion in the underlying
  /// vector. To achieve constant time removal, it never deletes any element.
  SmallVector<PHINode *, 32> NodeList;

  /// Keeps the elements in the underlying set implementation. This (and not the
  /// NodeList defined above) is the source of truth on whether an element
  /// is actually in the collection.
  MapType NodeMap;

  /// Points to the first valid (not deleted) element when the set is not empty
  /// and the value is not zero. Equals to the size of the underlying vector
  /// when the set is empty. When the value is 0, as in the beginning, the
  /// first element may or may not be valid.
  size_t FirstValidElement = 0;

public:
  /// Inserts a new element to the collection.
  /// \returns true if the element is actually added, i.e. was not in the
  /// collection before the operation.
  bool insert(PHINode *Ptr) {
    if (NodeMap.insert(std::make_pair(Ptr, NodeList.size())).second) {
      NodeList.push_back(Ptr);
      return true;
    }
    return false;
  }

  /// Removes the element from the collection.
  /// \returns whether the element is actually removed, i.e. was in the
  /// collection before the operation.
  bool erase(PHINode *Ptr) {
    if (NodeMap.erase(Ptr)) {
      SkipRemovedElements(FirstValidElement);
      return true;
    }
    return false;
  }

  /// Removes all elements and clears the collection.
  void clear() {
    NodeMap.clear();
    NodeList.clear();
    FirstValidElement = 0;
  }

  /// \returns an iterator that will iterate the elements in the order of
  /// insertion.
  iterator begin() {
    if (FirstValidElement == 0)
      SkipRemovedElements(FirstValidElement);
    return PhiNodeSetIterator(this, FirstValidElement);
  }

  /// \returns an iterator that points to the end of the collection.
  iterator end() { return PhiNodeSetIterator(this, NodeList.size()); }

  /// Returns the number of elements in the collection.
  size_t size() const { return NodeMap.size(); }

  /// \returns 1 if the given element is in the collection, and 0 if otherwise.
  size_t count(PHINode *Ptr) const { return NodeMap.count(Ptr); }

private:
  /// Updates the CurrentIndex so that it will point to a valid element.
  ///
  /// If the element of NodeList at CurrentIndex is valid, it does not
  /// change it. If there are no more valid elements, it updates CurrentIndex
  /// to point to the end of the NodeList.
  void SkipRemovedElements(size_t &CurrentIndex) {
    while (CurrentIndex < NodeList.size()) {
      auto it = NodeMap.find(NodeList[CurrentIndex]);
      // If the element has been deleted and added again later, NodeMap will
      // point to a different index, so CurrentIndex will still be invalid.
      if (it != NodeMap.end() && it->second == CurrentIndex)
        break;
      ++CurrentIndex;
    }
  }
};

PhiNodeSetIterator::PhiNodeSetIterator(PhiNodeSet *const Set, size_t Start)
    : Set(Set), CurrentIndex(Start) {}

PHINode *PhiNodeSetIterator::operator*() const {
  assert(CurrentIndex < Set->NodeList.size() &&
         "PhiNodeSet access out of range");
  return Set->NodeList[CurrentIndex];
}

PhiNodeSetIterator &PhiNodeSetIterator::operator++() {
  assert(CurrentIndex < Set->NodeList.size() &&
         "PhiNodeSet access out of range");
  ++CurrentIndex;
  Set->SkipRemovedElements(CurrentIndex);
  return *this;
}

bool PhiNodeSetIterator::operator==(const PhiNodeSetIterator &RHS) const {
  return CurrentIndex == RHS.CurrentIndex;
}

bool PhiNodeSetIterator::operator!=(const PhiNodeSetIterator &RHS) const {
  return !((*this) == RHS);
}

/// Keep track of simplification of Phi nodes.
/// Accept the set of all phi nodes and erase phi node from this set
/// if it is simplified.
class SimplificationTracker {
  DenseMap<Value *, Value *> Storage;
  const SimplifyQuery &SQ;
  // Tracks newly created Phi nodes. The elements are iterated by insertion
  // order.
  PhiNodeSet AllPhiNodes;
  // Tracks newly created Select nodes.
  SmallPtrSet<SelectInst *, 32> AllSelectNodes;

public:
  SimplificationTracker(const SimplifyQuery &sq) : SQ(sq) {}

  Value *Get(Value *V) {
    do {
      auto SV = Storage.find(V);
      if (SV == Storage.end())
        return V;
      V = SV->second;
    } while (true);
  }

  Value *Simplify(Value *Val) {
    SmallVector<Value *, 32> WorkList;
    SmallPtrSet<Value *, 32> Visited;
    WorkList.push_back(Val);
    while (!WorkList.empty()) {
      auto *P = WorkList.pop_back_val();
      if (!Visited.insert(P).second)
        continue;
      if (auto *PI = dyn_cast<Instruction>(P))
        if (Value *V = simplifyInstruction(cast<Instruction>(PI), SQ)) {
          for (auto *U : PI->users())
            WorkList.push_back(cast<Value>(U));
          Put(PI, V);
          PI->replaceAllUsesWith(V);
          if (auto *PHI = dyn_cast<PHINode>(PI))
            AllPhiNodes.erase(PHI);
          if (auto *Select = dyn_cast<SelectInst>(PI))
            AllSelectNodes.erase(Select);
          PI->eraseFromParent();
        }
    }
    return Get(Val);
  }

  void Put(Value *From, Value *To) { Storage.insert({From, To}); }

  void ReplacePhi(PHINode *From, PHINode *To) {
    Value *OldReplacement = Get(From);
    while (OldReplacement != From) {
      From = To;
      To = dyn_cast<PHINode>(OldReplacement);
      OldReplacement = Get(From);
    }
    assert(To && Get(To) == To && "Replacement PHI node is already replaced.");
    Put(From, To);
    From->replaceAllUsesWith(To);
    AllPhiNodes.erase(From);
    From->eraseFromParent();
  }

  PhiNodeSet &newPhiNodes() { return AllPhiNodes; }

  void insertNewPhi(PHINode *PN) { AllPhiNodes.insert(PN); }

  void insertNewSelect(SelectInst *SI) { AllSelectNodes.insert(SI); }

  unsigned countNewPhiNodes() const { return AllPhiNodes.size(); }

  unsigned countNewSelectNodes() const { return AllSelectNodes.size(); }

  void destroyNewNodes(Type *CommonType) {
    // For safe erasing, replace the uses with dummy value first.
    auto *Dummy = PoisonValue::get(CommonType);
    for (auto *I : AllPhiNodes) {
      I->replaceAllUsesWith(Dummy);
      I->eraseFromParent();
    }
    AllPhiNodes.clear();
    for (auto *I : AllSelectNodes) {
      I->replaceAllUsesWith(Dummy);
      I->eraseFromParent();
    }
    AllSelectNodes.clear();
  }
};

/// A helper class for combining addressing modes.
class AddressingModeCombiner {
  typedef DenseMap<Value *, Value *> FoldAddrToValueMapping;
  typedef std::pair<PHINode *, PHINode *> PHIPair;

private:
  /// The addressing modes we've collected.
  SmallVector<ExtAddrMode, 16> AddrModes;

  /// The field in which the AddrModes differ, when we have more than one.
  ExtAddrMode::FieldName DifferentField = ExtAddrMode::NoField;

  /// Are the AddrModes that we have all just equal to their original values?
  bool AllAddrModesTrivial = true;

  /// Common Type for all different fields in addressing modes.
  Type *CommonType = nullptr;

  /// SimplifyQuery for simplifyInstruction utility.
  const SimplifyQuery &SQ;

  /// Original Address.
  Value *Original;

  /// Common value among addresses
  Value *CommonValue = nullptr;

public:
  AddressingModeCombiner(const SimplifyQuery &_SQ, Value *OriginalValue)
      : SQ(_SQ), Original(OriginalValue) {}

  ~AddressingModeCombiner() { eraseCommonValueIfDead(); }

  /// Get the combined AddrMode
  const ExtAddrMode &getAddrMode() const { return AddrModes[0]; }

  /// Add a new AddrMode if it's compatible with the AddrModes we already
  /// have.
  /// \return True iff we succeeded in doing so.
  bool addNewAddrMode(ExtAddrMode &NewAddrMode) {
    // Take note of if we have any non-trivial AddrModes, as we need to detect
    // when all AddrModes are trivial as then we would introduce a phi or select
    // which just duplicates what's already there.
    AllAddrModesTrivial = AllAddrModesTrivial && NewAddrMode.isTrivial();

    // If this is the first addrmode then everything is fine.
    if (AddrModes.empty()) {
      AddrModes.emplace_back(NewAddrMode);
      return true;
    }

    // Figure out how different this is from the other address modes, which we
    // can do just by comparing against the first one given that we only care
    // about the cumulative difference.
    ExtAddrMode::FieldName ThisDifferentField =
        AddrModes[0].compare(NewAddrMode);
    if (DifferentField == ExtAddrMode::NoField)
      DifferentField = ThisDifferentField;
    else if (DifferentField != ThisDifferentField)
      DifferentField = ExtAddrMode::MultipleFields;

    // If NewAddrMode differs in more than one dimension we cannot handle it.
    bool CanHandle = DifferentField != ExtAddrMode::MultipleFields;

    // If Scale Field is different then we reject.
    CanHandle = CanHandle && DifferentField != ExtAddrMode::ScaleField;

    // We also must reject the case when base offset is different and
    // scale reg is not null, we cannot handle this case due to merge of
    // different offsets will be used as ScaleReg.
    CanHandle = CanHandle && (DifferentField != ExtAddrMode::BaseOffsField ||
                              !NewAddrMode.ScaledReg);

    // We also must reject the case when GV is different and BaseReg installed
    // due to we want to use base reg as a merge of GV values.
    CanHandle = CanHandle && (DifferentField != ExtAddrMode::BaseGVField ||
                              !NewAddrMode.HasBaseReg);

    // Even if NewAddMode is the same we still need to collect it due to
    // original value is different. And later we will need all original values
    // as anchors during finding the common Phi node.
    if (CanHandle)
      AddrModes.emplace_back(NewAddrMode);
    else
      AddrModes.clear();

    return CanHandle;
  }

  /// Combine the addressing modes we've collected into a single
  /// addressing mode.
  /// \return True iff we successfully combined them or we only had one so
  /// didn't need to combine them anyway.
  bool combineAddrModes() {
    // If we have no AddrModes then they can't be combined.
    if (AddrModes.size() == 0)
      return false;

    // A single AddrMode can trivially be combined.
    if (AddrModes.size() == 1 || DifferentField == ExtAddrMode::NoField)
      return true;

    // If the AddrModes we collected are all just equal to the value they are
    // derived from then combining them wouldn't do anything useful.
    if (AllAddrModesTrivial)
      return false;

    if (!addrModeCombiningAllowed())
      return false;

    // Build a map between <original value, basic block where we saw it> to
    // value of base register.
    // Bail out if there is no common type.
    FoldAddrToValueMapping Map;
    if (!initializeMap(Map))
      return false;

    CommonValue = findCommon(Map);
    if (CommonValue)
      AddrModes[0].SetCombinedField(DifferentField, CommonValue, AddrModes);
    return CommonValue != nullptr;
  }

private:
  /// `CommonValue` may be a placeholder inserted by us.
  /// If the placeholder is not used, we should remove this dead instruction.
  void eraseCommonValueIfDead() {
    if (CommonValue && CommonValue->getNumUses() == 0)
      if (Instruction *CommonInst = dyn_cast<Instruction>(CommonValue))
        CommonInst->eraseFromParent();
  }

  /// Initialize Map with anchor values. For address seen
  /// we set the value of different field saw in this address.
  /// At the same time we find a common type for different field we will
  /// use to create new Phi/Select nodes. Keep it in CommonType field.
  /// Return false if there is no common type found.
  bool initializeMap(FoldAddrToValueMapping &Map) {
    // Keep track of keys where the value is null. We will need to replace it
    // with constant null when we know the common type.
    SmallVector<Value *, 2> NullValue;
    Type *IntPtrTy = SQ.DL.getIntPtrType(AddrModes[0].OriginalValue->getType());
    for (auto &AM : AddrModes) {
      Value *DV = AM.GetFieldAsValue(DifferentField, IntPtrTy);
      if (DV) {
        auto *Type = DV->getType();
        if (CommonType && CommonType != Type)
          return false;
        CommonType = Type;
        Map[AM.OriginalValue] = DV;
      } else {
        NullValue.push_back(AM.OriginalValue);
      }
    }
    assert(CommonType && "At least one non-null value must be!");
    for (auto *V : NullValue)
      Map[V] = Constant::getNullValue(CommonType);
    return true;
  }

  /// We have mapping between value A and other value B where B was a field in
  /// addressing mode represented by A. Also we have an original value C
  /// representing an address we start with. Traversing from C through phi and
  /// selects we ended up with A's in a map. This utility function tries to find
  /// a value V which is a field in addressing mode C and traversing through phi
  /// nodes and selects we will end up in corresponded values B in a map.
  /// The utility will create a new Phi/Selects if needed.
  // The simple example looks as follows:
  // BB1:
  //   p1 = b1 + 40
  //   br cond BB2, BB3
  // BB2:
  //   p2 = b2 + 40
  //   br BB3
  // BB3:
  //   p = phi [p1, BB1], [p2, BB2]
  //   v = load p
  // Map is
  //   p1 -> b1
  //   p2 -> b2
  // Request is
  //   p -> ?
  // The function tries to find or build phi [b1, BB1], [b2, BB2] in BB3.
  Value *findCommon(FoldAddrToValueMapping &Map) {
    // Tracks the simplification of newly created phi nodes. The reason we use
    // this mapping is because we will add new created Phi nodes in AddrToBase.
    // Simplification of Phi nodes is recursive, so some Phi node may
    // be simplified after we added it to AddrToBase. In reality this
    // simplification is possible only if original phi/selects were not
    // simplified yet.
    // Using this mapping we can find the current value in AddrToBase.
    SimplificationTracker ST(SQ);

    // First step, DFS to create PHI nodes for all intermediate blocks.
    // Also fill traverse order for the second step.
    SmallVector<Value *, 32> TraverseOrder;
    InsertPlaceholders(Map, TraverseOrder, ST);

    // Second Step, fill new nodes by merged values and simplify if possible.
    FillPlaceholders(Map, TraverseOrder, ST);

    if (!AddrSinkNewSelects && ST.countNewSelectNodes() > 0) {
      ST.destroyNewNodes(CommonType);
      return nullptr;
    }

    // Now we'd like to match New Phi nodes to existed ones.
    unsigned PhiNotMatchedCount = 0;
    if (!MatchPhiSet(ST, AddrSinkNewPhis, PhiNotMatchedCount)) {
      ST.destroyNewNodes(CommonType);
      return nullptr;
    }

    auto *Result = ST.Get(Map.find(Original)->second);
    if (Result) {
      NumMemoryInstsPhiCreated += ST.countNewPhiNodes() + PhiNotMatchedCount;
      NumMemoryInstsSelectCreated += ST.countNewSelectNodes();
    }
    return Result;
  }

  /// Try to match PHI node to Candidate.
  /// Matcher tracks the matched Phi nodes.
  bool MatchPhiNode(PHINode *PHI, PHINode *Candidate,
                    SmallSetVector<PHIPair, 8> &Matcher,
                    PhiNodeSet &PhiNodesToMatch) {
    SmallVector<PHIPair, 8> WorkList;
    Matcher.insert({PHI, Candidate});
    SmallSet<PHINode *, 8> MatchedPHIs;
    MatchedPHIs.insert(PHI);
    WorkList.push_back({PHI, Candidate});
    SmallSet<PHIPair, 8> Visited;
    while (!WorkList.empty()) {
      auto Item = WorkList.pop_back_val();
      if (!Visited.insert(Item).second)
        continue;
      // We iterate over all incoming values to Phi to compare them.
      // If values are different and both of them Phi and the first one is a
      // Phi we added (subject to match) and both of them is in the same basic
      // block then we can match our pair if values match. So we state that
      // these values match and add it to work list to verify that.
      for (auto *B : Item.first->blocks()) {
        Value *FirstValue = Item.first->getIncomingValueForBlock(B);
        Value *SecondValue = Item.second->getIncomingValueForBlock(B);
        if (FirstValue == SecondValue)
          continue;

        PHINode *FirstPhi = dyn_cast<PHINode>(FirstValue);
        PHINode *SecondPhi = dyn_cast<PHINode>(SecondValue);

        // One of them is not Phi or
        // The first one is not Phi node from the set we'd like to match or
        // Phi nodes from different basic blocks then
        // we will not be able to match.
        if (!FirstPhi || !SecondPhi || !PhiNodesToMatch.count(FirstPhi) ||
            FirstPhi->getParent() != SecondPhi->getParent())
          return false;

        // If we already matched them then continue.
        if (Matcher.count({FirstPhi, SecondPhi}))
          continue;
        // So the values are different and does not match. So we need them to
        // match. (But we register no more than one match per PHI node, so that
        // we won't later try to replace them twice.)
        if (MatchedPHIs.insert(FirstPhi).second)
          Matcher.insert({FirstPhi, SecondPhi});
        // But me must check it.
        WorkList.push_back({FirstPhi, SecondPhi});
      }
    }
    return true;
  }

  /// For the given set of PHI nodes (in the SimplificationTracker) try
  /// to find their equivalents.
  /// Returns false if this matching fails and creation of new Phi is disabled.
  bool MatchPhiSet(SimplificationTracker &ST, bool AllowNewPhiNodes,
                   unsigned &PhiNotMatchedCount) {
    // Matched and PhiNodesToMatch iterate their elements in a deterministic
    // order, so the replacements (ReplacePhi) are also done in a deterministic
    // order.
    SmallSetVector<PHIPair, 8> Matched;
    SmallPtrSet<PHINode *, 8> WillNotMatch;
    PhiNodeSet &PhiNodesToMatch = ST.newPhiNodes();
    while (PhiNodesToMatch.size()) {
      PHINode *PHI = *PhiNodesToMatch.begin();

      // Add us, if no Phi nodes in the basic block we do not match.
      WillNotMatch.clear();
      WillNotMatch.insert(PHI);

      // Traverse all Phis until we found equivalent or fail to do that.
      bool IsMatched = false;
      for (auto &P : PHI->getParent()->phis()) {
        // Skip new Phi nodes.
        if (PhiNodesToMatch.count(&P))
          continue;
        if ((IsMatched = MatchPhiNode(PHI, &P, Matched, PhiNodesToMatch)))
          break;
        // If it does not match, collect all Phi nodes from matcher.
        // if we end up with no match, them all these Phi nodes will not match
        // later.
        for (auto M : Matched)
          WillNotMatch.insert(M.first);
        Matched.clear();
      }
      if (IsMatched) {
        // Replace all matched values and erase them.
        for (auto MV : Matched)
          ST.ReplacePhi(MV.first, MV.second);
        Matched.clear();
        continue;
      }
      // If we are not allowed to create new nodes then bail out.
      if (!AllowNewPhiNodes)
        return false;
      // Just remove all seen values in matcher. They will not match anything.
      PhiNotMatchedCount += WillNotMatch.size();
      for (auto *P : WillNotMatch)
        PhiNodesToMatch.erase(P);
    }
    return true;
  }
  /// Fill the placeholders with values from predecessors and simplify them.
  void FillPlaceholders(FoldAddrToValueMapping &Map,
                        SmallVectorImpl<Value *> &TraverseOrder,
                        SimplificationTracker &ST) {
    while (!TraverseOrder.empty()) {
      Value *Current = TraverseOrder.pop_back_val();
      assert(Map.contains(Current) && "No node to fill!!!");
      Value *V = Map[Current];

      if (SelectInst *Select = dyn_cast<SelectInst>(V)) {
        // CurrentValue also must be Select.
        auto *CurrentSelect = cast<SelectInst>(Current);
        auto *TrueValue = CurrentSelect->getTrueValue();
        assert(Map.contains(TrueValue) && "No True Value!");
        Select->setTrueValue(ST.Get(Map[TrueValue]));
        auto *FalseValue = CurrentSelect->getFalseValue();
        assert(Map.contains(FalseValue) && "No False Value!");
        Select->setFalseValue(ST.Get(Map[FalseValue]));
      } else {
        // Must be a Phi node then.
        auto *PHI = cast<PHINode>(V);
        // Fill the Phi node with values from predecessors.
        for (auto *B : predecessors(PHI->getParent())) {
          Value *PV = cast<PHINode>(Current)->getIncomingValueForBlock(B);
          assert(Map.contains(PV) && "No predecessor Value!");
          PHI->addIncoming(ST.Get(Map[PV]), B);
        }
      }
      Map[Current] = ST.Simplify(V);
    }
  }

  /// Starting from original value recursively iterates over def-use chain up to
  /// known ending values represented in a map. For each traversed phi/select
  /// inserts a placeholder Phi or Select.
  /// Reports all new created Phi/Select nodes by adding them to set.
  /// Also reports and order in what values have been traversed.
  void InsertPlaceholders(FoldAddrToValueMapping &Map,
                          SmallVectorImpl<Value *> &TraverseOrder,
                          SimplificationTracker &ST) {
    SmallVector<Value *, 32> Worklist;
    assert((isa<PHINode>(Original) || isa<SelectInst>(Original)) &&
           "Address must be a Phi or Select node");
    auto *Dummy = PoisonValue::get(CommonType);
    Worklist.push_back(Original);
    while (!Worklist.empty()) {
      Value *Current = Worklist.pop_back_val();
      // if it is already visited or it is an ending value then skip it.
      if (Map.contains(Current))
        continue;
      TraverseOrder.push_back(Current);

      // CurrentValue must be a Phi node or select. All others must be covered
      // by anchors.
      if (SelectInst *CurrentSelect = dyn_cast<SelectInst>(Current)) {
        // Is it OK to get metadata from OrigSelect?!
        // Create a Select placeholder with dummy value.
        SelectInst *Select = SelectInst::Create(
            CurrentSelect->getCondition(), Dummy, Dummy,
            CurrentSelect->getName(), CurrentSelect, CurrentSelect);
        Map[Current] = Select;
        ST.insertNewSelect(Select);
        // We are interested in True and False values.
        Worklist.push_back(CurrentSelect->getTrueValue());
        Worklist.push_back(CurrentSelect->getFalseValue());
      } else {
        // It must be a Phi node then.
        PHINode *CurrentPhi = cast<PHINode>(Current);
        unsigned PredCount = CurrentPhi->getNumIncomingValues();
        PHINode *PHI =
            PHINode::Create(CommonType, PredCount, "sunk_phi", CurrentPhi);
        Map[Current] = PHI;
        ST.insertNewPhi(PHI);
        append_range(Worklist, CurrentPhi->incoming_values());
      }
    }
  }

  bool addrModeCombiningAllowed() {
    if (DisableComplexAddrModes)
      return false;
    switch (DifferentField) {
    default:
      return false;
    case ExtAddrMode::BaseRegField:
      return AddrSinkCombineBaseReg;
    case ExtAddrMode::BaseGVField:
      return AddrSinkCombineBaseGV;
    case ExtAddrMode::BaseOffsField:
      return AddrSinkCombineBaseOffs;
    case ExtAddrMode::ScaledRegField:
      return AddrSinkCombineScaledReg;
    }
  }
};
} // end anonymous namespace

/// Try adding ScaleReg*Scale to the current addressing mode.
/// Return true and update AddrMode if this addr mode is legal for the target,
/// false if not.
bool AddressingModeMatcher::matchScaledValue(Value *ScaleReg, int64_t Scale,
                                             unsigned Depth) {
  // If Scale is 1, then this is the same as adding ScaleReg to the addressing
  // mode.  Just process that directly.
  if (Scale == 1)
    return matchAddr(ScaleReg, Depth);

  // If the scale is 0, it takes nothing to add this.
  if (Scale == 0)
    return true;

  // If we already have a scale of this value, we can add to it, otherwise, we
  // need an available scale field.
  if (AddrMode.Scale != 0 && AddrMode.ScaledReg != ScaleReg)
    return false;

  ExtAddrMode TestAddrMode = AddrMode;

  // Add scale to turn X*4+X*3 -> X*7.  This could also do things like
  // [A+B + A*7] -> [B+A*8].
  TestAddrMode.Scale += Scale;
  TestAddrMode.ScaledReg = ScaleReg;

  // If the new address isn't legal, bail out.
  if (!TLI.isLegalAddressingMode(DL, TestAddrMode, AccessTy, AddrSpace))
    return false;

  // It was legal, so commit it.
  AddrMode = TestAddrMode;

  // Okay, we decided that we can add ScaleReg+Scale to AddrMode.  Check now
  // to see if ScaleReg is actually X+C.  If so, we can turn this into adding
  // X*Scale + C*Scale to addr mode. If we found available IV increment, do not
  // go any further: we can reuse it and cannot eliminate it.
  ConstantInt *CI = nullptr;
  Value *AddLHS = nullptr;
  if (isa<Instruction>(ScaleReg) && // not a constant expr.
      match(ScaleReg, m_Add(m_Value(AddLHS), m_ConstantInt(CI))) &&
      !isIVIncrement(ScaleReg, &LI) && CI->getValue().isSignedIntN(64)) {
    TestAddrMode.InBounds = false;
    TestAddrMode.ScaledReg = AddLHS;
    TestAddrMode.BaseOffs += CI->getSExtValue() * TestAddrMode.Scale;

    // If this addressing mode is legal, commit it and remember that we folded
    // this instruction.
    if (TLI.isLegalAddressingMode(DL, TestAddrMode, AccessTy, AddrSpace)) {
      AddrModeInsts.push_back(cast<Instruction>(ScaleReg));
      AddrMode = TestAddrMode;
      return true;
    }
    // Restore status quo.
    TestAddrMode = AddrMode;
  }

  // If this is an add recurrence with a constant step, return the increment
  // instruction and the canonicalized step.
  auto GetConstantStep =
      [this](const Value *V) -> std::optional<std::pair<Instruction *, APInt>> {
    auto *PN = dyn_cast<PHINode>(V);
    if (!PN)
      return std::nullopt;
    auto IVInc = getIVIncrement(PN, &LI);
    if (!IVInc)
      return std::nullopt;
    // TODO: The result of the intrinsics above is two-complement. However when
    // IV inc is expressed as add or sub, iv.next is potentially a poison value.
    // If it has nuw or nsw flags, we need to make sure that these flags are
    // inferrable at the point of memory instruction. Otherwise we are replacing
    // well-defined two-complement computation with poison. Currently, to avoid
    // potentially complex analysis needed to prove this, we reject such cases.
    if (auto *OIVInc = dyn_cast<OverflowingBinaryOperator>(IVInc->first))
      if (OIVInc->hasNoSignedWrap() || OIVInc->hasNoUnsignedWrap())
        return std::nullopt;
    if (auto *ConstantStep = dyn_cast<ConstantInt>(IVInc->second))
      return std::make_pair(IVInc->first, ConstantStep->getValue());
    return std::nullopt;
  };

  // Try to account for the following special case:
  // 1. ScaleReg is an inductive variable;
  // 2. We use it with non-zero offset;
  // 3. IV's increment is available at the point of memory instruction.
  //
  // In this case, we may reuse the IV increment instead of the IV Phi to
  // achieve the following advantages:
  // 1. If IV step matches the offset, we will have no need in the offset;
  // 2. Even if they don't match, we will reduce the overlap of living IV
  //    and IV increment, that will potentially lead to better register
  //    assignment.
  if (AddrMode.BaseOffs) {
    if (auto IVStep = GetConstantStep(ScaleReg)) {
      Instruction *IVInc = IVStep->first;
      // The following assert is important to ensure a lack of infinite loops.
      // This transforms is (intentionally) the inverse of the one just above.
      // If they don't agree on the definition of an increment, we'd alternate
      // back and forth indefinitely.
      assert(isIVIncrement(IVInc, &LI) && "implied by GetConstantStep");
      APInt Step = IVStep->second;
      APInt Offset = Step * AddrMode.Scale;
      if (Offset.isSignedIntN(64)) {
        TestAddrMode.InBounds = false;
        TestAddrMode.ScaledReg = IVInc;
        TestAddrMode.BaseOffs -= Offset.getLimitedValue();
        // If this addressing mode is legal, commit it..
        // (Note that we defer the (expensive) domtree base legality check
        // to the very last possible point.)
        if (TLI.isLegalAddressingMode(DL, TestAddrMode, AccessTy, AddrSpace) &&
            getDTFn().dominates(IVInc, MemoryInst)) {
          AddrModeInsts.push_back(cast<Instruction>(IVInc));
          AddrMode = TestAddrMode;
          return true;
        }
        // Restore status quo.
        TestAddrMode = AddrMode;
      }
    }
  }

  // Otherwise, just return what we have.
  return true;
}

/// This is a little filter, which returns true if an addressing computation
/// involving I might be folded into a load/store accessing it.
/// This doesn't need to be perfect, but needs to accept at least
/// the set of instructions that MatchOperationAddr can.
static bool MightBeFoldableInst(Instruction *I) {
  switch (I->getOpcode()) {
  case Instruction::BitCast:
  case Instruction::AddrSpaceCast:
    // Don't touch identity bitcasts.
    if (I->getType() == I->getOperand(0)->getType())
      return false;
    return I->getType()->isIntOrPtrTy();
  case Instruction::PtrToInt:
    // PtrToInt is always a noop, as we know that the int type is pointer sized.
    return true;
  case Instruction::IntToPtr:
    // We know the input is intptr_t, so this is foldable.
    return true;
  case Instruction::Add:
    return true;
  case Instruction::Mul:
  case Instruction::Shl:
    // Can only handle X*C and X << C.
    return isa<ConstantInt>(I->getOperand(1));
  case Instruction::GetElementPtr:
    return true;
  default:
    return false;
  }
}

/// Check whether or not \p Val is a legal instruction for \p TLI.
/// \note \p Val is assumed to be the product of some type promotion.
/// Therefore if \p Val has an undefined state in \p TLI, this is assumed
/// to be legal, as the non-promoted value would have had the same state.
static bool isPromotedInstructionLegal(const TargetLowering &TLI,
                                       const DataLayout &DL, Value *Val) {
  Instruction *PromotedInst = dyn_cast<Instruction>(Val);
  if (!PromotedInst)
    return false;
  int ISDOpcode = TLI.InstructionOpcodeToISD(PromotedInst->getOpcode());
  // If the ISDOpcode is undefined, it was undefined before the promotion.
  if (!ISDOpcode)
    return true;
  // Otherwise, check if the promoted instruction is legal or not.
  return TLI.isOperationLegalOrCustom(
      ISDOpcode, TLI.getValueType(DL, PromotedInst->getType()));
}

namespace {

/// Hepler class to perform type promotion.
class TypePromotionHelper {
  /// Utility function to add a promoted instruction \p ExtOpnd to
  /// \p PromotedInsts and record the type of extension we have seen.
  static void addPromotedInst(InstrToOrigTy &PromotedInsts,
                              Instruction *ExtOpnd, bool IsSExt) {
    ExtType ExtTy = IsSExt ? SignExtension : ZeroExtension;
    InstrToOrigTy::iterator It = PromotedInsts.find(ExtOpnd);
    if (It != PromotedInsts.end()) {
      // If the new extension is same as original, the information in
      // PromotedInsts[ExtOpnd] is still correct.
      if (It->second.getInt() == ExtTy)
        return;

      // Now the new extension is different from old extension, we make
      // the type information invalid by setting extension type to
      // BothExtension.
      ExtTy = BothExtension;
    }
    PromotedInsts[ExtOpnd] = TypeIsSExt(ExtOpnd->getType(), ExtTy);
  }

  /// Utility function to query the original type of instruction \p Opnd
  /// with a matched extension type. If the extension doesn't match, we
  /// cannot use the information we had on the original type.
  /// BothExtension doesn't match any extension type.
  static const Type *getOrigType(const InstrToOrigTy &PromotedInsts,
                                 Instruction *Opnd, bool IsSExt) {
    ExtType ExtTy = IsSExt ? SignExtension : ZeroExtension;
    InstrToOrigTy::const_iterator It = PromotedInsts.find(Opnd);
    if (It != PromotedInsts.end() && It->second.getInt() == ExtTy)
      return It->second.getPointer();
    return nullptr;
  }

  /// Utility function to check whether or not a sign or zero extension
  /// of \p Inst with \p ConsideredExtType can be moved through \p Inst by
  /// either using the operands of \p Inst or promoting \p Inst.
  /// The type of the extension is defined by \p IsSExt.
  /// In other words, check if:
  /// ext (Ty Inst opnd1 opnd2 ... opndN) to ConsideredExtType.
  /// #1 Promotion applies:
  /// ConsideredExtType Inst (ext opnd1 to ConsideredExtType, ...).
  /// #2 Operand reuses:
  /// ext opnd1 to ConsideredExtType.
  /// \p PromotedInsts maps the instructions to their type before promotion.
  static bool canGetThrough(const Instruction *Inst, Type *ConsideredExtType,
                            const InstrToOrigTy &PromotedInsts, bool IsSExt);

  /// Utility function to determine if \p OpIdx should be promoted when
  /// promoting \p Inst.
  static bool shouldExtOperand(const Instruction *Inst, int OpIdx) {
    return !(isa<SelectInst>(Inst) && OpIdx == 0);
  }

  /// Utility function to promote the operand of \p Ext when this
  /// operand is a promotable trunc or sext or zext.
  /// \p PromotedInsts maps the instructions to their type before promotion.
  /// \p CreatedInstsCost[out] contains the cost of all instructions
  /// created to promote the operand of Ext.
  /// Newly added extensions are inserted in \p Exts.
  /// Newly added truncates are inserted in \p Truncs.
  /// Should never be called directly.
  /// \return The promoted value which is used instead of Ext.
  static Value *promoteOperandForTruncAndAnyExt(
      Instruction *Ext, TypePromotionTransaction &TPT,
      InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
      SmallVectorImpl<Instruction *> *Exts,
      SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI);

  /// Utility function to promote the operand of \p Ext when this
  /// operand is promotable and is not a supported trunc or sext.
  /// \p PromotedInsts maps the instructions to their type before promotion.
  /// \p CreatedInstsCost[out] contains the cost of all the instructions
  /// created to promote the operand of Ext.
  /// Newly added extensions are inserted in \p Exts.
  /// Newly added truncates are inserted in \p Truncs.
  /// Should never be called directly.
  /// \return The promoted value which is used instead of Ext.
  static Value *promoteOperandForOther(Instruction *Ext,
                                       TypePromotionTransaction &TPT,
                                       InstrToOrigTy &PromotedInsts,
                                       unsigned &CreatedInstsCost,
                                       SmallVectorImpl<Instruction *> *Exts,
                                       SmallVectorImpl<Instruction *> *Truncs,
                                       const TargetLowering &TLI, bool IsSExt);

  /// \see promoteOperandForOther.
  static Value *signExtendOperandForOther(
      Instruction *Ext, TypePromotionTransaction &TPT,
      InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
      SmallVectorImpl<Instruction *> *Exts,
      SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI) {
    return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInstsCost,
                                  Exts, Truncs, TLI, true);
  }

  /// \see promoteOperandForOther.
  static Value *zeroExtendOperandForOther(
      Instruction *Ext, TypePromotionTransaction &TPT,
      InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
      SmallVectorImpl<Instruction *> *Exts,
      SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI) {
    return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInstsCost,
                                  Exts, Truncs, TLI, false);
  }

public:
  /// Type for the utility function that promotes the operand of Ext.
  using Action = Value *(*)(Instruction *Ext, TypePromotionTransaction &TPT,
                            InstrToOrigTy &PromotedInsts,
                            unsigned &CreatedInstsCost,
                            SmallVectorImpl<Instruction *> *Exts,
                            SmallVectorImpl<Instruction *> *Truncs,
                            const TargetLowering &TLI);

  /// Given a sign/zero extend instruction \p Ext, return the appropriate
  /// action to promote the operand of \p Ext instead of using Ext.
  /// \return NULL if no promotable action is possible with the current
  /// sign extension.
  /// \p InsertedInsts keeps track of all the instructions inserted by the
  /// other CodeGenPrepare optimizations. This information is important
  /// because we do not want to promote these instructions as CodeGenPrepare
  /// will reinsert them later. Thus creating an infinite loop: create/remove.
  /// \p PromotedInsts maps the instructions to their type before promotion.
  static Action getAction(Instruction *Ext, const SetOfInstrs &InsertedInsts,
                          const TargetLowering &TLI,
                          const InstrToOrigTy &PromotedInsts);
};

} // end anonymous namespace

bool TypePromotionHelper::canGetThrough(const Instruction *Inst,
                                        Type *ConsideredExtType,
                                        const InstrToOrigTy &PromotedInsts,
                                        bool IsSExt) {
  // The promotion helper does not know how to deal with vector types yet.
  // To be able to fix that, we would need to fix the places where we
  // statically extend, e.g., constants and such.
  if (Inst->getType()->isVectorTy())
    return false;

  // We can always get through zext.
  if (isa<ZExtInst>(Inst))
    return true;

  // sext(sext) is ok too.
  if (IsSExt && isa<SExtInst>(Inst))
    return true;

  // We can get through binary operator, if it is legal. In other words, the
  // binary operator must have a nuw or nsw flag.
  if (const auto *BinOp = dyn_cast<BinaryOperator>(Inst))
    if (isa<OverflowingBinaryOperator>(BinOp) &&
        ((!IsSExt && BinOp->hasNoUnsignedWrap()) ||
         (IsSExt && BinOp->hasNoSignedWrap())))
      return true;

  // ext(and(opnd, cst)) --> and(ext(opnd), ext(cst))
  if ((Inst->getOpcode() == Instruction::And ||
       Inst->getOpcode() == Instruction::Or))
    return true;

  // ext(xor(opnd, cst)) --> xor(ext(opnd), ext(cst))
  if (Inst->getOpcode() == Instruction::Xor) {
    // Make sure it is not a NOT.
    if (const auto *Cst = dyn_cast<ConstantInt>(Inst->getOperand(1)))
      if (!Cst->getValue().isAllOnes())
        return true;
  }

  // zext(shrl(opnd, cst)) --> shrl(zext(opnd), zext(cst))
  // It may change a poisoned value into a regular value, like
  //     zext i32 (shrl i8 %val, 12)  -->  shrl i32 (zext i8 %val), 12
  //          poisoned value                    regular value
  // It should be OK since undef covers valid value.
  if (Inst->getOpcode() == Instruction::LShr && !IsSExt)
    return true;

  // and(ext(shl(opnd, cst)), cst) --> and(shl(ext(opnd), ext(cst)), cst)
  // It may change a poisoned value into a regular value, like
  //     zext i32 (shl i8 %val, 12)  -->  shl i32 (zext i8 %val), 12
  //          poisoned value                    regular value
  // It should be OK since undef covers valid value.
  if (Inst->getOpcode() == Instruction::Shl && Inst->hasOneUse()) {
    const auto *ExtInst = cast<const Instruction>(*Inst->user_begin());
    if (ExtInst->hasOneUse()) {
      const auto *AndInst = dyn_cast<const Instruction>(*ExtInst->user_begin());
      if (AndInst && AndInst->getOpcode() == Instruction::And) {
        const auto *Cst = dyn_cast<ConstantInt>(AndInst->getOperand(1));
        if (Cst &&
            Cst->getValue().isIntN(Inst->getType()->getIntegerBitWidth()))
          return true;
      }
    }
  }

  // Check if we can do the following simplification.
  // ext(trunc(opnd)) --> ext(opnd)
  if (!isa<TruncInst>(Inst))
    return false;

  Value *OpndVal = Inst->getOperand(0);
  // Check if we can use this operand in the extension.
  // If the type is larger than the result type of the extension, we cannot.
  if (!OpndVal->getType()->isIntegerTy() ||
      OpndVal->getType()->getIntegerBitWidth() >
          ConsideredExtType->getIntegerBitWidth())
    return false;

  // If the operand of the truncate is not an instruction, we will not have
  // any information on the dropped bits.
  // (Actually we could for constant but it is not worth the extra logic).
  Instruction *Opnd = dyn_cast<Instruction>(OpndVal);
  if (!Opnd)
    return false;

  // Check if the source of the type is narrow enough.
  // I.e., check that trunc just drops extended bits of the same kind of
  // the extension.
  // #1 get the type of the operand and check the kind of the extended bits.
  const Type *OpndType = getOrigType(PromotedInsts, Opnd, IsSExt);
  if (OpndType)
    ;
  else if ((IsSExt && isa<SExtInst>(Opnd)) || (!IsSExt && isa<ZExtInst>(Opnd)))
    OpndType = Opnd->getOperand(0)->getType();
  else
    return false;

  // #2 check that the truncate just drops extended bits.
  return Inst->getType()->getIntegerBitWidth() >=
         OpndType->getIntegerBitWidth();
}

TypePromotionHelper::Action TypePromotionHelper::getAction(
    Instruction *Ext, const SetOfInstrs &InsertedInsts,
    const TargetLowering &TLI, const InstrToOrigTy &PromotedInsts) {
  assert((isa<SExtInst>(Ext) || isa<ZExtInst>(Ext)) &&
         "Unexpected instruction type");
  Instruction *ExtOpnd = dyn_cast<Instruction>(Ext->getOperand(0));
  Type *ExtTy = Ext->getType();
  bool IsSExt = isa<SExtInst>(Ext);
  // If the operand of the extension is not an instruction, we cannot
  // get through.
  // If it, check we can get through.
  if (!ExtOpnd || !canGetThrough(ExtOpnd, ExtTy, PromotedInsts, IsSExt))
    return nullptr;

  // Do not promote if the operand has been added by codegenprepare.
  // Otherwise, it means we are undoing an optimization that is likely to be
  // redone, thus causing potential infinite loop.
  if (isa<TruncInst>(ExtOpnd) && InsertedInsts.count(ExtOpnd))
    return nullptr;

  // SExt or Trunc instructions.
  // Return the related handler.
  if (isa<SExtInst>(ExtOpnd) || isa<TruncInst>(ExtOpnd) ||
      isa<ZExtInst>(ExtOpnd))
    return promoteOperandForTruncAndAnyExt;

  // Regular instruction.
  // Abort early if we will have to insert non-free instructions.
  if (!ExtOpnd->hasOneUse() && !TLI.isTruncateFree(ExtTy, ExtOpnd->getType()))
    return nullptr;
  return IsSExt ? signExtendOperandForOther : zeroExtendOperandForOther;
}

Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
    Instruction *SExt, TypePromotionTransaction &TPT,
    InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
    SmallVectorImpl<Instruction *> *Exts,
    SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI) {
  // By construction, the operand of SExt is an instruction. Otherwise we cannot
  // get through it and this method should not be called.
  Instruction *SExtOpnd = cast<Instruction>(SExt->getOperand(0));
  Value *ExtVal = SExt;
  bool HasMergedNonFreeExt = false;
  if (isa<ZExtInst>(SExtOpnd)) {
    // Replace s|zext(zext(opnd))
    // => zext(opnd).
    HasMergedNonFreeExt = !TLI.isExtFree(SExtOpnd);
    Value *ZExt =
        TPT.createZExt(SExt, SExtOpnd->getOperand(0), SExt->getType());
    TPT.replaceAllUsesWith(SExt, ZExt);
    TPT.eraseInstruction(SExt);
    ExtVal = ZExt;
  } else {
    // Replace z|sext(trunc(opnd)) or sext(sext(opnd))
    // => z|sext(opnd).
    TPT.setOperand(SExt, 0, SExtOpnd->getOperand(0));
  }
  CreatedInstsCost = 0;

  // Remove dead code.
  if (SExtOpnd->use_empty())
    TPT.eraseInstruction(SExtOpnd);

  // Check if the extension is still needed.
  Instruction *ExtInst = dyn_cast<Instruction>(ExtVal);
  if (!ExtInst || ExtInst->getType() != ExtInst->getOperand(0)->getType()) {
    if (ExtInst) {
      if (Exts)
        Exts->push_back(ExtInst);
      CreatedInstsCost = !TLI.isExtFree(ExtInst) && !HasMergedNonFreeExt;
    }
    return ExtVal;
  }

  // At this point we have: ext ty opnd to ty.
  // Reassign the uses of ExtInst to the opnd and remove ExtInst.
  Value *NextVal = ExtInst->getOperand(0);
  TPT.eraseInstruction(ExtInst, NextVal);
  return NextVal;
}

Value *TypePromotionHelper::promoteOperandForOther(
    Instruction *Ext, TypePromotionTransaction &TPT,
    InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
    SmallVectorImpl<Instruction *> *Exts,
    SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI,
    bool IsSExt) {
  // By construction, the operand of Ext is an instruction. Otherwise we cannot
  // get through it and this method should not be called.
  Instruction *ExtOpnd = cast<Instruction>(Ext->getOperand(0));
  CreatedInstsCost = 0;
  if (!ExtOpnd->hasOneUse()) {
    // ExtOpnd will be promoted.
    // All its uses, but Ext, will need to use a truncated value of the
    // promoted version.
    // Create the truncate now.
    Value *Trunc = TPT.createTrunc(Ext, ExtOpnd->getType());
    if (Instruction *ITrunc = dyn_cast<Instruction>(Trunc)) {
      // Insert it just after the definition.
      ITrunc->moveAfter(ExtOpnd);
      if (Truncs)
        Truncs->push_back(ITrunc);
    }

    TPT.replaceAllUsesWith(ExtOpnd, Trunc);
    // Restore the operand of Ext (which has been replaced by the previous call
    // to replaceAllUsesWith) to avoid creating a cycle trunc <-> sext.
    TPT.setOperand(Ext, 0, ExtOpnd);
  }

  // Get through the Instruction:
  // 1. Update its type.
  // 2. Replace the uses of Ext by Inst.
  // 3. Extend each operand that needs to be extended.

  // Remember the original type of the instruction before promotion.
  // This is useful to know that the high bits are sign extended bits.
  addPromotedInst(PromotedInsts, ExtOpnd, IsSExt);
  // Step #1.
  TPT.mutateType(ExtOpnd, Ext->getType());
  // Step #2.
  TPT.replaceAllUsesWith(Ext, ExtOpnd);
  // Step #3.
  Instruction *ExtForOpnd = Ext;

  LLVM_DEBUG(dbgs() << "Propagate Ext to operands\n");
  for (int OpIdx = 0, EndOpIdx = ExtOpnd->getNumOperands(); OpIdx != EndOpIdx;
       ++OpIdx) {
    LLVM_DEBUG(dbgs() << "Operand:\n" << *(ExtOpnd->getOperand(OpIdx)) << '\n');
    if (ExtOpnd->getOperand(OpIdx)->getType() == Ext->getType() ||
        !shouldExtOperand(ExtOpnd, OpIdx)) {
      LLVM_DEBUG(dbgs() << "No need to propagate\n");
      continue;
    }
    // Check if we can statically extend the operand.
    Value *Opnd = ExtOpnd->getOperand(OpIdx);
    if (const ConstantInt *Cst = dyn_cast<ConstantInt>(Opnd)) {
      LLVM_DEBUG(dbgs() << "Statically extend\n");
      unsigned BitWidth = Ext->getType()->getIntegerBitWidth();
      APInt CstVal = IsSExt ? Cst->getValue().sext(BitWidth)
                            : Cst->getValue().zext(BitWidth);
      TPT.setOperand(ExtOpnd, OpIdx, ConstantInt::get(Ext->getType(), CstVal));
      continue;
    }
    // UndefValue are typed, so we have to statically sign extend them.
    if (isa<UndefValue>(Opnd)) {
      LLVM_DEBUG(dbgs() << "Statically extend\n");
      TPT.setOperand(ExtOpnd, OpIdx, UndefValue::get(Ext->getType()));
      continue;
    }

    // Otherwise we have to explicitly sign extend the operand.
    // Check if Ext was reused to extend an operand.
    if (!ExtForOpnd) {
      // If yes, create a new one.
      LLVM_DEBUG(dbgs() << "More operands to ext\n");
      Value *ValForExtOpnd = IsSExt ? TPT.createSExt(Ext, Opnd, Ext->getType())
                                    : TPT.createZExt(Ext, Opnd, Ext->getType());
      if (!isa<Instruction>(ValForExtOpnd)) {
        TPT.setOperand(ExtOpnd, OpIdx, ValForExtOpnd);
        continue;
      }
      ExtForOpnd = cast<Instruction>(ValForExtOpnd);
    }
    if (Exts)
      Exts->push_back(ExtForOpnd);
    TPT.setOperand(ExtForOpnd, 0, Opnd);

    // Move the sign extension before the insertion point.
    TPT.moveBefore(ExtForOpnd, ExtOpnd);
    TPT.setOperand(ExtOpnd, OpIdx, ExtForOpnd);
    CreatedInstsCost += !TLI.isExtFree(ExtForOpnd);
    // If more sext are required, new instructions will have to be created.
    ExtForOpnd = nullptr;
  }
  if (ExtForOpnd == Ext) {
    LLVM_DEBUG(dbgs() << "Extension is useless now\n");
    TPT.eraseInstruction(Ext);
  }
  return ExtOpnd;
}

/// Check whether or not promoting an instruction to a wider type is profitable.
/// \p NewCost gives the cost of extension instructions created by the
/// promotion.
/// \p OldCost gives the cost of extension instructions before the promotion
/// plus the number of instructions that have been
/// matched in the addressing mode the promotion.
/// \p PromotedOperand is the value that has been promoted.
/// \return True if the promotion is profitable, false otherwise.
bool AddressingModeMatcher::isPromotionProfitable(
    unsigned NewCost, unsigned OldCost, Value *PromotedOperand) const {
  LLVM_DEBUG(dbgs() << "OldCost: " << OldCost << "\tNewCost: " << NewCost
                    << '\n');
  // The cost of the new extensions is greater than the cost of the
  // old extension plus what we folded.
  // This is not profitable.
  if (NewCost > OldCost)
    return false;
  if (NewCost < OldCost)
    return true;
  // The promotion is neutral but it may help folding the sign extension in
  // loads for instance.
  // Check that we did not create an illegal instruction.
  return isPromotedInstructionLegal(TLI, DL, PromotedOperand);
}

/// Given an instruction or constant expr, see if we can fold the operation
/// into the addressing mode. If so, update the addressing mode and return
/// true, otherwise return false without modifying AddrMode.
/// If \p MovedAway is not NULL, it contains the information of whether or
/// not AddrInst has to be folded into the addressing mode on success.
/// If \p MovedAway == true, \p AddrInst will not be part of the addressing
/// because it has been moved away.
/// Thus AddrInst must not be added in the matched instructions.
/// This state can happen when AddrInst is a sext, since it may be moved away.
/// Therefore, AddrInst may not be valid when MovedAway is true and it must
/// not be referenced anymore.
bool AddressingModeMatcher::matchOperationAddr(User *AddrInst, unsigned Opcode,
                                               unsigned Depth,
                                               bool *MovedAway) {
  // Avoid exponential behavior on extremely deep expression trees.
  if (Depth >= 5)
    return false;

  // By default, all matched instructions stay in place.
  if (MovedAway)
    *MovedAway = false;

  switch (Opcode) {
  case Instruction::PtrToInt:
    // PtrToInt is always a noop, as we know that the int type is pointer sized.
    return matchAddr(AddrInst->getOperand(0), Depth);
  case Instruction::IntToPtr: {
    auto AS = AddrInst->getType()->getPointerAddressSpace();
    auto PtrTy = MVT::getIntegerVT(DL.getPointerSizeInBits(AS));
    // This inttoptr is a no-op if the integer type is pointer sized.
    if (TLI.getValueType(DL, AddrInst->getOperand(0)->getType()) == PtrTy)
      return matchAddr(AddrInst->getOperand(0), Depth);
    return false;
  }
  case Instruction::BitCast:
    // BitCast is always a noop, and we can handle it as long as it is
    // int->int or pointer->pointer (we don't want int<->fp or something).
    if (AddrInst->getOperand(0)->getType()->isIntOrPtrTy() &&
        // Don't touch identity bitcasts.  These were probably put here by LSR,
        // and we don't want to mess around with them.  Assume it knows what it
        // is doing.
        AddrInst->getOperand(0)->getType() != AddrInst->getType())
      return matchAddr(AddrInst->getOperand(0), Depth);
    return false;
  case Instruction::AddrSpaceCast: {
    unsigned SrcAS =
        AddrInst->getOperand(0)->getType()->getPointerAddressSpace();
    unsigned DestAS = AddrInst->getType()->getPointerAddressSpace();
    if (TLI.getTargetMachine().isNoopAddrSpaceCast(SrcAS, DestAS))
      return matchAddr(AddrInst->getOperand(0), Depth);
    return false;
  }
  case Instruction::Add: {
    // Check to see if we can merge in one operand, then the other.  If so, we
    // win.
    ExtAddrMode BackupAddrMode = AddrMode;
    unsigned OldSize = AddrModeInsts.size();
    // Start a transaction at this point.
    // The LHS may match but not the RHS.
    // Therefore, we need a higher level restoration point to undo partially
    // matched operation.
    TypePromotionTransaction::ConstRestorationPt LastKnownGood =
        TPT.getRestorationPoint();

    // Try to match an integer constant second to increase its chance of ending
    // up in `BaseOffs`, resp. decrease its chance of ending up in `BaseReg`.
    int First = 0, Second = 1;
    if (isa<ConstantInt>(AddrInst->getOperand(First))
      && !isa<ConstantInt>(AddrInst->getOperand(Second)))
        std::swap(First, Second);
    AddrMode.InBounds = false;
    if (matchAddr(AddrInst->getOperand(First), Depth + 1) &&
        matchAddr(AddrInst->getOperand(Second), Depth + 1))
      return true;

    // Restore the old addr mode info.
    AddrMode = BackupAddrMode;
    AddrModeInsts.resize(OldSize);
    TPT.rollback(LastKnownGood);

    // Otherwise this was over-aggressive.  Try merging operands in the opposite
    // order.
    if (matchAddr(AddrInst->getOperand(Second), Depth + 1) &&
        matchAddr(AddrInst->getOperand(First), Depth + 1))
      return true;

    // Otherwise we definitely can't merge the ADD in.
    AddrMode = BackupAddrMode;
    AddrModeInsts.resize(OldSize);
    TPT.rollback(LastKnownGood);
    break;
  }
  // case Instruction::Or:
  //  TODO: We can handle "Or Val, Imm" iff this OR is equivalent to an ADD.
  // break;
  case Instruction::Mul:
  case Instruction::Shl: {
    // Can only handle X*C and X << C.
    AddrMode.InBounds = false;
    ConstantInt *RHS = dyn_cast<ConstantInt>(AddrInst->getOperand(1));
    if (!RHS || RHS->getBitWidth() > 64)
      return false;
    int64_t Scale = Opcode == Instruction::Shl
                        ? 1LL << RHS->getLimitedValue(RHS->getBitWidth() - 1)
                        : RHS->getSExtValue();

    return matchScaledValue(AddrInst->getOperand(0), Scale, Depth);
  }
  case Instruction::GetElementPtr: {
    // Scan the GEP.  We check it if it contains constant offsets and at most
    // one variable offset.
    int VariableOperand = -1;
    unsigned VariableScale = 0;

    int64_t ConstantOffset = 0;
    gep_type_iterator GTI = gep_type_begin(AddrInst);
    for (unsigned i = 1, e = AddrInst->getNumOperands(); i != e; ++i, ++GTI) {
      if (StructType *STy = GTI.getStructTypeOrNull()) {
        const StructLayout *SL = DL.getStructLayout(STy);
        unsigned Idx =
            cast<ConstantInt>(AddrInst->getOperand(i))->getZExtValue();
        ConstantOffset += SL->getElementOffset(Idx);
      } else {
        TypeSize TS = DL.getTypeAllocSize(GTI.getIndexedType());
        if (TS.isNonZero()) {
          // The optimisations below currently only work for fixed offsets.
          if (TS.isScalable())
            return false;
          int64_t TypeSize = TS.getFixedValue();
          if (ConstantInt *CI =
                  dyn_cast<ConstantInt>(AddrInst->getOperand(i))) {
            const APInt &CVal = CI->getValue();
            if (CVal.getSignificantBits() <= 64) {
              ConstantOffset += CVal.getSExtValue() * TypeSize;
              continue;
            }
          }
          // We only allow one variable index at the moment.
          if (VariableOperand != -1)
            return false;

          // Remember the variable index.
          VariableOperand = i;
          VariableScale = TypeSize;
        }
      }
    }

    // A common case is for the GEP to only do a constant offset.  In this case,
    // just add it to the disp field and check validity.
    if (VariableOperand == -1) {
      AddrMode.BaseOffs += ConstantOffset;
      if (matchAddr(AddrInst->getOperand(0), Depth + 1)) {
          if (!cast<GEPOperator>(AddrInst)->isInBounds())
            AddrMode.InBounds = false;
          return true;
      }
      AddrMode.BaseOffs -= ConstantOffset;

      if (EnableGEPOffsetSplit && isa<GetElementPtrInst>(AddrInst) &&
          TLI.shouldConsiderGEPOffsetSplit() && Depth == 0 &&
          ConstantOffset > 0) {
          // Record GEPs with non-zero offsets as candidates for splitting in
          // the event that the offset cannot fit into the r+i addressing mode.
          // Simple and common case that only one GEP is used in calculating the
          // address for the memory access.
          Value *Base = AddrInst->getOperand(0);
          auto *BaseI = dyn_cast<Instruction>(Base);
          auto *GEP = cast<GetElementPtrInst>(AddrInst);
          if (isa<Argument>(Base) || isa<GlobalValue>(Base) ||
              (BaseI && !isa<CastInst>(BaseI) &&
               !isa<GetElementPtrInst>(BaseI))) {
            // Make sure the parent block allows inserting non-PHI instructions
            // before the terminator.
            BasicBlock *Parent = BaseI ? BaseI->getParent()
                                       : &GEP->getFunction()->getEntryBlock();
            if (!Parent->getTerminator()->isEHPad())
            LargeOffsetGEP = std::make_pair(GEP, ConstantOffset);
          }
      }

      return false;
    }

    // Save the valid addressing mode in case we can't match.
    ExtAddrMode BackupAddrMode = AddrMode;
    unsigned OldSize = AddrModeInsts.size();

    // See if the scale and offset amount is valid for this target.
    AddrMode.BaseOffs += ConstantOffset;
    if (!cast<GEPOperator>(AddrInst)->isInBounds())
      AddrMode.InBounds = false;

    // Match the base operand of the GEP.
    if (!matchAddr(AddrInst->getOperand(0), Depth + 1)) {
      // If it couldn't be matched, just stuff the value in a register.
      if (AddrMode.HasBaseReg) {
        AddrMode = BackupAddrMode;
        AddrModeInsts.resize(OldSize);
        return false;
      }
      AddrMode.HasBaseReg = true;
      AddrMode.BaseReg = AddrInst->getOperand(0);
    }

    // Match the remaining variable portion of the GEP.
    if (!matchScaledValue(AddrInst->getOperand(VariableOperand), VariableScale,
                          Depth)) {
      // If it couldn't be matched, try stuffing the base into a register
      // instead of matching it, and retrying the match of the scale.
      AddrMode = BackupAddrMode;
      AddrModeInsts.resize(OldSize);
      if (AddrMode.HasBaseReg)
        return false;
      AddrMode.HasBaseReg = true;
      AddrMode.BaseReg = AddrInst->getOperand(0);
      AddrMode.BaseOffs += ConstantOffset;
      if (!matchScaledValue(AddrInst->getOperand(VariableOperand),
                            VariableScale, Depth)) {
        // If even that didn't work, bail.
        AddrMode = BackupAddrMode;
        AddrModeInsts.resize(OldSize);
        return false;
      }
    }

    return true;
  }
  case Instruction::SExt:
  case Instruction::ZExt: {
    Instruction *Ext = dyn_cast<Instruction>(AddrInst);
    if (!Ext)
      return false;

    // Try to move this ext out of the way of the addressing mode.
    // Ask for a method for doing so.
    TypePromotionHelper::Action TPH =
        TypePromotionHelper::getAction(Ext, InsertedInsts, TLI, PromotedInsts);
    if (!TPH)
      return false;

    TypePromotionTransaction::ConstRestorationPt LastKnownGood =
        TPT.getRestorationPoint();
    unsigned CreatedInstsCost = 0;
    unsigned ExtCost = !TLI.isExtFree(Ext);
    Value *PromotedOperand =
        TPH(Ext, TPT, PromotedInsts, CreatedInstsCost, nullptr, nullptr, TLI);
    // SExt has been moved away.
    // Thus either it will be rematched later in the recursive calls or it is
    // gone. Anyway, we must not fold it into the addressing mode at this point.
    // E.g.,
    // op = add opnd, 1
    // idx = ext op
    // addr = gep base, idx
    // is now:
    // promotedOpnd = ext opnd            <- no match here
    // op = promoted_add promotedOpnd, 1  <- match (later in recursive calls)
    // addr = gep base, op                <- match
    if (MovedAway)
      *MovedAway = true;

    assert(PromotedOperand &&
           "TypePromotionHelper should have filtered out those cases");

    ExtAddrMode BackupAddrMode = AddrMode;
    unsigned OldSize = AddrModeInsts.size();

    if (!matchAddr(PromotedOperand, Depth) ||
        // The total of the new cost is equal to the cost of the created
        // instructions.
        // The total of the old cost is equal to the cost of the extension plus
        // what we have saved in the addressing mode.
        !isPromotionProfitable(CreatedInstsCost,
                               ExtCost + (AddrModeInsts.size() - OldSize),
                               PromotedOperand)) {
      AddrMode = BackupAddrMode;
      AddrModeInsts.resize(OldSize);
      LLVM_DEBUG(dbgs() << "Sign extension does not pay off: rollback\n");
      TPT.rollback(LastKnownGood);
      return false;
    }
    return true;
  }
  }
  return false;
}

/// If we can, try to add the value of 'Addr' into the current addressing mode.
/// If Addr can't be added to AddrMode this returns false and leaves AddrMode
/// unmodified. This assumes that Addr is either a pointer type or intptr_t
/// for the target.
///
bool AddressingModeMatcher::matchAddr(Value *Addr, unsigned Depth) {
  // Start a transaction at this point that we will rollback if the matching
  // fails.
  TypePromotionTransaction::ConstRestorationPt LastKnownGood =
      TPT.getRestorationPoint();
  if (ConstantInt *CI = dyn_cast<ConstantInt>(Addr)) {
    if (CI->getValue().isSignedIntN(64)) {
      // Fold in immediates if legal for the target.
      AddrMode.BaseOffs += CI->getSExtValue();
      if (TLI.isLegalAddressingMode(DL, AddrMode, AccessTy, AddrSpace))
        return true;
      AddrMode.BaseOffs -= CI->getSExtValue();
    }
  } else if (GlobalValue *GV = dyn_cast<GlobalValue>(Addr)) {
    // If this is a global variable, try to fold it into the addressing mode.
    if (!AddrMode.BaseGV) {
      AddrMode.BaseGV = GV;
      if (TLI.isLegalAddressingMode(DL, AddrMode, AccessTy, AddrSpace))
        return true;
      AddrMode.BaseGV = nullptr;
    }
  } else if (Instruction *I = dyn_cast<Instruction>(Addr)) {
    ExtAddrMode BackupAddrMode = AddrMode;
    unsigned OldSize = AddrModeInsts.size();

    // Check to see if it is possible to fold this operation.
    bool MovedAway = false;
    if (matchOperationAddr(I, I->getOpcode(), Depth, &MovedAway)) {
      // This instruction may have been moved away. If so, there is nothing
      // to check here.
      if (MovedAway)
        return true;
      // Okay, it's possible to fold this.  Check to see if it is actually
      // *profitable* to do so.  We use a simple cost model to avoid increasing
      // register pressure too much.
      if (I->hasOneUse() ||
          isProfitableToFoldIntoAddressingMode(I, BackupAddrMode, AddrMode)) {
        AddrModeInsts.push_back(I);
        return true;
      }

      // It isn't profitable to do this, roll back.
      AddrMode = BackupAddrMode;
      AddrModeInsts.resize(OldSize);
      TPT.rollback(LastKnownGood);
    }
  } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) {
    if (matchOperationAddr(CE, CE->getOpcode(), Depth))
      return true;
    TPT.rollback(LastKnownGood);
  } else if (isa<ConstantPointerNull>(Addr)) {
    // Null pointer gets folded without affecting the addressing mode.
    return true;
  }

  // Worse case, the target should support [reg] addressing modes. :)
  if (!AddrMode.HasBaseReg) {
    AddrMode.HasBaseReg = true;
    AddrMode.BaseReg = Addr;
    // Still check for legality in case the target supports [imm] but not [i+r].
    if (TLI.isLegalAddressingMode(DL, AddrMode, AccessTy, AddrSpace))
      return true;
    AddrMode.HasBaseReg = false;
    AddrMode.BaseReg = nullptr;
  }

  // If the base register is already taken, see if we can do [r+r].
  if (AddrMode.Scale == 0) {
    AddrMode.Scale = 1;
    AddrMode.ScaledReg = Addr;
    if (TLI.isLegalAddressingMode(DL, AddrMode, AccessTy, AddrSpace))
      return true;
    AddrMode.Scale = 0;
    AddrMode.ScaledReg = nullptr;
  }
  // Couldn't match.
  TPT.rollback(LastKnownGood);
  return false;
}

/// Check to see if all uses of OpVal by the specified inline asm call are due
/// to memory operands. If so, return true, otherwise return false.
static bool IsOperandAMemoryOperand(CallInst *CI, InlineAsm *IA, Value *OpVal,
                                    const TargetLowering &TLI,
                                    const TargetRegisterInfo &TRI) {
  const Function *F = CI->getFunction();
  TargetLowering::AsmOperandInfoVector TargetConstraints =
      TLI.ParseConstraints(F->getParent()->getDataLayout(), &TRI, *CI);

  for (TargetLowering::AsmOperandInfo &OpInfo : TargetConstraints) {
    // Compute the constraint code and ConstraintType to use.
    TLI.ComputeConstraintToUse(OpInfo, SDValue());

    // If this asm operand is our Value*, and if it isn't an indirect memory
    // operand, we can't fold it!  TODO: Also handle C_Address?
    if (OpInfo.CallOperandVal == OpVal &&
        (OpInfo.ConstraintType != TargetLowering::C_Memory ||
         !OpInfo.isIndirect))
      return false;
  }

  return true;
}

/// Recursively walk all the uses of I until we find a memory use.
/// If we find an obviously non-foldable instruction, return true.
/// Add accessed addresses and types to MemoryUses.
static bool FindAllMemoryUses(
    Instruction *I, SmallVectorImpl<std::pair<Use *, Type *>> &MemoryUses,
    SmallPtrSetImpl<Instruction *> &ConsideredInsts, const TargetLowering &TLI,
    const TargetRegisterInfo &TRI, bool OptSize, ProfileSummaryInfo *PSI,
    BlockFrequencyInfo *BFI, unsigned &SeenInsts) {
  // If we already considered this instruction, we're done.
  if (!ConsideredInsts.insert(I).second)
    return false;

  // If this is an obviously unfoldable instruction, bail out.
  if (!MightBeFoldableInst(I))
    return true;

  // Loop over all the uses, recursively processing them.
  for (Use &U : I->uses()) {
    // Conservatively return true if we're seeing a large number or a deep chain
    // of users. This avoids excessive compilation times in pathological cases.
    if (SeenInsts++ >= MaxAddressUsersToScan)
      return true;

    Instruction *UserI = cast<Instruction>(U.getUser());
    if (LoadInst *LI = dyn_cast<LoadInst>(UserI)) {
      MemoryUses.push_back({&U, LI->getType()});
      continue;
    }

    if (StoreInst *SI = dyn_cast<StoreInst>(UserI)) {
      if (U.getOperandNo() != StoreInst::getPointerOperandIndex())
        return true; // Storing addr, not into addr.
      MemoryUses.push_back({&U, SI->getValueOperand()->getType()});
      continue;
    }

    if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(UserI)) {
      if (U.getOperandNo() != AtomicRMWInst::getPointerOperandIndex())
        return true; // Storing addr, not into addr.
      MemoryUses.push_back({&U, RMW->getValOperand()->getType()});
      continue;
    }

    if (AtomicCmpXchgInst *CmpX = dyn_cast<AtomicCmpXchgInst>(UserI)) {
      if (U.getOperandNo() != AtomicCmpXchgInst::getPointerOperandIndex())
        return true; // Storing addr, not into addr.
      MemoryUses.push_back({&U, CmpX->getCompareOperand()->getType()});
      continue;
    }

    if (CallInst *CI = dyn_cast<CallInst>(UserI)) {
      if (CI->hasFnAttr(Attribute::Cold)) {
        // If this is a cold call, we can sink the addressing calculation into
        // the cold path.  See optimizeCallInst
        bool OptForSize =
            OptSize || llvm::shouldOptimizeForSize(CI->getParent(), PSI, BFI);
        if (!OptForSize)
          continue;
      }

      InlineAsm *IA = dyn_cast<InlineAsm>(CI->getCalledOperand());
      if (!IA)
        return true;

      // If this is a memory operand, we're cool, otherwise bail out.
      if (!IsOperandAMemoryOperand(CI, IA, I, TLI, TRI))
        return true;
      continue;
    }

    if (FindAllMemoryUses(UserI, MemoryUses, ConsideredInsts, TLI, TRI, OptSize,
                          PSI, BFI, SeenInsts))
      return true;
  }

  return false;
}

static bool FindAllMemoryUses(
    Instruction *I, SmallVectorImpl<std::pair<Use *, Type *>> &MemoryUses,
    const TargetLowering &TLI, const TargetRegisterInfo &TRI, bool OptSize,
    ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) {
  unsigned SeenInsts = 0;
  SmallPtrSet<Instruction *, 16> ConsideredInsts;
  return FindAllMemoryUses(I, MemoryUses, ConsideredInsts, TLI, TRI, OptSize,
                           PSI, BFI, SeenInsts);
}


/// Return true if Val is already known to be live at the use site that we're
/// folding it into. If so, there is no cost to include it in the addressing
/// mode. KnownLive1 and KnownLive2 are two values that we know are live at the
/// instruction already.
bool AddressingModeMatcher::valueAlreadyLiveAtInst(Value *Val,
                                                   Value *KnownLive1,
                                                   Value *KnownLive2) {
  // If Val is either of the known-live values, we know it is live!
  if (Val == nullptr || Val == KnownLive1 || Val == KnownLive2)
    return true;

  // All values other than instructions and arguments (e.g. constants) are live.
  if (!isa<Instruction>(Val) && !isa<Argument>(Val))
    return true;

  // If Val is a constant sized alloca in the entry block, it is live, this is
  // true because it is just a reference to the stack/frame pointer, which is
  // live for the whole function.
  if (AllocaInst *AI = dyn_cast<AllocaInst>(Val))
    if (AI->isStaticAlloca())
      return true;

  // Check to see if this value is already used in the memory instruction's
  // block.  If so, it's already live into the block at the very least, so we
  // can reasonably fold it.
  return Val->isUsedInBasicBlock(MemoryInst->getParent());
}

/// It is possible for the addressing mode of the machine to fold the specified
/// instruction into a load or store that ultimately uses it.
/// However, the specified instruction has multiple uses.
/// Given this, it may actually increase register pressure to fold it
/// into the load. For example, consider this code:
///
///     X = ...
///     Y = X+1
///     use(Y)   -> nonload/store
///     Z = Y+1
///     load Z
///
/// In this case, Y has multiple uses, and can be folded into the load of Z
/// (yielding load [X+2]).  However, doing this will cause both "X" and "X+1" to
/// be live at the use(Y) line.  If we don't fold Y into load Z, we use one
/// fewer register.  Since Y can't be folded into "use(Y)" we don't increase the
/// number of computations either.
///
/// Note that this (like most of CodeGenPrepare) is just a rough heuristic.  If
/// X was live across 'load Z' for other reasons, we actually *would* want to
/// fold the addressing mode in the Z case.  This would make Y die earlier.
bool AddressingModeMatcher::isProfitableToFoldIntoAddressingMode(
    Instruction *I, ExtAddrMode &AMBefore, ExtAddrMode &AMAfter) {
  if (IgnoreProfitability)
    return true;

  // AMBefore is the addressing mode before this instruction was folded into it,
  // and AMAfter is the addressing mode after the instruction was folded.  Get
  // the set of registers referenced by AMAfter and subtract out those
  // referenced by AMBefore: this is the set of values which folding in this
  // address extends the lifetime of.
  //
  // Note that there are only two potential values being referenced here,
  // BaseReg and ScaleReg (global addresses are always available, as are any
  // folded immediates).
  Value *BaseReg = AMAfter.BaseReg, *ScaledReg = AMAfter.ScaledReg;

  // If the BaseReg or ScaledReg was referenced by the previous addrmode, their
  // lifetime wasn't extended by adding this instruction.
  if (valueAlreadyLiveAtInst(BaseReg, AMBefore.BaseReg, AMBefore.ScaledReg))
    BaseReg = nullptr;
  if (valueAlreadyLiveAtInst(ScaledReg, AMBefore.BaseReg, AMBefore.ScaledReg))
    ScaledReg = nullptr;

  // If folding this instruction (and it's subexprs) didn't extend any live
  // ranges, we're ok with it.
  if (!BaseReg && !ScaledReg)
    return true;

  // If all uses of this instruction can have the address mode sunk into them,
  // we can remove the addressing mode and effectively trade one live register
  // for another (at worst.)  In this context, folding an addressing mode into
  // the use is just a particularly nice way of sinking it.
  SmallVector<std::pair<Use *, Type *>, 16> MemoryUses;
  if (FindAllMemoryUses(I, MemoryUses, TLI, TRI, OptSize, PSI, BFI))
    return false; // Has a non-memory, non-foldable use!

  // Now that we know that all uses of this instruction are part of a chain of
  // computation involving only operations that could theoretically be folded
  // into a memory use, loop over each of these memory operation uses and see
  // if they could  *actually* fold the instruction.  The assumption is that
  // addressing modes are cheap and that duplicating the computation involved
  // many times is worthwhile, even on a fastpath. For sinking candidates
  // (i.e. cold call sites), this serves as a way to prevent excessive code
  // growth since most architectures have some reasonable small and fast way to
  // compute an effective address.  (i.e LEA on x86)
  SmallVector<Instruction *, 32> MatchedAddrModeInsts;
  for (const std::pair<Use *, Type *> &Pair : MemoryUses) {
    Value *Address = Pair.first->get();
    Instruction *UserI = cast<Instruction>(Pair.first->getUser());
    Type *AddressAccessTy = Pair.second;
    unsigned AS = Address->getType()->getPointerAddressSpace();

    // Do a match against the root of this address, ignoring profitability. This
    // will tell us if the addressing mode for the memory operation will
    // *actually* cover the shared instruction.
    ExtAddrMode Result;
    std::pair<AssertingVH<GetElementPtrInst>, int64_t> LargeOffsetGEP(nullptr,
                                                                      0);
    TypePromotionTransaction::ConstRestorationPt LastKnownGood =
        TPT.getRestorationPoint();
    AddressingModeMatcher Matcher(MatchedAddrModeInsts, TLI, TRI, LI, getDTFn,
                                  AddressAccessTy, AS, UserI, Result,
                                  InsertedInsts, PromotedInsts, TPT,
                                  LargeOffsetGEP, OptSize, PSI, BFI);
    Matcher.IgnoreProfitability = true;
    bool Success = Matcher.matchAddr(Address, 0);
    (void)Success;
    assert(Success && "Couldn't select *anything*?");

    // The match was to check the profitability, the changes made are not
    // part of the original matcher. Therefore, they should be dropped
    // otherwise the original matcher will not present the right state.
    TPT.rollback(LastKnownGood);

    // If the match didn't cover I, then it won't be shared by it.
    if (!is_contained(MatchedAddrModeInsts, I))
      return false;

    MatchedAddrModeInsts.clear();
  }

  return true;
}

/// Return true if the specified values are defined in a
/// different basic block than BB.
static bool IsNonLocalValue(Value *V, BasicBlock *BB) {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return I->getParent() != BB;
  return false;
}

/// Sink addressing mode computation immediate before MemoryInst if doing so
/// can be done without increasing register pressure.  The need for the
/// register pressure constraint means this can end up being an all or nothing
/// decision for all uses of the same addressing computation.
///
/// Load and Store Instructions often have addressing modes that can do
/// significant amounts of computation. As such, instruction selection will try
/// to get the load or store to do as much computation as possible for the
/// program. The problem is that isel can only see within a single block. As
/// such, we sink as much legal addressing mode work into the block as possible.
///
/// This method is used to optimize both load/store and inline asms with memory
/// operands.  It's also used to sink addressing computations feeding into cold
/// call sites into their (cold) basic block.
///
/// The motivation for handling sinking into cold blocks is that doing so can
/// both enable other address mode sinking (by satisfying the register pressure
/// constraint above), and reduce register pressure globally (by removing the
/// addressing mode computation from the fast path entirely.).
bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
                                        Type *AccessTy, unsigned AddrSpace) {
  Value *Repl = Addr;

  // Try to collapse single-value PHI nodes.  This is necessary to undo
  // unprofitable PRE transformations.
  SmallVector<Value *, 8> worklist;
  SmallPtrSet<Value *, 16> Visited;
  worklist.push_back(Addr);

  // Use a worklist to iteratively look through PHI and select nodes, and
  // ensure that the addressing mode obtained from the non-PHI/select roots of
  // the graph are compatible.
  bool PhiOrSelectSeen = false;
  SmallVector<Instruction *, 16> AddrModeInsts;
  const SimplifyQuery SQ(*DL, TLInfo);
  AddressingModeCombiner AddrModes(SQ, Addr);
  TypePromotionTransaction TPT(RemovedInsts);
  TypePromotionTransaction::ConstRestorationPt LastKnownGood =
      TPT.getRestorationPoint();
  while (!worklist.empty()) {
    Value *V = worklist.pop_back_val();

    // We allow traversing cyclic Phi nodes.
    // In case of success after this loop we ensure that traversing through
    // Phi nodes ends up with all cases to compute address of the form
    //    BaseGV + Base + Scale * Index + Offset
    // where Scale and Offset are constans and BaseGV, Base and Index
    // are exactly the same Values in all cases.
    // It means that BaseGV, Scale and Offset dominate our memory instruction
    // and have the same value as they had in address computation represented
    // as Phi. So we can safely sink address computation to memory instruction.
    if (!Visited.insert(V).second)
      continue;

    // For a PHI node, push all of its incoming values.
    if (PHINode *P = dyn_cast<PHINode>(V)) {
      append_range(worklist, P->incoming_values());
      PhiOrSelectSeen = true;
      continue;
    }
    // Similar for select.
    if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
      worklist.push_back(SI->getFalseValue());
      worklist.push_back(SI->getTrueValue());
      PhiOrSelectSeen = true;
      continue;
    }

    // For non-PHIs, determine the addressing mode being computed.  Note that
    // the result may differ depending on what other uses our candidate
    // addressing instructions might have.
    AddrModeInsts.clear();
    std::pair<AssertingVH<GetElementPtrInst>, int64_t> LargeOffsetGEP(nullptr,
                                                                      0);
    // Defer the query (and possible computation of) the dom tree to point of
    // actual use.  It's expected that most address matches don't actually need
    // the domtree.
    auto getDTFn = [MemoryInst, this]() -> const DominatorTree & {
      Function *F = MemoryInst->getParent()->getParent();
      return this->getDT(*F);
    };
    ExtAddrMode NewAddrMode = AddressingModeMatcher::Match(
        V, AccessTy, AddrSpace, MemoryInst, AddrModeInsts, *TLI, *LI, getDTFn,
        *TRI, InsertedInsts, PromotedInsts, TPT, LargeOffsetGEP, OptSize, PSI,
        BFI.get());

    GetElementPtrInst *GEP = LargeOffsetGEP.first;
    if (GEP && !NewGEPBases.count(GEP)) {
      // If splitting the underlying data structure can reduce the offset of a
      // GEP, collect the GEP.  Skip the GEPs that are the new bases of
      // previously split data structures.
      LargeOffsetGEPMap[GEP->getPointerOperand()].push_back(LargeOffsetGEP);
      LargeOffsetGEPID.insert(std::make_pair(GEP, LargeOffsetGEPID.size()));
    }

    NewAddrMode.OriginalValue = V;
    if (!AddrModes.addNewAddrMode(NewAddrMode))
      break;
  }

  // Try to combine the AddrModes we've collected. If we couldn't collect any,
  // or we have multiple but either couldn't combine them or combining them
  // wouldn't do anything useful, bail out now.
  if (!AddrModes.combineAddrModes()) {
    TPT.rollback(LastKnownGood);
    return false;
  }
  bool Modified = TPT.commit();

  // Get the combined AddrMode (or the only AddrMode, if we only had one).
  ExtAddrMode AddrMode = AddrModes.getAddrMode();

  // If all the instructions matched are already in this BB, don't do anything.
  // If we saw a Phi node then it is not local definitely, and if we saw a
  // select then we want to push the address calculation past it even if it's
  // already in this BB.
  if (!PhiOrSelectSeen && none_of(AddrModeInsts, [&](Value *V) {
        return IsNonLocalValue(V, MemoryInst->getParent());
      })) {
    LLVM_DEBUG(dbgs() << "CGP: Found      local addrmode: " << AddrMode
                      << "\n");
    return Modified;
  }

  // Insert this computation right after this user.  Since our caller is
  // scanning from the top of the BB to the bottom, reuse of the expr are
  // guaranteed to happen later.
  IRBuilder<> Builder(MemoryInst);

  // Now that we determined the addressing expression we want to use and know
  // that we have to sink it into this block.  Check to see if we have already
  // done this for some other load/store instr in this block.  If so, reuse
  // the computation.  Before attempting reuse, check if the address is valid
  // as it may have been erased.

  WeakTrackingVH SunkAddrVH = SunkAddrs[Addr];

  Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr;
  Type *IntPtrTy = DL->getIntPtrType(Addr->getType());
  if (SunkAddr) {
    LLVM_DEBUG(dbgs() << "CGP: Reusing nonlocal addrmode: " << AddrMode
                      << " for " << *MemoryInst << "\n");
    if (SunkAddr->getType() != Addr->getType()) {
      if (SunkAddr->getType()->getPointerAddressSpace() !=
              Addr->getType()->getPointerAddressSpace() &&
          !DL->isNonIntegralPointerType(Addr->getType())) {
        // There are two reasons the address spaces might not match: a no-op
        // addrspacecast, or a ptrtoint/inttoptr pair. Either way, we emit a
        // ptrtoint/inttoptr pair to ensure we match the original semantics.
        // TODO: allow bitcast between different address space pointers with the
        // same size.
        SunkAddr = Builder.CreatePtrToInt(SunkAddr, IntPtrTy, "sunkaddr");
        SunkAddr =
            Builder.CreateIntToPtr(SunkAddr, Addr->getType(), "sunkaddr");
      } else
        SunkAddr = Builder.CreatePointerCast(SunkAddr, Addr->getType());
    }
  } else if (AddrSinkUsingGEPs || (!AddrSinkUsingGEPs.getNumOccurrences() &&
                                   SubtargetInfo->addrSinkUsingGEPs())) {
    // By default, we use the GEP-based method when AA is used later. This
    // prevents new inttoptr/ptrtoint pairs from degrading AA capabilities.
    LLVM_DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode
                      << " for " << *MemoryInst << "\n");
    Value *ResultPtr = nullptr, *ResultIndex = nullptr;

    // First, find the pointer.
    if (AddrMode.BaseReg && AddrMode.BaseReg->getType()->isPointerTy()) {
      ResultPtr = AddrMode.BaseReg;
      AddrMode.BaseReg = nullptr;
    }

    if (AddrMode.Scale && AddrMode.ScaledReg->getType()->isPointerTy()) {
      // We can't add more than one pointer together, nor can we scale a
      // pointer (both of which seem meaningless).
      if (ResultPtr || AddrMode.Scale != 1)
        return Modified;

      ResultPtr = AddrMode.ScaledReg;
      AddrMode.Scale = 0;
    }

    // It is only safe to sign extend the BaseReg if we know that the math
    // required to create it did not overflow before we extend it. Since
    // the original IR value was tossed in favor of a constant back when
    // the AddrMode was created we need to bail out gracefully if widths
    // do not match instead of extending it.
    //
    // (See below for code to add the scale.)
    if (AddrMode.Scale) {
      Type *ScaledRegTy = AddrMode.ScaledReg->getType();
      if (cast<IntegerType>(IntPtrTy)->getBitWidth() >
          cast<IntegerType>(ScaledRegTy)->getBitWidth())
        return Modified;
    }

    if (AddrMode.BaseGV) {
      if (ResultPtr)
        return Modified;

      ResultPtr = AddrMode.BaseGV;
    }

    // If the real base value actually came from an inttoptr, then the matcher
    // will look through it and provide only the integer value. In that case,
    // use it here.
    if (!DL->isNonIntegralPointerType(Addr->getType())) {
      if (!ResultPtr && AddrMode.BaseReg) {
        ResultPtr = Builder.CreateIntToPtr(AddrMode.BaseReg, Addr->getType(),
                                           "sunkaddr");
        AddrMode.BaseReg = nullptr;
      } else if (!ResultPtr && AddrMode.Scale == 1) {
        ResultPtr = Builder.CreateIntToPtr(AddrMode.ScaledReg, Addr->getType(),
                                           "sunkaddr");
        AddrMode.Scale = 0;
      }
    }

    if (!ResultPtr && !AddrMode.BaseReg && !AddrMode.Scale &&
        !AddrMode.BaseOffs) {
      SunkAddr = Constant::getNullValue(Addr->getType());
    } else if (!ResultPtr) {
      return Modified;
    } else {
      Type *I8PtrTy =
          Builder.getInt8PtrTy(Addr->getType()->getPointerAddressSpace());
      Type *I8Ty = Builder.getInt8Ty();

      // Start with the base register. Do this first so that subsequent address
      // matching finds it last, which will prevent it from trying to match it
      // as the scaled value in case it happens to be a mul. That would be
      // problematic if we've sunk a different mul for the scale, because then
      // we'd end up sinking both muls.
      if (AddrMode.BaseReg) {
        Value *V = AddrMode.BaseReg;
        if (V->getType() != IntPtrTy)
          V = Builder.CreateIntCast(V, IntPtrTy, /*isSigned=*/true, "sunkaddr");

        ResultIndex = V;
      }

      // Add the scale value.
      if (AddrMode.Scale) {
        Value *V = AddrMode.ScaledReg;
        if (V->getType() == IntPtrTy) {
          // done.
        } else {
          assert(cast<IntegerType>(IntPtrTy)->getBitWidth() <
                     cast<IntegerType>(V->getType())->getBitWidth() &&
                 "We can't transform if ScaledReg is too narrow");
          V = Builder.CreateTrunc(V, IntPtrTy, "sunkaddr");
        }

        if (AddrMode.Scale != 1)
          V = Builder.CreateMul(V, ConstantInt::get(IntPtrTy, AddrMode.Scale),
                                "sunkaddr");
        if (ResultIndex)
          ResultIndex = Builder.CreateAdd(ResultIndex, V, "sunkaddr");
        else
          ResultIndex = V;
      }

      // Add in the Base Offset if present.
      if (AddrMode.BaseOffs) {
        Value *V = ConstantInt::get(IntPtrTy, AddrMode.BaseOffs);
        if (ResultIndex) {
          // We need to add this separately from the scale above to help with
          // SDAG consecutive load/store merging.
          if (ResultPtr->getType() != I8PtrTy)
            ResultPtr = Builder.CreatePointerCast(ResultPtr, I8PtrTy);
          ResultPtr = Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex,
                                        "sunkaddr", AddrMode.InBounds);
        }

        ResultIndex = V;
      }

      if (!ResultIndex) {
        SunkAddr = ResultPtr;
      } else {
        if (ResultPtr->getType() != I8PtrTy)
          ResultPtr = Builder.CreatePointerCast(ResultPtr, I8PtrTy);
        SunkAddr = Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex, "sunkaddr",
                                     AddrMode.InBounds);
      }

      if (SunkAddr->getType() != Addr->getType()) {
        if (SunkAddr->getType()->getPointerAddressSpace() !=
                Addr->getType()->getPointerAddressSpace() &&
            !DL->isNonIntegralPointerType(Addr->getType())) {
          // There are two reasons the address spaces might not match: a no-op
          // addrspacecast, or a ptrtoint/inttoptr pair. Either way, we emit a
          // ptrtoint/inttoptr pair to ensure we match the original semantics.
          // TODO: allow bitcast between different address space pointers with
          // the same size.
          SunkAddr = Builder.CreatePtrToInt(SunkAddr, IntPtrTy, "sunkaddr");
          SunkAddr =
              Builder.CreateIntToPtr(SunkAddr, Addr->getType(), "sunkaddr");
        } else
          SunkAddr = Builder.CreatePointerCast(SunkAddr, Addr->getType());
      }
    }
  } else {
    // We'd require a ptrtoint/inttoptr down the line, which we can't do for
    // non-integral pointers, so in that case bail out now.
    Type *BaseTy = AddrMode.BaseReg ? AddrMode.BaseReg->getType() : nullptr;
    Type *ScaleTy = AddrMode.Scale ? AddrMode.ScaledReg->getType() : nullptr;
    PointerType *BasePtrTy = dyn_cast_or_null<PointerType>(BaseTy);
    PointerType *ScalePtrTy = dyn_cast_or_null<PointerType>(ScaleTy);
    if (DL->isNonIntegralPointerType(Addr->getType()) ||
        (BasePtrTy && DL->isNonIntegralPointerType(BasePtrTy)) ||
        (ScalePtrTy && DL->isNonIntegralPointerType(ScalePtrTy)) ||
        (AddrMode.BaseGV &&
         DL->isNonIntegralPointerType(AddrMode.BaseGV->getType())))
      return Modified;

    LLVM_DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode
                      << " for " << *MemoryInst << "\n");
    Type *IntPtrTy = DL->getIntPtrType(Addr->getType());
    Value *Result = nullptr;

    // Start with the base register. Do this first so that subsequent address
    // matching finds it last, which will prevent it from trying to match it
    // as the scaled value in case it happens to be a mul. That would be
    // problematic if we've sunk a different mul for the scale, because then
    // we'd end up sinking both muls.
    if (AddrMode.BaseReg) {
      Value *V = AddrMode.BaseReg;
      if (V->getType()->isPointerTy())
        V = Builder.CreatePtrToInt(V, IntPtrTy, "sunkaddr");
      if (V->getType() != IntPtrTy)
        V = Builder.CreateIntCast(V, IntPtrTy, /*isSigned=*/true, "sunkaddr");
      Result = V;
    }

    // Add the scale value.
    if (AddrMode.Scale) {
      Value *V = AddrMode.ScaledReg;
      if (V->getType() == IntPtrTy) {
        // done.
      } else if (V->getType()->isPointerTy()) {
        V = Builder.CreatePtrToInt(V, IntPtrTy, "sunkaddr");
      } else if (cast<IntegerType>(IntPtrTy)->getBitWidth() <
                 cast<IntegerType>(V->getType())->getBitWidth()) {
        V = Builder.CreateTrunc(V, IntPtrTy, "sunkaddr");
      } else {
        // It is only safe to sign extend the BaseReg if we know that the math
        // required to create it did not overflow before we extend it. Since
        // the original IR value was tossed in favor of a constant back when
        // the AddrMode was created we need to bail out gracefully if widths
        // do not match instead of extending it.
        Instruction *I = dyn_cast_or_null<Instruction>(Result);
        if (I && (Result != AddrMode.BaseReg))
          I->eraseFromParent();
        return Modified;
      }
      if (AddrMode.Scale != 1)
        V = Builder.CreateMul(V, ConstantInt::get(IntPtrTy, AddrMode.Scale),
                              "sunkaddr");
      if (Result)
        Result = Builder.CreateAdd(Result, V, "sunkaddr");
      else
        Result = V;
    }

    // Add in the BaseGV if present.
    if (AddrMode.BaseGV) {
      Value *V = Builder.CreatePtrToInt(AddrMode.BaseGV, IntPtrTy, "sunkaddr");
      if (Result)
        Result = Builder.CreateAdd(Result, V, "sunkaddr");
      else
        Result = V;
    }

    // Add in the Base Offset if present.
    if (AddrMode.BaseOffs) {
      Value *V = ConstantInt::get(IntPtrTy, AddrMode.BaseOffs);
      if (Result)
        Result = Builder.CreateAdd(Result, V, "sunkaddr");
      else
        Result = V;
    }

    if (!Result)
      SunkAddr = Constant::getNullValue(Addr->getType());
    else
      SunkAddr = Builder.CreateIntToPtr(Result, Addr->getType(), "sunkaddr");
  }

  MemoryInst->replaceUsesOfWith(Repl, SunkAddr);
  // Store the newly computed address into the cache. In the case we reused a
  // value, this should be idempotent.
  SunkAddrs[Addr] = WeakTrackingVH(SunkAddr);

  // If we have no uses, recursively delete the value and all dead instructions
  // using it.
  if (Repl->use_empty()) {
    resetIteratorIfInvalidatedWhileCalling(CurInstIterator->getParent(), [&]() {
      RecursivelyDeleteTriviallyDeadInstructions(
          Repl, TLInfo, nullptr,
          [&](Value *V) { removeAllAssertingVHReferences(V); });
    });
  }
  ++NumMemoryInsts;
  return true;
}

/// Rewrite GEP input to gather/scatter to enable SelectionDAGBuilder to find
/// a uniform base to use for ISD::MGATHER/MSCATTER. SelectionDAGBuilder can
/// only handle a 2 operand GEP in the same basic block or a splat constant
/// vector. The 2 operands to the GEP must have a scalar pointer and a vector
/// index.
///
/// If the existing GEP has a vector base pointer that is splat, we can look
/// through the splat to find the scalar pointer. If we can't find a scalar
/// pointer there's nothing we can do.
///
/// If we have a GEP with more than 2 indices where the middle indices are all
/// zeroes, we can replace it with 2 GEPs where the second has 2 operands.
///
/// If the final index isn't a vector or is a splat, we can emit a scalar GEP
/// followed by a GEP with an all zeroes vector index. This will enable
/// SelectionDAGBuilder to use the scalar GEP as the uniform base and have a
/// zero index.
bool CodeGenPrepare::optimizeGatherScatterInst(Instruction *MemoryInst,
                                               Value *Ptr) {
  Value *NewAddr;

  if (const auto *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {
    // Don't optimize GEPs that don't have indices.
    if (!GEP->hasIndices())
      return false;

    // If the GEP and the gather/scatter aren't in the same BB, don't optimize.
    // FIXME: We should support this by sinking the GEP.
    if (MemoryInst->getParent() != GEP->getParent())
      return false;

    SmallVector<Value *, 2> Ops(GEP->operands());

    bool RewriteGEP = false;

    if (Ops[0]->getType()->isVectorTy()) {
      Ops[0] = getSplatValue(Ops[0]);
      if (!Ops[0])
        return false;
      RewriteGEP = true;
    }

    unsigned FinalIndex = Ops.size() - 1;

    // Ensure all but the last index is 0.
    // FIXME: This isn't strictly required. All that's required is that they are
    // all scalars or splats.
    for (unsigned i = 1; i < FinalIndex; ++i) {
      auto *C = dyn_cast<Constant>(Ops[i]);
      if (!C)
        return false;
      if (isa<VectorType>(C->getType()))
        C = C->getSplatValue();
      auto *CI = dyn_cast_or_null<ConstantInt>(C);
      if (!CI || !CI->isZero())
        return false;
      // Scalarize the index if needed.
      Ops[i] = CI;
    }

    // Try to scalarize the final index.
    if (Ops[FinalIndex]->getType()->isVectorTy()) {
      if (Value *V = getSplatValue(Ops[FinalIndex])) {
        auto *C = dyn_cast<ConstantInt>(V);
        // Don't scalarize all zeros vector.
        if (!C || !C->isZero()) {
          Ops[FinalIndex] = V;
          RewriteGEP = true;
        }
      }
    }

    // If we made any changes or the we have extra operands, we need to generate
    // new instructions.
    if (!RewriteGEP && Ops.size() == 2)
      return false;

    auto NumElts = cast<VectorType>(Ptr->getType())->getElementCount();

    IRBuilder<> Builder(MemoryInst);

    Type *SourceTy = GEP->getSourceElementType();
    Type *ScalarIndexTy = DL->getIndexType(Ops[0]->getType()->getScalarType());

    // If the final index isn't a vector, emit a scalar GEP containing all ops
    // and a vector GEP with all zeroes final index.
    if (!Ops[FinalIndex]->getType()->isVectorTy()) {
      NewAddr = Builder.CreateGEP(SourceTy, Ops[0], ArrayRef(Ops).drop_front());
      auto *IndexTy = VectorType::get(ScalarIndexTy, NumElts);
      auto *SecondTy = GetElementPtrInst::getIndexedType(
          SourceTy, ArrayRef(Ops).drop_front());
      NewAddr =
          Builder.CreateGEP(SecondTy, NewAddr, Constant::getNullValue(IndexTy));
    } else {
      Value *Base = Ops[0];
      Value *Index = Ops[FinalIndex];

      // Create a scalar GEP if there are more than 2 operands.
      if (Ops.size() != 2) {
        // Replace the last index with 0.
        Ops[FinalIndex] =
            Constant::getNullValue(Ops[FinalIndex]->getType()->getScalarType());
        Base = Builder.CreateGEP(SourceTy, Base, ArrayRef(Ops).drop_front());
        SourceTy = GetElementPtrInst::getIndexedType(
            SourceTy, ArrayRef(Ops).drop_front());
      }

      // Now create the GEP with scalar pointer and vector index.
      NewAddr = Builder.CreateGEP(SourceTy, Base, Index);
    }
  } else if (!isa<Constant>(Ptr)) {
    // Not a GEP, maybe its a splat and we can create a GEP to enable
    // SelectionDAGBuilder to use it as a uniform base.
    Value *V = getSplatValue(Ptr);
    if (!V)
      return false;

    auto NumElts = cast<VectorType>(Ptr->getType())->getElementCount();

    IRBuilder<> Builder(MemoryInst);

    // Emit a vector GEP with a scalar pointer and all 0s vector index.
    Type *ScalarIndexTy = DL->getIndexType(V->getType()->getScalarType());
    auto *IndexTy = VectorType::get(ScalarIndexTy, NumElts);
    Type *ScalarTy;
    if (cast<IntrinsicInst>(MemoryInst)->getIntrinsicID() ==
        Intrinsic::masked_gather) {
      ScalarTy = MemoryInst->getType()->getScalarType();
    } else {
      assert(cast<IntrinsicInst>(MemoryInst)->getIntrinsicID() ==
             Intrinsic::masked_scatter);
      ScalarTy = MemoryInst->getOperand(0)->getType()->getScalarType();
    }
    NewAddr = Builder.CreateGEP(ScalarTy, V, Constant::getNullValue(IndexTy));
  } else {
    // Constant, SelectionDAGBuilder knows to check if its a splat.
    return false;
  }

  MemoryInst->replaceUsesOfWith(Ptr, NewAddr);

  // If we have no uses, recursively delete the value and all dead instructions
  // using it.
  if (Ptr->use_empty())
    RecursivelyDeleteTriviallyDeadInstructions(
        Ptr, TLInfo, nullptr,
        [&](Value *V) { removeAllAssertingVHReferences(V); });

  return true;
}

/// If there are any memory operands, use OptimizeMemoryInst to sink their
/// address computing into the block when possible / profitable.
bool CodeGenPrepare::optimizeInlineAsmInst(CallInst *CS) {
  bool MadeChange = false;

  const TargetRegisterInfo *TRI =
      TM->getSubtargetImpl(*CS->getFunction())->getRegisterInfo();
  TargetLowering::AsmOperandInfoVector TargetConstraints =
      TLI->ParseConstraints(*DL, TRI, *CS);
  unsigned ArgNo = 0;
  for (TargetLowering::AsmOperandInfo &OpInfo : TargetConstraints) {
    // Compute the constraint code and ConstraintType to use.
    TLI->ComputeConstraintToUse(OpInfo, SDValue());

    // TODO: Also handle C_Address?
    if (OpInfo.ConstraintType == TargetLowering::C_Memory &&
        OpInfo.isIndirect) {
      Value *OpVal = CS->getArgOperand(ArgNo++);
      MadeChange |= optimizeMemoryInst(CS, OpVal, OpVal->getType(), ~0u);
    } else if (OpInfo.Type == InlineAsm::isInput)
      ArgNo++;
  }

  return MadeChange;
}

/// Check if all the uses of \p Val are equivalent (or free) zero or
/// sign extensions.
static bool hasSameExtUse(Value *Val, const TargetLowering &TLI) {
  assert(!Val->use_empty() && "Input must have at least one use");
  const Instruction *FirstUser = cast<Instruction>(*Val->user_begin());
  bool IsSExt = isa<SExtInst>(FirstUser);
  Type *ExtTy = FirstUser->getType();
  for (const User *U : Val->users()) {
    const Instruction *UI = cast<Instruction>(U);
    if ((IsSExt && !isa<SExtInst>(UI)) || (!IsSExt && !isa<ZExtInst>(UI)))
      return false;
    Type *CurTy = UI->getType();
    // Same input and output types: Same instruction after CSE.
    if (CurTy == ExtTy)
      continue;

    // If IsSExt is true, we are in this situation:
    // a = Val
    // b = sext ty1 a to ty2
    // c = sext ty1 a to ty3
    // Assuming ty2 is shorter than ty3, this could be turned into:
    // a = Val
    // b = sext ty1 a to ty2
    // c = sext ty2 b to ty3
    // However, the last sext is not free.
    if (IsSExt)
      return false;

    // This is a ZExt, maybe this is free to extend from one type to another.
    // In that case, we would not account for a different use.
    Type *NarrowTy;
    Type *LargeTy;
    if (ExtTy->getScalarType()->getIntegerBitWidth() >
        CurTy->getScalarType()->getIntegerBitWidth()) {
      NarrowTy = CurTy;
      LargeTy = ExtTy;
    } else {
      NarrowTy = ExtTy;
      LargeTy = CurTy;
    }

    if (!TLI.isZExtFree(NarrowTy, LargeTy))
      return false;
  }
  // All uses are the same or can be derived from one another for free.
  return true;
}

/// Try to speculatively promote extensions in \p Exts and continue
/// promoting through newly promoted operands recursively as far as doing so is
/// profitable. Save extensions profitably moved up, in \p ProfitablyMovedExts.
/// When some promotion happened, \p TPT contains the proper state to revert
/// them.
///
/// \return true if some promotion happened, false otherwise.
bool CodeGenPrepare::tryToPromoteExts(
    TypePromotionTransaction &TPT, const SmallVectorImpl<Instruction *> &Exts,
    SmallVectorImpl<Instruction *> &ProfitablyMovedExts,
    unsigned CreatedInstsCost) {
  bool Promoted = false;

  // Iterate over all the extensions to try to promote them.
  for (auto *I : Exts) {
    // Early check if we directly have ext(load).
    if (isa<LoadInst>(I->getOperand(0))) {
      ProfitablyMovedExts.push_back(I);
      continue;
    }

    // Check whether or not we want to do any promotion.  The reason we have
    // this check inside the for loop is to catch the case where an extension
    // is directly fed by a load because in such case the extension can be moved
    // up without any promotion on its operands.
    if (!TLI->enableExtLdPromotion() || DisableExtLdPromotion)
      return false;

    // Get the action to perform the promotion.
    TypePromotionHelper::Action TPH =
        TypePromotionHelper::getAction(I, InsertedInsts, *TLI, PromotedInsts);
    // Check if we can promote.
    if (!TPH) {
      // Save the current extension as we cannot move up through its operand.
      ProfitablyMovedExts.push_back(I);
      continue;
    }

    // Save the current state.
    TypePromotionTransaction::ConstRestorationPt LastKnownGood =
        TPT.getRestorationPoint();
    SmallVector<Instruction *, 4> NewExts;
    unsigned NewCreatedInstsCost = 0;
    unsigned ExtCost = !TLI->isExtFree(I);
    // Promote.
    Value *PromotedVal = TPH(I, TPT, PromotedInsts, NewCreatedInstsCost,
                             &NewExts, nullptr, *TLI);
    assert(PromotedVal &&
           "TypePromotionHelper should have filtered out those cases");

    // We would be able to merge only one extension in a load.
    // Therefore, if we have more than 1 new extension we heuristically
    // cut this search path, because it means we degrade the code quality.
    // With exactly 2, the transformation is neutral, because we will merge
    // one extension but leave one. However, we optimistically keep going,
    // because the new extension may be removed too.
    long long TotalCreatedInstsCost = CreatedInstsCost + NewCreatedInstsCost;
    // FIXME: It would be possible to propagate a negative value instead of
    // conservatively ceiling it to 0.
    TotalCreatedInstsCost =
        std::max((long long)0, (TotalCreatedInstsCost - ExtCost));
    if (!StressExtLdPromotion &&
        (TotalCreatedInstsCost > 1 ||
         !isPromotedInstructionLegal(*TLI, *DL, PromotedVal))) {
      // This promotion is not profitable, rollback to the previous state, and
      // save the current extension in ProfitablyMovedExts as the latest
      // speculative promotion turned out to be unprofitable.
      TPT.rollback(LastKnownGood);
      ProfitablyMovedExts.push_back(I);
      continue;
    }
    // Continue promoting NewExts as far as doing so is profitable.
    SmallVector<Instruction *, 2> NewlyMovedExts;
    (void)tryToPromoteExts(TPT, NewExts, NewlyMovedExts, TotalCreatedInstsCost);
    bool NewPromoted = false;
    for (auto *ExtInst : NewlyMovedExts) {
      Instruction *MovedExt = cast<Instruction>(ExtInst);
      Value *ExtOperand = MovedExt->getOperand(0);
      // If we have reached to a load, we need this extra profitability check
      // as it could potentially be merged into an ext(load).
      if (isa<LoadInst>(ExtOperand) &&
          !(StressExtLdPromotion || NewCreatedInstsCost <= ExtCost ||
            (ExtOperand->hasOneUse() || hasSameExtUse(ExtOperand, *TLI))))
        continue;

      ProfitablyMovedExts.push_back(MovedExt);
      NewPromoted = true;
    }

    // If none of speculative promotions for NewExts is profitable, rollback
    // and save the current extension (I) as the last profitable extension.
    if (!NewPromoted) {
      TPT.rollback(LastKnownGood);
      ProfitablyMovedExts.push_back(I);
      continue;
    }
    // The promotion is profitable.
    Promoted = true;
  }
  return Promoted;
}

/// Merging redundant sexts when one is dominating the other.
bool CodeGenPrepare::mergeSExts(Function &F) {
  bool Changed = false;
  for (auto &Entry : ValToSExtendedUses) {
    SExts &Insts = Entry.second;
    SExts CurPts;
    for (Instruction *Inst : Insts) {
      if (RemovedInsts.count(Inst) || !isa<SExtInst>(Inst) ||
          Inst->getOperand(0) != Entry.first)
        continue;
      bool inserted = false;
      for (auto &Pt : CurPts) {
        if (getDT(F).dominates(Inst, Pt)) {
          replaceAllUsesWith(Pt, Inst, FreshBBs, IsHugeFunc);
          RemovedInsts.insert(Pt);
          Pt->removeFromParent();
          Pt = Inst;
          inserted = true;
          Changed = true;
          break;
        }
        if (!getDT(F).dominates(Pt, Inst))
          // Give up if we need to merge in a common dominator as the
          // experiments show it is not profitable.
          continue;
        replaceAllUsesWith(Inst, Pt, FreshBBs, IsHugeFunc);
        RemovedInsts.insert(Inst);
        Inst->removeFromParent();
        inserted = true;
        Changed = true;
        break;
      }
      if (!inserted)
        CurPts.push_back(Inst);
    }
  }
  return Changed;
}

// Splitting large data structures so that the GEPs accessing them can have
// smaller offsets so that they can be sunk to the same blocks as their users.
// For example, a large struct starting from %base is split into two parts
// where the second part starts from %new_base.
//
// Before:
// BB0:
//   %base     =
//
// BB1:
//   %gep0     = gep %base, off0
//   %gep1     = gep %base, off1
//   %gep2     = gep %base, off2
//
// BB2:
//   %load1    = load %gep0
//   %load2    = load %gep1
//   %load3    = load %gep2
//
// After:
// BB0:
//   %base     =
//   %new_base = gep %base, off0
//
// BB1:
//   %new_gep0 = %new_base
//   %new_gep1 = gep %new_base, off1 - off0
//   %new_gep2 = gep %new_base, off2 - off0
//
// BB2:
//   %load1    = load i32, i32* %new_gep0
//   %load2    = load i32, i32* %new_gep1
//   %load3    = load i32, i32* %new_gep2
//
// %new_gep1 and %new_gep2 can be sunk to BB2 now after the splitting because
// their offsets are smaller enough to fit into the addressing mode.
bool CodeGenPrepare::splitLargeGEPOffsets() {
  bool Changed = false;
  for (auto &Entry : LargeOffsetGEPMap) {
    Value *OldBase = Entry.first;
    SmallVectorImpl<std::pair<AssertingVH<GetElementPtrInst>, int64_t>>
        &LargeOffsetGEPs = Entry.second;
    auto compareGEPOffset =
        [&](const std::pair<GetElementPtrInst *, int64_t> &LHS,
            const std::pair<GetElementPtrInst *, int64_t> &RHS) {
          if (LHS.first == RHS.first)
            return false;
          if (LHS.second != RHS.second)
            return LHS.second < RHS.second;
          return LargeOffsetGEPID[LHS.first] < LargeOffsetGEPID[RHS.first];
        };
    // Sorting all the GEPs of the same data structures based on the offsets.
    llvm::sort(LargeOffsetGEPs, compareGEPOffset);
    LargeOffsetGEPs.erase(
        std::unique(LargeOffsetGEPs.begin(), LargeOffsetGEPs.end()),
        LargeOffsetGEPs.end());
    // Skip if all the GEPs have the same offsets.
    if (LargeOffsetGEPs.front().second == LargeOffsetGEPs.back().second)
      continue;
    GetElementPtrInst *BaseGEP = LargeOffsetGEPs.begin()->first;
    int64_t BaseOffset = LargeOffsetGEPs.begin()->second;
    Value *NewBaseGEP = nullptr;

    auto *LargeOffsetGEP = LargeOffsetGEPs.begin();
    while (LargeOffsetGEP != LargeOffsetGEPs.end()) {
      GetElementPtrInst *GEP = LargeOffsetGEP->first;
      int64_t Offset = LargeOffsetGEP->second;
      if (Offset != BaseOffset) {
        TargetLowering::AddrMode AddrMode;
        AddrMode.HasBaseReg = true;
        AddrMode.BaseOffs = Offset - BaseOffset;
        // The result type of the GEP might not be the type of the memory
        // access.
        if (!TLI->isLegalAddressingMode(*DL, AddrMode,
                                        GEP->getResultElementType(),
                                        GEP->getAddressSpace())) {
          // We need to create a new base if the offset to the current base is
          // too large to fit into the addressing mode. So, a very large struct
          // may be split into several parts.
          BaseGEP = GEP;
          BaseOffset = Offset;
          NewBaseGEP = nullptr;
        }
      }

      // Generate a new GEP to replace the current one.
      LLVMContext &Ctx = GEP->getContext();
      Type *PtrIdxTy = DL->getIndexType(GEP->getType());
      Type *I8PtrTy =
          Type::getInt8PtrTy(Ctx, GEP->getType()->getPointerAddressSpace());
      Type *I8Ty = Type::getInt8Ty(Ctx);

      if (!NewBaseGEP) {
        // Create a new base if we don't have one yet.  Find the insertion
        // pointer for the new base first.
        BasicBlock::iterator NewBaseInsertPt;
        BasicBlock *NewBaseInsertBB;
        if (auto *BaseI = dyn_cast<Instruction>(OldBase)) {
          // If the base of the struct is an instruction, the new base will be
          // inserted close to it.
          NewBaseInsertBB = BaseI->getParent();
          if (isa<PHINode>(BaseI))
            NewBaseInsertPt = NewBaseInsertBB->getFirstInsertionPt();
          else if (InvokeInst *Invoke = dyn_cast<InvokeInst>(BaseI)) {
            NewBaseInsertBB =
                SplitEdge(NewBaseInsertBB, Invoke->getNormalDest(), DT.get(), LI);
            NewBaseInsertPt = NewBaseInsertBB->getFirstInsertionPt();
          } else
            NewBaseInsertPt = std::next(BaseI->getIterator());
        } else {
          // If the current base is an argument or global value, the new base
          // will be inserted to the entry block.
          NewBaseInsertBB = &BaseGEP->getFunction()->getEntryBlock();
          NewBaseInsertPt = NewBaseInsertBB->getFirstInsertionPt();
        }
        IRBuilder<> NewBaseBuilder(NewBaseInsertBB, NewBaseInsertPt);
        // Create a new base.
        Value *BaseIndex = ConstantInt::get(PtrIdxTy, BaseOffset);
        NewBaseGEP = OldBase;
        if (NewBaseGEP->getType() != I8PtrTy)
          NewBaseGEP = NewBaseBuilder.CreatePointerCast(NewBaseGEP, I8PtrTy);
        NewBaseGEP =
            NewBaseBuilder.CreateGEP(I8Ty, NewBaseGEP, BaseIndex, "splitgep");
        NewGEPBases.insert(NewBaseGEP);
      }

      IRBuilder<> Builder(GEP);
      Value *NewGEP = NewBaseGEP;
      if (Offset == BaseOffset) {
        if (GEP->getType() != I8PtrTy)
          NewGEP = Builder.CreatePointerCast(NewGEP, GEP->getType());
      } else {
        // Calculate the new offset for the new GEP.
        Value *Index = ConstantInt::get(PtrIdxTy, Offset - BaseOffset);
        NewGEP = Builder.CreateGEP(I8Ty, NewBaseGEP, Index);

        if (GEP->getType() != I8PtrTy)
          NewGEP = Builder.CreatePointerCast(NewGEP, GEP->getType());
      }
      replaceAllUsesWith(GEP, NewGEP, FreshBBs, IsHugeFunc);
      LargeOffsetGEPID.erase(GEP);
      LargeOffsetGEP = LargeOffsetGEPs.erase(LargeOffsetGEP);
      GEP->eraseFromParent();
      Changed = true;
    }
  }
  return Changed;
}

bool CodeGenPrepare::optimizePhiType(
    PHINode *I, SmallPtrSetImpl<PHINode *> &Visited,
    SmallPtrSetImpl<Instruction *> &DeletedInstrs) {
  // We are looking for a collection on interconnected phi nodes that together
  // only use loads/bitcasts and are used by stores/bitcasts, and the bitcasts
  // are of the same type. Convert the whole set of nodes to the type of the
  // bitcast.
  Type *PhiTy = I->getType();
  Type *ConvertTy = nullptr;
  if (Visited.count(I) ||
      (!I->getType()->isIntegerTy() && !I->getType()->isFloatingPointTy()))
    return false;

  SmallVector<Instruction *, 4> Worklist;
  Worklist.push_back(cast<Instruction>(I));
  SmallPtrSet<PHINode *, 4> PhiNodes;
  SmallPtrSet<ConstantData *, 4> Constants;
  PhiNodes.insert(I);
  Visited.insert(I);
  SmallPtrSet<Instruction *, 4> Defs;
  SmallPtrSet<Instruction *, 4> Uses;
  // This works by adding extra bitcasts between load/stores and removing
  // existing bicasts. If we have a phi(bitcast(load)) or a store(bitcast(phi))
  // we can get in the situation where we remove a bitcast in one iteration
  // just to add it again in the next. We need to ensure that at least one
  // bitcast we remove are anchored to something that will not change back.
  bool AnyAnchored = false;

  while (!Worklist.empty()) {
    Instruction *II = Worklist.pop_back_val();

    if (auto *Phi = dyn_cast<PHINode>(II)) {
      // Handle Defs, which might also be PHI's
      for (Value *V : Phi->incoming_values()) {
        if (auto *OpPhi = dyn_cast<PHINode>(V)) {
          if (!PhiNodes.count(OpPhi)) {
            if (!Visited.insert(OpPhi).second)
              return false;
            PhiNodes.insert(OpPhi);
            Worklist.push_back(OpPhi);
          }
        } else if (auto *OpLoad = dyn_cast<LoadInst>(V)) {
          if (!OpLoad->isSimple())
            return false;
          if (Defs.insert(OpLoad).second)
            Worklist.push_back(OpLoad);
        } else if (auto *OpEx = dyn_cast<ExtractElementInst>(V)) {
          if (Defs.insert(OpEx).second)
            Worklist.push_back(OpEx);
        } else if (auto *OpBC = dyn_cast<BitCastInst>(V)) {
          if (!ConvertTy)
            ConvertTy = OpBC->getOperand(0)->getType();
          if (OpBC->getOperand(0)->getType() != ConvertTy)
            return false;
          if (Defs.insert(OpBC).second) {
            Worklist.push_back(OpBC);
            AnyAnchored |= !isa<LoadInst>(OpBC->getOperand(0)) &&
                           !isa<ExtractElementInst>(OpBC->getOperand(0));
          }
        } else if (auto *OpC = dyn_cast<ConstantData>(V))
          Constants.insert(OpC);
        else
          return false;
      }
    }

    // Handle uses which might also be phi's
    for (User *V : II->users()) {
      if (auto *OpPhi = dyn_cast<PHINode>(V)) {
        if (!PhiNodes.count(OpPhi)) {
          if (Visited.count(OpPhi))
            return false;
          PhiNodes.insert(OpPhi);
          Visited.insert(OpPhi);
          Worklist.push_back(OpPhi);
        }
      } else if (auto *OpStore = dyn_cast<StoreInst>(V)) {
        if (!OpStore->isSimple() || OpStore->getOperand(0) != II)
          return false;
        Uses.insert(OpStore);
      } else if (auto *OpBC = dyn_cast<BitCastInst>(V)) {
        if (!ConvertTy)
          ConvertTy = OpBC->getType();
        if (OpBC->getType() != ConvertTy)
          return false;
        Uses.insert(OpBC);
        AnyAnchored |=
            any_of(OpBC->users(), [](User *U) { return !isa<StoreInst>(U); });
      } else {
        return false;
      }
    }
  }

  if (!ConvertTy || !AnyAnchored ||
      !TLI->shouldConvertPhiType(PhiTy, ConvertTy))
    return false;

  LLVM_DEBUG(dbgs() << "Converting " << *I << "\n  and connected nodes to "
                    << *ConvertTy << "\n");

  // Create all the new phi nodes of the new type, and bitcast any loads to the
  // correct type.
  ValueToValueMap ValMap;
  for (ConstantData *C : Constants)
    ValMap[C] = ConstantExpr::getCast(Instruction::BitCast, C, ConvertTy);
  for (Instruction *D : Defs) {
    if (isa<BitCastInst>(D)) {
      ValMap[D] = D->getOperand(0);
      DeletedInstrs.insert(D);
    } else {
      ValMap[D] =
          new BitCastInst(D, ConvertTy, D->getName() + ".bc", D->getNextNode());
    }
  }
  for (PHINode *Phi : PhiNodes)
    ValMap[Phi] = PHINode::Create(ConvertTy, Phi->getNumIncomingValues(),
                                  Phi->getName() + ".tc", Phi);
  // Pipe together all the PhiNodes.
  for (PHINode *Phi : PhiNodes) {
    PHINode *NewPhi = cast<PHINode>(ValMap[Phi]);
    for (int i = 0, e = Phi->getNumIncomingValues(); i < e; i++)
      NewPhi->addIncoming(ValMap[Phi->getIncomingValue(i)],
                          Phi->getIncomingBlock(i));
    Visited.insert(NewPhi);
  }
  // And finally pipe up the stores and bitcasts
  for (Instruction *U : Uses) {
    if (isa<BitCastInst>(U)) {
      DeletedInstrs.insert(U);
      replaceAllUsesWith(U, ValMap[U->getOperand(0)], FreshBBs, IsHugeFunc);
    } else {
      U->setOperand(0,
                    new BitCastInst(ValMap[U->getOperand(0)], PhiTy, "bc", U));
    }
  }

  // Save the removed phis to be deleted later.
  for (PHINode *Phi : PhiNodes)
    DeletedInstrs.insert(Phi);
  return true;
}

bool CodeGenPrepare::optimizePhiTypes(Function &F) {
  if (!OptimizePhiTypes)
    return false;

  bool Changed = false;
  SmallPtrSet<PHINode *, 4> Visited;
  SmallPtrSet<Instruction *, 4> DeletedInstrs;

  // Attempt to optimize all the phis in the functions to the correct type.
  for (auto &BB : F)
    for (auto &Phi : BB.phis())
      Changed |= optimizePhiType(&Phi, Visited, DeletedInstrs);

  // Remove any old phi's that have been converted.
  for (auto *I : DeletedInstrs) {
    replaceAllUsesWith(I, PoisonValue::get(I->getType()), FreshBBs, IsHugeFunc);
    I->eraseFromParent();
  }

  return Changed;
}

/// Return true, if an ext(load) can be formed from an extension in
/// \p MovedExts.
bool CodeGenPrepare::canFormExtLd(
    const SmallVectorImpl<Instruction *> &MovedExts, LoadInst *&LI,
    Instruction *&Inst, bool HasPromoted) {
  for (auto *MovedExtInst : MovedExts) {
    if (isa<LoadInst>(MovedExtInst->getOperand(0))) {
      LI = cast<LoadInst>(MovedExtInst->getOperand(0));
      Inst = MovedExtInst;
      break;
    }
  }
  if (!LI)
    return false;

  // If they're already in the same block, there's nothing to do.
  // Make the cheap checks first if we did not promote.
  // If we promoted, we need to check if it is indeed profitable.
  if (!HasPromoted && LI->getParent() == Inst->getParent())
    return false;

  return TLI->isExtLoad(LI, Inst, *DL);
}

/// Move a zext or sext fed by a load into the same basic block as the load,
/// unless conditions are unfavorable. This allows SelectionDAG to fold the
/// extend into the load.
///
/// E.g.,
/// \code
/// %ld = load i32* %addr
/// %add = add nuw i32 %ld, 4
/// %zext = zext i32 %add to i64
// \endcode
/// =>
/// \code
/// %ld = load i32* %addr
/// %zext = zext i32 %ld to i64
/// %add = add nuw i64 %zext, 4
/// \encode
/// Note that the promotion in %add to i64 is done in tryToPromoteExts(), which
/// allow us to match zext(load i32*) to i64.
///
/// Also, try to promote the computations used to obtain a sign extended
/// value used into memory accesses.
/// E.g.,
/// \code
/// a = add nsw i32 b, 3
/// d = sext i32 a to i64
/// e = getelementptr ..., i64 d
/// \endcode
/// =>
/// \code
/// f = sext i32 b to i64
/// a = add nsw i64 f, 3
/// e = getelementptr ..., i64 a
/// \endcode
///
/// \p Inst[in/out] the extension may be modified during the process if some
/// promotions apply.
bool CodeGenPrepare::optimizeExt(Instruction *&Inst) {
  bool AllowPromotionWithoutCommonHeader = false;
  /// See if it is an interesting sext operations for the address type
  /// promotion before trying to promote it, e.g., the ones with the right
  /// type and used in memory accesses.
  bool ATPConsiderable = TTI->shouldConsiderAddressTypePromotion(
      *Inst, AllowPromotionWithoutCommonHeader);
  TypePromotionTransaction TPT(RemovedInsts);
  TypePromotionTransaction::ConstRestorationPt LastKnownGood =
      TPT.getRestorationPoint();
  SmallVector<Instruction *, 1> Exts;
  SmallVector<Instruction *, 2> SpeculativelyMovedExts;
  Exts.push_back(Inst);

  bool HasPromoted = tryToPromoteExts(TPT, Exts, SpeculativelyMovedExts);

  // Look for a load being extended.
  LoadInst *LI = nullptr;
  Instruction *ExtFedByLoad;

  // Try to promote a chain of computation if it allows to form an extended
  // load.
  if (canFormExtLd(SpeculativelyMovedExts, LI, ExtFedByLoad, HasPromoted)) {
    assert(LI && ExtFedByLoad && "Expect a valid load and extension");
    TPT.commit();
    // Move the extend into the same block as the load.
    ExtFedByLoad->moveAfter(LI);
    ++NumExtsMoved;
    Inst = ExtFedByLoad;
    return true;
  }

  // Continue promoting SExts if known as considerable depending on targets.
  if (ATPConsiderable &&
      performAddressTypePromotion(Inst, AllowPromotionWithoutCommonHeader,
                                  HasPromoted, TPT, SpeculativelyMovedExts))
    return true;

  TPT.rollback(LastKnownGood);
  return false;
}

// Perform address type promotion if doing so is profitable.
// If AllowPromotionWithoutCommonHeader == false, we should find other sext
// instructions that sign extended the same initial value. However, if
// AllowPromotionWithoutCommonHeader == true, we expect promoting the
// extension is just profitable.
bool CodeGenPrepare::performAddressTypePromotion(
    Instruction *&Inst, bool AllowPromotionWithoutCommonHeader,
    bool HasPromoted, TypePromotionTransaction &TPT,
    SmallVectorImpl<Instruction *> &SpeculativelyMovedExts) {
  bool Promoted = false;
  SmallPtrSet<Instruction *, 1> UnhandledExts;
  bool AllSeenFirst = true;
  for (auto *I : SpeculativelyMovedExts) {
    Value *HeadOfChain = I->getOperand(0);
    DenseMap<Value *, Instruction *>::iterator AlreadySeen =
        SeenChainsForSExt.find(HeadOfChain);
    // If there is an unhandled SExt which has the same header, try to promote
    // it as well.
    if (AlreadySeen != SeenChainsForSExt.end()) {
      if (AlreadySeen->second != nullptr)
        UnhandledExts.insert(AlreadySeen->second);
      AllSeenFirst = false;
    }
  }

  if (!AllSeenFirst || (AllowPromotionWithoutCommonHeader &&
                        SpeculativelyMovedExts.size() == 1)) {
    TPT.commit();
    if (HasPromoted)
      Promoted = true;
    for (auto *I : SpeculativelyMovedExts) {
      Value *HeadOfChain = I->getOperand(0);
      SeenChainsForSExt[HeadOfChain] = nullptr;
      ValToSExtendedUses[HeadOfChain].push_back(I);
    }
    // Update Inst as promotion happen.
    Inst = SpeculativelyMovedExts.pop_back_val();
  } else {
    // This is the first chain visited from the header, keep the current chain
    // as unhandled. Defer to promote this until we encounter another SExt
    // chain derived from the same header.
    for (auto *I : SpeculativelyMovedExts) {
      Value *HeadOfChain = I->getOperand(0);
      SeenChainsForSExt[HeadOfChain] = Inst;
    }
    return false;
  }

  if (!AllSeenFirst && !UnhandledExts.empty())
    for (auto *VisitedSExt : UnhandledExts) {
      if (RemovedInsts.count(VisitedSExt))
        continue;
      TypePromotionTransaction TPT(RemovedInsts);
      SmallVector<Instruction *, 1> Exts;
      SmallVector<Instruction *, 2> Chains;
      Exts.push_back(VisitedSExt);
      bool HasPromoted = tryToPromoteExts(TPT, Exts, Chains);
      TPT.commit();
      if (HasPromoted)
        Promoted = true;
      for (auto *I : Chains) {
        Value *HeadOfChain = I->getOperand(0);
        // Mark this as handled.
        SeenChainsForSExt[HeadOfChain] = nullptr;
        ValToSExtendedUses[HeadOfChain].push_back(I);
      }
    }
  return Promoted;
}

bool CodeGenPrepare::optimizeExtUses(Instruction *I) {
  BasicBlock *DefBB = I->getParent();

  // If the result of a {s|z}ext and its source are both live out, rewrite all
  // other uses of the source with result of extension.
  Value *Src = I->getOperand(0);
  if (Src->hasOneUse())
    return false;

  // Only do this xform if truncating is free.
  if (!TLI->isTruncateFree(I->getType(), Src->getType()))
    return false;

  // Only safe to perform the optimization if the source is also defined in
  // this block.
  if (!isa<Instruction>(Src) || DefBB != cast<Instruction>(Src)->getParent())
    return false;

  bool DefIsLiveOut = false;
  for (User *U : I->users()) {
    Instruction *UI = cast<Instruction>(U);

    // Figure out which BB this ext is used in.
    BasicBlock *UserBB = UI->getParent();
    if (UserBB == DefBB)
      continue;
    DefIsLiveOut = true;
    break;
  }
  if (!DefIsLiveOut)
    return false;

  // Make sure none of the uses are PHI nodes.
  for (User *U : Src->users()) {
    Instruction *UI = cast<Instruction>(U);
    BasicBlock *UserBB = UI->getParent();
    if (UserBB == DefBB)
      continue;
    // Be conservative. We don't want this xform to end up introducing
    // reloads just before load / store instructions.
    if (isa<PHINode>(UI) || isa<LoadInst>(UI) || isa<StoreInst>(UI))
      return false;
  }

  // InsertedTruncs - Only insert one trunc in each block once.
  DenseMap<BasicBlock *, Instruction *> InsertedTruncs;

  bool MadeChange = false;
  for (Use &U : Src->uses()) {
    Instruction *User = cast<Instruction>(U.getUser());

    // Figure out which BB this ext is used in.
    BasicBlock *UserBB = User->getParent();
    if (UserBB == DefBB)
      continue;

    // Both src and def are live in this block. Rewrite the use.
    Instruction *&InsertedTrunc = InsertedTruncs[UserBB];

    if (!InsertedTrunc) {
      BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
      assert(InsertPt != UserBB->end());
      InsertedTrunc = new TruncInst(I, Src->getType(), "", &*InsertPt);
      InsertedInsts.insert(InsertedTrunc);
    }

    // Replace a use of the {s|z}ext source with a use of the result.
    U = InsertedTrunc;
    ++NumExtUses;
    MadeChange = true;
  }

  return MadeChange;
}

// Find loads whose uses only use some of the loaded value's bits.  Add an "and"
// just after the load if the target can fold this into one extload instruction,
// with the hope of eliminating some of the other later "and" instructions using
// the loaded value.  "and"s that are made trivially redundant by the insertion
// of the new "and" are removed by this function, while others (e.g. those whose
// path from the load goes through a phi) are left for isel to potentially
// remove.
//
// For example:
//
// b0:
//   x = load i32
//   ...
// b1:
//   y = and x, 0xff
//   z = use y
//
// becomes:
//
// b0:
//   x = load i32
//   x' = and x, 0xff
//   ...
// b1:
//   z = use x'
//
// whereas:
//
// b0:
//   x1 = load i32
//   ...
// b1:
//   x2 = load i32
//   ...
// b2:
//   x = phi x1, x2
//   y = and x, 0xff
//
// becomes (after a call to optimizeLoadExt for each load):
//
// b0:
//   x1 = load i32
//   x1' = and x1, 0xff
//   ...
// b1:
//   x2 = load i32
//   x2' = and x2, 0xff
//   ...
// b2:
//   x = phi x1', x2'
//   y = and x, 0xff
bool CodeGenPrepare::optimizeLoadExt(LoadInst *Load) {
  if (!Load->isSimple() || !Load->getType()->isIntOrPtrTy())
    return false;

  // Skip loads we've already transformed.
  if (Load->hasOneUse() &&
      InsertedInsts.count(cast<Instruction>(*Load->user_begin())))
    return false;

  // Look at all uses of Load, looking through phis, to determine how many bits
  // of the loaded value are needed.
  SmallVector<Instruction *, 8> WorkList;
  SmallPtrSet<Instruction *, 16> Visited;
  SmallVector<Instruction *, 8> AndsToMaybeRemove;
  for (auto *U : Load->users())
    WorkList.push_back(cast<Instruction>(U));

  EVT LoadResultVT = TLI->getValueType(*DL, Load->getType());
  unsigned BitWidth = LoadResultVT.getSizeInBits();
  // If the BitWidth is 0, do not try to optimize the type
  if (BitWidth == 0)
    return false;

  APInt DemandBits(BitWidth, 0);
  APInt WidestAndBits(BitWidth, 0);

  while (!WorkList.empty()) {
    Instruction *I = WorkList.pop_back_val();

    // Break use-def graph loops.
    if (!Visited.insert(I).second)
      continue;

    // For a PHI node, push all of its users.
    if (auto *Phi = dyn_cast<PHINode>(I)) {
      for (auto *U : Phi->users())
        WorkList.push_back(cast<Instruction>(U));
      continue;
    }

    switch (I->getOpcode()) {
    case Instruction::And: {
      auto *AndC = dyn_cast<ConstantInt>(I->getOperand(1));
      if (!AndC)
        return false;
      APInt AndBits = AndC->getValue();
      DemandBits |= AndBits;
      // Keep track of the widest and mask we see.
      if (AndBits.ugt(WidestAndBits))
        WidestAndBits = AndBits;
      if (AndBits == WidestAndBits && I->getOperand(0) == Load)
        AndsToMaybeRemove.push_back(I);
      break;
    }

    case Instruction::Shl: {
      auto *ShlC = dyn_cast<ConstantInt>(I->getOperand(1));
      if (!ShlC)
        return false;
      uint64_t ShiftAmt = ShlC->getLimitedValue(BitWidth - 1);
      DemandBits.setLowBits(BitWidth - ShiftAmt);
      break;
    }

    case Instruction::Trunc: {
      EVT TruncVT = TLI->getValueType(*DL, I->getType());
      unsigned TruncBitWidth = TruncVT.getSizeInBits();
      DemandBits.setLowBits(TruncBitWidth);
      break;
    }

    default:
      return false;
    }
  }

  uint32_t ActiveBits = DemandBits.getActiveBits();
  // Avoid hoisting (and (load x) 1) since it is unlikely to be folded by the
  // target even if isLoadExtLegal says an i1 EXTLOAD is valid.  For example,
  // for the AArch64 target isLoadExtLegal(ZEXTLOAD, i32, i1) returns true, but
  // (and (load x) 1) is not matched as a single instruction, rather as a LDR
  // followed by an AND.
  // TODO: Look into removing this restriction by fixing backends to either
  // return false for isLoadExtLegal for i1 or have them select this pattern to
  // a single instruction.
  //
  // Also avoid hoisting if we didn't see any ands with the exact DemandBits
  // mask, since these are the only ands that will be removed by isel.
  if (ActiveBits <= 1 || !DemandBits.isMask(ActiveBits) ||
      WidestAndBits != DemandBits)
    return false;

  LLVMContext &Ctx = Load->getType()->getContext();
  Type *TruncTy = Type::getIntNTy(Ctx, ActiveBits);
  EVT TruncVT = TLI->getValueType(*DL, TruncTy);

  // Reject cases that won't be matched as extloads.
  if (!LoadResultVT.bitsGT(TruncVT) || !TruncVT.isRound() ||
      !TLI->isLoadExtLegal(ISD::ZEXTLOAD, LoadResultVT, TruncVT))
    return false;

  IRBuilder<> Builder(Load->getNextNode());
  auto *NewAnd = cast<Instruction>(
      Builder.CreateAnd(Load, ConstantInt::get(Ctx, DemandBits)));
  // Mark this instruction as "inserted by CGP", so that other
  // optimizations don't touch it.
  InsertedInsts.insert(NewAnd);

  // Replace all uses of load with new and (except for the use of load in the
  // new and itself).
  replaceAllUsesWith(Load, NewAnd, FreshBBs, IsHugeFunc);
  NewAnd->setOperand(0, Load);

  // Remove any and instructions that are now redundant.
  for (auto *And : AndsToMaybeRemove)
    // Check that the and mask is the same as the one we decided to put on the
    // new and.
    if (cast<ConstantInt>(And->getOperand(1))->getValue() == DemandBits) {
      replaceAllUsesWith(And, NewAnd, FreshBBs, IsHugeFunc);
      if (&*CurInstIterator == And)
        CurInstIterator = std::next(And->getIterator());
      And->eraseFromParent();
      ++NumAndUses;
    }

  ++NumAndsAdded;
  return true;
}

/// Check if V (an operand of a select instruction) is an expensive instruction
/// that is only used once.
static bool sinkSelectOperand(const TargetTransformInfo *TTI, Value *V) {
  auto *I = dyn_cast<Instruction>(V);
  // If it's safe to speculatively execute, then it should not have side
  // effects; therefore, it's safe to sink and possibly *not* execute.
  return I && I->hasOneUse() && isSafeToSpeculativelyExecute(I) &&
         TTI->isExpensiveToSpeculativelyExecute(I);
}

/// Returns true if a SelectInst should be turned into an explicit branch.
static bool isFormingBranchFromSelectProfitable(const TargetTransformInfo *TTI,
                                                const TargetLowering *TLI,
                                                SelectInst *SI) {
  // If even a predictable select is cheap, then a branch can't be cheaper.
  if (!TLI->isPredictableSelectExpensive())
    return false;

  // FIXME: This should use the same heuristics as IfConversion to determine
  // whether a select is better represented as a branch.

  // If metadata tells us that the select condition is obviously predictable,
  // then we want to replace the select with a branch.
  uint64_t TrueWeight, FalseWeight;
  if (extractBranchWeights(*SI, TrueWeight, FalseWeight)) {
    uint64_t Max = std::max(TrueWeight, FalseWeight);
    uint64_t Sum = TrueWeight + FalseWeight;
    if (Sum != 0) {
      auto Probability = BranchProbability::getBranchProbability(Max, Sum);
      if (Probability > TTI->getPredictableBranchThreshold())
        return true;
    }
  }

  CmpInst *Cmp = dyn_cast<CmpInst>(SI->getCondition());

  // If a branch is predictable, an out-of-order CPU can avoid blocking on its
  // comparison condition. If the compare has more than one use, there's
  // probably another cmov or setcc around, so it's not worth emitting a branch.
  if (!Cmp || !Cmp->hasOneUse())
    return false;

  // If either operand of the select is expensive and only needed on one side
  // of the select, we should form a branch.
  if (sinkSelectOperand(TTI, SI->getTrueValue()) ||
      sinkSelectOperand(TTI, SI->getFalseValue()))
    return true;

  return false;
}

/// If \p isTrue is true, return the true value of \p SI, otherwise return
/// false value of \p SI. If the true/false value of \p SI is defined by any
/// select instructions in \p Selects, look through the defining select
/// instruction until the true/false value is not defined in \p Selects.
static Value *
getTrueOrFalseValue(SelectInst *SI, bool isTrue,
                    const SmallPtrSet<const Instruction *, 2> &Selects) {
  Value *V = nullptr;

  for (SelectInst *DefSI = SI; DefSI != nullptr && Selects.count(DefSI);
       DefSI = dyn_cast<SelectInst>(V)) {
    assert(DefSI->getCondition() == SI->getCondition() &&
           "The condition of DefSI does not match with SI");
    V = (isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue());
  }

  assert(V && "Failed to get select true/false value");
  return V;
}

bool CodeGenPrepare::optimizeShiftInst(BinaryOperator *Shift) {
  assert(Shift->isShift() && "Expected a shift");

  // If this is (1) a vector shift, (2) shifts by scalars are cheaper than
  // general vector shifts, and (3) the shift amount is a select-of-splatted
  // values, hoist the shifts before the select:
  //   shift Op0, (select Cond, TVal, FVal) -->
  //   select Cond, (shift Op0, TVal), (shift Op0, FVal)
  //
  // This is inverting a generic IR transform when we know that the cost of a
  // general vector shift is more than the cost of 2 shift-by-scalars.
  // We can't do this effectively in SDAG because we may not be able to
  // determine if the select operands are splats from within a basic block.
  Type *Ty = Shift->getType();
  if (!Ty->isVectorTy() || !TLI->isVectorShiftByScalarCheap(Ty))
    return false;
  Value *Cond, *TVal, *FVal;
  if (!match(Shift->getOperand(1),
             m_OneUse(m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal)))))
    return false;
  if (!isSplatValue(TVal) || !isSplatValue(FVal))
    return false;

  IRBuilder<> Builder(Shift);
  BinaryOperator::BinaryOps Opcode = Shift->getOpcode();
  Value *NewTVal = Builder.CreateBinOp(Opcode, Shift->getOperand(0), TVal);
  Value *NewFVal = Builder.CreateBinOp(Opcode, Shift->getOperand(0), FVal);
  Value *NewSel = Builder.CreateSelect(Cond, NewTVal, NewFVal);
  replaceAllUsesWith(Shift, NewSel, FreshBBs, IsHugeFunc);
  Shift->eraseFromParent();
  return true;
}

bool CodeGenPrepare::optimizeFunnelShift(IntrinsicInst *Fsh) {
  Intrinsic::ID Opcode = Fsh->getIntrinsicID();
  assert((Opcode == Intrinsic::fshl || Opcode == Intrinsic::fshr) &&
         "Expected a funnel shift");

  // If this is (1) a vector funnel shift, (2) shifts by scalars are cheaper
  // than general vector shifts, and (3) the shift amount is select-of-splatted
  // values, hoist the funnel shifts before the select:
  //   fsh Op0, Op1, (select Cond, TVal, FVal) -->
  //   select Cond, (fsh Op0, Op1, TVal), (fsh Op0, Op1, FVal)
  //
  // This is inverting a generic IR transform when we know that the cost of a
  // general vector shift is more than the cost of 2 shift-by-scalars.
  // We can't do this effectively in SDAG because we may not be able to
  // determine if the select operands are splats from within a basic block.
  Type *Ty = Fsh->getType();
  if (!Ty->isVectorTy() || !TLI->isVectorShiftByScalarCheap(Ty))
    return false;
  Value *Cond, *TVal, *FVal;
  if (!match(Fsh->getOperand(2),
             m_OneUse(m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal)))))
    return false;
  if (!isSplatValue(TVal) || !isSplatValue(FVal))
    return false;

  IRBuilder<> Builder(Fsh);
  Value *X = Fsh->getOperand(0), *Y = Fsh->getOperand(1);
  Value *NewTVal = Builder.CreateIntrinsic(Opcode, Ty, {X, Y, TVal});
  Value *NewFVal = Builder.CreateIntrinsic(Opcode, Ty, {X, Y, FVal});
  Value *NewSel = Builder.CreateSelect(Cond, NewTVal, NewFVal);
  replaceAllUsesWith(Fsh, NewSel, FreshBBs, IsHugeFunc);
  Fsh->eraseFromParent();
  return true;
}

/// If we have a SelectInst that will likely profit from branch prediction,
/// turn it into a branch.
bool CodeGenPrepare::optimizeSelectInst(SelectInst *SI) {
  if (DisableSelectToBranch)
    return false;

  // If the SelectOptimize pass is enabled, selects have already been optimized.
  if (!getCGPassBuilderOption().DisableSelectOptimize)
    return false;

  // Find all consecutive select instructions that share the same condition.
  SmallVector<SelectInst *, 2> ASI;
  ASI.push_back(SI);
  for (BasicBlock::iterator It = ++BasicBlock::iterator(SI);
       It != SI->getParent()->end(); ++It) {
    SelectInst *I = dyn_cast<SelectInst>(&*It);
    if (I && SI->getCondition() == I->getCondition()) {
      ASI.push_back(I);
    } else {
      break;
    }
  }

  SelectInst *LastSI = ASI.back();
  // Increment the current iterator to skip all the rest of select instructions
  // because they will be either "not lowered" or "all lowered" to branch.
  CurInstIterator = std::next(LastSI->getIterator());

  bool VectorCond = !SI->getCondition()->getType()->isIntegerTy(1);

  // Can we convert the 'select' to CF ?
  if (VectorCond || SI->getMetadata(LLVMContext::MD_unpredictable))
    return false;

  TargetLowering::SelectSupportKind SelectKind;
  if (SI->getType()->isVectorTy())
    SelectKind = TargetLowering::ScalarCondVectorVal;
  else
    SelectKind = TargetLowering::ScalarValSelect;

  if (TLI->isSelectSupported(SelectKind) &&
      (!isFormingBranchFromSelectProfitable(TTI, TLI, SI) || OptSize ||
       llvm::shouldOptimizeForSize(SI->getParent(), PSI, BFI.get())))
    return false;

  // The DominatorTree needs to be rebuilt by any consumers after this
  // transformation. We simply reset here rather than setting the ModifiedDT
  // flag to avoid restarting the function walk in runOnFunction for each
  // select optimized.
  DT.reset();

  // Transform a sequence like this:
  //    start:
  //       %cmp = cmp uge i32 %a, %b
  //       %sel = select i1 %cmp, i32 %c, i32 %d
  //
  // Into:
  //    start:
  //       %cmp = cmp uge i32 %a, %b
  //       %cmp.frozen = freeze %cmp
  //       br i1 %cmp.frozen, label %select.true, label %select.false
  //    select.true:
  //       br label %select.end
  //    select.false:
  //       br label %select.end
  //    select.end:
  //       %sel = phi i32 [ %c, %select.true ], [ %d, %select.false ]
  //
  // %cmp should be frozen, otherwise it may introduce undefined behavior.
  // In addition, we may sink instructions that produce %c or %d from
  // the entry block into the destination(s) of the new branch.
  // If the true or false blocks do not contain a sunken instruction, that
  // block and its branch may be optimized away. In that case, one side of the
  // first branch will point directly to select.end, and the corresponding PHI
  // predecessor block will be the start block.

  // First, we split the block containing the select into 2 blocks.
  BasicBlock *StartBlock = SI->getParent();
  BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(LastSI));
  BasicBlock *EndBlock = StartBlock->splitBasicBlock(SplitPt, "select.end");
  if (IsHugeFunc)
    FreshBBs.insert(EndBlock);
  Loop *L = LI->getLoopFor(StartBlock);
  if (L)
    L->addBasicBlockToLoop(EndBlock, *LI);
  BFI->setBlockFreq(EndBlock, BFI->getBlockFreq(StartBlock).getFrequency());
  // Delete the unconditional branch that was just created by the split.
  StartBlock->getTerminator()->eraseFromParent();

  // These are the new basic blocks for the conditional branch.
  // At least one will become an actual new basic block.
  BasicBlock *TrueBlock = nullptr;
  BasicBlock *FalseBlock = nullptr;
  BranchInst *TrueBranch = nullptr;
  BranchInst *FalseBranch = nullptr;

  // Sink expensive instructions into the conditional blocks to avoid executing
  // them speculatively.
  for (SelectInst *SI : ASI) {
    if (sinkSelectOperand(TTI, SI->getTrueValue())) {
      if (TrueBlock == nullptr) {
        TrueBlock = BasicBlock::Create(SI->getContext(), "select.true.sink",
                                       EndBlock->getParent(), EndBlock);
        TrueBranch = BranchInst::Create(EndBlock, TrueBlock);
        if (IsHugeFunc)
          FreshBBs.insert(TrueBlock);
        if (L)
          L->addBasicBlockToLoop(TrueBlock, *LI);
        TrueBranch->setDebugLoc(SI->getDebugLoc());
      }
      auto *TrueInst = cast<Instruction>(SI->getTrueValue());
      TrueInst->moveBefore(TrueBranch);
    }
    if (sinkSelectOperand(TTI, SI->getFalseValue())) {
      if (FalseBlock == nullptr) {
        FalseBlock = BasicBlock::Create(SI->getContext(), "select.false.sink",
                                        EndBlock->getParent(), EndBlock);
        if (IsHugeFunc)
          FreshBBs.insert(FalseBlock);
        if (L)
          L->addBasicBlockToLoop(FalseBlock, *LI);
        FalseBranch = BranchInst::Create(EndBlock, FalseBlock);
        FalseBranch->setDebugLoc(SI->getDebugLoc());
      }
      auto *FalseInst = cast<Instruction>(SI->getFalseValue());
      FalseInst->moveBefore(FalseBranch);
    }
  }

  // If there was nothing to sink, then arbitrarily choose the 'false' side
  // for a new input value to the PHI.
  if (TrueBlock == FalseBlock) {
    assert(TrueBlock == nullptr &&
           "Unexpected basic block transform while optimizing select");

    FalseBlock = BasicBlock::Create(SI->getContext(), "select.false",
                                    EndBlock->getParent(), EndBlock);
    if (IsHugeFunc)
      FreshBBs.insert(FalseBlock);
    if (L)
      L->addBasicBlockToLoop(FalseBlock, *LI);
    auto *FalseBranch = BranchInst::Create(EndBlock, FalseBlock);
    FalseBranch->setDebugLoc(SI->getDebugLoc());
  }

  // Insert the real conditional branch based on the original condition.
  // If we did not create a new block for one of the 'true' or 'false' paths
  // of the condition, it means that side of the branch goes to the end block
  // directly and the path originates from the start block from the point of
  // view of the new PHI.
  BasicBlock *TT, *FT;
  if (TrueBlock == nullptr) {
    TT = EndBlock;
    FT = FalseBlock;
    TrueBlock = StartBlock;
  } else if (FalseBlock == nullptr) {
    TT = TrueBlock;
    FT = EndBlock;
    FalseBlock = StartBlock;
  } else {
    TT = TrueBlock;
    FT = FalseBlock;
  }
  IRBuilder<> IB(SI);
  auto *CondFr = IB.CreateFreeze(SI->getCondition(), SI->getName() + ".frozen");
  IB.CreateCondBr(CondFr, TT, FT, SI);

  SmallPtrSet<const Instruction *, 2> INS;
  INS.insert(ASI.begin(), ASI.end());
  // Use reverse iterator because later select may use the value of the
  // earlier select, and we need to propagate value through earlier select
  // to get the PHI operand.
  for (SelectInst *SI : llvm::reverse(ASI)) {
    // The select itself is replaced with a PHI Node.
    PHINode *PN = PHINode::Create(SI->getType(), 2, "", &EndBlock->front());
    PN->takeName(SI);
    PN->addIncoming(getTrueOrFalseValue(SI, true, INS), TrueBlock);
    PN->addIncoming(getTrueOrFalseValue(SI, false, INS), FalseBlock);
    PN->setDebugLoc(SI->getDebugLoc());

    replaceAllUsesWith(SI, PN, FreshBBs, IsHugeFunc);
    SI->eraseFromParent();
    INS.erase(SI);
    ++NumSelectsExpanded;
  }

  // Instruct OptimizeBlock to skip to the next block.
  CurInstIterator = StartBlock->end();
  return true;
}

/// Some targets only accept certain types for splat inputs. For example a VDUP
/// in MVE takes a GPR (integer) register, and the instruction that incorporate
/// a VDUP (such as a VADD qd, qm, rm) also require a gpr register.
bool CodeGenPrepare::optimizeShuffleVectorInst(ShuffleVectorInst *SVI) {
  // Accept shuf(insertelem(undef/poison, val, 0), undef/poison, <0,0,..>) only
  if (!match(SVI, m_Shuffle(m_InsertElt(m_Undef(), m_Value(), m_ZeroInt()),
                            m_Undef(), m_ZeroMask())))
    return false;
  Type *NewType = TLI->shouldConvertSplatType(SVI);
  if (!NewType)
    return false;

  auto *SVIVecType = cast<FixedVectorType>(SVI->getType());
  assert(!NewType->isVectorTy() && "Expected a scalar type!");
  assert(NewType->getScalarSizeInBits() == SVIVecType->getScalarSizeInBits() &&
         "Expected a type of the same size!");
  auto *NewVecType =
      FixedVectorType::get(NewType, SVIVecType->getNumElements());

  // Create a bitcast (shuffle (insert (bitcast(..))))
  IRBuilder<> Builder(SVI->getContext());
  Builder.SetInsertPoint(SVI);
  Value *BC1 = Builder.CreateBitCast(
      cast<Instruction>(SVI->getOperand(0))->getOperand(1), NewType);
  Value *Shuffle = Builder.CreateVectorSplat(NewVecType->getNumElements(), BC1);
  Value *BC2 = Builder.CreateBitCast(Shuffle, SVIVecType);

  replaceAllUsesWith(SVI, BC2, FreshBBs, IsHugeFunc);
  RecursivelyDeleteTriviallyDeadInstructions(
      SVI, TLInfo, nullptr,
      [&](Value *V) { removeAllAssertingVHReferences(V); });

  // Also hoist the bitcast up to its operand if it they are not in the same
  // block.
  if (auto *BCI = dyn_cast<Instruction>(BC1))
    if (auto *Op = dyn_cast<Instruction>(BCI->getOperand(0)))
      if (BCI->getParent() != Op->getParent() && !isa<PHINode>(Op) &&
          !Op->isTerminator() && !Op->isEHPad())
        BCI->moveAfter(Op);

  return true;
}

bool CodeGenPrepare::tryToSinkFreeOperands(Instruction *I) {
  // If the operands of I can be folded into a target instruction together with
  // I, duplicate and sink them.
  SmallVector<Use *, 4> OpsToSink;
  if (!TLI->shouldSinkOperands(I, OpsToSink))
    return false;

  // OpsToSink can contain multiple uses in a use chain (e.g.
  // (%u1 with %u1 = shufflevector), (%u2 with %u2 = zext %u1)). The dominating
  // uses must come first, so we process the ops in reverse order so as to not
  // create invalid IR.
  BasicBlock *TargetBB = I->getParent();
  bool Changed = false;
  SmallVector<Use *, 4> ToReplace;
  Instruction *InsertPoint = I;
  DenseMap<const Instruction *, unsigned long> InstOrdering;
  unsigned long InstNumber = 0;
  for (const auto &I : *TargetBB)
    InstOrdering[&I] = InstNumber++;

  for (Use *U : reverse(OpsToSink)) {
    auto *UI = cast<Instruction>(U->get());
    if (isa<PHINode>(UI))
      continue;
    if (UI->getParent() == TargetBB) {
      if (InstOrdering[UI] < InstOrdering[InsertPoint])
        InsertPoint = UI;
      continue;
    }
    ToReplace.push_back(U);
  }

  SetVector<Instruction *> MaybeDead;
  DenseMap<Instruction *, Instruction *> NewInstructions;
  for (Use *U : ToReplace) {
    auto *UI = cast<Instruction>(U->get());
    Instruction *NI = UI->clone();

    if (IsHugeFunc) {
      // Now we clone an instruction, its operands' defs may sink to this BB
      // now. So we put the operands defs' BBs into FreshBBs to do optimization.
      for (unsigned I = 0; I < NI->getNumOperands(); ++I) {
        auto *OpDef = dyn_cast<Instruction>(NI->getOperand(I));
        if (!OpDef)
          continue;
        FreshBBs.insert(OpDef->getParent());
      }
    }

    NewInstructions[UI] = NI;
    MaybeDead.insert(UI);
    LLVM_DEBUG(dbgs() << "Sinking " << *UI << " to user " << *I << "\n");
    NI->insertBefore(InsertPoint);
    InsertPoint = NI;
    InsertedInsts.insert(NI);

    // Update the use for the new instruction, making sure that we update the
    // sunk instruction uses, if it is part of a chain that has already been
    // sunk.
    Instruction *OldI = cast<Instruction>(U->getUser());
    if (NewInstructions.count(OldI))
      NewInstructions[OldI]->setOperand(U->getOperandNo(), NI);
    else
      U->set(NI);
    Changed = true;
  }

  // Remove instructions that are dead after sinking.
  for (auto *I : MaybeDead) {
    if (!I->hasNUsesOrMore(1)) {
      LLVM_DEBUG(dbgs() << "Removing dead instruction: " << *I << "\n");
      I->eraseFromParent();
    }
  }

  return Changed;
}

bool CodeGenPrepare::optimizeSwitchType(SwitchInst *SI) {
  Value *Cond = SI->getCondition();
  Type *OldType = Cond->getType();
  LLVMContext &Context = Cond->getContext();
  EVT OldVT = TLI->getValueType(*DL, OldType);
  MVT RegType = TLI->getPreferredSwitchConditionType(Context, OldVT);
  unsigned RegWidth = RegType.getSizeInBits();

  if (RegWidth <= cast<IntegerType>(OldType)->getBitWidth())
    return false;

  // If the register width is greater than the type width, expand the condition
  // of the switch instruction and each case constant to the width of the
  // register. By widening the type of the switch condition, subsequent
  // comparisons (for case comparisons) will not need to be extended to the
  // preferred register width, so we will potentially eliminate N-1 extends,
  // where N is the number of cases in the switch.
  auto *NewType = Type::getIntNTy(Context, RegWidth);

  // Extend the switch condition and case constants using the target preferred
  // extend unless the switch condition is a function argument with an extend
  // attribute. In that case, we can avoid an unnecessary mask/extension by
  // matching the argument extension instead.
  Instruction::CastOps ExtType = Instruction::ZExt;
  // Some targets prefer SExt over ZExt.
  if (TLI->isSExtCheaperThanZExt(OldVT, RegType))
    ExtType = Instruction::SExt;

  if (auto *Arg = dyn_cast<Argument>(Cond)) {
    if (Arg->hasSExtAttr())
      ExtType = Instruction::SExt;
    if (Arg->hasZExtAttr())
      ExtType = Instruction::ZExt;
  }

  auto *ExtInst = CastInst::Create(ExtType, Cond, NewType);
  ExtInst->insertBefore(SI);
  ExtInst->setDebugLoc(SI->getDebugLoc());
  SI->setCondition(ExtInst);
  for (auto Case : SI->cases()) {
    const APInt &NarrowConst = Case.getCaseValue()->getValue();
    APInt WideConst = (ExtType == Instruction::ZExt)
                          ? NarrowConst.zext(RegWidth)
                          : NarrowConst.sext(RegWidth);
    Case.setValue(ConstantInt::get(Context, WideConst));
  }

  return true;
}

bool CodeGenPrepare::optimizeSwitchPhiConstants(SwitchInst *SI) {
  // The SCCP optimization tends to produce code like this:
  //   switch(x) { case 42: phi(42, ...) }
  // Materializing the constant for the phi-argument needs instructions; So we
  // change the code to:
  //   switch(x) { case 42: phi(x, ...) }

  Value *Condition = SI->getCondition();
  // Avoid endless loop in degenerate case.
  if (isa<ConstantInt>(*Condition))
    return false;

  bool Changed = false;
  BasicBlock *SwitchBB = SI->getParent();
  Type *ConditionType = Condition->getType();

  for (const SwitchInst::CaseHandle &Case : SI->cases()) {
    ConstantInt *CaseValue = Case.getCaseValue();
    BasicBlock *CaseBB = Case.getCaseSuccessor();
    // Set to true if we previously checked that `CaseBB` is only reached by
    // a single case from this switch.
    bool CheckedForSinglePred = false;
    for (PHINode &PHI : CaseBB->phis()) {
      Type *PHIType = PHI.getType();
      // If ZExt is free then we can also catch patterns like this:
      //   switch((i32)x) { case 42: phi((i64)42, ...); }
      // and replace `(i64)42` with `zext i32 %x to i64`.
      bool TryZExt =
          PHIType->isIntegerTy() &&
          PHIType->getIntegerBitWidth() > ConditionType->getIntegerBitWidth() &&
          TLI->isZExtFree(ConditionType, PHIType);
      if (PHIType == ConditionType || TryZExt) {
        // Set to true to skip this case because of multiple preds.
        bool SkipCase = false;
        Value *Replacement = nullptr;
        for (unsigned I = 0, E = PHI.getNumIncomingValues(); I != E; I++) {
          Value *PHIValue = PHI.getIncomingValue(I);
          if (PHIValue != CaseValue) {
            if (!TryZExt)
              continue;
            ConstantInt *PHIValueInt = dyn_cast<ConstantInt>(PHIValue);
            if (!PHIValueInt ||
                PHIValueInt->getValue() !=
                    CaseValue->getValue().zext(PHIType->getIntegerBitWidth()))
              continue;
          }
          if (PHI.getIncomingBlock(I) != SwitchBB)
            continue;
          // We cannot optimize if there are multiple case labels jumping to
          // this block.  This check may get expensive when there are many
          // case labels so we test for it last.
          if (!CheckedForSinglePred) {
            CheckedForSinglePred = true;
            if (SI->findCaseDest(CaseBB) == nullptr) {
              SkipCase = true;
              break;
            }
          }

          if (Replacement == nullptr) {
            if (PHIValue == CaseValue) {
              Replacement = Condition;
            } else {
              IRBuilder<> Builder(SI);
              Replacement = Builder.CreateZExt(Condition, PHIType);
            }
          }
          PHI.setIncomingValue(I, Replacement);
          Changed = true;
        }
        if (SkipCase)
          break;
      }
    }
  }
  return Changed;
}

bool CodeGenPrepare::optimizeSwitchInst(SwitchInst *SI) {
  bool Changed = optimizeSwitchType(SI);
  Changed |= optimizeSwitchPhiConstants(SI);
  return Changed;
}

namespace {

/// Helper class to promote a scalar operation to a vector one.
/// This class is used to move downward extractelement transition.
/// E.g.,
/// a = vector_op <2 x i32>
/// b = extractelement <2 x i32> a, i32 0
/// c = scalar_op b
/// store c
///
/// =>
/// a = vector_op <2 x i32>
/// c = vector_op a (equivalent to scalar_op on the related lane)
/// * d = extractelement <2 x i32> c, i32 0
/// * store d
/// Assuming both extractelement and store can be combine, we get rid of the
/// transition.
class VectorPromoteHelper {
  /// DataLayout associated with the current module.
  const DataLayout &DL;

  /// Used to perform some checks on the legality of vector operations.
  const TargetLowering &TLI;

  /// Used to estimated the cost of the promoted chain.
  const TargetTransformInfo &TTI;

  /// The transition being moved downwards.
  Instruction *Transition;

  /// The sequence of instructions to be promoted.
  SmallVector<Instruction *, 4> InstsToBePromoted;

  /// Cost of combining a store and an extract.
  unsigned StoreExtractCombineCost;

  /// Instruction that will be combined with the transition.
  Instruction *CombineInst = nullptr;

  /// The instruction that represents the current end of the transition.
  /// Since we are faking the promotion until we reach the end of the chain
  /// of computation, we need a way to get the current end of the transition.
  Instruction *getEndOfTransition() const {
    if (InstsToBePromoted.empty())
      return Transition;
    return InstsToBePromoted.back();
  }

  /// Return the index of the original value in the transition.
  /// E.g., for "extractelement <2 x i32> c, i32 1" the original value,
  /// c, is at index 0.
  unsigned getTransitionOriginalValueIdx() const {
    assert(isa<ExtractElementInst>(Transition) &&
           "Other kind of transitions are not supported yet");
    return 0;
  }

  /// Return the index of the index in the transition.
  /// E.g., for "extractelement <2 x i32> c, i32 0" the index
  /// is at index 1.
  unsigned getTransitionIdx() const {
    assert(isa<ExtractElementInst>(Transition) &&
           "Other kind of transitions are not supported yet");
    return 1;
  }

  /// Get the type of the transition.
  /// This is the type of the original value.
  /// E.g., for "extractelement <2 x i32> c, i32 1" the type of the
  /// transition is <2 x i32>.
  Type *getTransitionType() const {
    return Transition->getOperand(getTransitionOriginalValueIdx())->getType();
  }

  /// Promote \p ToBePromoted by moving \p Def downward through.
  /// I.e., we have the following sequence:
  /// Def = Transition <ty1> a to <ty2>
  /// b = ToBePromoted <ty2> Def, ...
  /// =>
  /// b = ToBePromoted <ty1> a, ...
  /// Def = Transition <ty1> ToBePromoted to <ty2>
  void promoteImpl(Instruction *ToBePromoted);

  /// Check whether or not it is profitable to promote all the
  /// instructions enqueued to be promoted.
  bool isProfitableToPromote() {
    Value *ValIdx = Transition->getOperand(getTransitionOriginalValueIdx());
    unsigned Index = isa<ConstantInt>(ValIdx)
                         ? cast<ConstantInt>(ValIdx)->getZExtValue()
                         : -1;
    Type *PromotedType = getTransitionType();

    StoreInst *ST = cast<StoreInst>(CombineInst);
    unsigned AS = ST->getPointerAddressSpace();
    // Check if this store is supported.
    if (!TLI.allowsMisalignedMemoryAccesses(
            TLI.getValueType(DL, ST->getValueOperand()->getType()), AS,
            ST->getAlign())) {
      // If this is not supported, there is no way we can combine
      // the extract with the store.
      return false;
    }

    // The scalar chain of computation has to pay for the transition
    // scalar to vector.
    // The vector chain has to account for the combining cost.
    enum TargetTransformInfo::TargetCostKind CostKind =
        TargetTransformInfo::TCK_RecipThroughput;
    InstructionCost ScalarCost =
        TTI.getVectorInstrCost(*Transition, PromotedType, CostKind, Index);
    InstructionCost VectorCost = StoreExtractCombineCost;
    for (const auto &Inst : InstsToBePromoted) {
      // Compute the cost.
      // By construction, all instructions being promoted are arithmetic ones.
      // Moreover, one argument is a constant that can be viewed as a splat
      // constant.
      Value *Arg0 = Inst->getOperand(0);
      bool IsArg0Constant = isa<UndefValue>(Arg0) || isa<ConstantInt>(Arg0) ||
                            isa<ConstantFP>(Arg0);
      TargetTransformInfo::OperandValueInfo Arg0Info, Arg1Info;
      if (IsArg0Constant)
        Arg0Info.Kind = TargetTransformInfo::OK_UniformConstantValue;
      else
        Arg1Info.Kind = TargetTransformInfo::OK_UniformConstantValue;

      ScalarCost += TTI.getArithmeticInstrCost(
          Inst->getOpcode(), Inst->getType(), CostKind, Arg0Info, Arg1Info);
      VectorCost += TTI.getArithmeticInstrCost(Inst->getOpcode(), PromotedType,
                                               CostKind, Arg0Info, Arg1Info);
    }
    LLVM_DEBUG(
        dbgs() << "Estimated cost of computation to be promoted:\nScalar: "
               << ScalarCost << "\nVector: " << VectorCost << '\n');
    return ScalarCost > VectorCost;
  }

  /// Generate a constant vector with \p Val with the same
  /// number of elements as the transition.
  /// \p UseSplat defines whether or not \p Val should be replicated
  /// across the whole vector.
  /// In other words, if UseSplat == true, we generate <Val, Val, ..., Val>,
  /// otherwise we generate a vector with as many undef as possible:
  /// <undef, ..., undef, Val, undef, ..., undef> where \p Val is only
  /// used at the index of the extract.
  Value *getConstantVector(Constant *Val, bool UseSplat) const {
    unsigned ExtractIdx = std::numeric_limits<unsigned>::max();
    if (!UseSplat) {
      // If we cannot determine where the constant must be, we have to
      // use a splat constant.
      Value *ValExtractIdx = Transition->getOperand(getTransitionIdx());
      if (ConstantInt *CstVal = dyn_cast<ConstantInt>(ValExtractIdx))
        ExtractIdx = CstVal->getSExtValue();
      else
        UseSplat = true;
    }

    ElementCount EC = cast<VectorType>(getTransitionType())->getElementCount();
    if (UseSplat)
      return ConstantVector::getSplat(EC, Val);

    if (!EC.isScalable()) {
      SmallVector<Constant *, 4> ConstVec;
      UndefValue *UndefVal = UndefValue::get(Val->getType());
      for (unsigned Idx = 0; Idx != EC.getKnownMinValue(); ++Idx) {
        if (Idx == ExtractIdx)
          ConstVec.push_back(Val);
        else
          ConstVec.push_back(UndefVal);
      }
      return ConstantVector::get(ConstVec);
    } else
      llvm_unreachable(
          "Generate scalable vector for non-splat is unimplemented");
  }

  /// Check if promoting to a vector type an operand at \p OperandIdx
  /// in \p Use can trigger undefined behavior.
  static bool canCauseUndefinedBehavior(const Instruction *Use,
                                        unsigned OperandIdx) {
    // This is not safe to introduce undef when the operand is on
    // the right hand side of a division-like instruction.
    if (OperandIdx != 1)
      return false;
    switch (Use->getOpcode()) {
    default:
      return false;
    case Instruction::SDiv:
    case Instruction::UDiv:
    case Instruction::SRem:
    case Instruction::URem:
      return true;
    case Instruction::FDiv:
    case Instruction::FRem:
      return !Use->hasNoNaNs();
    }
    llvm_unreachable(nullptr);
  }

public:
  VectorPromoteHelper(const DataLayout &DL, const TargetLowering &TLI,
                      const TargetTransformInfo &TTI, Instruction *Transition,
                      unsigned CombineCost)
      : DL(DL), TLI(TLI), TTI(TTI), Transition(Transition),
        StoreExtractCombineCost(CombineCost) {
    assert(Transition && "Do not know how to promote null");
  }

  /// Check if we can promote \p ToBePromoted to \p Type.
  bool canPromote(const Instruction *ToBePromoted) const {
    // We could support CastInst too.
    return isa<BinaryOperator>(ToBePromoted);
  }

  /// Check if it is profitable to promote \p ToBePromoted
  /// by moving downward the transition through.
  bool shouldPromote(const Instruction *ToBePromoted) const {
    // Promote only if all the operands can be statically expanded.
    // Indeed, we do not want to introduce any new kind of transitions.
    for (const Use &U : ToBePromoted->operands()) {
      const Value *Val = U.get();
      if (Val == getEndOfTransition()) {
        // If the use is a division and the transition is on the rhs,
        // we cannot promote the operation, otherwise we may create a
        // division by zero.
        if (canCauseUndefinedBehavior(ToBePromoted, U.getOperandNo()))
          return false;
        continue;
      }
      if (!isa<ConstantInt>(Val) && !isa<UndefValue>(Val) &&
          !isa<ConstantFP>(Val))
        return false;
    }
    // Check that the resulting operation is legal.
    int ISDOpcode = TLI.InstructionOpcodeToISD(ToBePromoted->getOpcode());
    if (!ISDOpcode)
      return false;
    return StressStoreExtract ||
           TLI.isOperationLegalOrCustom(
               ISDOpcode, TLI.getValueType(DL, getTransitionType(), true));
  }

  /// Check whether or not \p Use can be combined
  /// with the transition.
  /// I.e., is it possible to do Use(Transition) => AnotherUse?
  bool canCombine(const Instruction *Use) { return isa<StoreInst>(Use); }

  /// Record \p ToBePromoted as part of the chain to be promoted.
  void enqueueForPromotion(Instruction *ToBePromoted) {
    InstsToBePromoted.push_back(ToBePromoted);
  }

  /// Set the instruction that will be combined with the transition.
  void recordCombineInstruction(Instruction *ToBeCombined) {
    assert(canCombine(ToBeCombined) && "Unsupported instruction to combine");
    CombineInst = ToBeCombined;
  }

  /// Promote all the instructions enqueued for promotion if it is
  /// is profitable.
  /// \return True if the promotion happened, false otherwise.
  bool promote() {
    // Check if there is something to promote.
    // Right now, if we do not have anything to combine with,
    // we assume the promotion is not profitable.
    if (InstsToBePromoted.empty() || !CombineInst)
      return false;

    // Check cost.
    if (!StressStoreExtract && !isProfitableToPromote())
      return false;

    // Promote.
    for (auto &ToBePromoted : InstsToBePromoted)
      promoteImpl(ToBePromoted);
    InstsToBePromoted.clear();
    return true;
  }
};

} // end anonymous namespace

void VectorPromoteHelper::promoteImpl(Instruction *ToBePromoted) {
  // At this point, we know that all the operands of ToBePromoted but Def
  // can be statically promoted.
  // For Def, we need to use its parameter in ToBePromoted:
  // b = ToBePromoted ty1 a
  // Def = Transition ty1 b to ty2
  // Move the transition down.
  // 1. Replace all uses of the promoted operation by the transition.
  // = ... b => = ... Def.
  assert(ToBePromoted->getType() == Transition->getType() &&
         "The type of the result of the transition does not match "
         "the final type");
  ToBePromoted->replaceAllUsesWith(Transition);
  // 2. Update the type of the uses.
  // b = ToBePromoted ty2 Def => b = ToBePromoted ty1 Def.
  Type *TransitionTy = getTransitionType();
  ToBePromoted->mutateType(TransitionTy);
  // 3. Update all the operands of the promoted operation with promoted
  // operands.
  // b = ToBePromoted ty1 Def => b = ToBePromoted ty1 a.
  for (Use &U : ToBePromoted->operands()) {
    Value *Val = U.get();
    Value *NewVal = nullptr;
    if (Val == Transition)
      NewVal = Transition->getOperand(getTransitionOriginalValueIdx());
    else if (isa<UndefValue>(Val) || isa<ConstantInt>(Val) ||
             isa<ConstantFP>(Val)) {
      // Use a splat constant if it is not safe to use undef.
      NewVal = getConstantVector(
          cast<Constant>(Val),
          isa<UndefValue>(Val) ||
              canCauseUndefinedBehavior(ToBePromoted, U.getOperandNo()));
    } else
      llvm_unreachable("Did you modified shouldPromote and forgot to update "
                       "this?");
    ToBePromoted->setOperand(U.getOperandNo(), NewVal);
  }
  Transition->moveAfter(ToBePromoted);
  Transition->setOperand(getTransitionOriginalValueIdx(), ToBePromoted);
}

/// Some targets can do store(extractelement) with one instruction.
/// Try to push the extractelement towards the stores when the target
/// has this feature and this is profitable.
bool CodeGenPrepare::optimizeExtractElementInst(Instruction *Inst) {
  unsigned CombineCost = std::numeric_limits<unsigned>::max();
  if (DisableStoreExtract ||
      (!StressStoreExtract &&
       !TLI->canCombineStoreAndExtract(Inst->getOperand(0)->getType(),
                                       Inst->getOperand(1), CombineCost)))
    return false;

  // At this point we know that Inst is a vector to scalar transition.
  // Try to move it down the def-use chain, until:
  // - We can combine the transition with its single use
  //   => we got rid of the transition.
  // - We escape the current basic block
  //   => we would need to check that we are moving it at a cheaper place and
  //      we do not do that for now.
  BasicBlock *Parent = Inst->getParent();
  LLVM_DEBUG(dbgs() << "Found an interesting transition: " << *Inst << '\n');
  VectorPromoteHelper VPH(*DL, *TLI, *TTI, Inst, CombineCost);
  // If the transition has more than one use, assume this is not going to be
  // beneficial.
  while (Inst->hasOneUse()) {
    Instruction *ToBePromoted = cast<Instruction>(*Inst->user_begin());
    LLVM_DEBUG(dbgs() << "Use: " << *ToBePromoted << '\n');

    if (ToBePromoted->getParent() != Parent) {
      LLVM_DEBUG(dbgs() << "Instruction to promote is in a different block ("
                        << ToBePromoted->getParent()->getName()
                        << ") than the transition (" << Parent->getName()
                        << ").\n");
      return false;
    }

    if (VPH.canCombine(ToBePromoted)) {
      LLVM_DEBUG(dbgs() << "Assume " << *Inst << '\n'
                        << "will be combined with: " << *ToBePromoted << '\n');
      VPH.recordCombineInstruction(ToBePromoted);
      bool Changed = VPH.promote();
      NumStoreExtractExposed += Changed;
      return Changed;
    }

    LLVM_DEBUG(dbgs() << "Try promoting.\n");
    if (!VPH.canPromote(ToBePromoted) || !VPH.shouldPromote(ToBePromoted))
      return false;

    LLVM_DEBUG(dbgs() << "Promoting is possible... Enqueue for promotion!\n");

    VPH.enqueueForPromotion(ToBePromoted);
    Inst = ToBePromoted;
  }
  return false;
}

/// For the instruction sequence of store below, F and I values
/// are bundled together as an i64 value before being stored into memory.
/// Sometimes it is more efficient to generate separate stores for F and I,
/// which can remove the bitwise instructions or sink them to colder places.
///
///   (store (or (zext (bitcast F to i32) to i64),
///              (shl (zext I to i64), 32)), addr)  -->
///   (store F, addr) and (store I, addr+4)
///
/// Similarly, splitting for other merged store can also be beneficial, like:
/// For pair of {i32, i32}, i64 store --> two i32 stores.
/// For pair of {i32, i16}, i64 store --> two i32 stores.
/// For pair of {i16, i16}, i32 store --> two i16 stores.
/// For pair of {i16, i8},  i32 store --> two i16 stores.
/// For pair of {i8, i8},   i16 store --> two i8 stores.
///
/// We allow each target to determine specifically which kind of splitting is
/// supported.
///
/// The store patterns are commonly seen from the simple code snippet below
/// if only std::make_pair(...) is sroa transformed before inlined into hoo.
///   void goo(const std::pair<int, float> &);
///   hoo() {
///     ...
///     goo(std::make_pair(tmp, ftmp));
///     ...
///   }
///
/// Although we already have similar splitting in DAG Combine, we duplicate
/// it in CodeGenPrepare to catch the case in which pattern is across
/// multiple BBs. The logic in DAG Combine is kept to catch case generated
/// during code expansion.
static bool splitMergedValStore(StoreInst &SI, const DataLayout &DL,
                                const TargetLowering &TLI) {
  // Handle simple but common cases only.
  Type *StoreType = SI.getValueOperand()->getType();

  // The code below assumes shifting a value by <number of bits>,
  // whereas scalable vectors would have to be shifted by
  // <2log(vscale) + number of bits> in order to store the
  // low/high parts. Bailing out for now.
  if (StoreType->isScalableTy())
    return false;

  if (!DL.typeSizeEqualsStoreSize(StoreType) ||
      DL.getTypeSizeInBits(StoreType) == 0)
    return false;

  unsigned HalfValBitSize = DL.getTypeSizeInBits(StoreType) / 2;
  Type *SplitStoreType = Type::getIntNTy(SI.getContext(), HalfValBitSize);
  if (!DL.typeSizeEqualsStoreSize(SplitStoreType))
    return false;

  // Don't split the store if it is volatile.
  if (SI.isVolatile())
    return false;

  // Match the following patterns:
  // (store (or (zext LValue to i64),
  //            (shl (zext HValue to i64), 32)), HalfValBitSize)
  //  or
  // (store (or (shl (zext HValue to i64), 32)), HalfValBitSize)
  //            (zext LValue to i64),
  // Expect both operands of OR and the first operand of SHL have only
  // one use.
  Value *LValue, *HValue;
  if (!match(SI.getValueOperand(),
             m_c_Or(m_OneUse(m_ZExt(m_Value(LValue))),
                    m_OneUse(m_Shl(m_OneUse(m_ZExt(m_Value(HValue))),
                                   m_SpecificInt(HalfValBitSize))))))
    return false;

  // Check LValue and HValue are int with size less or equal than 32.
  if (!LValue->getType()->isIntegerTy() ||
      DL.getTypeSizeInBits(LValue->getType()) > HalfValBitSize ||
      !HValue->getType()->isIntegerTy() ||
      DL.getTypeSizeInBits(HValue->getType()) > HalfValBitSize)
    return false;

  // If LValue/HValue is a bitcast instruction, use the EVT before bitcast
  // as the input of target query.
  auto *LBC = dyn_cast<BitCastInst>(LValue);
  auto *HBC = dyn_cast<BitCastInst>(HValue);
  EVT LowTy = LBC ? EVT::getEVT(LBC->getOperand(0)->getType())
                  : EVT::getEVT(LValue->getType());
  EVT HighTy = HBC ? EVT::getEVT(HBC->getOperand(0)->getType())
                   : EVT::getEVT(HValue->getType());
  if (!ForceSplitStore && !TLI.isMultiStoresCheaperThanBitsMerge(LowTy, HighTy))
    return false;

  // Start to split store.
  IRBuilder<> Builder(SI.getContext());
  Builder.SetInsertPoint(&SI);

  // If LValue/HValue is a bitcast in another BB, create a new one in current
  // BB so it may be merged with the splitted stores by dag combiner.
  if (LBC && LBC->getParent() != SI.getParent())
    LValue = Builder.CreateBitCast(LBC->getOperand(0), LBC->getType());
  if (HBC && HBC->getParent() != SI.getParent())
    HValue = Builder.CreateBitCast(HBC->getOperand(0), HBC->getType());

  bool IsLE = SI.getModule()->getDataLayout().isLittleEndian();
  auto CreateSplitStore = [&](Value *V, bool Upper) {
    V = Builder.CreateZExtOrBitCast(V, SplitStoreType);
    Value *Addr = Builder.CreateBitCast(
        SI.getOperand(1),
        SplitStoreType->getPointerTo(SI.getPointerAddressSpace()));
    Align Alignment = SI.getAlign();
    const bool IsOffsetStore = (IsLE && Upper) || (!IsLE && !Upper);
    if (IsOffsetStore) {
      Addr = Builder.CreateGEP(
          SplitStoreType, Addr,
          ConstantInt::get(Type::getInt32Ty(SI.getContext()), 1));

      // When splitting the store in half, naturally one half will retain the
      // alignment of the original wider store, regardless of whether it was
      // over-aligned or not, while the other will require adjustment.
      Alignment = commonAlignment(Alignment, HalfValBitSize / 8);
    }
    Builder.CreateAlignedStore(V, Addr, Alignment);
  };

  CreateSplitStore(LValue, false);
  CreateSplitStore(HValue, true);

  // Delete the old store.
  SI.eraseFromParent();
  return true;
}

// Return true if the GEP has two operands, the first operand is of a sequential
// type, and the second operand is a constant.
static bool GEPSequentialConstIndexed(GetElementPtrInst *GEP) {
  gep_type_iterator I = gep_type_begin(*GEP);
  return GEP->getNumOperands() == 2 && I.isSequential() &&
         isa<ConstantInt>(GEP->getOperand(1));
}

// Try unmerging GEPs to reduce liveness interference (register pressure) across
// IndirectBr edges. Since IndirectBr edges tend to touch on many blocks,
// reducing liveness interference across those edges benefits global register
// allocation. Currently handles only certain cases.
//
// For example, unmerge %GEPI and %UGEPI as below.
//
// ---------- BEFORE ----------
// SrcBlock:
//   ...
//   %GEPIOp = ...
//   ...
//   %GEPI = gep %GEPIOp, Idx
//   ...
//   indirectbr ... [ label %DstB0, label %DstB1, ... label %DstBi ... ]
//   (* %GEPI is alive on the indirectbr edges due to other uses ahead)
//   (* %GEPIOp is alive on the indirectbr edges only because of it's used by
//   %UGEPI)
//
// DstB0: ... (there may be a gep similar to %UGEPI to be unmerged)
// DstB1: ... (there may be a gep similar to %UGEPI to be unmerged)
// ...
//
// DstBi:
//   ...
//   %UGEPI = gep %GEPIOp, UIdx
// ...
// ---------------------------
//
// ---------- AFTER ----------
// SrcBlock:
//   ... (same as above)
//    (* %GEPI is still alive on the indirectbr edges)
//    (* %GEPIOp is no longer alive on the indirectbr edges as a result of the
//    unmerging)
// ...
//
// DstBi:
//   ...
//   %UGEPI = gep %GEPI, (UIdx-Idx)
//   ...
// ---------------------------
//
// The register pressure on the IndirectBr edges is reduced because %GEPIOp is
// no longer alive on them.
//
// We try to unmerge GEPs here in CodGenPrepare, as opposed to limiting merging
// of GEPs in the first place in InstCombiner::visitGetElementPtrInst() so as
// not to disable further simplications and optimizations as a result of GEP
// merging.
//
// Note this unmerging may increase the length of the data flow critical path
// (the path from %GEPIOp to %UGEPI would go through %GEPI), which is a tradeoff
// between the register pressure and the length of data-flow critical
// path. Restricting this to the uncommon IndirectBr case would minimize the
// impact of potentially longer critical path, if any, and the impact on compile
// time.
static bool tryUnmergingGEPsAcrossIndirectBr(GetElementPtrInst *GEPI,
                                             const TargetTransformInfo *TTI) {
  BasicBlock *SrcBlock = GEPI->getParent();
  // Check that SrcBlock ends with an IndirectBr. If not, give up. The common
  // (non-IndirectBr) cases exit early here.
  if (!isa<IndirectBrInst>(SrcBlock->getTerminator()))
    return false;
  // Check that GEPI is a simple gep with a single constant index.
  if (!GEPSequentialConstIndexed(GEPI))
    return false;
  ConstantInt *GEPIIdx = cast<ConstantInt>(GEPI->getOperand(1));
  // Check that GEPI is a cheap one.
  if (TTI->getIntImmCost(GEPIIdx->getValue(), GEPIIdx->getType(),
                         TargetTransformInfo::TCK_SizeAndLatency) >
      TargetTransformInfo::TCC_Basic)
    return false;
  Value *GEPIOp = GEPI->getOperand(0);
  // Check that GEPIOp is an instruction that's also defined in SrcBlock.
  if (!isa<Instruction>(GEPIOp))
    return false;
  auto *GEPIOpI = cast<Instruction>(GEPIOp);
  if (GEPIOpI->getParent() != SrcBlock)
    return false;
  // Check that GEP is used outside the block, meaning it's alive on the
  // IndirectBr edge(s).
  if (llvm::none_of(GEPI->users(), [&](User *Usr) {
        if (auto *I = dyn_cast<Instruction>(Usr)) {
          if (I->getParent() != SrcBlock) {
            return true;
          }
        }
        return false;
      }))
    return false;
  // The second elements of the GEP chains to be unmerged.
  std::vector<GetElementPtrInst *> UGEPIs;
  // Check each user of GEPIOp to check if unmerging would make GEPIOp not alive
  // on IndirectBr edges.
  for (User *Usr : GEPIOp->users()) {
    if (Usr == GEPI)
      continue;
    // Check if Usr is an Instruction. If not, give up.
    if (!isa<Instruction>(Usr))
      return false;
    auto *UI = cast<Instruction>(Usr);
    // Check if Usr in the same block as GEPIOp, which is fine, skip.
    if (UI->getParent() == SrcBlock)
      continue;
    // Check if Usr is a GEP. If not, give up.
    if (!isa<GetElementPtrInst>(Usr))
      return false;
    auto *UGEPI = cast<GetElementPtrInst>(Usr);
    // Check if UGEPI is a simple gep with a single constant index and GEPIOp is
    // the pointer operand to it. If so, record it in the vector. If not, give
    // up.
    if (!GEPSequentialConstIndexed(UGEPI))
      return false;
    if (UGEPI->getOperand(0) != GEPIOp)
      return false;
    if (GEPIIdx->getType() !=
        cast<ConstantInt>(UGEPI->getOperand(1))->getType())
      return false;
    ConstantInt *UGEPIIdx = cast<ConstantInt>(UGEPI->getOperand(1));
    if (TTI->getIntImmCost(UGEPIIdx->getValue(), UGEPIIdx->getType(),
                           TargetTransformInfo::TCK_SizeAndLatency) >
        TargetTransformInfo::TCC_Basic)
      return false;
    UGEPIs.push_back(UGEPI);
  }
  if (UGEPIs.size() == 0)
    return false;
  // Check the materializing cost of (Uidx-Idx).
  for (GetElementPtrInst *UGEPI : UGEPIs) {
    ConstantInt *UGEPIIdx = cast<ConstantInt>(UGEPI->getOperand(1));
    APInt NewIdx = UGEPIIdx->getValue() - GEPIIdx->getValue();
    InstructionCost ImmCost = TTI->getIntImmCost(
        NewIdx, GEPIIdx->getType(), TargetTransformInfo::TCK_SizeAndLatency);
    if (ImmCost > TargetTransformInfo::TCC_Basic)
      return false;
  }
  // Now unmerge between GEPI and UGEPIs.
  for (GetElementPtrInst *UGEPI : UGEPIs) {
    UGEPI->setOperand(0, GEPI);
    ConstantInt *UGEPIIdx = cast<ConstantInt>(UGEPI->getOperand(1));
    Constant *NewUGEPIIdx = ConstantInt::get(
        GEPIIdx->getType(), UGEPIIdx->getValue() - GEPIIdx->getValue());
    UGEPI->setOperand(1, NewUGEPIIdx);
    // If GEPI is not inbounds but UGEPI is inbounds, change UGEPI to not
    // inbounds to avoid UB.
    if (!GEPI->isInBounds()) {
      UGEPI->setIsInBounds(false);
    }
  }
  // After unmerging, verify that GEPIOp is actually only used in SrcBlock (not
  // alive on IndirectBr edges).
  assert(llvm::none_of(GEPIOp->users(),
                       [&](User *Usr) {
                         return cast<Instruction>(Usr)->getParent() != SrcBlock;
                       }) &&
         "GEPIOp is used outside SrcBlock");
  return true;
}

static bool optimizeBranch(BranchInst *Branch, const TargetLowering &TLI,
                           SmallSet<BasicBlock *, 32> &FreshBBs,
                           bool IsHugeFunc) {
  // Try and convert
  //  %c = icmp ult %x, 8
  //  br %c, bla, blb
  //  %tc = lshr %x, 3
  // to
  //  %tc = lshr %x, 3
  //  %c = icmp eq %tc, 0
  //  br %c, bla, blb
  // Creating the cmp to zero can be better for the backend, especially if the
  // lshr produces flags that can be used automatically.
  if (!TLI.preferZeroCompareBranch() || !Branch->isConditional())
    return false;

  ICmpInst *Cmp = dyn_cast<ICmpInst>(Branch->getCondition());
  if (!Cmp || !isa<ConstantInt>(Cmp->getOperand(1)) || !Cmp->hasOneUse())
    return false;

  Value *X = Cmp->getOperand(0);
  APInt CmpC = cast<ConstantInt>(Cmp->getOperand(1))->getValue();

  for (auto *U : X->users()) {
    Instruction *UI = dyn_cast<Instruction>(U);
    // A quick dominance check
    if (!UI ||
        (UI->getParent() != Branch->getParent() &&
         UI->getParent() != Branch->getSuccessor(0) &&
         UI->getParent() != Branch->getSuccessor(1)) ||
        (UI->getParent() != Branch->getParent() &&
         !UI->getParent()->getSinglePredecessor()))
      continue;

    if (CmpC.isPowerOf2() && Cmp->getPredicate() == ICmpInst::ICMP_ULT &&
        match(UI, m_Shr(m_Specific(X), m_SpecificInt(CmpC.logBase2())))) {
      IRBuilder<> Builder(Branch);
      if (UI->getParent() != Branch->getParent())
        UI->moveBefore(Branch);
      Value *NewCmp = Builder.CreateCmp(ICmpInst::ICMP_EQ, UI,
                                        ConstantInt::get(UI->getType(), 0));
      LLVM_DEBUG(dbgs() << "Converting " << *Cmp << "\n");
      LLVM_DEBUG(dbgs() << " to compare on zero: " << *NewCmp << "\n");
      replaceAllUsesWith(Cmp, NewCmp, FreshBBs, IsHugeFunc);
      return true;
    }
    if (Cmp->isEquality() &&
        (match(UI, m_Add(m_Specific(X), m_SpecificInt(-CmpC))) ||
         match(UI, m_Sub(m_Specific(X), m_SpecificInt(CmpC))))) {
      IRBuilder<> Builder(Branch);
      if (UI->getParent() != Branch->getParent())
        UI->moveBefore(Branch);
      Value *NewCmp = Builder.CreateCmp(Cmp->getPredicate(), UI,
                                        ConstantInt::get(UI->getType(), 0));
      LLVM_DEBUG(dbgs() << "Converting " << *Cmp << "\n");
      LLVM_DEBUG(dbgs() << " to compare on zero: " << *NewCmp << "\n");
      replaceAllUsesWith(Cmp, NewCmp, FreshBBs, IsHugeFunc);
      return true;
    }
  }
  return false;
}

bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) {
  // Bail out if we inserted the instruction to prevent optimizations from
  // stepping on each other's toes.
  if (InsertedInsts.count(I))
    return false;

  // TODO: Move into the switch on opcode below here.
  if (PHINode *P = dyn_cast<PHINode>(I)) {
    // It is possible for very late stage optimizations (such as SimplifyCFG)
    // to introduce PHI nodes too late to be cleaned up.  If we detect such a
    // trivial PHI, go ahead and zap it here.
    if (Value *V = simplifyInstruction(P, {*DL, TLInfo})) {
      LargeOffsetGEPMap.erase(P);
      replaceAllUsesWith(P, V, FreshBBs, IsHugeFunc);
      P->eraseFromParent();
      ++NumPHIsElim;
      return true;
    }
    return false;
  }

  if (CastInst *CI = dyn_cast<CastInst>(I)) {
    // If the source of the cast is a constant, then this should have
    // already been constant folded.  The only reason NOT to constant fold
    // it is if something (e.g. LSR) was careful to place the constant
    // evaluation in a block other than then one that uses it (e.g. to hoist
    // the address of globals out of a loop).  If this is the case, we don't
    // want to forward-subst the cast.
    if (isa<Constant>(CI->getOperand(0)))
      return false;

    if (OptimizeNoopCopyExpression(CI, *TLI, *DL))
      return true;

    if ((isa<UIToFPInst>(I) || isa<FPToUIInst>(I) || isa<TruncInst>(I)) &&
        TLI->optimizeExtendOrTruncateConversion(
            I, LI->getLoopFor(I->getParent()), *TTI))
      return true;

    if (isa<ZExtInst>(I) || isa<SExtInst>(I)) {
      /// Sink a zext or sext into its user blocks if the target type doesn't
      /// fit in one register
      if (TLI->getTypeAction(CI->getContext(),
                             TLI->getValueType(*DL, CI->getType())) ==
          TargetLowering::TypeExpandInteger) {
        return SinkCast(CI);
      } else {
        if (TLI->optimizeExtendOrTruncateConversion(
                I, LI->getLoopFor(I->getParent()), *TTI))
          return true;

        bool MadeChange = optimizeExt(I);
        return MadeChange | optimizeExtUses(I);
      }
    }
    return false;
  }

  if (auto *Cmp = dyn_cast<CmpInst>(I))
    if (optimizeCmp(Cmp, ModifiedDT))
      return true;

  if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
    LI->setMetadata(LLVMContext::MD_invariant_group, nullptr);
    bool Modified = optimizeLoadExt(LI);
    unsigned AS = LI->getPointerAddressSpace();
    Modified |= optimizeMemoryInst(I, I->getOperand(0), LI->getType(), AS);
    return Modified;
  }

  if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
    if (splitMergedValStore(*SI, *DL, *TLI))
      return true;
    SI->setMetadata(LLVMContext::MD_invariant_group, nullptr);
    unsigned AS = SI->getPointerAddressSpace();
    return optimizeMemoryInst(I, SI->getOperand(1),
                              SI->getOperand(0)->getType(), AS);
  }

  if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
    unsigned AS = RMW->getPointerAddressSpace();
    return optimizeMemoryInst(I, RMW->getPointerOperand(), RMW->getType(), AS);
  }

  if (AtomicCmpXchgInst *CmpX = dyn_cast<AtomicCmpXchgInst>(I)) {
    unsigned AS = CmpX->getPointerAddressSpace();
    return optimizeMemoryInst(I, CmpX->getPointerOperand(),
                              CmpX->getCompareOperand()->getType(), AS);
  }

  BinaryOperator *BinOp = dyn_cast<BinaryOperator>(I);

  if (BinOp && BinOp->getOpcode() == Instruction::And && EnableAndCmpSinking &&
      sinkAndCmp0Expression(BinOp, *TLI, InsertedInsts))
    return true;

  // TODO: Move this into the switch on opcode - it handles shifts already.
  if (BinOp && (BinOp->getOpcode() == Instruction::AShr ||
                BinOp->getOpcode() == Instruction::LShr)) {
    ConstantInt *CI = dyn_cast<ConstantInt>(BinOp->getOperand(1));
    if (CI && TLI->hasExtractBitsInsn())
      if (OptimizeExtractBits(BinOp, CI, *TLI, *DL))
        return true;
  }

  if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
    if (GEPI->hasAllZeroIndices()) {
      /// The GEP operand must be a pointer, so must its result -> BitCast
      Instruction *NC = new BitCastInst(GEPI->getOperand(0), GEPI->getType(),
                                        GEPI->getName(), GEPI);
      NC->setDebugLoc(GEPI->getDebugLoc());
      replaceAllUsesWith(GEPI, NC, FreshBBs, IsHugeFunc);
      RecursivelyDeleteTriviallyDeadInstructions(
          GEPI, TLInfo, nullptr,
          [&](Value *V) { removeAllAssertingVHReferences(V); });
      ++NumGEPsElim;
      optimizeInst(NC, ModifiedDT);
      return true;
    }
    if (tryUnmergingGEPsAcrossIndirectBr(GEPI, TTI)) {
      return true;
    }
    return false;
  }

  if (FreezeInst *FI = dyn_cast<FreezeInst>(I)) {
    // freeze(icmp a, const)) -> icmp (freeze a), const
    // This helps generate efficient conditional jumps.
    Instruction *CmpI = nullptr;
    if (ICmpInst *II = dyn_cast<ICmpInst>(FI->getOperand(0)))
      CmpI = II;
    else if (FCmpInst *F = dyn_cast<FCmpInst>(FI->getOperand(0)))
      CmpI = F->getFastMathFlags().none() ? F : nullptr;

    if (CmpI && CmpI->hasOneUse()) {
      auto Op0 = CmpI->getOperand(0), Op1 = CmpI->getOperand(1);
      bool Const0 = isa<ConstantInt>(Op0) || isa<ConstantFP>(Op0) ||
                    isa<ConstantPointerNull>(Op0);
      bool Const1 = isa<ConstantInt>(Op1) || isa<ConstantFP>(Op1) ||
                    isa<ConstantPointerNull>(Op1);
      if (Const0 || Const1) {
        if (!Const0 || !Const1) {
          auto *F = new FreezeInst(Const0 ? Op1 : Op0, "", CmpI);
          F->takeName(FI);
          CmpI->setOperand(Const0 ? 1 : 0, F);
        }
        replaceAllUsesWith(FI, CmpI, FreshBBs, IsHugeFunc);
        FI->eraseFromParent();
        return true;
      }
    }
    return false;
  }

  if (tryToSinkFreeOperands(I))
    return true;

  switch (I->getOpcode()) {
  case Instruction::Shl:
  case Instruction::LShr:
  case Instruction::AShr:
    return optimizeShiftInst(cast<BinaryOperator>(I));
  case Instruction::Call:
    return optimizeCallInst(cast<CallInst>(I), ModifiedDT);
  case Instruction::Select:
    return optimizeSelectInst(cast<SelectInst>(I));
  case Instruction::ShuffleVector:
    return optimizeShuffleVectorInst(cast<ShuffleVectorInst>(I));
  case Instruction::Switch:
    return optimizeSwitchInst(cast<SwitchInst>(I));
  case Instruction::ExtractElement:
    return optimizeExtractElementInst(cast<ExtractElementInst>(I));
  case Instruction::Br:
    return optimizeBranch(cast<BranchInst>(I), *TLI, FreshBBs, IsHugeFunc);
  }

  return false;
}

/// Given an OR instruction, check to see if this is a bitreverse
/// idiom. If so, insert the new intrinsic and return true.
bool CodeGenPrepare::makeBitReverse(Instruction &I) {
  if (!I.getType()->isIntegerTy() ||
      !TLI->isOperationLegalOrCustom(ISD::BITREVERSE,
                                     TLI->getValueType(*DL, I.getType(), true)))
    return false;

  SmallVector<Instruction *, 4> Insts;
  if (!recognizeBSwapOrBitReverseIdiom(&I, false, true, Insts))
    return false;
  Instruction *LastInst = Insts.back();
  replaceAllUsesWith(&I, LastInst, FreshBBs, IsHugeFunc);
  RecursivelyDeleteTriviallyDeadInstructions(
      &I, TLInfo, nullptr,
      [&](Value *V) { removeAllAssertingVHReferences(V); });
  return true;
}

// In this pass we look for GEP and cast instructions that are used
// across basic blocks and rewrite them to improve basic-block-at-a-time
// selection.
bool CodeGenPrepare::optimizeBlock(BasicBlock &BB, ModifyDT &ModifiedDT) {
  SunkAddrs.clear();
  bool MadeChange = false;

  do {
    CurInstIterator = BB.begin();
    ModifiedDT = ModifyDT::NotModifyDT;
    while (CurInstIterator != BB.end()) {
      MadeChange |= optimizeInst(&*CurInstIterator++, ModifiedDT);
      if (ModifiedDT != ModifyDT::NotModifyDT) {
        // For huge function we tend to quickly go though the inner optmization
        // opportunities in the BB. So we go back to the BB head to re-optimize
        // each instruction instead of go back to the function head.
        if (IsHugeFunc) {
          DT.reset();
          getDT(*BB.getParent());
          break;
        } else {
          return true;
        }
      }
    }
  } while (ModifiedDT == ModifyDT::ModifyInstDT);

  bool MadeBitReverse = true;
  while (MadeBitReverse) {
    MadeBitReverse = false;
    for (auto &I : reverse(BB)) {
      if (makeBitReverse(I)) {
        MadeBitReverse = MadeChange = true;
        break;
      }
    }
  }
  MadeChange |= dupRetToEnableTailCallOpts(&BB, ModifiedDT);

  return MadeChange;
}

// Some CGP optimizations may move or alter what's computed in a block. Check
// whether a dbg.value intrinsic could be pointed at a more appropriate operand.
bool CodeGenPrepare::fixupDbgValue(Instruction *I) {
  assert(isa<DbgValueInst>(I));
  DbgValueInst &DVI = *cast<DbgValueInst>(I);

  // Does this dbg.value refer to a sunk address calculation?
  bool AnyChange = false;
  SmallDenseSet<Value *> LocationOps(DVI.location_ops().begin(),
                                     DVI.location_ops().end());
  for (Value *Location : LocationOps) {
    WeakTrackingVH SunkAddrVH = SunkAddrs[Location];
    Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr;
    if (SunkAddr) {
      // Point dbg.value at locally computed address, which should give the best
      // opportunity to be accurately lowered. This update may change the type
      // of pointer being referred to; however this makes no difference to
      // debugging information, and we can't generate bitcasts that may affect
      // codegen.
      DVI.replaceVariableLocationOp(Location, SunkAddr);
      AnyChange = true;
    }
  }
  return AnyChange;
}

// A llvm.dbg.value may be using a value before its definition, due to
// optimizations in this pass and others. Scan for such dbg.values, and rescue
// them by moving the dbg.value to immediately after the value definition.
// FIXME: Ideally this should never be necessary, and this has the potential
// to re-order dbg.value intrinsics.
bool CodeGenPrepare::placeDbgValues(Function &F) {
  bool MadeChange = false;
  DominatorTree DT(F);

  for (BasicBlock &BB : F) {
    for (Instruction &Insn : llvm::make_early_inc_range(BB)) {
      DbgValueInst *DVI = dyn_cast<DbgValueInst>(&Insn);
      if (!DVI)
        continue;

      SmallVector<Instruction *, 4> VIs;
      for (Value *V : DVI->getValues())
        if (Instruction *VI = dyn_cast_or_null<Instruction>(V))
          VIs.push_back(VI);

      // This DVI may depend on multiple instructions, complicating any
      // potential sink. This block takes the defensive approach, opting to
      // "undef" the DVI if it has more than one instruction and any of them do
      // not dominate DVI.
      for (Instruction *VI : VIs) {
        if (VI->isTerminator())
          continue;

        // If VI is a phi in a block with an EHPad terminator, we can't insert
        // after it.
        if (isa<PHINode>(VI) && VI->getParent()->getTerminator()->isEHPad())
          continue;

        // If the defining instruction dominates the dbg.value, we do not need
        // to move the dbg.value.
        if (DT.dominates(VI, DVI))
          continue;

        // If we depend on multiple instructions and any of them doesn't
        // dominate this DVI, we probably can't salvage it: moving it to
        // after any of the instructions could cause us to lose the others.
        if (VIs.size() > 1) {
          LLVM_DEBUG(
              dbgs()
              << "Unable to find valid location for Debug Value, undefing:\n"
              << *DVI);
          DVI->setKillLocation();
          break;
        }

        LLVM_DEBUG(dbgs() << "Moving Debug Value before :\n"
                          << *DVI << ' ' << *VI);
        DVI->removeFromParent();
        if (isa<PHINode>(VI))
          DVI->insertBefore(&*VI->getParent()->getFirstInsertionPt());
        else
          DVI->insertAfter(VI);
        MadeChange = true;
        ++NumDbgValueMoved;
      }
    }
  }
  return MadeChange;
}

// Group scattered pseudo probes in a block to favor SelectionDAG. Scattered
// probes can be chained dependencies of other regular DAG nodes and block DAG
// combine optimizations.
bool CodeGenPrepare::placePseudoProbes(Function &F) {
  bool MadeChange = false;
  for (auto &Block : F) {
    // Move the rest probes to the beginning of the block.
    auto FirstInst = Block.getFirstInsertionPt();
    while (FirstInst != Block.end() && FirstInst->isDebugOrPseudoInst())
      ++FirstInst;
    BasicBlock::iterator I(FirstInst);
    I++;
    while (I != Block.end()) {
      if (auto *II = dyn_cast<PseudoProbeInst>(I++)) {
        II->moveBefore(&*FirstInst);
        MadeChange = true;
      }
    }
  }
  return MadeChange;
}

/// Scale down both weights to fit into uint32_t.
static void scaleWeights(uint64_t &NewTrue, uint64_t &NewFalse) {
  uint64_t NewMax = (NewTrue > NewFalse) ? NewTrue : NewFalse;
  uint32_t Scale = (NewMax / std::numeric_limits<uint32_t>::max()) + 1;
  NewTrue = NewTrue / Scale;
  NewFalse = NewFalse / Scale;
}

/// Some targets prefer to split a conditional branch like:
/// \code
///   %0 = icmp ne i32 %a, 0
///   %1 = icmp ne i32 %b, 0
///   %or.cond = or i1 %0, %1
///   br i1 %or.cond, label %TrueBB, label %FalseBB
/// \endcode
/// into multiple branch instructions like:
/// \code
///   bb1:
///     %0 = icmp ne i32 %a, 0
///     br i1 %0, label %TrueBB, label %bb2
///   bb2:
///     %1 = icmp ne i32 %b, 0
///     br i1 %1, label %TrueBB, label %FalseBB
/// \endcode
/// This usually allows instruction selection to do even further optimizations
/// and combine the compare with the branch instruction. Currently this is
/// applied for targets which have "cheap" jump instructions.
///
/// FIXME: Remove the (equivalent?) implementation in SelectionDAG.
///
bool CodeGenPrepare::splitBranchCondition(Function &F, ModifyDT &ModifiedDT) {
  if (!TM->Options.EnableFastISel || TLI->isJumpExpensive())
    return false;

  bool MadeChange = false;
  for (auto &BB : F) {
    // Does this BB end with the following?
    //   %cond1 = icmp|fcmp|binary instruction ...
    //   %cond2 = icmp|fcmp|binary instruction ...
    //   %cond.or = or|and i1 %cond1, cond2
    //   br i1 %cond.or label %dest1, label %dest2"
    Instruction *LogicOp;
    BasicBlock *TBB, *FBB;
    if (!match(BB.getTerminator(),
               m_Br(m_OneUse(m_Instruction(LogicOp)), TBB, FBB)))
      continue;

    auto *Br1 = cast<BranchInst>(BB.getTerminator());
    if (Br1->getMetadata(LLVMContext::MD_unpredictable))
      continue;

    // The merging of mostly empty BB can cause a degenerate branch.
    if (TBB == FBB)
      continue;

    unsigned Opc;
    Value *Cond1, *Cond2;
    if (match(LogicOp,
              m_LogicalAnd(m_OneUse(m_Value(Cond1)), m_OneUse(m_Value(Cond2)))))
      Opc = Instruction::And;
    else if (match(LogicOp, m_LogicalOr(m_OneUse(m_Value(Cond1)),
                                        m_OneUse(m_Value(Cond2)))))
      Opc = Instruction::Or;
    else
      continue;

    auto IsGoodCond = [](Value *Cond) {
      return match(
          Cond,
          m_CombineOr(m_Cmp(), m_CombineOr(m_LogicalAnd(m_Value(), m_Value()),
                                           m_LogicalOr(m_Value(), m_Value()))));
    };
    if (!IsGoodCond(Cond1) || !IsGoodCond(Cond2))
      continue;

    LLVM_DEBUG(dbgs() << "Before branch condition splitting\n"; BB.dump());

    // Create a new BB.
    auto *TmpBB =
        BasicBlock::Create(BB.getContext(), BB.getName() + ".cond.split",
                           BB.getParent(), BB.getNextNode());
    if (IsHugeFunc)
      FreshBBs.insert(TmpBB);

    // Update original basic block by using the first condition directly by the
    // branch instruction and removing the no longer needed and/or instruction.
    Br1->setCondition(Cond1);
    LogicOp->eraseFromParent();

    // Depending on the condition we have to either replace the true or the
    // false successor of the original branch instruction.
    if (Opc == Instruction::And)
      Br1->setSuccessor(0, TmpBB);
    else
      Br1->setSuccessor(1, TmpBB);

    // Fill in the new basic block.
    auto *Br2 = IRBuilder<>(TmpBB).CreateCondBr(Cond2, TBB, FBB);
    if (auto *I = dyn_cast<Instruction>(Cond2)) {
      I->removeFromParent();
      I->insertBefore(Br2);
    }

    // Update PHI nodes in both successors. The original BB needs to be
    // replaced in one successor's PHI nodes, because the branch comes now from
    // the newly generated BB (NewBB). In the other successor we need to add one
    // incoming edge to the PHI nodes, because both branch instructions target
    // now the same successor. Depending on the original branch condition
    // (and/or) we have to swap the successors (TrueDest, FalseDest), so that
    // we perform the correct update for the PHI nodes.
    // This doesn't change the successor order of the just created branch
    // instruction (or any other instruction).
    if (Opc == Instruction::Or)
      std::swap(TBB, FBB);

    // Replace the old BB with the new BB.
    TBB->replacePhiUsesWith(&BB, TmpBB);

    // Add another incoming edge from the new BB.
    for (PHINode &PN : FBB->phis()) {
      auto *Val = PN.getIncomingValueForBlock(&BB);
      PN.addIncoming(Val, TmpBB);
    }

    // Update the branch weights (from SelectionDAGBuilder::
    // FindMergedConditions).
    if (Opc == Instruction::Or) {
      // Codegen X | Y as:
      // BB1:
      //   jmp_if_X TBB
      //   jmp TmpBB
      // TmpBB:
      //   jmp_if_Y TBB
      //   jmp FBB
      //

      // We have flexibility in setting Prob for BB1 and Prob for NewBB.
      // The requirement is that
      //   TrueProb for BB1 + (FalseProb for BB1 * TrueProb for TmpBB)
      //     = TrueProb for original BB.
      // Assuming the original weights are A and B, one choice is to set BB1's
      // weights to A and A+2B, and set TmpBB's weights to A and 2B. This choice
      // assumes that
      //   TrueProb for BB1 == FalseProb for BB1 * TrueProb for TmpBB.
      // Another choice is to assume TrueProb for BB1 equals to TrueProb for
      // TmpBB, but the math is more complicated.
      uint64_t TrueWeight, FalseWeight;
      if (extractBranchWeights(*Br1, TrueWeight, FalseWeight)) {
        uint64_t NewTrueWeight = TrueWeight;
        uint64_t NewFalseWeight = TrueWeight + 2 * FalseWeight;
        scaleWeights(NewTrueWeight, NewFalseWeight);
        Br1->setMetadata(LLVMContext::MD_prof,
                         MDBuilder(Br1->getContext())
                             .createBranchWeights(TrueWeight, FalseWeight));

        NewTrueWeight = TrueWeight;
        NewFalseWeight = 2 * FalseWeight;
        scaleWeights(NewTrueWeight, NewFalseWeight);
        Br2->setMetadata(LLVMContext::MD_prof,
                         MDBuilder(Br2->getContext())
                             .createBranchWeights(TrueWeight, FalseWeight));
      }
    } else {
      // Codegen X & Y as:
      // BB1:
      //   jmp_if_X TmpBB
      //   jmp FBB
      // TmpBB:
      //   jmp_if_Y TBB
      //   jmp FBB
      //
      //  This requires creation of TmpBB after CurBB.

      // We have flexibility in setting Prob for BB1 and Prob for TmpBB.
      // The requirement is that
      //   FalseProb for BB1 + (TrueProb for BB1 * FalseProb for TmpBB)
      //     = FalseProb for original BB.
      // Assuming the original weights are A and B, one choice is to set BB1's
      // weights to 2A+B and B, and set TmpBB's weights to 2A and B. This choice
      // assumes that
      //   FalseProb for BB1 == TrueProb for BB1 * FalseProb for TmpBB.
      uint64_t TrueWeight, FalseWeight;
      if (extractBranchWeights(*Br1, TrueWeight, FalseWeight)) {
        uint64_t NewTrueWeight = 2 * TrueWeight + FalseWeight;
        uint64_t NewFalseWeight = FalseWeight;
        scaleWeights(NewTrueWeight, NewFalseWeight);
        Br1->setMetadata(LLVMContext::MD_prof,
                         MDBuilder(Br1->getContext())
                             .createBranchWeights(TrueWeight, FalseWeight));

        NewTrueWeight = 2 * TrueWeight;
        NewFalseWeight = FalseWeight;
        scaleWeights(NewTrueWeight, NewFalseWeight);
        Br2->setMetadata(LLVMContext::MD_prof,
                         MDBuilder(Br2->getContext())
                             .createBranchWeights(TrueWeight, FalseWeight));
      }
    }

    ModifiedDT = ModifyDT::ModifyBBDT;
    MadeChange = true;

    LLVM_DEBUG(dbgs() << "After branch condition splitting\n"; BB.dump();
               TmpBB->dump());
  }
  return MadeChange;
}
