//===- TargetPassConfig.cpp - Target independent code generation passes ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces to access the target independent code
// generation passes provided by the LLVM backend.
//
//===---------------------------------------------------------------------===//

#include "llvm/CodeGen/TargetPassConfig.h"
#include "CodeGenOptions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/ScopedNoAliasAA.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
#include "llvm/CodeGen/CSEConfigBase.h"
#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
#include "llvm/CodeGen/MachineBlockHashInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/IR/Verifier.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Discriminator.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Target/CGPassBuilderOption.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils.h"
#include <cassert>
#include <optional>
#include <string>

using namespace llvm;

static const CodeGenOptions &getOpts(const TargetMachine &TM) {
  return cl::LibraryOptionsContext::get<CodeGenOptions>(
      TM.Options.MCOptions.LibraryOptions);
}

namespace {
class TriggerCrashFunctionLegacyPass : public FunctionPass {
public:
  static char ID;
  TriggerCrashFunctionLegacyPass() : FunctionPass(ID) {}
  bool runOnFunction(Function &F) override {
    abort();
    return false;
  }
  StringRef getPassName() const override { return "TriggerCrashFunctionPass"; }
};
} // namespace

char TriggerCrashFunctionLegacyPass::ID = 0;

// Enable or disable the MachineOutliner.
static cl::opt<RunOutliner> EnableMachineOutliner(
    "enable-machine-outliner", cl::desc("Enable the machine outliner"),
    cl::Hidden, cl::ValueOptional, cl::init(RunOutliner::TargetDefault),
    cl::values(
        clEnumValN(RunOutliner::AlwaysOutline, "always",
                   "Run on all functions guaranteed to be beneficial"),
        clEnumValN(RunOutliner::OptimisticPGO, "optimistic-pgo",
                   "Outline cold code only. If a code block does not have "
                   "profile data, optimistically assume it is cold."),
        clEnumValN(RunOutliner::ConservativePGO, "conservative-pgo",
                   "Outline cold code only. If a code block does not have "
                   "profile, data, conservatively assume it is hot."),
        clEnumValN(RunOutliner::NeverOutline, "never", "Disable all outlining"),
        // Sentinel value for unspecified option.
        clEnumValN(RunOutliner::AlwaysOutline, "", "")));

/// Option names for limiting the codegen pipeline.
/// Those are used in error reporting and we didn't want
/// to duplicate their names all over the place.
static const char StartAfterOptName[] = "start-after";
static const char StartBeforeOptName[] = "start-before";
static const char StopAfterOptName[] = "stop-after";
static const char StopBeforeOptName[] = "stop-before";

/// Allow standard passes to be disabled by command line options. This supports
/// simple binary flags that either suppress the pass or do nothing.
/// i.e. -disable-mypass=false has no effect.
/// These should be converted to boolOrDefault in order to use applyOverride.
static IdentifyingPassPtr applyDisable(IdentifyingPassPtr PassID,
                                       bool Override) {
  if (Override)
    return IdentifyingPassPtr();
  return PassID;
}

/// Allow standard passes to be disabled by the command line, regardless of who
/// is adding the pass.
///
/// StandardID is the pass identified in the standard pass pipeline and provided
/// to addPass(). It may be a target-specific ID in the case that the target
/// directly adds its own pass, but in that case we harmlessly fall through.
///
/// TargetID is the pass that the target has configured to override StandardID.
///
/// StandardID may be a pseudo ID. In that case TargetID is the name of the real
/// pass to run. This allows multiple options to control a single pass depending
/// on where in the pipeline that pass is added.
static IdentifyingPassPtr overridePass(const CodeGenOptions &Opts,
                                       AnalysisID StandardID,
                                       IdentifyingPassPtr TargetID) {
  if (StandardID == &PostRASchedulerID)
    return applyDisable(TargetID, Opts.disable_post_ra);

  if (StandardID == &BranchFolderPassID)
    return applyDisable(TargetID, Opts.disable_branch_fold);

  if (StandardID == &TailDuplicateLegacyID)
    return applyDisable(TargetID, Opts.disable_tail_duplicate);

  if (StandardID == &EarlyTailDuplicateLegacyID)
    return applyDisable(TargetID, Opts.disable_early_taildup);

  if (StandardID == &MachineBlockPlacementID)
    return applyDisable(TargetID, Opts.disable_block_placement);

  if (StandardID == &StackSlotColoringID)
    return applyDisable(TargetID, Opts.disable_ssc);

  if (StandardID == &DeadMachineInstructionElimID)
    return applyDisable(TargetID, Opts.disable_machine_dce);

  if (StandardID == &EarlyIfConverterLegacyID)
    return applyDisable(TargetID, Opts.disable_early_ifcvt);

  if (StandardID == &EarlyMachineLICMID)
    return applyDisable(TargetID, Opts.disable_machine_licm);

  if (StandardID == &MachineCSELegacyID)
    return applyDisable(TargetID, Opts.disable_machine_cse);

  if (StandardID == &MachineLICMID)
    return applyDisable(TargetID, Opts.disable_postra_machine_licm);

  if (StandardID == &MachineSinkingLegacyID)
    return applyDisable(TargetID, Opts.disable_machine_sink);

  if (StandardID == &PostRAMachineSinkingID)
    return applyDisable(TargetID, Opts.disable_postra_machine_sink);

  if (StandardID == &MachineCopyPropagationID)
    return applyDisable(TargetID, Opts.disable_copyprop);

  return TargetID;
}

// Find the FSProfile file name. The internal option takes the precedence
// before getting from TargetMachine.
static std::string getFSProfileFile(const CodeGenOptions &Opts,
                                    const TargetMachine *TM) {
  if (!Opts.fs_profile_file.empty())
    return Opts.fs_profile_file.str();
  const std::optional<PGOOptions> &PGOOpt = TM->getPGOOption();
  if (PGOOpt == std::nullopt || PGOOpt->Action != PGOOptions::SampleUse)
    return std::string();
  return PGOOpt->ProfileFile;
}

// Find the Profile remapping file name. The internal option takes the
// precedence before getting from TargetMachine.
static std::string getFSRemappingFile(const CodeGenOptions &Opts,
                                      const TargetMachine *TM) {
  if (!Opts.fs_remapping_file.empty())
    return Opts.fs_remapping_file.str();
  const std::optional<PGOOptions> &PGOOpt = TM->getPGOOption();
  if (PGOOpt == std::nullopt || PGOOpt->Action != PGOOptions::SampleUse)
    return std::string();
  return PGOOpt->ProfileRemappingFile;
}

//===---------------------------------------------------------------------===//
/// TargetPassConfig
//===---------------------------------------------------------------------===//

INITIALIZE_PASS(TargetPassConfig, "targetpassconfig",
                "Target Pass Configuration", false, false)
char TargetPassConfig::ID = 0;

namespace {

struct InsertedPass {
  AnalysisID TargetPassID;
  IdentifyingPassPtr InsertedPassID;

  InsertedPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID)
      : TargetPassID(TargetPassID), InsertedPassID(InsertedPassID) {}

