llvm/llvm/lib/CodeGen/TargetPassConfig.cpp

//===- 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 "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/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>

usingnamespacellvm;

static cl::opt<bool>
    EnableIPRA("enable-ipra", cl::init(false), cl::Hidden,
               cl::desc("Enable interprocedural register allocation "
                        "to reduce load/store at procedure calls."));
static cl::opt<bool> DisablePostRASched("disable-post-ra", cl::Hidden,
    cl::desc("Disable Post Regalloc Scheduler"));
static cl::opt<bool> DisableBranchFold("disable-branch-fold", cl::Hidden,
    cl::desc("Disable branch folding"));
static cl::opt<bool> DisableTailDuplicate("disable-tail-duplicate", cl::Hidden,
    cl::desc("Disable tail duplication"));
static cl::opt<bool> DisableEarlyTailDup("disable-early-taildup", cl::Hidden,
    cl::desc("Disable pre-register allocation tail duplication"));
static cl::opt<bool> DisableBlockPlacement("disable-block-placement",
    cl::Hidden, cl::desc("Disable probability-driven block placement"));
static cl::opt<bool> EnableBlockPlacementStats("enable-block-placement-stats",
    cl::Hidden, cl::desc("Collect probability-driven block placement stats"));
static cl::opt<bool> DisableSSC("disable-ssc", cl::Hidden,
    cl::desc("Disable Stack Slot Coloring"));
static cl::opt<bool> DisableMachineDCE("disable-machine-dce", cl::Hidden,
    cl::desc("Disable Machine Dead Code Elimination"));
static cl::opt<bool> DisableEarlyIfConversion("disable-early-ifcvt", cl::Hidden,
    cl::desc("Disable Early If-conversion"));
static cl::opt<bool> DisableMachineLICM("disable-machine-licm", cl::Hidden,
    cl::desc("Disable Machine LICM"));
static cl::opt<bool> DisableMachineCSE("disable-machine-cse", cl::Hidden,
    cl::desc("Disable Machine Common Subexpression Elimination"));
static cl::opt<cl::boolOrDefault> OptimizeRegAlloc(
    "optimize-regalloc", cl::Hidden,
    cl::desc("Enable optimized register allocation compilation path."));
static cl::opt<bool> DisablePostRAMachineLICM("disable-postra-machine-licm",
    cl::Hidden,
    cl::desc("Disable Machine LICM"));
static cl::opt<bool> DisableMachineSink("disable-machine-sink", cl::Hidden,
    cl::desc("Disable Machine Sinking"));
static cl::opt<bool> DisablePostRAMachineSink("disable-postra-machine-sink",
    cl::Hidden,
    cl::desc("Disable PostRA Machine Sinking"));
static cl::opt<bool> DisableLSR("disable-lsr", cl::Hidden,
    cl::desc("Disable Loop Strength Reduction Pass"));
static cl::opt<bool> DisableConstantHoisting("disable-constant-hoisting",
    cl::Hidden, cl::desc("Disable ConstantHoisting"));
static cl::opt<bool> DisableCGP("disable-cgp", cl::Hidden,
    cl::desc("Disable Codegen Prepare"));
static cl::opt<bool> DisableCopyProp("disable-copyprop", cl::Hidden,
    cl::desc("Disable Copy Propagation pass"));
static cl::opt<bool> DisablePartialLibcallInlining("disable-partial-libcall-inlining",
    cl::Hidden, cl::desc("Disable Partial Libcall Inlining"));
static cl::opt<bool> DisableAtExitBasedGlobalDtorLowering(
    "disable-atexit-based-global-dtor-lowering", cl::Hidden,
    cl::desc("For MachO, disable atexit()-based global destructor lowering"));
static cl::opt<bool> EnableImplicitNullChecks(
    "enable-implicit-null-checks",
    cl::desc("Fold null checks into faulting memory operations"),
    cl::init(false), cl::Hidden);
static cl::opt<bool> DisableMergeICmps("disable-mergeicmps",
    cl::desc("Disable MergeICmps Pass"),
    cl::init(false), cl::Hidden);
static cl::opt<bool> PrintLSR("print-lsr-output", cl::Hidden,
    cl::desc("Print LLVM IR produced by the loop-reduce pass"));
static cl::opt<bool>
    PrintISelInput("print-isel-input", cl::Hidden,
                   cl::desc("Print LLVM IR input to isel pass"));
static cl::opt<cl::boolOrDefault>
    VerifyMachineCode("verify-machineinstrs", cl::Hidden,
                      cl::desc("Verify generated machine code"));
static cl::opt<cl::boolOrDefault>
    DebugifyAndStripAll("debugify-and-strip-all-safe", cl::Hidden,
                        cl::desc("Debugify MIR before and Strip debug after "
                                 "each pass except those known to be unsafe "
                                 "when debug info is present"));
static cl::opt<cl::boolOrDefault> DebugifyCheckAndStripAll(
    "debugify-check-and-strip-all-safe", cl::Hidden,
    cl::desc(
        "Debugify MIR before, by checking and stripping the debug info after, "
        "each pass except those known to be unsafe when debug info is "
        "present"));
// 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::NeverOutline, "never",
                          "Disable all outlining"),
               // Sentinel value for unspecified option.
               clEnumValN(RunOutliner::AlwaysOutline, "", "")));
// Disable the pass to fix unwind information. Whether the pass is included in
// the pipeline is controlled via the target options, this option serves as
// manual override.
static cl::opt<bool> DisableCFIFixup("disable-cfi-fixup", cl::Hidden,
                                     cl::desc("Disable the CFI fixup pass"));
// Enable or disable FastISel. Both options are needed, because
// FastISel is enabled by default with -fast, and we wish to be
// able to enable or disable fast-isel independently from -O0.
static cl::opt<cl::boolOrDefault>
EnableFastISelOption("fast-isel", cl::Hidden,
  cl::desc("Enable the \"fast\" instruction selector"));

static cl::opt<cl::boolOrDefault> EnableGlobalISelOption(
    "global-isel", cl::Hidden,
    cl::desc("Enable the \"global\" instruction selector"));

// FIXME: remove this after switching to NPM or GlobalISel, whichever gets there
//        first...
static cl::opt<bool>
    PrintAfterISel("print-after-isel", cl::init(false), cl::Hidden,
                   cl::desc("Print machine instrs after ISel"));

static cl::opt<GlobalISelAbortMode> EnableGlobalISelAbort(
    "global-isel-abort", cl::Hidden,
    cl::desc("Enable abort calls when \"global\" instruction selection "
             "fails to lower/select an instruction"),
    cl::values(
        clEnumValN(GlobalISelAbortMode::Disable, "0", "Disable the abort"),
        clEnumValN(GlobalISelAbortMode::Enable, "1", "Enable the abort"),
        clEnumValN(GlobalISelAbortMode::DisableWithDiag, "2",
                   "Disable the abort but emit a diagnostic on failure")));

// Disable MIRProfileLoader before RegAlloc. This is for for debugging and
// tuning purpose.
static cl::opt<bool> DisableRAFSProfileLoader(
    "disable-ra-fsprofile-loader", cl::init(false), cl::Hidden,
    cl::desc("Disable MIRProfileLoader before RegAlloc"));
// Disable MIRProfileLoader before BloackPlacement. This is for for debugging
// and tuning purpose.
static cl::opt<bool> DisableLayoutFSProfileLoader(
    "disable-layout-fsprofile-loader", cl::init(false), cl::Hidden,
    cl::desc("Disable MIRProfileLoader before BlockPlacement"));
// Specify FSProfile file name.
static cl::opt<std::string>
    FSProfileFile("fs-profile-file", cl::init(""), cl::value_desc("filename"),
                  cl::desc("Flow Sensitive profile file name."), cl::Hidden);