  Pass *getInsertedPass() const {
    assert(InsertedPassID.isValid() && "Illegal Pass ID!");
    if (InsertedPassID.isInstance())
      return InsertedPassID.getInstance();
    Pass *NP = Pass::createPass(InsertedPassID.getID());
    assert(NP && "Pass ID not registered");
    return NP;
  }
};

} // end anonymous namespace

namespace llvm {

class PassConfigImpl {
public:
  // List of passes explicitly substituted by this target. Normally this is
  // empty, but it is a convenient way to suppress or replace specific passes
  // that are part of a standard pass pipeline without overridding the entire
  // pipeline. This mechanism allows target options to inherit a standard pass's
  // user interface. For example, a target may disable a standard pass by
  // default by substituting a pass ID of zero, and the user may still enable
  // that standard pass with an explicit command line option.
  DenseMap<AnalysisID,IdentifyingPassPtr> TargetPasses;

  /// Store the pairs of <AnalysisID, AnalysisID> of which the second pass
  /// is inserted after each instance of the first one.
  SmallVector<InsertedPass, 4> InsertedPasses;
};

} // end namespace llvm

// Out of line virtual method.
TargetPassConfig::~TargetPassConfig() {
  delete Impl;
}

static const PassInfo *getPassInfo(StringRef PassName) {
  if (PassName.empty())
    return nullptr;

  const PassRegistry &PR = *PassRegistry::getPassRegistry();
  const PassInfo *PI = PR.getPassInfo(PassName);
  if (!PI)
    reportFatalUsageError(Twine('\"') + Twine(PassName) +
                          Twine("\" pass is not registered."));
  return PI;
}

static AnalysisID getPassIDFromName(StringRef PassName) {
  const PassInfo *PI = getPassInfo(PassName);
  return PI ? PI->getTypeInfo() : nullptr;
}

static std::pair<StringRef, unsigned>
getPassNameAndInstanceNum(StringRef PassName) {
  StringRef Name, InstanceNumStr;
  std::tie(Name, InstanceNumStr) = PassName.split(',');

  unsigned InstanceNum = 0;
  if (!InstanceNumStr.empty() && InstanceNumStr.getAsInteger(10, InstanceNum))
    reportFatalUsageError("invalid pass instance specifier " + PassName);

  return std::make_pair(Name, InstanceNum);
}

void TargetPassConfig::setStartStopPasses() {
  StringRef StartBeforeName;
  std::tie(StartBeforeName, StartBeforeInstanceNum) =
      getPassNameAndInstanceNum(Opts.start_before);

  StringRef StartAfterName;
  std::tie(StartAfterName, StartAfterInstanceNum) =
      getPassNameAndInstanceNum(Opts.start_after);

  StringRef StopBeforeName;
  std::tie(StopBeforeName, StopBeforeInstanceNum) =
      getPassNameAndInstanceNum(Opts.stop_before);

  StringRef StopAfterName;
  std::tie(StopAfterName, StopAfterInstanceNum) =
      getPassNameAndInstanceNum(Opts.stop_after);

  StartBefore = getPassIDFromName(StartBeforeName);
  StartAfter = getPassIDFromName(StartAfterName);
  StopBefore = getPassIDFromName(StopBeforeName);
  StopAfter = getPassIDFromName(StopAfterName);
  if (StartBefore && StartAfter)
    reportFatalUsageError(Twine(StartBeforeOptName) + Twine(" and ") +
                          Twine(StartAfterOptName) + Twine(" specified!"));
  if (StopBefore && StopAfter)
    reportFatalUsageError(Twine(StopBeforeOptName) + Twine(" and ") +
                          Twine(StopAfterOptName) + Twine(" specified!"));
  Started = (StartAfter == nullptr) && (StartBefore == nullptr);
}

static cl::boolOrDefault toBoolOrDefault(BoolOrDefault B) {
  if (B == BoolOrDefault::Default)
    return cl::boolOrDefault::BOU_UNSET;
  return B == BoolOrDefault::True ? cl::boolOrDefault::BOU_TRUE
                                  : cl::boolOrDefault::BOU_FALSE;
}

static MachineVerifierMode
computeMachineVerifierMode(const CodeGenOptions &Opts, bool VerifyEach) {
  if (VerifyEach)
    return MachineVerifierMode::Each;
  return Opts.disable_mir_output_verify ? MachineVerifierMode::None
                                        : MachineVerifierMode::End;
}

CGPassBuilderOption llvm::getCGPassBuilderOption(const TargetMachine &TM) {
  const CodeGenOptions &Opts = getOpts(TM);
  CGPassBuilderOption Opt;
  Opt.EnableGlobalISelAbort = Opts.global_isel_abort;
  if (Opts.enable_ipra != BoolOrDefault::Default)
    Opt.EnableIPRA = Opts.enable_ipra == BoolOrDefault::True;
  Opt.EnableFastISelOption = toBoolOrDefault(Opts.fast_isel);
  Opt.EnableRegAllocFastTied = toBoolOrDefault(Opts.regalloc_fast_tied);
  Opt.EnableMachinePipeliner = toBoolOrDefault(Opts.enable_pipeliner);
  Opt.EnableGlobalISelOption = toBoolOrDefault(Opts.global_isel);
  Opt.VerifyMachineCode = computeMachineVerifierMode(
      Opts, valueOr(Opts.verify_machineinstrs, false));
  Opt.DisableAtExitBasedGlobalDtorLowering =
      Opts.disable_atexit_based_global_dtor_lowering;
  Opt.DisableExpandReductions = Opts.disable_expand_reductions;
  Opt.PrintAfterISel = Opts.print_after_isel;
  Opt.FSProfileFile = Opts.fs_profile_file.str();
  Opt.EnableGCEmptyBlocks = Opts.enable_gc_empty_basic_blocks;
  Opt.EnableBlockPlacementStats = Opts.enable_block_placement_stats;
  Opt.EnableGlobalMergeFunc = Opts.enable_global_merge_func;
  Opt.EnableImplicitNullChecks = Opts.enable_implicit_null_checks;
  Opt.EnableMachineOutliner = EnableMachineOutliner;
  Opt.MISchedPostRA = Opts.misched_postra;
  Opt.DisableLSR = Opts.disable_lsr;
  Opt.DisableConstantHoisting = Opts.disable_constant_hoisting;
  Opt.DisableCGP = Opts.disable_cgp;
  Opt.DisablePartialLibcallInlining = Opts.disable_partial_libcall_inlining;
  Opt.DisableSelectOptimize = Opts.disable_select_optimize;
  Opt.PrintISelInput = Opts.print_isel_input;
  Opt.PrintRegUsage = Opts.print_regusage;
  Opt.DebugifyAndStripAll = toBoolOrDefault(Opts.debugify_and_strip_all_safe);
  Opt.DebugifyCheckAndStripAll =
      toBoolOrDefault(Opts.debugify_check_and_strip_all_safe);
  Opt.DisableRAFSProfileLoader = Opts.disable_ra_fsprofile_loader;
  Opt.DisableCFIFixup = Opts.disable_cfi_fixup;
  return Opt;
}