// Specify Remapping file for FSProfile.
static cl::opt<std::string> FSRemappingFile(
    "fs-remapping-file", cl::init(""), cl::value_desc("filename"),
    cl::desc("Flow Sensitive profile remapping file name."), cl::Hidden);

// Temporary option to allow experimenting with MachineScheduler as a post-RA
// scheduler. Targets can "properly" enable this with
// substitutePass(&PostRASchedulerID, &PostMachineSchedulerID).
// Targets can return true in targetSchedulesPostRAScheduling() and
// insert a PostRA scheduling pass wherever it wants.
static cl::opt<bool> MISchedPostRA(
    "misched-postra", cl::Hidden,
    cl::desc(
        "Run MachineScheduler post regalloc (independent of preRA sched)"));

// Experimental option to run live interval analysis early.
static cl::opt<bool> EarlyLiveIntervals("early-live-intervals", cl::Hidden,
    cl::desc("Run live interval analysis earlier in the pipeline"));

static cl::opt<bool> DisableReplaceWithVecLib(
    "disable-replace-with-vec-lib", cl::Hidden,
    cl::desc("Disable replace with vector math call pass"));

/// 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[] =;
static const char StartBeforeOptName[] =;
static const char StopAfterOptName[] =;
static const char StopBeforeOptName[] =;

static cl::opt<std::string>
    StartAfterOpt(StringRef(StartAfterOptName),
                  cl::desc("Resume compilation after a specific pass"),
                  cl::value_desc("pass-name"), cl::init(""), cl::Hidden);

static cl::opt<std::string>
    StartBeforeOpt(StringRef(StartBeforeOptName),
                   cl::desc("Resume compilation before a specific pass"),
                   cl::value_desc("pass-name"), cl::init(""), cl::Hidden);

static cl::opt<std::string>
    StopAfterOpt(StringRef(StopAfterOptName),
                 cl::desc("Stop compilation after a specific pass"),
                 cl::value_desc("pass-name"), cl::init(""), cl::Hidden);

static cl::opt<std::string>
    StopBeforeOpt(StringRef(StopBeforeOptName),
                  cl::desc("Stop compilation before a specific pass"),
                  cl::value_desc("pass-name"), cl::init(""), cl::Hidden);

/// Enable the machine function splitter pass.
static cl::opt<bool> EnableMachineFunctionSplitter(
    "enable-split-machine-functions", cl::Hidden,
    cl::desc("Split out cold blocks from machine functions based on profile "
             "information."));

/// Disable the expand reductions pass for testing.
static cl::opt<bool> DisableExpandReductions(
    "disable-expand-reductions", cl::init(false), cl::Hidden,
    cl::desc("Disable the expand reduction intrinsics pass from running"));

/// Disable the select optimization pass.
static cl::opt<bool> DisableSelectOptimize(
    "disable-select-optimize", cl::init(true), cl::Hidden,
    cl::desc("Disable the select-optimization pass from running"));

/// Enable garbage-collecting empty basic blocks.
static cl::opt<bool>
    GCEmptyBlocks("gc-empty-basic-blocks", cl::init(false), cl::Hidden,
                  cl::desc("Enable garbage-collecting empty basic blocks"));

/// 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) {}

/// 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(AnalysisID StandardID,
                                       IdentifyingPassPtr TargetID) {}

// Find the FSProfile file name. The internal option takes the precedence
// before getting from TargetMachine.
static std::string getFSProfileFile(const TargetMachine *TM) {}

// Find the Profile remapping file name. The internal option takes the
// precedence before getting from TargetMachine.
static std::string getFSRemappingFile(const TargetMachine *TM) {}

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

INITIALIZE_PASS()
char TargetPassConfig::ID =;

namespace {

struct InsertedPass {};

} // end anonymous namespace

namespace llvm {

extern cl::opt<bool> EnableFSDiscriminator;

class PassConfigImpl {};

} // end namespace llvm

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

static const PassInfo *getPassInfo(StringRef PassName) {}

static AnalysisID getPassIDFromName(StringRef PassName) {}