void llvm::registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
                                   TargetMachine &TM) {
  const CodeGenOptions &Opts = getOpts(TM);

  // Register a callback for disabling passes.
  PIC.registerShouldRunOptionalPassCallback([&Opts](StringRef P, IRUnitRef) {

#define DISABLE_PASS(Option, Name)                                             \
  if (Option && P.contains(#Name))                                             \
    return false;
    DISABLE_PASS(Opts.disable_block_placement, MachineBlockPlacementPass)
    DISABLE_PASS(Opts.disable_branch_fold, BranchFolderPass)
    DISABLE_PASS(Opts.disable_copyprop, MachineCopyPropagationPass)
    DISABLE_PASS(Opts.disable_early_ifcvt, EarlyIfConverterLegacyPass)
    DISABLE_PASS(Opts.disable_early_taildup, EarlyTailDuplicatePass)
    DISABLE_PASS(Opts.disable_machine_cse, MachineCSELegacyPass)
    DISABLE_PASS(Opts.disable_machine_dce, DeadMachineInstructionElimPass)
    DISABLE_PASS(Opts.disable_machine_licm, EarlyMachineLICMPass)
    DISABLE_PASS(Opts.disable_machine_sink, MachineSinkingPass)
    DISABLE_PASS(Opts.disable_postra_machine_licm, MachineLICMPass)
    DISABLE_PASS(Opts.disable_postra_machine_sink, PostRAMachineSinkingPass)
    DISABLE_PASS(Opts.disable_post_ra, PostRASchedulerPass)
    DISABLE_PASS(Opts.disable_ssc, StackSlotColoringPass)
    DISABLE_PASS(Opts.disable_tail_duplicate, TailDuplicatePass)

    return true;
  });
}

Expected<TargetPassConfig::StartStopInfo>
TargetPassConfig::getStartStopInfo(const TargetMachine &TM,
                                   PassInstrumentationCallbacks &PIC) {
  const CodeGenOptions &Opts = getOpts(TM);
  auto [StartBefore, StartBeforeInstanceNum] =
      getPassNameAndInstanceNum(Opts.start_before);
  auto [StartAfter, StartAfterInstanceNum] =
      getPassNameAndInstanceNum(Opts.start_after);
  auto [StopBefore, StopBeforeInstanceNum] =
      getPassNameAndInstanceNum(Opts.stop_before);
  auto [StopAfter, StopAfterInstanceNum] =
      getPassNameAndInstanceNum(Opts.stop_after);

  if (!StartBefore.empty() && !StartAfter.empty())
    return make_error<StringError>(
        Twine(StartBeforeOptName) + " and " + StartAfterOptName + " specified!",
        std::make_error_code(std::errc::invalid_argument));
  if (!StopBefore.empty() && !StopAfter.empty())
    return make_error<StringError>(
        Twine(StopBeforeOptName) + " and " + StopAfterOptName + " specified!",
        std::make_error_code(std::errc::invalid_argument));

  StartStopInfo Result;
  Result.StartPass = StartBefore.empty() ? StartAfter : StartBefore;
  Result.StopPass = StopBefore.empty() ? StopAfter : StopBefore;
  Result.StartInstanceNum =
      StartBefore.empty() ? StartAfterInstanceNum : StartBeforeInstanceNum;
  Result.StopInstanceNum =
      StopBefore.empty() ? StopAfterInstanceNum : StopBeforeInstanceNum;
  Result.StartAfter = !StartAfter.empty();
  Result.StopAfter = !StopAfter.empty();
  Result.StartInstanceNum += Result.StartInstanceNum == 0;
  Result.StopInstanceNum += Result.StopInstanceNum == 0;
  return Result;
}

// Out of line constructor provides default values for pass options and
// registers all common codegen passes.
TargetPassConfig::TargetPassConfig(TargetMachine &TM, PassManagerBase &PM)
    : ImmutablePass(ID), PM(&PM), Opts(getOpts(TM)), TM(&TM) {
  Impl = new PassConfigImpl();

  PassRegistry &PR = *PassRegistry::getPassRegistry();
  // Register all target independent codegen passes to activate their PassIDs,
  // including this pass itself.
  initializeCodeGen(PR);

  initializeLibcallLoweringInfoWrapperPass(PR);

  // Also register alias analysis passes required by codegen passes.
  initializeBasicAAWrapperPassPass(PR);
  initializeAAResultsWrapperPassPass(PR);

  if (Opts.enable_ipra != BoolOrDefault::Default) {
    TM.Options.EnableIPRA = Opts.enable_ipra == BoolOrDefault::True;
  } else {
    // If not explicitly specified, use target default.
    TM.Options.EnableIPRA |= TM.useIPRA();
  }

  if (TM.Options.EnableIPRA)
    setRequiresCodeGenSCCOrder();

  if (Opts.regalloc_fast_tied != BoolOrDefault::Default)
    TM.setEnableTiedFastRegAlloc(Opts.regalloc_fast_tied ==
                                 BoolOrDefault::True);

  if (Opts.global_isel_abort)
    TM.Options.GlobalISelAbort = *Opts.global_isel_abort;

  bool VerifyEach = valueOr(Opts.verify_machineinstrs, false);
#ifdef EXPENSIVE_CHECKS
  if (Opts.verify_machineinstrs == BoolOrDefault::Default)
    VerifyEach = TM.isMachineVerifierClean();
#endif
  VerifyMode = computeMachineVerifierMode(Opts, VerifyEach);

  if (Opts.function_splitting)
    TM.Options.FunctionSplitting = *Opts.function_splitting;

  setStartStopPasses();
}

CodeGenOptLevel TargetPassConfig::getOptLevel() const {
  return TM->getOptLevel();
}

/// Insert InsertedPassID pass after TargetPassID.
void TargetPassConfig::insertPass(AnalysisID TargetPassID,
                                  IdentifyingPassPtr InsertedPassID) {
  assert(((!InsertedPassID.isInstance() &&
           TargetPassID != InsertedPassID.getID()) ||
          (InsertedPassID.isInstance() &&
           TargetPassID != InsertedPassID.getInstance()->getPassID())) &&
         "Insert a pass after itself!");
  Impl->InsertedPasses.emplace_back(TargetPassID, InsertedPassID);
}

/// createPassConfig - Create a pass configuration object to be used by
/// addPassToEmitX methods for generating a pipeline of CodeGen passes.
///
/// Targets may override this to extend TargetPassConfig.
TargetPassConfig *
CodeGenTargetMachineImpl::createPassConfig(PassManagerBase &PM) {
  return new TargetPassConfig(*this, PM);
}

template <> Pass *llvm::callDefaultCtor<TargetPassConfig>() {
  reportFatalUsageError("trying to construct TargetPassConfig without a target "
                        "machine. Scheduling a CodeGen pass without a target "
                        "triple set?");
}

bool TargetPassConfig::willCompleteCodeGenPipeline() const {
  return Opts.stop_before.empty() && Opts.stop_after.empty();
}

bool TargetPassConfig::hasLimitedCodeGenPipeline() const {
  return !Opts.start_before.empty() || !Opts.start_after.empty() ||
         !willCompleteCodeGenPipeline();
}

static std::string formatLimitReason(StringRef StartAfter,
                                     StringRef StartBefore, StringRef StopAfter,
                                     StringRef StopBefore) {
  std::string Res;
  StringRef PassNames[] = {StartAfter, StartBefore, StopAfter, StopBefore};
  static const char *OptNames[] = {StartAfterOptName, StartBeforeOptName,
                                   StopAfterOptName, StopBeforeOptName};
  bool IsFirst = true;
  for (int Idx = 0; Idx < 4; ++Idx)
    if (!PassNames[Idx].empty()) {
      if (!IsFirst)
        Res += " and ";
      IsFirst = false;
      Res += OptNames[Idx];
    }
  return Res;
}

std::string TargetPassConfig::getLimitedCodeGenPipelineReason() const {
  return formatLimitReason(Opts.start_after, Opts.start_before, Opts.stop_after,
                           Opts.stop_before);
}

std::string TargetPassConfig::StartStopInfo::getLimitReason() const {
  return formatLimitReason(
      StartAfter ? StartPass : "", StartAfter ? "" : StartPass,
      StopAfter ? StopPass : "", StopAfter ? "" : StopPass);
}

// Helper to verify the analysis is really immutable.
void TargetPassConfig::setOpt(bool &Opt, bool Val) {
  assert(!Initialized && "PassConfig is immutable");
  Opt = Val;
}

void TargetPassConfig::substitutePass(AnalysisID StandardID,
                                      IdentifyingPassPtr TargetID) {
  Impl->TargetPasses[StandardID] = TargetID;
}

IdentifyingPassPtr TargetPassConfig::getPassSubstitution(AnalysisID ID) const {
  DenseMap<AnalysisID, IdentifyingPassPtr>::const_iterator
    I = Impl->TargetPasses.find(ID);
  if (I == Impl->TargetPasses.end())
    return ID;
  return I->second;
}

bool TargetPassConfig::isPassSubstitutedOrOverridden(AnalysisID ID) const {
  IdentifyingPassPtr TargetID = getPassSubstitution(ID);
  IdentifyingPassPtr FinalPtr = overridePass(Opts, ID, TargetID);
  return !FinalPtr.isValid() || FinalPtr.isInstance() ||
      FinalPtr.getID() != ID;
}

/// Add a pass to the PassManager if that pass is supposed to be run.  If the
/// Started/Stopped flags indicate either that the compilation should start at
/// a later pass or that it should stop after an earlier pass, then do not add
/// the pass.  Finally, compare the current pass against the StartAfter
/// and StopAfter options and change the Started/Stopped flags accordingly.
void TargetPassConfig::addPass(Pass *P) {
  assert(!Initialized && "PassConfig is immutable");

  // Cache the Pass ID here in case the pass manager finds this pass is
  // redundant with ones already scheduled / available, and deletes it.
  // Fundamentally, once we add the pass to the manager, we no longer own it
  // and shouldn't reference it.
  AnalysisID PassID = P->getPassID();

  if (StartBefore == PassID && StartBeforeCount++ == StartBeforeInstanceNum)
    Started = true;
  if (StopBefore == PassID && StopBeforeCount++ == StopBeforeInstanceNum)
    Stopped = true;
  if (Started && !Stopped) {
    if (AddingMachinePasses) {
      // Construct banner message before PM->add() as that may delete the pass.
      std::string Banner =
          std::string("After ") + std::string(P->getPassName());
      addMachinePrePasses();
      PM->add(P);
      addMachinePostPasses(Banner);
    } else {
      PM->add(P);
    }

    // Add the passes after the pass P if there is any.
    for (const auto &IP : Impl->InsertedPasses)
      if (IP.TargetPassID == PassID)
        addPass(IP.getInsertedPass());
  } else {
    delete P;
  }

  if (StopAfter == PassID && StopAfterCount++ == StopAfterInstanceNum)
    Stopped = true;

  if (StartAfter == PassID && StartAfterCount++ == StartAfterInstanceNum)
    Started = true;
  if (Stopped && !Started)
    reportFatalUsageError("Cannot stop compilation after pass that is not run");
}

/// Add a CodeGen pass at this point in the pipeline after checking for target
/// and command line overrides.
///
/// addPass cannot return a pointer to the pass instance because is internal the
/// PassManager and the instance we create here may already be freed.
AnalysisID TargetPassConfig::addPass(AnalysisID PassID) {
  IdentifyingPassPtr TargetID = getPassSubstitution(PassID);
  IdentifyingPassPtr FinalPtr = overridePass(Opts, PassID, TargetID);
  if (!FinalPtr.isValid())
    return nullptr;

  Pass *P;
  if (FinalPtr.isInstance())
    P = FinalPtr.getInstance();
  else {
    P = Pass::createPass(FinalPtr.getID());
    if (!P)
      llvm_unreachable("Pass ID not registered");
  }
  AnalysisID FinalID = P->getPassID();
  addPass(P); // Ends the lifetime of P.

  return FinalID;
}

void TargetPassConfig::printAndVerify(const std::string &Banner) {
  addPrintPass(Banner);
  addVerifyPass(Banner);
}

void TargetPassConfig::addPrintPass(const std::string &Banner) {
  if (Opts.print_after_isel)
    PM->add(createMachineFunctionPrinterPass(dbgs(), Banner));
}

void TargetPassConfig::addVerifyPass(const std::string &Banner) {
  if (VerifyMode == MachineVerifierMode::Each)
    PM->add(createMachineVerifierPass(Banner));
}

void TargetPassConfig::addDebugifyPass() {
  PM->add(createDebugifyMachineModulePass());
}

void TargetPassConfig::addStripDebugPass() {
  PM->add(createStripDebugMachineModuleLegacyPass(/*OnlyDebugified=*/true));
}

void TargetPassConfig::addCheckDebugPass() {
  PM->add(createCheckDebugMachineModuleLegacyPass());
}

void TargetPassConfig::addMachinePrePasses(bool AllowDebugify) {
  if (AllowDebugify && DebugifyIsSafe &&
      (valueOr(Opts.debugify_and_strip_all_safe, false) ||
       valueOr(Opts.debugify_check_and_strip_all_safe, false)))
    addDebugifyPass();
}

void TargetPassConfig::addMachinePostPasses(const std::string &Banner) {
  if (DebugifyIsSafe) {
    if (valueOr(Opts.debugify_check_and_strip_all_safe, false)) {
      addCheckDebugPass();
      addStripDebugPass();
    } else if (valueOr(Opts.debugify_and_strip_all_safe, false))
      addStripDebugPass();
  }
  addVerifyPass(Banner);
}

/// Add common target configurable passes that perform LLVM IR to IR transforms
/// following machine independent optimization.
void TargetPassConfig::addIRPasses() {
  // Before running any passes, run the verifier to determine if the input
  // coming from the front-end and/or optimizer is valid.
  if (!DisableVerify)
    addPass(createVerifierPass());

  if (getOptLevel() != CodeGenOptLevel::None) {
    // Basic AliasAnalysis support.
    // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
    // BasicAliasAnalysis wins if they disagree. This is intended to help
    // support "obvious" type-punning idioms.
    addPass(createTypeBasedAAWrapperPass());
    addPass(createScopedNoAliasAAWrapperPass());
    addPass(createBasicAAWrapperPass());

    // Run loop strength reduction before anything else.
    if (!Opts.disable_lsr) {
      addPass(createCanonicalizeFreezeInLoopsPass());
      addPass(createLoopStrengthReducePass());
      if (EnableLoopTermFold)
        addPass(createLoopTermFoldPass());
    }
  }

  // Run GC lowering passes for builtin collectors
  // TODO: add a pass insertion point here
  addPass(&GCLoweringID);
  addPass(&ShadowStackGCLoweringID);

  // For MachO, lower @llvm.global_dtors into @llvm.global_ctors with
  // __cxa_atexit() calls to avoid emitting the deprecated __mod_term_func.
  if (TM->getTargetTriple().isOSBinFormatMachO() &&
      !Opts.disable_atexit_based_global_dtor_lowering)
    addPass(createLowerGlobalDtorsLegacyPass());

  // Make sure that no unreachable blocks are instruction selected.
  addPass(createUnreachableBlockEliminationPass());

  // Prepare expensive constants for SelectionDAG.
  if (getOptLevel() != CodeGenOptLevel::None && !Opts.disable_constant_hoisting)
    addPass(createConstantHoistingPass());

  if (getOptLevel() != CodeGenOptLevel::None &&
      !Opts.disable_replace_with_vec_lib)
    addPass(createReplaceWithVeclibLegacyPass());

  if (getOptLevel() != CodeGenOptLevel::None &&
      !Opts.disable_partial_libcall_inlining)
    addPass(createPartiallyInlineLibCallsPass());

  // Instrument function entry after all inlining.
  addPass(createPostInlineEntryExitInstrumenterPass());

  // Add scalarization of target's unsupported masked memory intrinsics pass.
  // the unsupported intrinsic will be replaced with a chain of basic blocks,
  // that stores/loads element one-by-one if the appropriate mask bit is set.
  addPass(createScalarizeMaskedMemIntrinLegacyPass());

  // Expand reduction intrinsics into shuffle sequences if the target wants to.
  // Allow disabling it for testing purposes.
  if (!Opts.disable_expand_reductions)
    addPass(createExpandReductionsPass());

  // Convert conditional moves to conditional jumps when profitable.
  if (getOptLevel() != CodeGenOptLevel::None && !Opts.disable_select_optimize)
    addPass(createSelectOptimizePass());

  if (Opts.enable_global_merge_func)
    addPass(createGlobalMergeFuncPass());

  if (TM->getTargetTriple().isOSWindows())
    addPass(createWindowsSecureHotPatchingPass());
}

/// Turn exception handling constructs into something the code generators can
/// handle.
void TargetPassConfig::addPassesToHandleExceptions() {
  // The module's exception model is not known when the pipeline is built, so
  // schedule the preparation pass for every model the target supports. Each
  // pass does nothing for other models.
  bool HasEHPrep = false;

  // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
  // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
  // catch info can get misplaced when a selector ends up more than one block
  // removed from the parent invoke(s). This could happen when a landing
  // pad is shared by multiple invokes and is also a target of a normal
  // edge from elsewhere.
  if (TM->supportsExceptionModel(ExceptionHandling::SjLj)) {
    addPass(createSjLjEHPreparePass(TM));
    HasEHPrep = true;
  }

  // We support using both GCC-style and MSVC-style exceptions on Windows, so
  // WinEHPrepare runs in addition to DwarfEHPrepare below. Each pass will only
  // actually run if it recognizes the personality function.
  //
  // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
  // on catchpads and cleanuppads because it does not outline them into
  // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
  // should remove PHIs there. WinEHPrepare derives this from the Wasm
  // personality, so no explicit flag is needed here.
  if (TM->supportsExceptionModel(ExceptionHandling::WinEH) ||
      TM->supportsExceptionModel(ExceptionHandling::Wasm)) {
    addPass(createWinEHPass());
    HasEHPrep = true;
  }

  if (TM->supportsExceptionModel(ExceptionHandling::Wasm))
    addPass(createWasmEHPass());

  if (TM->supportsExceptionModel(ExceptionHandling::DwarfCFI)) {
    addPass(createDwarfEHPass(getOptLevel()));
    HasEHPrep = true;
  }

  // If the target supports no exception model, nothing else lowers invokes.
  if (!HasEHPrep) {
    addPass(createLowerInvokePass());

    // The lower invoke pass may create unreachable code. Remove it.
    addPass(createUnreachableBlockEliminationPass());
  }
}

/// Add pass to prepare the LLVM IR for code generation. This should be done
/// before exception handling preparation passes.
void TargetPassConfig::addCodeGenPrepare() {
  if (getOptLevel() != CodeGenOptLevel::None && !Opts.disable_cgp)
    addPass(createCodeGenPrepareLegacyPass());
}

/// Add common passes that perform LLVM IR to IR transforms in preparation for
/// instruction selection.
void TargetPassConfig::addISelPrepare() {
  addPreISel();

  // Force codegen to run according to the callgraph.
  if (requiresCodeGenSCCOrder())
    addPass(new DummyCGSCCPass);

  addPass(createInlineAsmPreparePass());

  // Add both the safe stack and the stack protection passes: each of them will
  // only protect functions that have corresponding attributes.
  addPass(createSafeStackPass());
  addPass(createStackProtectorPass());

  if (Opts.print_isel_input)
    addPass(createPrintFunctionPass(
        dbgs(), "\n\n*** Final LLVM Code input to ISel ***\n"));

  // All passes which modify the LLVM IR are now complete; run the verifier
  // to ensure that the IR is valid.
  if (!DisableVerify)
    addPass(createVerifierPass());
}

bool TargetPassConfig::addCoreISelPasses() {
  // Enable FastISel with -fast-isel, but allow that to be overridden.
  TM->setO0WantsFastISel(valueOr(Opts.fast_isel, true));

  // Determine an instruction selector.
  enum class SelectorType { SelectionDAG, FastISel, GlobalISel };
  SelectorType Selector;

  if (valueOr(Opts.fast_isel, false))
    Selector = SelectorType::FastISel;
  else if (valueOr(Opts.global_isel, false) ||
           (TM->Options.EnableGlobalISel && valueOr(Opts.global_isel, true)))
    Selector = SelectorType::GlobalISel;
  else if (TM->getOptLevel() == CodeGenOptLevel::None &&
           TM->getO0WantsFastISel())
    Selector = SelectorType::FastISel;
  else
    Selector = SelectorType::SelectionDAG;

  // Set consistently TM->Options.EnableFastISel and EnableGlobalISel.
  if (Selector == SelectorType::FastISel) {
    TM->setFastISel(true);
    TM->setGlobalISel(false);
  } else if (Selector == SelectorType::GlobalISel) {
    TM->setFastISel(false);
    TM->setGlobalISel(true);
  }

  // FIXME: Injecting into the DAGISel pipeline seems to cause issues with
  //        analyses needing to be re-run. This can result in being unable to
  //        schedule passes (particularly with 'Function Alias Analysis
  //        Results'). It's not entirely clear why but AFAICT this seems to be
  //        due to one FunctionPassManager not being able to use analyses from a
  //        previous one. As we're injecting a ModulePass we break the usual
  //        pass manager into two. GlobalISel with the fallback path disabled
  //        and -run-pass seem to be unaffected. The majority of GlobalISel
  //        testing uses -run-pass so this probably isn't too bad.
  SaveAndRestore SavedDebugifyIsSafe(DebugifyIsSafe);
  if (Selector != SelectorType::GlobalISel || !isGlobalISelAbortEnabled())
    DebugifyIsSafe = false;

  // Add instruction selector passes for global isel if enabled.
  if (Selector == SelectorType::GlobalISel) {
    SaveAndRestore SavedAddingMachinePasses(AddingMachinePasses, true);
    if (addIRTranslator())
      return true;

    addPreLegalizeMachineIR();

    if (addLegalizeMachineIR())
      return true;

    // Before running the register bank selector, ask the target if it
    // wants to run some passes.
    addPreRegBankSelect();

    if (addRegBankSelect())
      return true;

    addPreGlobalInstructionSelect();

    if (addGlobalInstructionSelect())
      return true;
  }

  // Pass to reset the MachineFunction if the ISel failed. Outside of the above
  // if so that the verifier is not added to it.
  if (Selector == SelectorType::GlobalISel)
    addPass(createResetMachineFunctionLegacyPass(
        reportDiagnosticWhenGlobalISelFallback(), isGlobalISelAbortEnabled()));

  // Run the SDAG InstSelector, providing a fallback path when we do not want to
  // abort on not-yet-supported input.
  if (Selector != SelectorType::GlobalISel || !isGlobalISelAbortEnabled())
    if (addInstSelector())
      return true;

  // Expand pseudo-instructions emitted by ISel. Don't run the verifier before
  // FinalizeISel.
  addPass(&FinalizeISelID);

  // Print the instruction selected machine code...
  printAndVerify("After Instruction Selection");

  return false;
}

bool TargetPassConfig::addISelPasses() {
  if (TM->useEmulatedTLS())
    addPass(createLowerEmuTLSPass());

  PM->add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
  // ObjCARCContract operates on ObjC intrinsics and must run before
  // PreISelIntrinsicLowering.
  if (getOptLevel() != CodeGenOptLevel::None)
    addPass(createObjCARCContractPass());
  addPass(createPreISelIntrinsicLoweringPass());
  addPass(createExpandIRInstsPass(getOptLevel()));
  addIRPasses();

  if (Opts.codegen_pipeline_trigger_crash)
    addPass(new TriggerCrashFunctionLegacyPass());

  addCodeGenPrepare();
  addPassesToHandleExceptions();
  addISelPrepare();

  return addCoreISelPasses();
}

/// -regalloc=... command line option.
static FunctionPass *useDefaultRegisterAllocator() { return nullptr; }
static cl::opt<RegisterRegAlloc::FunctionPassCtor, false,
               RegisterPassParser<RegisterRegAlloc>>
    RegAlloc("regalloc", cl::Hidden, cl::init(&useDefaultRegisterAllocator),
             cl::desc("Register allocator to use"));

/// Add the complete set of target-independent postISel code generator passes.
///
/// This can be read as the standard order of major LLVM CodeGen stages. Stages
/// with nontrivial configuration or multiple passes are broken out below in
/// add%Stage routines.
///
/// Any TargetPassConfig::addXX routine may be overriden by the Target. The
/// addPre/Post methods with empty header implementations allow injecting
/// target-specific fixups just before or after major stages. Additionally,
/// targets have the flexibility to change pass order within a stage by
/// overriding default implementation of add%Stage routines below. Each
/// technique has maintainability tradeoffs because alternate pass orders are
/// not well supported. addPre/Post works better if the target pass is easily
/// tied to a common pass. But if it has subtle dependencies on multiple passes,
/// the target should override the stage instead.
///
/// TODO: We could use a single addPre/Post(ID) hook to allow pass injection
/// before/after any target-independent pass. But it's currently overkill.
void TargetPassConfig::addMachinePasses() {
  AddingMachinePasses = true;

  // Add passes that optimize machine instructions in SSA form.
  if (getOptLevel() != CodeGenOptLevel::None) {
    addMachineSSAOptimization();
  } else {
    // If the target requests it, assign local variables to stack slots relative
    // to one another and simplify frame index references where possible.
    addPass(&LocalStackSlotAllocationID);
  }

  if (TM->Options.EnableIPRA)
    addPass(createRegUsageInfoPropPass());

  if (getOptLevel() != CodeGenOptLevel::None &&
      valueOr(getOpts(*TM).enable_pipeliner, isMachinePipelinerEnabled()))
    addPass(&MachinePipelinerID);

  // Run pre-ra passes.
  addPreRegAlloc();

  // Debugifying the register allocator passes seems to provoke some
  // non-determinism that affects CodeGen and there doesn't seem to be a point
  // where it becomes safe again so stop debugifying here.
  DebugifyIsSafe = false;

  // Add a FSDiscriminator pass right before RA, so that we could get
  // more precise SampleFDO profile for RA.
  if (EnableFSDiscriminator) {
    addPass(createMIRAddFSDiscriminatorsPass(
        sampleprof::FSDiscriminatorPass::Pass1));
    const std::string ProfileFile = getFSProfileFile(Opts, TM);
    if (!ProfileFile.empty() && !Opts.disable_ra_fsprofile_loader)
      addPass(createMIRProfileLoaderPass(
          ProfileFile, getFSRemappingFile(Opts, TM),
          sampleprof::FSDiscriminatorPass::Pass1, nullptr));
  }

  // Run register allocation and passes that are tightly coupled with it,
  // including phi elimination and scheduling.
  if (getOptimizeRegAlloc())
    addOptimizedRegAlloc();
  else
    addFastRegAlloc();

  // Run post-ra passes.
  addPostRegAlloc();

  addPass(&RemoveRedundantDebugValuesID);

  addPass(&FixupStatepointCallerSavedID);

  // Insert prolog/epilog code.  Eliminate abstract frame index references...
  if (getOptLevel() != CodeGenOptLevel::None) {
    addPass(&PostRAMachineSinkingID);
    addPass(&ShrinkWrapID);
  }

  // Prolog/Epilog inserter needs a TargetMachine to instantiate. But only
  // do so if it hasn't been disabled, substituted, or overridden.
  if (!isPassSubstitutedOrOverridden(&PrologEpilogCodeInserterID))
      addPass(createPrologEpilogInserterPass());

  /// Add passes that optimize machine instructions after register allocation.
  if (getOptLevel() != CodeGenOptLevel::None)
      addMachineLateOptimization();

  // Expand pseudo instructions before second scheduling pass.
  addPass(&ExpandPostRAPseudosID);

  // Run pre-sched2 passes.
  addPreSched2();

  if (Opts.enable_implicit_null_checks)
    addPass(&ImplicitNullChecksID);

  // Second pass scheduler.
  // Let Target optionally insert this pass by itself at some other
  // point.
  if (getOptLevel() != CodeGenOptLevel::None &&
      !TM->targetSchedulesPostRAScheduling()) {
    if (Opts.misched_postra)
      addPass(&PostMachineSchedulerID);
    else
      addPass(&PostRASchedulerID);
  }

  // GC
  addGCPasses();

  // Basic block placement.
  if (getOptLevel() != CodeGenOptLevel::None)
    addBlockPlacement();

  // Insert before XRay Instrumentation.
  addPass(&FEntryInserterID);

  addPass(&XRayInstrumentationID);
  addPass(&PatchableFunctionID);

  addPreEmitPass();

  if (TM->Options.EnableIPRA)
    // Collect register usage information and produce a register mask of
    // clobbered registers, to be used to optimize call sites.
    addPass(createRegUsageInfoCollector());

  // FIXME: Some backends are incompatible with running the verifier after
  // addPreEmitPass.  Maybe only pass "false" here for those targets?
  addPass(&FuncletLayoutID);

  addPass(&RemoveLoadsIntoFakeUsesID);
  addPass(&StackMapLivenessID);
  addPass(&LiveDebugValuesID);
  addPass(&MachineSanitizerBinaryMetadataID);

  if (TM->Options.EnableMachineOutliner &&
      getOptLevel() != CodeGenOptLevel::None &&
      EnableMachineOutliner != RunOutliner::NeverOutline) {
    if (EnableMachineOutliner != RunOutliner::TargetDefault ||
        TM->supportsDefaultOutlining())
      addPass(createMachineOutlinerPass(EnableMachineOutliner));
  }

  if (Opts.enable_gc_empty_basic_blocks)
    addPass(llvm::createGCEmptyBasicBlocksLegacyPass());

  if (EnableFSDiscriminator)
    addPass(createMIRAddFSDiscriminatorsPass(
        sampleprof::FSDiscriminatorPass::PassLast));

  const bool SplitFunctionsWithPGO =
      TM->Options.FunctionSplitting == FunctionSplittingMode::All;

  if (SplitFunctionsWithPGO || Opts.split_static_data ||
      TM->Options.EnableStaticDataPartitioning) {
    const std::string ProfileFile = getFSProfileFile(Opts, TM);
    if (!ProfileFile.empty()) {
      if (EnableFSDiscriminator) {
        addPass(createMIRProfileLoaderPass(
            ProfileFile, getFSRemappingFile(Opts, TM),
            sampleprof::FSDiscriminatorPass::PassLast, nullptr));
      } else {
        // Sample profile is given, but FSDiscriminator is not
        // enabled, this may result in performance regression.
        WithColor::warning()
            << "Using AutoFDO without FSDiscriminator for MFS may regress "
               "performance.\n";
      }
    }
  }

  if (Opts.split_static_data || TM->Options.EnableStaticDataPartitioning) {
    // The static data splitter pass is a machine function pass. and
    // static data annotator pass is a module-wide pass. See the file comment
    // in StaticDataAnnotator.cpp for the motivation.
    addPass(createStaticDataSplitterLegacyPass());
    addPass(createStaticDataAnnotatorLegacyPass());
  }
  // We run the BasicBlockSections pass if we need BB sections, BB address map,
  // or function splitting. With function splitting, functions which are
  // eligible for basic-block-sections optimizations (`=all`, or `=list=` with
  // function included in the list profile) get that optimization, and the other
  // functions are split using their PGO/AutoFDO profile.
  if (TM->getBBSectionsType() != llvm::BasicBlockSection::None ||
      TM->Options.BBAddrMap || SplitFunctionsWithPGO) {
    if (shouldEmitBBHash() || Opts.basic_block_section_match_infer)
      addPass(llvm::createMachineBlockHashInfoPass());
    if (TM->getBBSectionsType() == llvm::BasicBlockSection::List) {
      addPass(llvm::createBasicBlockSectionsProfileReaderWrapperPass(
          TM->getBBSectionsFuncListBuf()));
      if (!Opts.basic_block_section_match_infer || Opts.propeller_match_bbid)
        addPass(llvm::createBasicBlockPathCloningPass());
      if (Opts.basic_block_section_match_infer)
        addPass(llvm::createBasicBlockMatchingAndInferencePass());
      else
        addPass(llvm::createInsertCodePrefetchPass());
    }
    addPass(llvm::createBasicBlockSectionsPass(SplitFunctionsWithPGO));
  }

  addPostBBSections();

  if (!Opts.disable_cfi_fixup && TM->Options.EnableCFIFixup)
    addPass(createCFIFixupLegacy());

  PM->add(createStackFrameLayoutAnalysisPass());

  // Add passes that directly emit MI after all other MI passes.
  addPreEmitPass2();

  AddingMachinePasses = false;
}

/// Add passes that optimize machine instructions in SSA form.
void TargetPassConfig::addMachineSSAOptimization() {
  // Pre-ra tail duplication.
  addPass(&EarlyTailDuplicateLegacyID);

  // Optimize PHIs before DCE: removing dead PHI cycles may make more
  // instructions dead.
  addPass(&OptimizePHIsLegacyID);

  // This pass merges large allocas. StackSlotColoring is a different pass
  // which merges spill slots.
  addPass(&StackColoringLegacyID);

  // If the target requests it, assign local variables to stack slots relative
  // to one another and simplify frame index references where possible.
  addPass(&LocalStackSlotAllocationID);

  // With optimization, dead code should already be eliminated. However
  // there is one known exception: lowered code for arguments that are only
  // used by tail calls, where the tail calls reuse the incoming stack
  // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
  addPass(&DeadMachineInstructionElimID);

  // Allow targets to insert passes that improve instruction level parallelism,
  // like if-conversion. Such passes will typically need dominator trees and
  // loop info, just like LICM and CSE below.
  addILPOpts();

  addPass(&EarlyMachineLICMID);
  addPass(&MachineCSELegacyID);

  addPass(&MachineSinkingLegacyID);

  addPass(&PeepholeOptimizerLegacyID);
  // Clean-up the dead code that may have been generated by peephole
  // rewriting.
  addPass(&DeadMachineInstructionElimID);
}

//===---------------------------------------------------------------------===//
/// Register Allocation Pass Configuration
//===---------------------------------------------------------------------===//

/// A dummy default pass factory indicates whether the register allocator is
/// overridden on the command line.
static llvm::once_flag InitializeDefaultRegisterAllocatorFlag;

static RegisterRegAlloc
defaultRegAlloc("default",
                "pick register allocator based on -O option",
                useDefaultRegisterAllocator);

static void initializeDefaultRegisterAllocatorOnce() {
  if (!RegisterRegAlloc::getDefault())
    RegisterRegAlloc::setDefault(RegAlloc);
}

bool TargetPassConfig::getOptimizeRegAlloc() const {
  // An explicit -regalloc choice implies its pipeline: only the fast
  // allocator uses the unoptimized one.
  llvm::call_once(InitializeDefaultRegisterAllocatorFlag,
                  initializeDefaultRegisterAllocatorOnce);
  RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault();
  if (Ctor != (RegisterRegAlloc::FunctionPassCtor)&useDefaultRegisterAllocator)
    return Ctor !=
           (RegisterRegAlloc::FunctionPassCtor)&createFastRegisterAllocator;
  return getOptLevel() != CodeGenOptLevel::None;
}

/// Instantiate the default register allocator pass for this target for either
/// the optimized or unoptimized allocation path. This will be added to the pass
/// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc
/// in the optimized case.
///
/// A target that uses the standard regalloc pass order for fast or optimized
/// allocation may still override this for per-target regalloc
/// selection. But -regalloc=... always takes precedence.
FunctionPass *TargetPassConfig::createTargetRegisterAllocator(bool Optimized) {
  if (Optimized)
    return createGreedyRegisterAllocator();
  else
    return createFastRegisterAllocator();
}

/// Find and instantiate the register allocation pass requested by this target
/// at the current optimization level.  Different register allocators are
/// defined as separate passes because they may require different analysis.
///
/// This helper ensures that the regalloc= option is always available,
/// even for targets that override the default allocator.
///
/// FIXME: When MachinePassRegistry register pass IDs instead of function ptrs,
/// this can be folded into addPass.
FunctionPass *TargetPassConfig::createRegAllocPass(bool Optimized) {
  // getOptimizeRegAlloc, called before the pipeline branches, has initialized
  // the global default.
  RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault();
  if (Ctor != useDefaultRegisterAllocator)
    return Ctor();

  // With no -regalloc= override, ask the target for a regalloc pass.
  return createTargetRegisterAllocator(Optimized);
}

bool TargetPassConfig::isCustomizedRegAlloc() {
  return RegAlloc !=
         (RegisterRegAlloc::FunctionPassCtor)&useDefaultRegisterAllocator;
}

bool TargetPassConfig::addRegAssignAndRewriteFast() {
  if (RegAlloc != (RegisterRegAlloc::FunctionPassCtor)&useDefaultRegisterAllocator &&
      RegAlloc != (RegisterRegAlloc::FunctionPassCtor)&createFastRegisterAllocator)
    reportFatalUsageError(
        "Must use fast (default) register allocator for unoptimized regalloc.");

  addPass(createRegAllocPass(false));

  return true;
}

bool TargetPassConfig::addRegAssignAndRewriteOptimized() {
  // Add the selected register allocation pass.
  addPass(createRegAllocPass(true));

  // Allow targets to change the register assignments before rewriting.
  addPreRewrite();

  // Finally rewrite virtual registers.
  addPass(&VirtRegRewriterID);

  // Regalloc scoring for ML-driven eviction - noop except when learning a new
  // eviction policy.
  addPass(createRegAllocScoringPass());
  return true;
}

/// Return true if the default global register allocator is in use and
/// has not be overriden on the command line with '-regalloc=...'
bool TargetPassConfig::usingDefaultRegAlloc() const {
  return RegAlloc.getNumOccurrences() == 0;
}

/// Add the minimum set of target-independent passes that are required for
/// register allocation. No coalescing or scheduling.
void TargetPassConfig::addFastRegAlloc() {
  addPass(&PHIEliminationID);
  if (!TM->enableTiedFastRegAlloc())
    addPass(&TwoAddressInstructionPassID);

  addRegAssignAndRewriteFast();
}

/// Add standard target-independent passes that are tightly coupled with
/// optimized register allocation, including coalescing, machine instruction
/// scheduling, and register allocation itself.
void TargetPassConfig::addOptimizedRegAlloc() {
  addPass(&DetectDeadLanesID);

  addPass(&InitUndefID);

  addPass(&ProcessImplicitDefsID);

  // LiveIntervals requires pure SSA form and no unreachable blocks.
  // Explicit addition of UnreachableMachineBlockElim allows stopping before or
  // after it with -stop-before/-stop-after.
  addPass(&UnreachableMachineBlockElimID);

  // Run SSA machine scheduler runs just before PHI elimination.
  if (EnableSSAMachineScheduler) {
    addPass(&LiveIntervalsID);
    addPass(&SSAMachineSchedulerID);
  }

  // LiveIntervals is computed unconditionally before TwoAddressInstruction so
  // that pass can rely on it instead of LiveVariables. This is a step toward
  // removing LiveVariables entirely.
  addPass(&LiveIntervalsID);

  // Edge splitting is smarter with machine loop info.
  addPass(&MachineLoopInfoID);
  addPass(&PHIEliminationID);

  addPass(&TwoAddressInstructionPassID);
  addPass(&RegisterCoalescerID);

  // The machine scheduler may accidentally create disconnected components
  // when moving subregister definitions around, avoid this by splitting them to
  // separate vregs before. Splitting can also improve reg. allocation quality.
  addPass(&RenameIndependentSubregsID);

  // PreRA instruction scheduling.
  addPass(&MachineSchedulerID);

  if (addRegAssignAndRewriteOptimized()) {
    // Perform stack slot coloring and post-ra machine LICM.
    addPass(&StackSlotColoringID);

    // Allow targets to expand pseudo instructions depending on the choice of
    // registers before MachineCopyPropagation.
    addPostRewrite();

    // Copy propagate to forward register uses and try to eliminate COPYs that
    // were not coalesced.
    addPass(&MachineCopyPropagationID);

    // Run post-ra machine LICM to hoist reloads / remats.
    //
    // FIXME: can this move into MachineLateOptimization?
    addPass(&MachineLICMID);
  }
}

//===---------------------------------------------------------------------===//
/// Post RegAlloc Pass Configuration
//===---------------------------------------------------------------------===//

/// Add passes that optimize machine instructions after register allocation.
void TargetPassConfig::addMachineLateOptimization() {
  // Cleanup of redundant immediate/address loads.
  addPass(&MachineLateInstrsCleanupID);

  // Branch folding must be run after regalloc and prolog/epilog insertion.
  addPass(&BranchFolderPassID);

  // Tail duplication.
  // Note that duplicating tail just increases code size and degrades
  // performance for targets that require Structured Control Flow.
  // In addition it can also make CFG irreducible. Thus we disable it.
  if (!TM->requiresStructuredCFG())
    addPass(&TailDuplicateLegacyID);

  // Copy propagation.
  addPass(&MachineCopyPropagationID);
}

/// Add standard GC passes.
bool TargetPassConfig::addGCPasses() {
  addPass(&GCMachineCodeAnalysisID);
  return true;
}

/// Add standard basic block placement passes.
void TargetPassConfig::addBlockPlacement() {
  if (EnableFSDiscriminator) {
    addPass(createMIRAddFSDiscriminatorsPass(
        sampleprof::FSDiscriminatorPass::Pass2));
    const std::string ProfileFile = getFSProfileFile(Opts, TM);
    if (!ProfileFile.empty() && !Opts.disable_layout_fsprofile_loader)
      addPass(createMIRProfileLoaderPass(
          ProfileFile, getFSRemappingFile(Opts, TM),
          sampleprof::FSDiscriminatorPass::Pass2, nullptr));
  }
  if (addPass(&MachineBlockPlacementID)) {
    // Run a separate pass to collect block placement statistics.
    if (Opts.enable_block_placement_stats)
      addPass(&MachineBlockPlacementStatsID);
  }
}

//===---------------------------------------------------------------------===//
/// GlobalISel Configuration
//===---------------------------------------------------------------------===//
bool TargetPassConfig::isGlobalISelAbortEnabled() const {
  return TM->Options.GlobalISelAbort == GlobalISelAbortMode::Enable;
}

bool TargetPassConfig::reportDiagnosticWhenGlobalISelFallback() const {
  return TM->Options.GlobalISelAbort == GlobalISelAbortMode::DisableWithDiag;
}

std::unique_ptr<CSEConfigBase> TargetPassConfig::getCSEConfig() const {
  return std::make_unique<CSEConfigBase>();
}