static std::pair<StringRef, unsigned>
getPassNameAndInstanceNum(StringRef PassName) {}

void TargetPassConfig::setStartStopPasses() {}

CGPassBuilderOption llvm::getCGPassBuilderOption() {}

void llvm::registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
                                   LLVMTargetMachine &LLVMTM) {}

Expected<TargetPassConfig::StartStopInfo>
TargetPassConfig::getStartStopInfo(PassInstrumentationCallbacks &PIC) {}

// Out of line constructor provides default values for pass options and
// registers all common codegen passes.
TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm)
    :{}

CodeGenOptLevel TargetPassConfig::getOptLevel() const {}

/// Insert InsertedPassID pass after TargetPassID.
void TargetPassConfig::insertPass(AnalysisID TargetPassID,
                                  IdentifyingPassPtr 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 *LLVMTargetMachine::createPassConfig(PassManagerBase &PM) {}

TargetPassConfig::TargetPassConfig()
  :{}

bool TargetPassConfig::willCompleteCodeGenPipeline() {}

bool TargetPassConfig::hasLimitedCodeGenPipeline() {}

std::string TargetPassConfig::getLimitedCodeGenPipelineReason() {}

// Helper to verify the analysis is really immutable.
void TargetPassConfig::setOpt(bool &Opt, bool Val) {}

void TargetPassConfig::substitutePass(AnalysisID StandardID,
                                      IdentifyingPassPtr TargetID) {}

IdentifyingPassPtr TargetPassConfig::getPassSubstitution(AnalysisID ID) const {}

bool TargetPassConfig::isPassSubstitutedOrOverridden(AnalysisID ID) const {}

/// 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) {}

/// 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) {}

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

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

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

void TargetPassConfig::addDebugifyPass() {}

void TargetPassConfig::addStripDebugPass() {}

void TargetPassConfig::addCheckDebugPass() {}

void TargetPassConfig::addMachinePrePasses(bool AllowDebugify) {}

void TargetPassConfig::addMachinePostPasses(const std::string &Banner) {}

/// Add common target configurable passes that perform LLVM IR to IR transforms
/// following machine independent optimization.
void TargetPassConfig::addIRPasses() {}

/// Turn exception handling constructs into something the code generators can
/// handle.
void TargetPassConfig::addPassesToHandleExceptions() {}

/// Add pass to prepare the LLVM IR for code generation. This should be done
/// before exception handling preparation passes.
void TargetPassConfig::addCodeGenPrepare() {}

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

bool TargetPassConfig::addCoreISelPasses() {}

bool TargetPassConfig::addISelPasses() {}

/// -regalloc=... command line option.
static FunctionPass *useDefaultRegisterAllocator() {}
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() {}

/// Add passes that optimize machine instructions in SSA form.
void TargetPassConfig::addMachineSSAOptimization() {}

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

bool TargetPassConfig::getOptimizeRegAlloc() const {}

/// 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() {}

/// 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) {}

/// 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) {}

bool TargetPassConfig::isCustomizedRegAlloc() {}

bool TargetPassConfig::addRegAssignAndRewriteFast() {}

bool TargetPassConfig::addRegAssignAndRewriteOptimized() {}

/// 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 {}

/// Add the minimum set of target-independent passes that are required for
/// register allocation. No coalescing or scheduling.
void TargetPassConfig::addFastRegAlloc() {}

/// 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() {}

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

/// Add passes that optimize machine instructions after register allocation.
void TargetPassConfig::addMachineLateOptimization() {}

/// Add standard GC passes.
bool TargetPassConfig::addGCPasses() {}

/// Add standard basic block placement passes.
void TargetPassConfig::addBlockPlacement() {}

//===---------------------------------------------------------------------===//
/// GlobalISel Configuration
//===---------------------------------------------------------------------===//
bool TargetPassConfig::isGlobalISelAbortEnabled() const {}

bool TargetPassConfig::reportDiagnosticWhenGlobalISelFallback() const {}

bool TargetPassConfig::isGISelCSEEnabled() const {}

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