diff --git a/llvm/docs/HowToUpdateDebugInfo.rst b/llvm/docs/HowToUpdateDebugInfo.rst index 7df2a8a25827..fff0cdbe59c8 100644 --- a/llvm/docs/HowToUpdateDebugInfo.rst +++ b/llvm/docs/HowToUpdateDebugInfo.rst @@ -1,424 +1,440 @@ ======================================================= How to Update Debug Info: A Guide for LLVM Pass Authors ======================================================= .. contents:: :local: Introduction ============ Certain kinds of code transformations can inadvertently result in a loss of debug info, or worse, make debug info misrepresent the state of a program. This document specifies how to correctly update debug info in various kinds of code transformations, and offers suggestions for how to create targeted debug info tests for arbitrary transformations. For more on the philosophy behind LLVM debugging information, see :doc:`SourceLevelDebugging`. Rules for updating debug locations ================================== .. _WhenToPreserveLocation: When to preserve an instruction location ---------------------------------------- A transformation should preserve the debug location of an instruction if the instruction either remains in its basic block, or if its basic block is folded into a predecessor that branches unconditionally. The APIs to use are ``IRBuilder``, or ``Instruction::setDebugLoc``. The purpose of this rule is to ensure that common block-local optimizations preserve the ability to set breakpoints on source locations corresponding to the instructions they touch. Debugging, crash logs, and SamplePGO accuracy would be severely impacted if that ability were lost. Examples of transformations that should follow this rule include: * Instruction scheduling. Block-local instruction reordering should not drop source locations, even though this may lead to jumpy single-stepping behavior. * Simple jump threading. For example, if block ``B1`` unconditionally jumps to ``B2``, *and* is its unique predecessor, instructions from ``B2`` can be hoisted into ``B1``. Source locations from ``B2`` should be preserved. * Peephole optimizations that replace or expand an instruction, like ``(add X X) => (shl X 1)``. The location of the ``shl`` instruction should be the same as the location of the ``add`` instruction. * Tail duplication. For example, if blocks ``B1`` and ``B2`` both unconditionally branch to ``B3`` and ``B3`` can be folded into its predecessors, source locations from ``B3`` should be preserved. Examples of transformations for which this rule *does not* apply include: * LICM. E.g., if an instruction is moved from the loop body to the preheader, the rule for :ref:`dropping locations` applies. .. _WhenToMergeLocation: When to merge instruction locations ----------------------------------- A transformation should merge instruction locations if it replaces multiple instructions with a single merged instruction, *and* that merged instruction does not correspond to any of the original instructions' locations. The API to use is ``Instruction::applyMergedLocation``. The purpose of this rule is to ensure that a) the single merged instruction has a location with an accurate scope attached, and b) to prevent misleading single-stepping (or breakpoint) behavior. Often, merged instructions are memory accesses which can trap: having an accurate scope attached greatly assists in crash triage by identifying the (possibly inlined) function where the bad memory access occurred. This rule is also meant to assist SamplePGO by banning scenarios in which a sample of a block containing a merged instruction is misattributed to a block containing one of the instructions-to-be-merged. Examples of transformations that should follow this rule include: * Merging identical loads/stores which occur on both sides of a CFG diamond (see the ``MergedLoadStoreMotion`` pass). * Merging identical loop-invariant stores (see the LICM utility ``llvm::promoteLoopAccessesToScalars``). * Peephole optimizations which combine multiple instructions together, like ``(add (mul A B) C) => llvm.fma.f32(A, B, C)``. Note that the location of the ``fma`` does not exactly correspond to the locations of either the ``mul`` or the ``add`` instructions. Examples of transformations for which this rule *does not* apply include: * Block-local peepholes which delete redundant instructions, like ``(sext (zext i8 %x to i16) to i32) => (zext i8 %x to i32)``. The inner ``zext`` is modified but remains in its block, so the rule for :ref:`preserving locations` should apply. * Converting an if-then-else CFG diamond into a ``select``. Preserving the debug locations of speculated instructions can make it seem like a condition is true when it's not (or vice versa), which leads to a confusing single-stepping experience. The rule for :ref:`dropping locations` should apply here. * Hoisting identical instructions which appear in several successor blocks into a predecessor block (see ``BranchFolder::HoistCommonCodeInSuccs``). In this case there is no single merged instruction. The rule for :ref:`dropping locations` applies. .. _WhenToDropLocation: When to drop an instruction location ------------------------------------ A transformation should drop debug locations if the rules for :ref:`preserving` and :ref:`merging` debug locations do not apply. The API to use is ``Instruction::dropLocation()``. The purpose of this rule is to prevent erratic or misleading single-stepping behavior in situations in which an instruction has no clear, unambiguous relationship to a source location. To handle an instruction without a location, the DWARF generator defaults to allowing the last-set location after a label to cascade forward, or to setting a line 0 location with viable scope information if no previous location is available. See the discussion in the section about :ref:`merging locations` for examples of when the rule for dropping locations applies. Rules for updating debug values =============================== Deleting an IR-level Instruction -------------------------------- When an ``Instruction`` is deleted, its debug uses change to ``undef``. This is a loss of debug info: the value of one or more source variables becomes unavailable, starting with the ``llvm.dbg.value(undef, ...)``. When there is no way to reconstitute the value of the lost instruction, this is the best possible outcome. However, it's often possible to do better: * If the dying instruction can be RAUW'd, do so. The ``Value::replaceAllUsesWith`` API transparently updates debug uses of the dying instruction to point to the replacement value. * If the dying instruction cannot be RAUW'd, call ``llvm::salvageDebugInfo`` on it. This makes a best-effort attempt to rewrite debug uses of the dying instruction by describing its effect as a ``DIExpression``. * If one of the **operands** of a dying instruction would become trivially dead, use ``llvm::replaceAllDbgUsesWith`` to rewrite the debug uses of that operand. Consider the following example function: .. code-block:: llvm define i16 @foo(i16 %a) { %b = sext i16 %a to i32 %c = and i32 %b, 15 call void @llvm.dbg.value(metadata i32 %c, ...) %d = trunc i32 %c to i16 ret i16 %d } Now, here's what happens after the unnecessary truncation instruction ``%d`` is replaced with a simplified instruction: .. code-block:: llvm define i16 @foo(i16 %a) { call void @llvm.dbg.value(metadata i32 undef, ...) %simplified = and i16 %a, 15 ret i16 %simplified } Note that after deleting ``%d``, all uses of its operand ``%c`` become trivially dead. The debug use which used to point to ``%c`` is now ``undef``, and debug info is needlessly lost. To solve this problem, do: .. code-block:: cpp llvm::replaceAllDbgUsesWith(%c, theSimplifiedAndInstruction, ...) This results in better debug info because the debug use of ``%c`` is preserved: .. code-block:: llvm define i16 @foo(i16 %a) { %simplified = and i16 %a, 15 call void @llvm.dbg.value(metadata i16 %simplified, ...) ret i16 %simplified } You may have noticed that ``%simplified`` is narrower than ``%c``: this is not a problem, because ``llvm::replaceAllDbgUsesWith`` takes care of inserting the necessary conversion operations into the DIExpressions of updated debug uses. Deleting a MIR-level MachineInstr --------------------------------- TODO How to automatically convert tests into debug info tests ======================================================== .. _IRDebugify: Mutation testing for IR-level transformations --------------------------------------------- An IR test case for a transformation can, in many cases, be automatically mutated to test debug info handling within that transformation. This is a simple way to test for proper debug info handling. The ``debugify`` utility ^^^^^^^^^^^^^^^^^^^^^^^^ The ``debugify`` testing utility is just a pair of passes: ``debugify`` and ``check-debugify``. The first applies synthetic debug information to every instruction of the module, and the second checks that this DI is still available after an optimization has occurred, reporting any errors/warnings while doing so. The instructions are assigned sequentially increasing line locations, and are immediately used by debug value intrinsics everywhere possible. For example, here is a module before: .. code-block:: llvm define void @f(i32* %x) { entry: %x.addr = alloca i32*, align 8 store i32* %x, i32** %x.addr, align 8 %0 = load i32*, i32** %x.addr, align 8 store i32 10, i32* %0, align 4 ret void } and after running ``opt -debugify``: .. code-block:: llvm define void @f(i32* %x) !dbg !6 { entry: %x.addr = alloca i32*, align 8, !dbg !12 call void @llvm.dbg.value(metadata i32** %x.addr, metadata !9, metadata !DIExpression()), !dbg !12 store i32* %x, i32** %x.addr, align 8, !dbg !13 %0 = load i32*, i32** %x.addr, align 8, !dbg !14 call void @llvm.dbg.value(metadata i32* %0, metadata !11, metadata !DIExpression()), !dbg !14 store i32 10, i32* %0, align 4, !dbg !15 ret void, !dbg !16 } !llvm.dbg.cu = !{!0} !llvm.debugify = !{!3, !4} !llvm.module.flags = !{!5} !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "debugify-sample.ll", directory: "/") !2 = !{} !3 = !{i32 5} !4 = !{i32 2} !5 = !{i32 2, !"Debug Info Version", i32 3} !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8) !7 = !DISubroutineType(types: !2) !8 = !{!9, !11} !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10) !10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned) !11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 3, type: !10) !12 = !DILocation(line: 1, column: 1, scope: !6) !13 = !DILocation(line: 2, column: 1, scope: !6) !14 = !DILocation(line: 3, column: 1, scope: !6) !15 = !DILocation(line: 4, column: 1, scope: !6) !16 = !DILocation(line: 5, column: 1, scope: !6) Using ``debugify`` ^^^^^^^^^^^^^^^^^^ A simple way to use ``debugify`` is as follows: .. code-block:: bash $ opt -debugify -pass-to-test -check-debugify sample.ll This will inject synthetic DI to ``sample.ll`` run the ``pass-to-test`` and then check for missing DI. The ``-check-debugify`` step can of course be omitted in favor of more customizable FileCheck directives. Some other ways to run debugify are available: .. code-block:: bash # Same as the above example. $ opt -enable-debugify -pass-to-test sample.ll # Suppresses verbose debugify output. $ opt -enable-debugify -debugify-quiet -pass-to-test sample.ll # Prepend -debugify before and append -check-debugify -strip after # each pass on the pipeline (similar to -verify-each). $ opt -debugify-each -O2 sample.ll In order for ``check-debugify`` to work, the DI must be coming from ``debugify``. Thus, modules with existing DI will be skipped. ``debugify`` can be used to test a backend, e.g: .. code-block:: bash $ opt -debugify < sample.ll | llc -o - There is also a MIR-level debugify pass that can be run before each backend pass, see: :ref:`Mutation testing for MIR-level transformations`. ``debugify`` in regression tests ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The output of the ``debugify`` pass must be stable enough to use in regression tests. Changes to this pass are not allowed to break existing tests. .. note:: Regression tests must be robust. Avoid hardcoding line/variable numbers in check lines. In cases where this can't be avoided (say, if a test wouldn't be precise enough), moving the test to its own file is preferred. .. _MIRDebugify: Mutation testing for MIR-level transformations ---------------------------------------------- A variant of the ``debugify`` utility described in :ref:`Mutation testing for IR-level transformations` can be used for MIR-level transformations as well: much like the IR-level pass, ``mir-debugify`` inserts sequentially increasing line locations to each -``MachineInstr`` in a ``Module`` (although there is no equivalent MIR-level -``check-debugify`` pass). +``MachineInstr`` in a ``Module``. And the MIR-level ``mir-check-debugify`` is +similar to IR-level ``check-debugify`` pass. For example, here is a snippet before: .. code-block:: llvm name: test body: | bb.1 (%ir-block.0): %0:_(s32) = IMPLICIT_DEF %1:_(s32) = IMPLICIT_DEF %2:_(s32) = G_CONSTANT i32 2 %3:_(s32) = G_ADD %0, %2 %4:_(s32) = G_SUB %3, %1 and after running ``llc -run-pass=mir-debugify``: .. code-block:: llvm name: test body: | bb.0 (%ir-block.0): %0:_(s32) = IMPLICIT_DEF debug-location !12 DBG_VALUE %0(s32), $noreg, !9, !DIExpression(), debug-location !12 %1:_(s32) = IMPLICIT_DEF debug-location !13 DBG_VALUE %1(s32), $noreg, !11, !DIExpression(), debug-location !13 %2:_(s32) = G_CONSTANT i32 2, debug-location !14 DBG_VALUE %2(s32), $noreg, !9, !DIExpression(), debug-location !14 %3:_(s32) = G_ADD %0, %2, debug-location !DILocation(line: 4, column: 1, scope: !6) DBG_VALUE %3(s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !6) %4:_(s32) = G_SUB %3, %1, debug-location !DILocation(line: 5, column: 1, scope: !6) DBG_VALUE %4(s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !6) By default, ``mir-debugify`` inserts ``DBG_VALUE`` instructions **everywhere** it is legal to do so. In particular, every (non-PHI) machine instruction that defines a register must be followed by a ``DBG_VALUE`` use of that def. If an instruction does not define a register, but can be followed by a debug inst, MIRDebugify inserts a ``DBG_VALUE`` that references a constant. Insertion of ``DBG_VALUE``'s can be disabled by setting ``-debugify-level=locations``. To run MIRDebugify once, simply insert ``mir-debugify`` into your ``llc`` invocation, like: .. code-block:: bash # Before some other pass. $ llc -run-pass=mir-debugify,other-pass ... # After some other pass. $ llc -run-pass=other-pass,mir-debugify ... To run MIRDebugify before each pass in a pipeline, use ``-debugify-and-strip-all-safe``. This can be combined with ``-start-before`` and ``-start-after``. For example: .. code-block:: bash $ llc -debugify-and-strip-all-safe -run-pass=... $ llc -debugify-and-strip-all-safe -O1 +If you want to check it after each pass in a pipeline, use +``-debugify-check-and-strip-all-safe``. This can also be combined with +``-start-before`` and ``-start-after``. For example: + +.. code-block:: bash + + $ llc -debugify-check-and-strip-all-safe -run-pass=... + $ llc -debugify-check-and-strip-all-safe -O1 + +To check all debug info from a test, use ``mir-check-debugify``, like: + +.. code-block:: bash + + $ llc -run-pass=mir-debugify,other-pass,mir-check-debugify + To strip out all debug info from a test, use ``mir-strip-debug``, like: .. code-block:: bash $ llc -run-pass=mir-debugify,other-pass,mir-strip-debug -It can be useful to combine ``mir-debugify`` and ``mir-strip-debug`` to -identify backend transformations which break in the presence of debug info. -For example, to run the AArch64 backend tests with all normal passes -"sandwiched" in between MIRDebugify and MIRStripDebugify mutation passes, run: +It can be useful to combine ``mir-debugify``, ``mir-check-debugify`` and/or +``mir-strip-debug`` to identify backend transformations which break in +the presence of debug info. For example, to run the AArch64 backend tests +with all normal passes "sandwiched" in between MIRDebugify and +MIRStripDebugify mutation passes, run: .. code-block:: bash $ llvm-lit test/CodeGen/AArch64 -Dllc="llc -debugify-and-strip-all-safe" Using LostDebugLocObserver -------------------------- TODO diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index 47037bac6270..676ed2c65eb1 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -1,494 +1,497 @@ //===-- Passes.h - Target independent code generation passes ----*- C++ -*-===// // // 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. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_PASSES_H #define LLVM_CODEGEN_PASSES_H #include "llvm/Support/CodeGen.h" #include #include namespace llvm { class FunctionPass; class MachineFunction; class MachineFunctionPass; class MemoryBuffer; class ModulePass; class Pass; class TargetMachine; class TargetRegisterClass; class raw_ostream; } // End llvm namespace /// List of target independent CodeGen pass IDs. namespace llvm { FunctionPass *createAtomicExpandPass(); /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a /// block that cannot be reached?). As such, a code generator should either /// not instruction select unreachable blocks, or run this pass as its /// last LLVM modifying pass to clean up blocks that are not reachable from /// the entry block. FunctionPass *createUnreachableBlockEliminationPass(); /// createBasicBlockSections Pass - This pass assigns sections to machine /// basic blocks and is enabled with -fbasic-block-sections. Buf is a memory /// buffer that contains the list of functions and basic block ids to /// selectively enable basic block sections. MachineFunctionPass *createBasicBlockSectionsPass(const MemoryBuffer *Buf); /// createMachineFunctionSplitterPass - This pass splits machine functions /// using profile information. MachineFunctionPass *createMachineFunctionSplitterPass(); /// MachineFunctionPrinter pass - This pass prints out the machine function to /// the given stream as a debugging tool. MachineFunctionPass * createMachineFunctionPrinterPass(raw_ostream &OS, const std::string &Banner =""); /// MIRPrinting pass - this pass prints out the LLVM IR into the given stream /// using the MIR serialization format. MachineFunctionPass *createPrintMIRPass(raw_ostream &OS); /// This pass resets a MachineFunction when it has the FailedISel property /// as if it was just created. /// If EmitFallbackDiag is true, the pass will emit a /// DiagnosticInfoISelFallback for every MachineFunction it resets. /// If AbortOnFailedISel is true, abort compilation instead of resetting. MachineFunctionPass *createResetMachineFunctionPass(bool EmitFallbackDiag, bool AbortOnFailedISel); /// createCodeGenPreparePass - Transform the code to expose more pattern /// matching during instruction selection. FunctionPass *createCodeGenPreparePass(); /// AtomicExpandID -- Lowers atomic operations in terms of either cmpxchg /// load-linked/store-conditional loops. extern char &AtomicExpandID; /// MachineLoopInfo - This pass is a loop analysis pass. extern char &MachineLoopInfoID; /// MachineDominators - This pass is a machine dominators analysis pass. extern char &MachineDominatorsID; /// MachineDominanaceFrontier - This pass is a machine dominators analysis pass. extern char &MachineDominanceFrontierID; /// MachineRegionInfo - This pass computes SESE regions for machine functions. extern char &MachineRegionInfoPassID; /// EdgeBundles analysis - Bundle machine CFG edges. extern char &EdgeBundlesID; /// LiveVariables pass - This pass computes the set of blocks in which each /// variable is life and sets machine operand kill flags. extern char &LiveVariablesID; /// PHIElimination - This pass eliminates machine instruction PHI nodes /// by inserting copy instructions. This destroys SSA information, but is the /// desired input for some register allocators. This pass is "required" by /// these register allocator like this: AU.addRequiredID(PHIEliminationID); extern char &PHIEliminationID; /// LiveIntervals - This analysis keeps track of the live ranges of virtual /// and physical registers. extern char &LiveIntervalsID; /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. extern char &LiveStacksID; /// TwoAddressInstruction - This pass reduces two-address instructions to /// use two operands. This destroys SSA information but it is desired by /// register allocators. extern char &TwoAddressInstructionPassID; /// ProcessImpicitDefs pass - This pass removes IMPLICIT_DEFs. extern char &ProcessImplicitDefsID; /// RegisterCoalescer - This pass merges live ranges to eliminate copies. extern char &RegisterCoalescerID; /// MachineScheduler - This pass schedules machine instructions. extern char &MachineSchedulerID; /// PostMachineScheduler - This pass schedules machine instructions postRA. extern char &PostMachineSchedulerID; /// SpillPlacement analysis. Suggest optimal placement of spill code between /// basic blocks. extern char &SpillPlacementID; /// ShrinkWrap pass. Look for the best place to insert save and restore // instruction and update the MachineFunctionInfo with that information. extern char &ShrinkWrapID; /// LiveRangeShrink pass. Move instruction close to its definition to shrink /// the definition's live range. extern char &LiveRangeShrinkID; /// Greedy register allocator. extern char &RAGreedyID; /// Basic register allocator. extern char &RABasicID; /// VirtRegRewriter pass. Rewrite virtual registers to physical registers as /// assigned in VirtRegMap. extern char &VirtRegRewriterID; /// UnreachableMachineBlockElimination - This pass removes unreachable /// machine basic blocks. extern char &UnreachableMachineBlockElimID; /// DeadMachineInstructionElim - This pass removes dead machine instructions. extern char &DeadMachineInstructionElimID; /// This pass adds dead/undef flags after analyzing subregister lanes. extern char &DetectDeadLanesID; /// This pass perform post-ra machine sink for COPY instructions. extern char &PostRAMachineSinkingID; /// FastRegisterAllocation Pass - This pass register allocates as fast as /// possible. It is best suited for debug code where live ranges are short. /// FunctionPass *createFastRegisterAllocator(); /// BasicRegisterAllocation Pass - This pass implements a degenerate global /// register allocator using the basic regalloc framework. /// FunctionPass *createBasicRegisterAllocator(); /// Greedy register allocation pass - This pass implements a global register /// allocator for optimized builds. /// FunctionPass *createGreedyRegisterAllocator(); /// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean /// Quadratic Prograaming (PBQP) based register allocator. /// FunctionPass *createDefaultPBQPRegisterAllocator(); /// PrologEpilogCodeInserter - This pass inserts prolog and epilog code, /// and eliminates abstract frame references. extern char &PrologEpilogCodeInserterID; MachineFunctionPass *createPrologEpilogInserterPass(); /// ExpandPostRAPseudos - This pass expands pseudo instructions after /// register allocation. extern char &ExpandPostRAPseudosID; /// PostRAHazardRecognizer - This pass runs the post-ra hazard /// recognizer. extern char &PostRAHazardRecognizerID; /// PostRAScheduler - This pass performs post register allocation /// scheduling. extern char &PostRASchedulerID; /// BranchFolding - This pass performs machine code CFG based /// optimizations to delete branches to branches, eliminate branches to /// successor blocks (creating fall throughs), and eliminating branches over /// branches. extern char &BranchFolderPassID; /// BranchRelaxation - This pass replaces branches that need to jump further /// than is supported by a branch instruction. extern char &BranchRelaxationPassID; /// MachineFunctionPrinterPass - This pass prints out MachineInstr's. extern char &MachineFunctionPrinterPassID; /// MIRPrintingPass - this pass prints out the LLVM IR using the MIR /// serialization format. extern char &MIRPrintingPassID; /// TailDuplicate - Duplicate blocks with unconditional branches /// into tails of their predecessors. extern char &TailDuplicateID; /// Duplicate blocks with unconditional branches into tails of their /// predecessors. Variant that works before register allocation. extern char &EarlyTailDuplicateID; /// MachineTraceMetrics - This pass computes critical path and CPU resource /// usage in an ensemble of traces. extern char &MachineTraceMetricsID; /// EarlyIfConverter - This pass performs if-conversion on SSA form by /// inserting cmov instructions. extern char &EarlyIfConverterID; /// EarlyIfPredicator - This pass performs if-conversion on SSA form by /// predicating if/else block and insert select at the join point. extern char &EarlyIfPredicatorID; /// This pass performs instruction combining using trace metrics to estimate /// critical-path and resource depth. extern char &MachineCombinerID; /// StackSlotColoring - This pass performs stack coloring and merging. /// It merges disjoint allocas to reduce the stack size. extern char &StackColoringID; /// IfConverter - This pass performs machine code if conversion. extern char &IfConverterID; FunctionPass *createIfConverter( std::function Ftor); /// MachineBlockPlacement - This pass places basic blocks based on branch /// probabilities. extern char &MachineBlockPlacementID; /// MachineBlockPlacementStats - This pass collects statistics about the /// basic block placement using branch probabilities and block frequency /// information. extern char &MachineBlockPlacementStatsID; /// GCLowering Pass - Used by gc.root to perform its default lowering /// operations. FunctionPass *createGCLoweringPass(); /// ShadowStackGCLowering - Implements the custom lowering mechanism /// used by the shadow stack GC. Only runs on functions which opt in to /// the shadow stack collector. FunctionPass *createShadowStackGCLoweringPass(); /// GCMachineCodeAnalysis - Target-independent pass to mark safe points /// in machine code. Must be added very late during code generation, just /// prior to output, and importantly after all CFG transformations (such as /// branch folding). extern char &GCMachineCodeAnalysisID; /// Creates a pass to print GC metadata. /// FunctionPass *createGCInfoPrinter(raw_ostream &OS); /// MachineCSE - This pass performs global CSE on machine instructions. extern char &MachineCSEID; /// MIRCanonicalizer - This pass canonicalizes MIR by renaming vregs /// according to the semantics of the instruction as well as hoists /// code. extern char &MIRCanonicalizerID; /// ImplicitNullChecks - This pass folds null pointer checks into nearby /// memory operations. extern char &ImplicitNullChecksID; /// This pass performs loop invariant code motion on machine instructions. extern char &MachineLICMID; /// This pass performs loop invariant code motion on machine instructions. /// This variant works before register allocation. \see MachineLICMID. extern char &EarlyMachineLICMID; /// MachineSinking - This pass performs sinking on machine instructions. extern char &MachineSinkingID; /// MachineCopyPropagation - This pass performs copy propagation on /// machine instructions. extern char &MachineCopyPropagationID; /// PeepholeOptimizer - This pass performs peephole optimizations - /// like extension and comparison eliminations. extern char &PeepholeOptimizerID; /// OptimizePHIs - This pass optimizes machine instruction PHIs /// to take advantage of opportunities created during DAG legalization. extern char &OptimizePHIsID; /// StackSlotColoring - This pass performs stack slot coloring. extern char &StackSlotColoringID; /// This pass lays out funclets contiguously. extern char &FuncletLayoutID; /// This pass inserts the XRay instrumentation sleds if they are supported by /// the target platform. extern char &XRayInstrumentationID; /// This pass inserts FEntry calls extern char &FEntryInserterID; /// This pass implements the "patchable-function" attribute. extern char &PatchableFunctionID; /// createStackProtectorPass - This pass adds stack protectors to functions. /// FunctionPass *createStackProtectorPass(); /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// FunctionPass *createMachineVerifierPass(const std::string& Banner); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. FunctionPass *createDwarfEHPass(CodeGenOpt::Level OptLevel); /// createWinEHPass - Prepares personality functions used by MSVC on Windows, /// in addition to the Itanium LSDA based personalities. FunctionPass *createWinEHPass(bool DemoteCatchSwitchPHIOnly = false); /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); /// createWasmEHPass - This pass adapts exception handling code to use /// WebAssembly's exception handling scheme. FunctionPass *createWasmEHPass(); /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them /// when it is estimated by the target to be out of range of normal frame /// pointer or stack pointer index addressing. extern char &LocalStackSlotAllocationID; /// This pass expands pseudo-instructions, reserves registers and adjusts /// machine frame information. extern char &FinalizeISelID; /// UnpackMachineBundles - This pass unpack machine instruction bundles. extern char &UnpackMachineBundlesID; FunctionPass * createUnpackMachineBundles(std::function Ftor); /// FinalizeMachineBundles - This pass finalize machine instruction /// bundles (created earlier, e.g. during pre-RA scheduling). extern char &FinalizeMachineBundlesID; /// StackMapLiveness - This pass analyses the register live-out set of /// stackmap/patchpoint intrinsics and attaches the calculated information to /// the intrinsic for later emission to the StackMap. extern char &StackMapLivenessID; /// LiveDebugValues pass extern char &LiveDebugValuesID; /// createJumpInstrTables - This pass creates jump-instruction tables. ModulePass *createJumpInstrTablesPass(); /// InterleavedAccess Pass - This pass identifies and matches interleaved /// memory accesses to target specific intrinsics. /// FunctionPass *createInterleavedAccessPass(); /// InterleavedLoadCombines Pass - This pass identifies interleaved loads and /// combines them into wide loads detectable by InterleavedAccessPass /// FunctionPass *createInterleavedLoadCombinePass(); /// LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all /// TLS variables for the emulated TLS model. /// ModulePass *createLowerEmuTLSPass(); /// This pass lowers the \@llvm.load.relative and \@llvm.objc.* intrinsics to /// instructions. This is unsafe to do earlier because a pass may combine the /// constant initializer into the load, which may result in an overflowing /// evaluation. ModulePass *createPreISelIntrinsicLoweringPass(); /// GlobalMerge - This pass merges internal (by default) globals into structs /// to enable reuse of a base pointer by indexed addressing modes. /// It can also be configured to focus on size optimizations only. /// Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset, bool OnlyOptimizeForSize = false, bool MergeExternalByDefault = false); /// This pass splits the stack into a safe stack and an unsafe stack to /// protect against stack-based overflow vulnerabilities. FunctionPass *createSafeStackPass(); /// This pass detects subregister lanes in a virtual register that are used /// independently of other lanes and splits them into separate virtual /// registers. extern char &RenameIndependentSubregsID; /// This pass is executed POST-RA to collect which physical registers are /// preserved by given machine function. FunctionPass *createRegUsageInfoCollector(); /// Return a MachineFunction pass that identifies call sites /// and propagates register usage information of callee to caller /// if available with PysicalRegisterUsageInfo pass. FunctionPass *createRegUsageInfoPropPass(); /// This pass performs software pipelining on machine instructions. extern char &MachinePipelinerID; /// This pass frees the memory occupied by the MachineFunction. FunctionPass *createFreeMachineFunctionPass(); /// This pass performs outlining on machine instructions directly before /// printing assembly. ModulePass *createMachineOutlinerPass(bool RunOnAllFunctions = true); /// This pass expands the experimental reduction intrinsics into sequences of /// shuffles. FunctionPass *createExpandReductionsPass(); // This pass expands memcmp() to load/stores. FunctionPass *createExpandMemCmpPass(); /// Creates Break False Dependencies pass. \see BreakFalseDeps.cpp FunctionPass *createBreakFalseDeps(); // This pass expands indirectbr instructions. FunctionPass *createIndirectBrExpandPass(); /// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp FunctionPass *createCFIInstrInserter(); /// Creates CFGuard longjmp target identification pass. /// \see CFGuardLongjmp.cpp FunctionPass *createCFGuardLongjmpPass(); /// Create Hardware Loop pass. \see HardwareLoops.cpp FunctionPass *createHardwareLoopsPass(); /// This pass inserts pseudo probe annotation for callsite profiling. FunctionPass *createPseudoProbeInserter(); /// Create IR Type Promotion pass. \see TypePromotion.cpp FunctionPass *createTypePromotionPass(); /// Creates MIR Debugify pass. \see MachineDebugify.cpp ModulePass *createDebugifyMachineModulePass(); /// Creates MIR Strip Debug pass. \see MachineStripDebug.cpp /// If OnlyDebugified is true then it will only strip debug info if it was /// added by a Debugify pass. The module will be left unchanged if the debug /// info was generated by another source such as clang. ModulePass *createStripDebugMachineModulePass(bool OnlyDebugified); + /// Creates MIR Check Debug pass. \see MachineCheckDebugify.cpp + ModulePass *createCheckDebugMachineModulePass(); + /// The pass fixups statepoint machine instruction to replace usage of /// caller saved registers with stack slots. extern char &FixupStatepointCallerSavedID; /// The pass transform load/store <256 x i32> to AMX load/store intrinsics /// or split the data to two <128 x i32>. FunctionPass *createX86LowerAMXTypePass(); } // End llvm namespace #endif diff --git a/llvm/include/llvm/CodeGen/TargetPassConfig.h b/llvm/include/llvm/CodeGen/TargetPassConfig.h index fc5245216941..9b42b0756d41 100644 --- a/llvm/include/llvm/CodeGen/TargetPassConfig.h +++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h @@ -1,467 +1,470 @@ //===- TargetPassConfig.h - Code Generation pass options --------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // /// Target-Independent Code Generator Pass Configuration Options pass. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_TARGETPASSCONFIG_H #define LLVM_CODEGEN_TARGETPASSCONFIG_H #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include #include namespace llvm { class LLVMTargetMachine; struct MachineSchedContext; class PassConfigImpl; class ScheduleDAGInstrs; class CSEConfigBase; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { class PassManagerBase; } // end namespace legacy using legacy::PassManagerBase; /// Discriminated union of Pass ID types. /// /// The PassConfig API prefers dealing with IDs because they are safer and more /// efficient. IDs decouple configuration from instantiation. This way, when a /// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to /// refer to a Pass pointer after adding it to a pass manager, which deletes /// redundant pass instances. /// /// However, it is convient to directly instantiate target passes with /// non-default ctors. These often don't have a registered PassInfo. Rather than /// force all target passes to implement the pass registry boilerplate, allow /// the PassConfig API to handle either type. /// /// AnalysisID is sadly char*, so PointerIntPair won't work. class IdentifyingPassPtr { union { AnalysisID ID; Pass *P; }; bool IsInstance = false; public: IdentifyingPassPtr() : P(nullptr) {} IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr) {} IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {} bool isValid() const { return P; } bool isInstance() const { return IsInstance; } AnalysisID getID() const { assert(!IsInstance && "Not a Pass ID"); return ID; } Pass *getInstance() const { assert(IsInstance && "Not a Pass Instance"); return P; } }; /// Target-Independent Code Generator Pass Configuration Options. /// /// This is an ImmutablePass solely for the purpose of exposing CodeGen options /// to the internals of other CodeGen passes. class TargetPassConfig : public ImmutablePass { private: PassManagerBase *PM = nullptr; AnalysisID StartBefore = nullptr; AnalysisID StartAfter = nullptr; AnalysisID StopBefore = nullptr; AnalysisID StopAfter = nullptr; unsigned StartBeforeInstanceNum = 0; unsigned StartBeforeCount = 0; unsigned StartAfterInstanceNum = 0; unsigned StartAfterCount = 0; unsigned StopBeforeInstanceNum = 0; unsigned StopBeforeCount = 0; unsigned StopAfterInstanceNum = 0; unsigned StopAfterCount = 0; bool Started = true; bool Stopped = false; bool AddingMachinePasses = false; bool DebugifyIsSafe = true; /// Set the StartAfter, StartBefore and StopAfter passes to allow running only /// a portion of the normal code-gen pass sequence. /// /// If the StartAfter and StartBefore pass ID is zero, then compilation will /// begin at the normal point; otherwise, clear the Started flag to indicate /// that passes should not be added until the starting pass is seen. If the /// Stop pass ID is zero, then compilation will continue to the end. /// /// This function expects that at least one of the StartAfter or the /// StartBefore pass IDs is null. void setStartStopPasses(); protected: LLVMTargetMachine *TM; PassConfigImpl *Impl = nullptr; // Internal data structures bool Initialized = false; // Flagged after all passes are configured. // Target Pass Options // Targets provide a default setting, user flags override. bool DisableVerify = false; /// Default setting for -enable-tail-merge on this target. bool EnableTailMerge = true; /// Require processing of functions such that callees are generated before /// callers. bool RequireCodeGenSCCOrder = false; /// Add the actual instruction selection passes. This does not include /// preparation passes on IR. bool addCoreISelPasses(); public: TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm); // Dummy constructor. TargetPassConfig(); ~TargetPassConfig() override; static char ID; /// Get the right type of TargetMachine for this target. template TMC &getTM() const { return *static_cast(TM); } // void setInitialized() { Initialized = true; } CodeGenOpt::Level getOptLevel() const; /// Returns true if one of the `-start-after`, `-start-before`, `-stop-after` /// or `-stop-before` options is set. static bool hasLimitedCodeGenPipeline(); /// Returns true if none of the `-stop-before` and `-stop-after` options is /// set. static bool willCompleteCodeGenPipeline(); /// If hasLimitedCodeGenPipeline is true, this method /// returns a string with the name of the options, separated /// by \p Separator that caused this pipeline to be limited. static std::string getLimitedCodeGenPipelineReason(const char *Separator = "/"); void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } bool getEnableTailMerge() const { return EnableTailMerge; } void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, Enable); } bool requiresCodeGenSCCOrder() const { return RequireCodeGenSCCOrder; } void setRequiresCodeGenSCCOrder(bool Enable = true) { setOpt(RequireCodeGenSCCOrder, Enable); } /// Allow the target to override a specific pass without overriding the pass /// pipeline. When passes are added to the standard pipeline at the /// point where StandardID is expected, add TargetID in its place. void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID); /// Insert InsertedPassID pass after TargetPassID pass. void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID, bool VerifyAfter = true); /// Allow the target to enable a specific standard pass by default. void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); } /// Allow the target to disable a specific standard pass by default. void disablePass(AnalysisID PassID) { substitutePass(PassID, IdentifyingPassPtr()); } /// Return the pass substituted for StandardID by the target. /// If no substitution exists, return StandardID. IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const; /// Return true if the pass has been substituted by the target or /// overridden on the command line. bool isPassSubstitutedOrOverridden(AnalysisID ID) const; /// Return true if the optimized regalloc pipeline is enabled. bool getOptimizeRegAlloc() const; /// Return true if the default global register allocator is in use and /// has not be overriden on the command line with '-regalloc=...' bool usingDefaultRegAlloc() const; /// High level function that adds all passes necessary to go from llvm IR /// representation to the MI representation. /// Adds IR based lowering and target specific optimization passes and finally /// the core instruction selection passes. /// \returns true if an error occurred, false otherwise. bool addISelPasses(); /// Add common target configurable passes that perform LLVM IR to IR /// transforms following machine independent optimization. virtual void addIRPasses(); /// Add passes to lower exception handling for the code generator. void addPassesToHandleExceptions(); /// Add pass to prepare the LLVM IR for code generation. This should be done /// before exception handling preparation passes. virtual void addCodeGenPrepare(); /// Add common passes that perform LLVM IR to IR transforms in preparation for /// instruction selection. virtual void addISelPrepare(); /// addInstSelector - This method should install an instruction selector pass, /// which converts from LLVM code to machine instructions. virtual bool addInstSelector() { return true; } /// This method should install an IR translator pass, which converts from /// LLVM code to machine instructions with possibly generic opcodes. virtual bool addIRTranslator() { return true; } /// This method may be implemented by targets that want to run passes /// immediately before legalization. virtual void addPreLegalizeMachineIR() {} /// This method should install a legalize pass, which converts the instruction /// sequence into one that can be selected by the target. virtual bool addLegalizeMachineIR() { return true; } /// This method may be implemented by targets that want to run passes /// immediately before the register bank selection. virtual void addPreRegBankSelect() {} /// This method should install a register bank selector pass, which /// assigns register banks to virtual registers without a register /// class or register banks. virtual bool addRegBankSelect() { return true; } /// This method may be implemented by targets that want to run passes /// immediately before the (global) instruction selection. virtual void addPreGlobalInstructionSelect() {} /// This method should install a (global) instruction selector pass, which /// converts possibly generic instructions to fully target-specific /// instructions, thereby constraining all generic virtual registers to /// register classes. virtual bool addGlobalInstructionSelect() { return true; } /// Add the complete, standard set of LLVM CodeGen passes. /// Fully developed targets will not generally override this. virtual void addMachinePasses(); /// Create an instance of ScheduleDAGInstrs to be run within the standard /// MachineScheduler pass for this function and target at the current /// optimization level. /// /// This can also be used to plug a new MachineSchedStrategy into an instance /// of the standard ScheduleDAGMI: /// return new ScheduleDAGMI(C, std::make_unique(C), /*RemoveKillFlags=*/false) /// /// Return NULL to select the default (generic) machine scheduler. virtual ScheduleDAGInstrs * createMachineScheduler(MachineSchedContext *C) const { return nullptr; } /// Similar to createMachineScheduler but used when postRA machine scheduling /// is enabled. virtual ScheduleDAGInstrs * createPostMachineScheduler(MachineSchedContext *C) const { return nullptr; } /// printAndVerify - Add a pass to dump then verify the machine function, if /// those steps are enabled. void printAndVerify(const std::string &Banner); /// Add a pass to print the machine function if printing is enabled. void addPrintPass(const std::string &Banner); /// Add a pass to perform basic verification of the machine function if /// verification is enabled. void addVerifyPass(const std::string &Banner); /// Add a pass to add synthesized debug info to the MIR. void addDebugifyPass(); /// Add a pass to remove debug info from the MIR. void addStripDebugPass(); + /// Add a pass to check synthesized debug info for MIR. + void addCheckDebugPass(); + /// Add standard passes before a pass that's about to be added. For example, /// the DebugifyMachineModulePass if it is enabled. void addMachinePrePasses(bool AllowDebugify = true); /// Add standard passes after a pass that has just been added. For example, /// the MachineVerifier if it is enabled. void addMachinePostPasses(const std::string &Banner, bool AllowVerify = true, bool AllowStrip = true); /// Check whether or not GlobalISel should abort on error. /// When this is disabled, GlobalISel will fall back on SDISel instead of /// erroring out. bool isGlobalISelAbortEnabled() const; /// Check whether or not a diagnostic should be emitted when GlobalISel /// uses the fallback path. In other words, it will emit a diagnostic /// when GlobalISel failed and isGlobalISelAbortEnabled is false. virtual bool reportDiagnosticWhenGlobalISelFallback() const; /// Check whether continuous CSE should be enabled in GISel passes. /// By default, it's enabled for non O0 levels. virtual bool isGISelCSEEnabled() const; /// Returns the CSEConfig object to use for the current optimization level. virtual std::unique_ptr getCSEConfig() const; protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); /// Methods with trivial inline returns are convenient points in the common /// codegen pass pipeline where targets may insert passes. Methods with /// out-of-line standard implementations are major CodeGen stages called by /// addMachinePasses. Some targets may override major stages when inserting /// passes is insufficient, but maintaining overriden stages is more work. /// /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM /// passes (which are run just before instruction selector). virtual bool addPreISel() { return true; } /// addMachineSSAOptimization - Add standard passes that optimize machine /// instructions in SSA form. virtual void addMachineSSAOptimization(); /// Add passes that optimize instruction level parallelism for out-of-order /// targets. These passes are run while the machine code is still in SSA /// form, so they can use MachineTraceMetrics to control their heuristics. /// /// All passes added here should preserve the MachineDominatorTree, /// MachineLoopInfo, and MachineTraceMetrics analyses. virtual bool addILPOpts() { return false; } /// This method may be implemented by targets that want to run passes /// immediately before register allocation. virtual void addPreRegAlloc() { } /// createTargetRegisterAllocator - Create the register allocator pass for /// this target at the current optimization level. virtual FunctionPass *createTargetRegisterAllocator(bool Optimized); /// addFastRegAlloc - Add the minimum set of target-independent passes that /// are required for fast register allocation. virtual void addFastRegAlloc(); /// addOptimizedRegAlloc - Add passes related to register allocation. /// LLVMTargetMachine provides standard regalloc passes for most targets. virtual void addOptimizedRegAlloc(); /// addPreRewrite - Add passes to the optimized register allocation pipeline /// after register allocation is complete, but before virtual registers are /// rewritten to physical registers. /// /// These passes must preserve VirtRegMap and LiveIntervals, and when running /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. /// When these passes run, VirtRegMap contains legal physreg assignments for /// all virtual registers. /// /// Note if the target overloads addRegAssignAndRewriteOptimized, this may not /// be honored. This is also not generally used for the the fast variant, /// where the allocation and rewriting are done in one pass. virtual bool addPreRewrite() { return false; } /// Add passes to be run immediately after virtual registers are rewritten /// to physical registers. virtual void addPostRewrite() { } /// This method may be implemented by targets that want to run passes after /// register allocation pass pipeline but before prolog-epilog insertion. virtual void addPostRegAlloc() { } /// Add passes that optimize machine instructions after register allocation. virtual void addMachineLateOptimization(); /// This method may be implemented by targets that want to run passes after /// prolog-epilog insertion and before the second instruction scheduling pass. virtual void addPreSched2() { } /// addGCPasses - Add late codegen passes that analyze code for garbage /// collection. This should return true if GC info should be printed after /// these passes. virtual bool addGCPasses(); /// Add standard basic block placement passes. virtual void addBlockPlacement(); /// This pass may be implemented by targets that want to run passes /// immediately before machine code is emitted. virtual void addPreEmitPass() { } /// Targets may add passes immediately before machine code is emitted in this /// callback. This is called even later than `addPreEmitPass`. // FIXME: Rename `addPreEmitPass` to something more sensible given its actual // position and remove the `2` suffix here as this callback is what // `addPreEmitPass` *should* be but in reality isn't. virtual void addPreEmitPass2() {} /// Utilities for targets to add passes to the pass manager. /// /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. /// @p verifyAfter if true and adding a machine function pass add an extra /// machine verification pass afterwards. AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. /// @p verifyAfter if true and adding a machine function pass add an extra /// machine verification pass afterwards. void addPass(Pass *P, bool verifyAfter = true); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. virtual FunctionPass *createRegAllocPass(bool Optimized); /// Add core register alloator passes which do the actual register assignment /// and rewriting. \returns true if any passes were added. virtual bool addRegAssignmentFast(); virtual bool addRegAssignmentOptimized(); }; } // end namespace llvm #endif // LLVM_CODEGEN_TARGETPASSCONFIG_H diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index b8420ade06a7..e1b3a8dd3f3a 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -1,453 +1,454 @@ //===- llvm/InitializePasses.h - Initialize All Passes ----------*- C++ -*-===// // // 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 contains the declarations for the pass initialization routines // for the entire LLVM project. // //===----------------------------------------------------------------------===// #ifndef LLVM_INITIALIZEPASSES_H #define LLVM_INITIALIZEPASSES_H namespace llvm { class PassRegistry; /// Initialize all passes linked into the TransformUtils library. void initializeCore(PassRegistry&); /// Initialize all passes linked into the TransformUtils library. void initializeTransformUtils(PassRegistry&); /// Initialize all passes linked into the ScalarOpts library. void initializeScalarOpts(PassRegistry&); /// Initialize all passes linked into the ObjCARCOpts library. void initializeObjCARCOpts(PassRegistry&); /// Initialize all passes linked into the Vectorize library. void initializeVectorization(PassRegistry&); /// Initialize all passes linked into the InstCombine library. void initializeInstCombine(PassRegistry&); /// Initialize all passes linked into the AggressiveInstCombine library. void initializeAggressiveInstCombine(PassRegistry&); /// Initialize all passes linked into the IPO library. void initializeIPO(PassRegistry&); /// Initialize all passes linked into the Instrumentation library. void initializeInstrumentation(PassRegistry&); /// Initialize all passes linked into the Analysis library. void initializeAnalysis(PassRegistry&); /// Initialize all passes linked into the Coroutines library. void initializeCoroutines(PassRegistry&); /// Initialize all passes linked into the CodeGen library. void initializeCodeGen(PassRegistry&); /// Initialize all passes linked into the GlobalISel library. void initializeGlobalISel(PassRegistry&); /// Initialize all passes linked into the CodeGen library. void initializeTarget(PassRegistry&); void initializeAAEvalLegacyPassPass(PassRegistry&); void initializeAAResultsWrapperPassPass(PassRegistry&); void initializeADCELegacyPassPass(PassRegistry&); void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&); void initializeModuleAddressSanitizerLegacyPassPass(PassRegistry &); void initializeASanGlobalsMetadataWrapperPassPass(PassRegistry &); void initializeAddressSanitizerLegacyPassPass(PassRegistry &); void initializeAggressiveInstCombinerLegacyPassPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeAlwaysInlinerLegacyPassPass(PassRegistry&); void initializeAssumeSimplifyPassLegacyPassPass(PassRegistry &); void initializeAssumeBuilderPassLegacyPassPass(PassRegistry &); void initializeAnnotation2MetadataLegacyPass(PassRegistry &); void initializeAnnotationRemarksLegacyPass(PassRegistry &); void initializeOpenMPOptLegacyPassPass(PassRegistry &); void initializeArgPromotionPass(PassRegistry&); void initializeAssumptionCacheTrackerPass(PassRegistry&); void initializeAtomicExpandPass(PassRegistry&); void initializeAttributorLegacyPassPass(PassRegistry&); void initializeAttributorCGSCCLegacyPassPass(PassRegistry &); void initializeBasicBlockSectionsPass(PassRegistry &); void initializeBDCELegacyPassPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAAWrapperPassPass(PassRegistry&); void initializeBlockExtractorLegacyPassPass(PassRegistry &); void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&); void initializeBoundsCheckingLegacyPassPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&); void initializeBranchRelaxationPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); void initializeBreakFalseDepsPass(PassRegistry&); void initializeCanonicalizeAliasesLegacyPassPass(PassRegistry &); void initializeCanonicalizeFreezeInLoopsPass(PassRegistry &); void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry&); void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&); void initializeCFGPrinterLegacyPassPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); void initializeCFGuardPass(PassRegistry&); void initializeCFGuardLongjmpPass(PassRegistry&); void initializeCFGViewerLegacyPassPass(PassRegistry&); void initializeCFIInstrInserterPass(PassRegistry&); void initializeCFLAndersAAWrapperPassPass(PassRegistry&); void initializeCFLSteensAAWrapperPassPass(PassRegistry&); void initializeCGProfileLegacyPassPass(PassRegistry &); void initializeCallGraphDOTPrinterPass(PassRegistry&); void initializeCallGraphPrinterLegacyPassPass(PassRegistry&); void initializeCallGraphViewerPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry&); void initializeCallSiteSplittingLegacyPassPass(PassRegistry&); void initializeCalledValuePropagationLegacyPassPass(PassRegistry &); +void initializeCheckDebugMachineModulePass(PassRegistry &); void initializeCodeGenPreparePass(PassRegistry&); void initializeConstantHoistingLegacyPassPass(PassRegistry&); void initializeConstantMergeLegacyPassPass(PassRegistry&); void initializeConstraintEliminationPass(PassRegistry &); void initializeControlHeightReductionLegacyPassPass(PassRegistry&); void initializeCorrelatedValuePropagationPass(PassRegistry&); void initializeCostModelAnalysisPass(PassRegistry&); void initializeCrossDSOCFIPass(PassRegistry&); void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCELegacyPassPass(PassRegistry&); void initializeDSELegacyPassPass(PassRegistry&); void initializeDataFlowSanitizerLegacyPassPass(PassRegistry &); void initializeDeadMachineInstructionElimPass(PassRegistry&); void initializeDebugifyMachineModulePass(PassRegistry &); void initializeDelinearizationPass(PassRegistry&); void initializeDemandedBitsWrapperPassPass(PassRegistry&); void initializeDependenceAnalysisPass(PassRegistry&); void initializeDependenceAnalysisWrapperPassPass(PassRegistry&); void initializeDetectDeadLanesPass(PassRegistry&); void initializeDivRemPairsLegacyPassPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); void initializeDomPrinterPass(PassRegistry&); void initializeDomViewerPass(PassRegistry&); void initializeDominanceFrontierWrapperPassPass(PassRegistry&); void initializeDominatorTreeWrapperPassPass(PassRegistry&); void initializeDwarfEHPreparePass(PassRegistry&); void initializeEarlyCSELegacyPassPass(PassRegistry&); void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry&); void initializeEarlyIfConverterPass(PassRegistry&); void initializeEarlyIfPredicatorPass(PassRegistry &); void initializeEarlyMachineLICMPass(PassRegistry&); void initializeEarlyTailDuplicatePass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry&); void initializeEntryExitInstrumenterPass(PassRegistry&); void initializeExpandMemCmpPassPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); void initializeExpandReductionsPass(PassRegistry&); void initializeMakeGuardsExplicitLegacyPassPass(PassRegistry&); void initializeExternalAAWrapperPassPass(PassRegistry&); void initializeFEntryInserterPass(PassRegistry&); void initializeFinalizeISelPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeFixIrreduciblePass(PassRegistry &); void initializeFixupStatepointCallerSavedPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); void initializeFloat2IntLegacyPassPass(PassRegistry&); void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&); void initializeForwardControlFlowIntegrityPass(PassRegistry&); void initializeFuncletLayoutPass(PassRegistry&); void initializeFunctionImportLegacyPassPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); void initializeGCOVProfilerLegacyPassPass(PassRegistry&); void initializeGVNHoistLegacyPassPass(PassRegistry&); void initializeGVNLegacyPassPass(PassRegistry&); void initializeGVNSinkLegacyPassPass(PassRegistry&); void initializeGlobalDCELegacyPassPass(PassRegistry&); void initializeGlobalMergePass(PassRegistry&); void initializeGlobalOptLegacyPassPass(PassRegistry&); void initializeGlobalSplitPass(PassRegistry&); void initializeGlobalsAAWrapperPassPass(PassRegistry&); void initializeGuardWideningLegacyPassPass(PassRegistry&); void initializeHardwareLoopsPass(PassRegistry&); void initializeMemProfilerLegacyPassPass(PassRegistry &); void initializeHotColdSplittingLegacyPassPass(PassRegistry&); void initializeHWAddressSanitizerLegacyPassPass(PassRegistry &); void initializeIPSCCPLegacyPassPass(PassRegistry&); void initializeIRCELegacyPassPass(PassRegistry&); void initializeIRSimilarityIdentifierWrapperPassPass(PassRegistry&); void initializeIRTranslatorPass(PassRegistry&); void initializeIVUsersWrapperPassPass(PassRegistry&); void initializeIfConverterPass(PassRegistry&); void initializeImmutableModuleSummaryIndexWrapperPassPass(PassRegistry&); void initializeImplicitNullChecksPass(PassRegistry&); void initializeIndVarSimplifyLegacyPassPass(PassRegistry&); void initializeIndirectBrExpandPassPass(PassRegistry&); void initializeInferAddressSpacesPass(PassRegistry&); void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&); void initializeInjectTLIMappingsLegacyPass(PassRegistry &); void initializeInlineCostAnalysisPass(PassRegistry&); void initializeInstCountLegacyPassPass(PassRegistry &); void initializeInstNamerPass(PassRegistry&); void initializeInstSimplifyLegacyPassPass(PassRegistry &); void initializeInstrProfilingLegacyPassPass(PassRegistry&); void initializeInstrOrderFileLegacyPassPass(PassRegistry&); void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstructionSelectPass(PassRegistry&); void initializeInterleavedAccessPass(PassRegistry&); void initializeInterleavedLoadCombinePass(PassRegistry &); void initializeInternalizeLegacyPassPass(PassRegistry&); void initializeIntervalPartitionPass(PassRegistry&); void initializeJumpThreadingPass(PassRegistry&); void initializeLCSSAVerificationPassPass(PassRegistry&); void initializeLCSSAWrapperPassPass(PassRegistry&); void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&); void initializeLazyBranchProbabilityInfoPassPass(PassRegistry&); void initializeLazyMachineBlockFrequencyInfoPassPass(PassRegistry&); void initializeLazyValueInfoPrinterPass(PassRegistry&); void initializeLazyValueInfoWrapperPassPass(PassRegistry&); void initializeLegacyDivergenceAnalysisPass(PassRegistry&); void initializeLegacyLICMPassPass(PassRegistry&); void initializeLegacyLoopSinkPassPass(PassRegistry&); void initializeLegalizerPass(PassRegistry&); void initializeGISelCSEAnalysisWrapperPassPass(PassRegistry &); void initializeGISelKnownBitsAnalysisPass(PassRegistry &); void initializeLibCallsShrinkWrapLegacyPassPass(PassRegistry&); void initializeLintLegacyPassPass(PassRegistry &); void initializeLiveDebugValuesPass(PassRegistry&); void initializeLiveDebugVariablesPass(PassRegistry&); void initializeLiveIntervalsPass(PassRegistry&); void initializeLiveRangeShrinkPass(PassRegistry&); void initializeLiveRegMatrixPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); void initializeLoadStoreVectorizerLegacyPassPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLocalizerPass(PassRegistry&); void initializeLoopAccessLegacyAnalysisPass(PassRegistry&); void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&); void initializeLoopDeletionLegacyPassPass(PassRegistry&); void initializeLoopDistributeLegacyPass(PassRegistry&); void initializeLoopExtractorLegacyPassPass(PassRegistry &); void initializeLoopGuardWideningLegacyPassPass(PassRegistry&); void initializeLoopFuseLegacyPass(PassRegistry&); void initializeLoopIdiomRecognizeLegacyPassPass(PassRegistry&); void initializeLoopInfoWrapperPassPass(PassRegistry&); void initializeLoopInstSimplifyLegacyPassPass(PassRegistry&); void initializeLoopInterchangeLegacyPassPass(PassRegistry &); void initializeLoopFlattenLegacyPassPass(PassRegistry&); void initializeLoopLoadEliminationPass(PassRegistry&); void initializeLoopPassPass(PassRegistry&); void initializeLoopPredicationLegacyPassPass(PassRegistry&); void initializeLoopRerollLegacyPassPass(PassRegistry &); void initializeLoopRotateLegacyPassPass(PassRegistry&); void initializeLoopSimplifyCFGLegacyPassPass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); void initializeLoopUnrollAndJamPass(PassRegistry&); void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopVectorizePass(PassRegistry&); void initializeLoopVersioningLICMLegacyPassPass(PassRegistry &); void initializeLoopVersioningLegacyPassPass(PassRegistry &); void initializeLowerAtomicLegacyPassPass(PassRegistry&); void initializeLowerConstantIntrinsicsPass(PassRegistry&); void initializeLowerEmuTLSPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&); void initializeLowerWidenableConditionLegacyPassPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokeLegacyPassPass(PassRegistry&); void initializeLowerSwitchLegacyPassPass(PassRegistry &); void initializeLowerTypeTestsPass(PassRegistry&); void initializeLowerMatrixIntrinsicsLegacyPassPass(PassRegistry &); void initializeLowerMatrixIntrinsicsMinimalLegacyPassPass(PassRegistry &); void initializeMIRCanonicalizerPass(PassRegistry &); void initializeMIRNamerPass(PassRegistry &); void initializeMIRPrintingPassPass(PassRegistry&); void initializeMachineBlockFrequencyInfoPass(PassRegistry&); void initializeMachineBlockPlacementPass(PassRegistry&); void initializeMachineBlockPlacementStatsPass(PassRegistry&); void initializeMachineBranchProbabilityInfoPass(PassRegistry&); void initializeMachineCSEPass(PassRegistry&); void initializeMachineCombinerPass(PassRegistry&); void initializeMachineCopyPropagationPass(PassRegistry&); void initializeMachineDominanceFrontierPass(PassRegistry&); void initializeMachineDominatorTreePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); void initializeMachineFunctionSplitterPass(PassRegistry &); void initializeMachineLICMPass(PassRegistry&); void initializeMachineLoopInfoPass(PassRegistry&); void initializeMachineModuleInfoWrapperPassPass(PassRegistry &); void initializeMachineOptimizationRemarkEmitterPassPass(PassRegistry&); void initializeMachineOutlinerPass(PassRegistry&); void initializeMachinePipelinerPass(PassRegistry&); void initializeMachinePostDominatorTreePass(PassRegistry&); void initializeMachineRegionInfoPassPass(PassRegistry&); void initializeMachineSchedulerPass(PassRegistry&); void initializeMachineSinkingPass(PassRegistry&); void initializeMachineTraceMetricsPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptLegacyPassPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); void initializeMemDerefPrinterPass(PassRegistry&); void initializeMemoryDependenceWrapperPassPass(PassRegistry&); void initializeMemorySSAPrinterLegacyPassPass(PassRegistry&); void initializeMemorySSAWrapperPassPass(PassRegistry&); void initializeMemorySanitizerLegacyPassPass(PassRegistry&); void initializeMergeFunctionsLegacyPassPass(PassRegistry&); void initializeMergeICmpsLegacyPassPass(PassRegistry &); void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&); void initializeMetaRenamerPass(PassRegistry&); void initializeModuleDebugInfoLegacyPrinterPass(PassRegistry &); void initializeModuleMemProfilerLegacyPassPass(PassRegistry &); void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&); void initializeModuloScheduleTestPass(PassRegistry&); void initializeMustExecutePrinterPass(PassRegistry&); void initializeMustBeExecutedContextPrinterPass(PassRegistry&); void initializeNameAnonGlobalLegacyPassPass(PassRegistry&); void initializeUniqueInternalLinkageNamesLegacyPassPass(PassRegistry &); void initializeNaryReassociateLegacyPassPass(PassRegistry&); void initializeNewGVNLegacyPassPass(PassRegistry&); void initializeObjCARCAAWrapperPassPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCContractLegacyPassPass(PassRegistry &); void initializeObjCARCExpandPass(PassRegistry&); void initializeObjCARCOptLegacyPassPass(PassRegistry &); void initializeOptimizationRemarkEmitterWrapperPassPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&); void initializePAEvalPass(PassRegistry&); void initializePEIPass(PassRegistry&); void initializePGOIndirectCallPromotionLegacyPassPass(PassRegistry&); void initializePGOInstrumentationGenLegacyPassPass(PassRegistry&); void initializePGOInstrumentationUseLegacyPassPass(PassRegistry&); void initializePGOInstrumentationGenCreateVarLegacyPassPass(PassRegistry&); void initializePGOMemOPSizeOptLegacyPassPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); void initializePartialInlinerLegacyPassPass(PassRegistry&); void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry&); void initializePatchableFunctionPass(PassRegistry&); void initializePeepholeOptimizerPass(PassRegistry&); void initializePhiValuesWrapperPassPass(PassRegistry&); void initializePhysicalRegisterUsageInfoPass(PassRegistry&); void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); void initializePlaceSafepointsPass(PassRegistry&); void initializePostDomOnlyPrinterPass(PassRegistry&); void initializePostDomOnlyViewerPass(PassRegistry&); void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); void initializePostDominatorTreeWrapperPassPass(PassRegistry&); void initializePostInlineEntryExitInstrumenterPass(PassRegistry&); void initializePostMachineSchedulerPass(PassRegistry&); void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); void initializePostRAHazardRecognizerPass(PassRegistry&); void initializePostRAMachineSinkingPass(PassRegistry&); void initializePostRASchedulerPass(PassRegistry&); void initializePreISelIntrinsicLoweringLegacyPassPass(PassRegistry&); void initializePredicateInfoPrinterLegacyPassPass(PassRegistry&); void initializePrintFunctionPassWrapperPass(PassRegistry&); void initializePrintModulePassWrapperPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); void initializeProfileSummaryInfoWrapperPassPass(PassRegistry&); void initializePromoteLegacyPassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); void initializeRABasicPass(PassRegistry&); void initializePseudoProbeInserterPass(PassRegistry &); void initializeRAGreedyPass(PassRegistry&); void initializeReachingDefAnalysisPass(PassRegistry&); void initializeReassociateLegacyPassPass(PassRegistry&); void initializeRedundantDbgInstEliminationPass(PassRegistry&); void initializeRegAllocFastPass(PassRegistry&); void initializeRegBankSelectPass(PassRegistry&); void initializeRegToMemLegacyPass(PassRegistry&); void initializeRegUsageInfoCollectorPass(PassRegistry&); void initializeRegUsageInfoPropagationPass(PassRegistry&); void initializeRegionInfoPassPass(PassRegistry&); void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); void initializeRenameIndependentSubregsPass(PassRegistry&); void initializeResetMachineFunctionPass(PassRegistry&); void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); void initializeRewriteStatepointsForGCLegacyPassPass(PassRegistry &); void initializeRewriteSymbolsLegacyPassPass(PassRegistry&); void initializeSCCPLegacyPassPass(PassRegistry&); void initializeSCEVAAWrapperPassPass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeSROALegacyPassPass(PassRegistry&); void initializeSafeStackLegacyPassPass(PassRegistry&); void initializeSafepointIRVerifierPass(PassRegistry&); void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&); void initializeModuleSanitizerCoverageLegacyPassPass(PassRegistry &); void initializeScalarEvolutionWrapperPassPass(PassRegistry&); void initializeScalarizeMaskedMemIntrinLegacyPassPass(PassRegistry &); void initializeScalarizerLegacyPassPass(PassRegistry&); void initializeScavengerTestPass(PassRegistry&); void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&); void initializeSeparateConstOffsetFromGEPLegacyPassPass(PassRegistry &); void initializeShadowStackGCLoweringPass(PassRegistry&); void initializeShrinkWrapPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); void initializeSimpleLoopUnswitchLegacyPassPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingLegacyPassPass(PassRegistry&); void initializeSjLjEHPreparePass(PassRegistry&); void initializeSlotIndexesPass(PassRegistry&); void initializeSpeculativeExecutionLegacyPassPass(PassRegistry&); void initializeSpillPlacementPass(PassRegistry&); void initializeStackColoringPass(PassRegistry&); void initializeStackMapLivenessPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); void initializeStackSafetyGlobalInfoWrapperPassPass(PassRegistry &); void initializeStackSafetyInfoWrapperPassPass(PassRegistry &); void initializeStackSlotColoringPass(PassRegistry&); void initializeStraightLineStrengthReduceLegacyPassPass(PassRegistry &); void initializeStripDeadDebugInfoPass(PassRegistry&); void initializeStripDeadPrototypesLegacyPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); void initializeStripDebugMachineModulePass(PassRegistry &); void initializeStripGCRelocatesLegacyPass(PassRegistry &); void initializeStripNonDebugSymbolsPass(PassRegistry&); void initializeStripNonLineTableDebugLegacyPassPass(PassRegistry &); void initializeStripSymbolsPass(PassRegistry&); void initializeStructurizeCFGLegacyPassPass(PassRegistry &); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePass(PassRegistry&); void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeTargetTransformInfoWrapperPassPass(PassRegistry&); void initializeThreadSanitizerLegacyPassPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAAWrapperPassPass(PassRegistry&); void initializeTypePromotionPass(PassRegistry&); void initializeUnifyFunctionExitNodesLegacyPassPass(PassRegistry &); void initializeUnifyLoopExitsLegacyPassPass(PassRegistry &); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeUnreachableBlockElimLegacyPassPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); void initializeVectorCombineLegacyPassPass(PassRegistry&); void initializeVerifierLegacyPassPass(PassRegistry&); void initializeVirtRegMapPass(PassRegistry&); void initializeVirtRegRewriterPass(PassRegistry&); void initializeWarnMissedTransformationsLegacyPass(PassRegistry &); void initializeWasmEHPreparePass(PassRegistry&); void initializeWholeProgramDevirtPass(PassRegistry&); void initializeWinEHPreparePass(PassRegistry&); void initializeWriteBitcodePassPass(PassRegistry&); void initializeWriteThinLTOBitcodePass(PassRegistry&); void initializeXRayInstrumentationPass(PassRegistry&); } // end namespace llvm #endif // LLVM_INITIALIZEPASSES_H diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 7dc854cbbf20..d50349c514a3 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -1,217 +1,218 @@ add_llvm_component_library(LLVMCodeGen AggressiveAntiDepBreaker.cpp AllocationOrder.cpp Analysis.cpp AtomicExpandPass.cpp BasicTargetTransformInfo.cpp BranchFolding.cpp BranchRelaxation.cpp BreakFalseDeps.cpp BuiltinGCs.cpp BasicBlockSections.cpp CalcSpillWeights.cpp CallingConvLower.cpp CFGuardLongjmp.cpp CFIInstrInserter.cpp CodeGen.cpp CodeGenPrepare.cpp CommandFlags.cpp CriticalAntiDepBreaker.cpp DeadMachineInstructionElim.cpp DetectDeadLanes.cpp DFAPacketizer.cpp DwarfEHPrepare.cpp EarlyIfConversion.cpp EdgeBundles.cpp ExecutionDomainFix.cpp ExpandMemCmp.cpp ExpandPostRAPseudos.cpp ExpandReductions.cpp FaultMaps.cpp FEntryInserter.cpp FinalizeISel.cpp FixupStatepointCallerSaved.cpp FuncletLayout.cpp GCMetadata.cpp GCMetadataPrinter.cpp GCRootLowering.cpp GCStrategy.cpp GlobalMerge.cpp HardwareLoops.cpp IfConversion.cpp ImplicitNullChecks.cpp IndirectBrExpandPass.cpp InlineSpiller.cpp InterferenceCache.cpp InterleavedAccessPass.cpp InterleavedLoadCombinePass.cpp IntrinsicLowering.cpp LatencyPriorityQueue.cpp LazyMachineBlockFrequencyInfo.cpp LexicalScopes.cpp LiveDebugVariables.cpp LiveIntervals.cpp LiveInterval.cpp LiveIntervalUnion.cpp LivePhysRegs.cpp LiveRangeCalc.cpp LiveIntervalCalc.cpp LiveRangeEdit.cpp LiveRangeShrink.cpp LiveRegMatrix.cpp LiveRegUnits.cpp LiveStacks.cpp LiveVariables.cpp LLVMTargetMachine.cpp LocalStackSlotAllocation.cpp LoopTraversal.cpp LowLevelType.cpp LowerEmuTLS.cpp MachineBasicBlock.cpp MachineBlockFrequencyInfo.cpp MachineBlockPlacement.cpp MachineBranchProbabilityInfo.cpp MachineCombiner.cpp MachineCopyPropagation.cpp MachineCSE.cpp + MachineCheckDebugify.cpp MachineDebugify.cpp MachineDominanceFrontier.cpp MachineDominators.cpp MachineFrameInfo.cpp MachineFunction.cpp MachineFunctionPass.cpp MachineFunctionPrinterPass.cpp MachineFunctionSplitter.cpp MachineInstrBundle.cpp MachineInstr.cpp MachineLICM.cpp MachineLoopInfo.cpp MachineLoopUtils.cpp MachineModuleInfo.cpp MachineModuleInfoImpls.cpp MachineOperand.cpp MachineOptimizationRemarkEmitter.cpp MachineOutliner.cpp MachinePassManager.cpp MachinePipeliner.cpp MachinePostDominators.cpp MachineRegionInfo.cpp MachineRegisterInfo.cpp MachineScheduler.cpp MachineSink.cpp MachineSizeOpts.cpp MachineSSAUpdater.cpp MachineStripDebug.cpp MachineTraceMetrics.cpp MachineVerifier.cpp ModuloSchedule.cpp MultiHazardRecognizer.cpp PatchableFunction.cpp MBFIWrapper.cpp MIRPrinter.cpp MIRPrintingPass.cpp MacroFusion.cpp NonRelocatableStringpool.cpp OptimizePHIs.cpp ParallelCG.cpp PeepholeOptimizer.cpp PHIElimination.cpp PHIEliminationUtils.cpp PostRAHazardRecognizer.cpp PostRASchedulerList.cpp PreISelIntrinsicLowering.cpp ProcessImplicitDefs.cpp PrologEpilogInserter.cpp PseudoProbeInserter.cpp PseudoSourceValue.cpp RDFGraph.cpp RDFLiveness.cpp RDFRegisters.cpp ReachingDefAnalysis.cpp RegAllocBase.cpp RegAllocBasic.cpp RegAllocFast.cpp RegAllocGreedy.cpp RegAllocPBQP.cpp RegisterClassInfo.cpp RegisterCoalescer.cpp RegisterPressure.cpp RegisterScavenging.cpp RenameIndependentSubregs.cpp MachineStableHash.cpp MIRVRegNamerUtils.cpp MIRNamerPass.cpp MIRCanonicalizerPass.cpp RegisterUsageInfo.cpp RegUsageInfoCollector.cpp RegUsageInfoPropagate.cpp ResetMachineFunctionPass.cpp SafeStack.cpp SafeStackLayout.cpp ScheduleDAG.cpp ScheduleDAGInstrs.cpp ScheduleDAGPrinter.cpp ScoreboardHazardRecognizer.cpp ShadowStackGCLowering.cpp ShrinkWrap.cpp SjLjEHPrepare.cpp SlotIndexes.cpp SpillPlacement.cpp SplitKit.cpp StackColoring.cpp StackMapLivenessAnalysis.cpp StackMaps.cpp StackProtector.cpp StackSlotColoring.cpp SwiftErrorValueTracking.cpp SwitchLoweringUtils.cpp TailDuplication.cpp TailDuplicator.cpp TargetFrameLoweringImpl.cpp TargetInstrInfo.cpp TargetLoweringBase.cpp TargetLoweringObjectFileImpl.cpp TargetOptionsImpl.cpp TargetPassConfig.cpp TargetRegisterInfo.cpp TargetSchedule.cpp TargetSubtargetInfo.cpp TypePromotion.cpp TwoAddressInstructionPass.cpp UnreachableBlockElim.cpp ValueTypes.cpp VirtRegMap.cpp WasmEHPrepare.cpp WinEHPrepare.cpp XRayInstrumentation.cpp LiveDebugValues/LiveDebugValues.cpp LiveDebugValues/VarLocBasedImpl.cpp LiveDebugValues/InstrRefBasedImpl.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen/PBQP LINK_LIBS ${LLVM_PTHREAD_LIB} DEPENDS intrinsics_gen LINK_COMPONENTS Analysis BitReader BitWriter Core MC ProfileData Scalar Support Target TransformUtils ) add_subdirectory(SelectionDAG) add_subdirectory(AsmPrinter) add_subdirectory(MIRParser) add_subdirectory(GlobalISel) diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp index 92a2b73f52e3..94925498b01c 100644 --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -1,125 +1,126 @@ //===-- CodeGen.cpp -------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the common initialization routines for the // CodeGen library. // //===----------------------------------------------------------------------===// #include "llvm-c/Initialization.h" #include "llvm/InitializePasses.h" #include "llvm/PassRegistry.h" using namespace llvm; /// initializeCodeGen - Initialize all passes linked into the CodeGen library. void llvm::initializeCodeGen(PassRegistry &Registry) { initializeAtomicExpandPass(Registry); initializeBasicBlockSectionsPass(Registry); initializeBranchFolderPassPass(Registry); initializeBranchRelaxationPass(Registry); initializeCFGuardLongjmpPass(Registry); initializeCFIInstrInserterPass(Registry); + initializeCheckDebugMachineModulePass(Registry); initializeCodeGenPreparePass(Registry); initializeDeadMachineInstructionElimPass(Registry); initializeDebugifyMachineModulePass(Registry); initializeDetectDeadLanesPass(Registry); initializeDwarfEHPreparePass(Registry); initializeEarlyIfConverterPass(Registry); initializeEarlyIfPredicatorPass(Registry); initializeEarlyMachineLICMPass(Registry); initializeEarlyTailDuplicatePass(Registry); initializeExpandMemCmpPassPass(Registry); initializeExpandPostRAPass(Registry); initializeFEntryInserterPass(Registry); initializeFinalizeISelPass(Registry); initializeFinalizeMachineBundlesPass(Registry); initializeFixupStatepointCallerSavedPass(Registry); initializeFuncletLayoutPass(Registry); initializeGCMachineCodeAnalysisPass(Registry); initializeGCModuleInfoPass(Registry); initializeHardwareLoopsPass(Registry); initializeIfConverterPass(Registry); initializeImplicitNullChecksPass(Registry); initializeIndirectBrExpandPassPass(Registry); initializeInterleavedLoadCombinePass(Registry); initializeInterleavedAccessPass(Registry); initializeLiveDebugValuesPass(Registry); initializeLiveDebugVariablesPass(Registry); initializeLiveIntervalsPass(Registry); initializeLiveRangeShrinkPass(Registry); initializeLiveStacksPass(Registry); initializeLiveVariablesPass(Registry); initializeLocalStackSlotPassPass(Registry); initializeLowerIntrinsicsPass(Registry); initializeMIRCanonicalizerPass(Registry); initializeMIRNamerPass(Registry); initializeMachineBlockFrequencyInfoPass(Registry); initializeMachineBlockPlacementPass(Registry); initializeMachineBlockPlacementStatsPass(Registry); initializeMachineCSEPass(Registry); initializeMachineCombinerPass(Registry); initializeMachineCopyPropagationPass(Registry); initializeMachineDominatorTreePass(Registry); initializeMachineFunctionPrinterPassPass(Registry); initializeMachineLICMPass(Registry); initializeMachineLoopInfoPass(Registry); initializeMachineModuleInfoWrapperPassPass(Registry); initializeMachineOptimizationRemarkEmitterPassPass(Registry); initializeMachineOutlinerPass(Registry); initializeMachinePipelinerPass(Registry); initializeModuloScheduleTestPass(Registry); initializeMachinePostDominatorTreePass(Registry); initializeMachineRegionInfoPassPass(Registry); initializeMachineSchedulerPass(Registry); initializeMachineSinkingPass(Registry); initializeMachineVerifierPassPass(Registry); initializeOptimizePHIsPass(Registry); initializePEIPass(Registry); initializePHIEliminationPass(Registry); initializePatchableFunctionPass(Registry); initializePeepholeOptimizerPass(Registry); initializePostMachineSchedulerPass(Registry); initializePostRAHazardRecognizerPass(Registry); initializePostRAMachineSinkingPass(Registry); initializePostRASchedulerPass(Registry); initializePreISelIntrinsicLoweringLegacyPassPass(Registry); initializeProcessImplicitDefsPass(Registry); initializeRABasicPass(Registry); initializeRAGreedyPass(Registry); initializeRegAllocFastPass(Registry); initializeRegUsageInfoCollectorPass(Registry); initializeRegUsageInfoPropagationPass(Registry); initializeRegisterCoalescerPass(Registry); initializeRenameIndependentSubregsPass(Registry); initializeSafeStackLegacyPassPass(Registry); initializeShrinkWrapPass(Registry); initializeSjLjEHPreparePass(Registry); initializeSlotIndexesPass(Registry); initializeStackColoringPass(Registry); initializeStackMapLivenessPass(Registry); initializeStackProtectorPass(Registry); initializeStackSlotColoringPass(Registry); initializeStripDebugMachineModulePass(Registry); initializeTailDuplicatePass(Registry); initializeTargetPassConfigPass(Registry); initializeTwoAddressInstructionPassPass(Registry); initializeTypePromotionPass(Registry); initializeUnpackMachineBundlesPass(Registry); initializeUnreachableBlockElimLegacyPassPass(Registry); initializeUnreachableMachineBlockElimPass(Registry); initializeVirtRegMapPass(Registry); initializeVirtRegRewriterPass(Registry); initializeWasmEHPreparePass(Registry); initializeWinEHPreparePass(Registry); initializeXRayInstrumentationPass(Registry); } void LLVMInitializeCodeGen(LLVMPassRegistryRef R) { initializeCodeGen(*unwrap(R)); } diff --git a/llvm/lib/CodeGen/MachineCheckDebugify.cpp b/llvm/lib/CodeGen/MachineCheckDebugify.cpp new file mode 100644 index 000000000000..bd7f0f862947 --- /dev/null +++ b/llvm/lib/CodeGen/MachineCheckDebugify.cpp @@ -0,0 +1,126 @@ +//===- MachineCheckDebugify.cpp - Check debug info ------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file This checks debug info after mir-debugify (+ pass-to-test). Currently +/// it simply checks the integrity of line info in DILocation and +/// DILocalVariable which mir-debugifiy generated before. +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/InitializePasses.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/Utils/Debugify.h" + +#define DEBUG_TYPE "mir-check-debugify" + +using namespace llvm; + +namespace { + +struct CheckDebugMachineModule : public ModulePass { + bool runOnModule(Module &M) override { + MachineModuleInfo &MMI = + getAnalysis().getMMI(); + + NamedMDNode *NMD = M.getNamedMetadata("llvm.mir.debugify"); + if (!NMD) { + errs() << "WARNING: Please run mir-debugify to generate " + "llvm.mir.debugify metadata first.\n"; + return false; + } + + auto getDebugifyOperand = [&](unsigned Idx) -> unsigned { + return mdconst::extract(NMD->getOperand(Idx)->getOperand(0)) + ->getZExtValue(); + }; + assert(NMD->getNumOperands() == 2 && + "llvm.mir.debugify should have exactly 2 operands!"); + unsigned NumLines = getDebugifyOperand(0); + unsigned NumVars = getDebugifyOperand(1); + BitVector MissingLines{NumLines, true}; + BitVector MissingVars{NumVars, true}; + + for (Function &F : M.functions()) { + MachineFunction *MF = MMI.getMachineFunction(F); + if (!MF) + continue; + for (MachineBasicBlock &MBB : *MF) { + // Find missing lines. + // TODO: Avoid meta instructions other than dbg_val. + for (MachineInstr &MI : MBB) { + if (MI.isDebugValue()) + continue; + const DebugLoc DL = MI.getDebugLoc(); + if (DL && DL.getLine() != 0) { + MissingLines.reset(DL.getLine() - 1); + continue; + } + + if (!DL) { + errs() << "WARNING: Instruction with empty DebugLoc in function "; + errs() << F.getName() << " --"; + MI.print(errs()); + } + } + + // Find missing variables. + // TODO: Handle DBG_INSTR_REF which is under an experimental option now. + for (MachineInstr &MI : MBB) { + if (!MI.isDebugValue()) + continue; + const DILocalVariable *LocalVar = MI.getDebugVariable(); + unsigned Var = ~0U; + + (void)to_integer(LocalVar->getName(), Var, 10); + assert(Var <= NumVars && "Unexpected name for DILocalVariable"); + MissingVars.reset(Var - 1); + } + } + } + + bool Fail = false; + for (unsigned Idx : MissingLines.set_bits()) { + errs() << "WARNING: Missing line " << Idx + 1 << "\n"; + Fail = true; + } + + for (unsigned Idx : MissingVars.set_bits()) { + errs() << "WARNING: Missing variable " << Idx + 1 << "\n"; + Fail = true; + } + errs() << "Machine IR debug info check: "; + errs() << (Fail ? "FAIL" : "PASS") << "\n"; + + return false; + } + + CheckDebugMachineModule() : ModulePass(ID) {} + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addPreserved(); + AU.setPreservesCFG(); + } + + static char ID; // Pass identification. +}; +char CheckDebugMachineModule::ID = 0; + +} // end anonymous namespace + +INITIALIZE_PASS_BEGIN(CheckDebugMachineModule, DEBUG_TYPE, + "Machine Check Debug Module", false, false) +INITIALIZE_PASS_END(CheckDebugMachineModule, DEBUG_TYPE, + "Machine Check Debug Module", false, false) + +ModulePass *llvm::createCheckDebugMachineModulePass() { + return new CheckDebugMachineModule(); +} diff --git a/llvm/lib/CodeGen/MachineDebugify.cpp b/llvm/lib/CodeGen/MachineDebugify.cpp index bf57ec0e8c28..599a81847592 100644 --- a/llvm/lib/CodeGen/MachineDebugify.cpp +++ b/llvm/lib/CodeGen/MachineDebugify.cpp @@ -1,172 +1,202 @@ //===- MachineDebugify.cpp - Attach synthetic debug info to everything ----===// // // 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 // //===----------------------------------------------------------------------===// /// /// \file This pass attaches synthetic debug info to everything. It can be used /// to create targeted tests for debug info preservation, or test for CodeGen /// differences with vs. without debug info. /// /// This isn't intended to have feature parity with Debugify. //===----------------------------------------------------------------------===// #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/InitializePasses.h" #include "llvm/Transforms/Utils/Debugify.h" #define DEBUG_TYPE "mir-debugify" using namespace llvm; namespace { bool applyDebugifyMetadataToMachineFunction(MachineModuleInfo &MMI, DIBuilder &DIB, Function &F) { MachineFunction *MaybeMF = MMI.getMachineFunction(F); if (!MaybeMF) return false; MachineFunction &MF = *MaybeMF; const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); DISubprogram *SP = F.getSubprogram(); assert(SP && "IR Debugify just created it?"); Module &M = *F.getParent(); LLVMContext &Ctx = M.getContext(); unsigned NextLine = SP->getLine(); for (MachineBasicBlock &MBB : MF) { for (MachineInstr &MI : MBB) { // This will likely emit line numbers beyond the end of the imagined // source function and into subsequent ones. We don't do anything about // that as it doesn't really matter to the compiler where the line is in // the imaginary source code. MI.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); } } // Find local variables defined by debugify. No attempt is made to match up // MIR-level regs to the 'correct' IR-level variables: there isn't a simple // way to do that, and it isn't necessary to find interesting CodeGen bugs. // Instead, simply keep track of one variable per line. Later, we can insert // DBG_VALUE insts that point to these local variables. Emitting DBG_VALUEs // which cover a wide range of lines can help stress the debug info passes: // if we can't do that, fall back to using the local variable which precedes // all the others. Function *DbgValF = M.getFunction("llvm.dbg.value"); DbgValueInst *EarliestDVI = nullptr; DenseMap Line2Var; DIExpression *Expr = nullptr; if (DbgValF) { for (const Use &U : DbgValF->uses()) { auto *DVI = dyn_cast(U.getUser()); if (!DVI || DVI->getFunction() != &F) continue; unsigned Line = DVI->getDebugLoc().getLine(); assert(Line != 0 && "debugify should not insert line 0 locations"); Line2Var[Line] = DVI->getVariable(); if (!EarliestDVI || Line < EarliestDVI->getDebugLoc().getLine()) EarliestDVI = DVI; Expr = DVI->getExpression(); } } if (Line2Var.empty()) return true; // Now, try to insert a DBG_VALUE instruction after each real instruction. // Do this by introducing debug uses of each register definition. If that is // not possible (e.g. we have a phi or a meta instruction), emit a constant. uint64_t NextImm = 0; + SmallSet VarSet; const MCInstrDesc &DbgValDesc = TII.get(TargetOpcode::DBG_VALUE); for (MachineBasicBlock &MBB : MF) { MachineBasicBlock::iterator FirstNonPHIIt = MBB.getFirstNonPHI(); - for (auto I = MBB.begin(), E = MBB.end(); I != E; ) { + for (auto I = MBB.begin(), E = MBB.end(); I != E;) { MachineInstr &MI = *I; ++I; // `I` may point to a DBG_VALUE created in the previous loop iteration. if (MI.isDebugInstr()) continue; // It's not allowed to insert DBG_VALUEs after a terminator. if (MI.isTerminator()) continue; // Find a suitable insertion point for the DBG_VALUE. auto InsertBeforeIt = MI.isPHI() ? FirstNonPHIIt : I; // Find a suitable local variable for the DBG_VALUE. unsigned Line = MI.getDebugLoc().getLine(); if (!Line2Var.count(Line)) Line = EarliestDVI->getDebugLoc().getLine(); DILocalVariable *LocalVar = Line2Var[Line]; assert(LocalVar && "No variable for current line?"); + VarSet.insert(LocalVar); // Emit DBG_VALUEs for register definitions. SmallVector RegDefs; for (MachineOperand &MO : MI.operands()) if (MO.isReg() && MO.isDef() && MO.getReg()) RegDefs.push_back(&MO); for (MachineOperand *MO : RegDefs) BuildMI(MBB, InsertBeforeIt, MI.getDebugLoc(), DbgValDesc, /*IsIndirect=*/false, *MO, LocalVar, Expr); // OK, failing that, emit a constant DBG_VALUE. if (RegDefs.empty()) { auto ImmOp = MachineOperand::CreateImm(NextImm++); BuildMI(MBB, InsertBeforeIt, MI.getDebugLoc(), DbgValDesc, /*IsIndirect=*/false, ImmOp, LocalVar, Expr); } } } + // Here we save the number of lines and variables into "llvm.mir.debugify". + // It is useful for mir-check-debugify. + NamedMDNode *NMD = M.getNamedMetadata("llvm.mir.debugify"); + IntegerType *Int32Ty = Type::getInt32Ty(Ctx); + if (!NMD) { + NMD = M.getOrInsertNamedMetadata("llvm.mir.debugify"); + auto addDebugifyOperand = [&](unsigned N) { + NMD->addOperand(MDNode::get( + Ctx, ValueAsMetadata::getConstant(ConstantInt::get(Int32Ty, N)))); + }; + // Add number of lines. + addDebugifyOperand(NextLine - 1); + // Add number of variables. + addDebugifyOperand(VarSet.size()); + } else { + assert(NMD->getNumOperands() == 2 && + "llvm.mir.debugify should have exactly 2 operands!"); + auto setDebugifyOperand = [&](unsigned Idx, unsigned N) { + NMD->setOperand(Idx, MDNode::get(Ctx, ValueAsMetadata::getConstant( + ConstantInt::get(Int32Ty, N)))); + }; + // Set number of lines. + setDebugifyOperand(0, NextLine - 1); + // Set number of variables. + setDebugifyOperand(1, VarSet.size()); + } + return true; } /// ModulePass for attaching synthetic debug info to everything, used with the /// legacy module pass manager. struct DebugifyMachineModule : public ModulePass { bool runOnModule(Module &M) override { MachineModuleInfo &MMI = getAnalysis().getMMI(); return applyDebugifyMetadata( M, M.functions(), "ModuleDebugify: ", [&](DIBuilder &DIB, Function &F) -> bool { return applyDebugifyMetadataToMachineFunction(MMI, DIB, F); }); } DebugifyMachineModule() : ModulePass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.addPreserved(); AU.setPreservesCFG(); } static char ID; // Pass identification. }; char DebugifyMachineModule::ID = 0; } // end anonymous namespace INITIALIZE_PASS_BEGIN(DebugifyMachineModule, DEBUG_TYPE, "Machine Debugify Module", false, false) INITIALIZE_PASS_END(DebugifyMachineModule, DEBUG_TYPE, "Machine Debugify Module", false, false) ModulePass *llvm::createDebugifyMachineModulePass() { return new DebugifyMachineModule(); } diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 48686b9e04f8..10c1ff988ac5 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -1,1304 +1,1321 @@ //===- 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/CFLAndersAliasAnalysis.h" #include "llvm/Analysis/CFLSteensAliasAnalysis.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.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/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/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/Threading.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" #include #include using namespace llvm; static cl::opt EnableIPRA("enable-ipra", cl::init(false), cl::Hidden, cl::desc("Enable interprocedural register allocation " "to reduce load/store at procedure calls.")); static cl::opt DisablePostRASched("disable-post-ra", cl::Hidden, cl::desc("Disable Post Regalloc Scheduler")); static cl::opt DisableBranchFold("disable-branch-fold", cl::Hidden, cl::desc("Disable branch folding")); static cl::opt DisableTailDuplicate("disable-tail-duplicate", cl::Hidden, cl::desc("Disable tail duplication")); static cl::opt DisableEarlyTailDup("disable-early-taildup", cl::Hidden, cl::desc("Disable pre-register allocation tail duplication")); static cl::opt DisableBlockPlacement("disable-block-placement", cl::Hidden, cl::desc("Disable probability-driven block placement")); static cl::opt EnableBlockPlacementStats("enable-block-placement-stats", cl::Hidden, cl::desc("Collect probability-driven block placement stats")); static cl::opt DisableSSC("disable-ssc", cl::Hidden, cl::desc("Disable Stack Slot Coloring")); static cl::opt DisableMachineDCE("disable-machine-dce", cl::Hidden, cl::desc("Disable Machine Dead Code Elimination")); static cl::opt DisableEarlyIfConversion("disable-early-ifcvt", cl::Hidden, cl::desc("Disable Early If-conversion")); static cl::opt DisableMachineLICM("disable-machine-licm", cl::Hidden, cl::desc("Disable Machine LICM")); static cl::opt DisableMachineCSE("disable-machine-cse", cl::Hidden, cl::desc("Disable Machine Common Subexpression Elimination")); static cl::opt OptimizeRegAlloc( "optimize-regalloc", cl::Hidden, cl::desc("Enable optimized register allocation compilation path.")); static cl::opt DisablePostRAMachineLICM("disable-postra-machine-licm", cl::Hidden, cl::desc("Disable Machine LICM")); static cl::opt DisableMachineSink("disable-machine-sink", cl::Hidden, cl::desc("Disable Machine Sinking")); static cl::opt DisablePostRAMachineSink("disable-postra-machine-sink", cl::Hidden, cl::desc("Disable PostRA Machine Sinking")); static cl::opt DisableLSR("disable-lsr", cl::Hidden, cl::desc("Disable Loop Strength Reduction Pass")); static cl::opt DisableConstantHoisting("disable-constant-hoisting", cl::Hidden, cl::desc("Disable ConstantHoisting")); static cl::opt DisableCGP("disable-cgp", cl::Hidden, cl::desc("Disable Codegen Prepare")); static cl::opt DisableCopyProp("disable-copyprop", cl::Hidden, cl::desc("Disable Copy Propagation pass")); static cl::opt DisablePartialLibcallInlining("disable-partial-libcall-inlining", cl::Hidden, cl::desc("Disable Partial Libcall Inlining")); static cl::opt EnableImplicitNullChecks( "enable-implicit-null-checks", cl::desc("Fold null checks into faulting memory operations"), cl::init(false), cl::Hidden); static cl::opt DisableMergeICmps("disable-mergeicmps", cl::desc("Disable MergeICmps Pass"), cl::init(false), cl::Hidden); static cl::opt PrintLSR("print-lsr-output", cl::Hidden, cl::desc("Print LLVM IR produced by the loop-reduce pass")); static cl::opt PrintISelInput("print-isel-input", cl::Hidden, cl::desc("Print LLVM IR input to isel pass")); static cl::opt PrintGCInfo("print-gc", cl::Hidden, cl::desc("Dump garbage collector data")); static cl::opt VerifyMachineCode("verify-machineinstrs", cl::Hidden, cl::desc("Verify generated machine code"), cl::ZeroOrMore); static cl::opt 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"), cl::ZeroOrMore); +static cl::opt 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"), + cl::ZeroOrMore); enum RunOutliner { AlwaysOutline, NeverOutline, TargetDefault }; // Enable or disable the MachineOutliner. static cl::opt EnableMachineOutliner( "enable-machine-outliner", cl::desc("Enable the machine outliner"), cl::Hidden, cl::ValueOptional, cl::init(TargetDefault), cl::values(clEnumValN(AlwaysOutline, "always", "Run on all functions guaranteed to be beneficial"), clEnumValN(NeverOutline, "never", "Disable all outlining"), // Sentinel value for unspecified option. clEnumValN(AlwaysOutline, "", ""))); // 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 EnableFastISelOption("fast-isel", cl::Hidden, cl::desc("Enable the \"fast\" instruction selector")); static cl::opt 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 PrintAfterISel("print-after-isel", cl::init(false), cl::Hidden, cl::desc("Print machine instrs after ISel")); static cl::opt 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"))); // 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 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 EarlyLiveIntervals("early-live-intervals", cl::Hidden, cl::desc("Run live interval analysis earlier in the pipeline")); // Experimental option to use CFL-AA in codegen enum class CFLAAType { None, Steensgaard, Andersen, Both }; static cl::opt UseCFLAA( "use-cfl-aa-in-codegen", cl::init(CFLAAType::None), cl::Hidden, cl::desc("Enable the new, experimental CFL alias analysis in CodeGen"), cl::values(clEnumValN(CFLAAType::None, "none", "Disable CFL-AA"), clEnumValN(CFLAAType::Steensgaard, "steens", "Enable unification-based CFL-AA"), clEnumValN(CFLAAType::Andersen, "anders", "Enable inclusion-based CFL-AA"), clEnumValN(CFLAAType::Both, "both", "Enable both variants of CFL-AA"))); /// 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"; static cl::opt StartAfterOpt(StringRef(StartAfterOptName), cl::desc("Resume compilation after a specific pass"), cl::value_desc("pass-name"), cl::init(""), cl::Hidden); static cl::opt StartBeforeOpt(StringRef(StartBeforeOptName), cl::desc("Resume compilation before a specific pass"), cl::value_desc("pass-name"), cl::init(""), cl::Hidden); static cl::opt StopAfterOpt(StringRef(StopAfterOptName), cl::desc("Stop compilation after a specific pass"), cl::value_desc("pass-name"), cl::init(""), cl::Hidden); static cl::opt 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 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 DisableExpandReductions( "disable-expand-reductions", cl::init(false), cl::Hidden, cl::desc("Disable the expand reduction intrinsics pass from running")); /// 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(AnalysisID StandardID, IdentifyingPassPtr TargetID) { if (StandardID == &PostRASchedulerID) return applyDisable(TargetID, DisablePostRASched); if (StandardID == &BranchFolderPassID) return applyDisable(TargetID, DisableBranchFold); if (StandardID == &TailDuplicateID) return applyDisable(TargetID, DisableTailDuplicate); if (StandardID == &EarlyTailDuplicateID) return applyDisable(TargetID, DisableEarlyTailDup); if (StandardID == &MachineBlockPlacementID) return applyDisable(TargetID, DisableBlockPlacement); if (StandardID == &StackSlotColoringID) return applyDisable(TargetID, DisableSSC); if (StandardID == &DeadMachineInstructionElimID) return applyDisable(TargetID, DisableMachineDCE); if (StandardID == &EarlyIfConverterID) return applyDisable(TargetID, DisableEarlyIfConversion); if (StandardID == &EarlyMachineLICMID) return applyDisable(TargetID, DisableMachineLICM); if (StandardID == &MachineCSEID) return applyDisable(TargetID, DisableMachineCSE); if (StandardID == &MachineLICMID) return applyDisable(TargetID, DisablePostRAMachineLICM); if (StandardID == &MachineSinkingID) return applyDisable(TargetID, DisableMachineSink); if (StandardID == &PostRAMachineSinkingID) return applyDisable(TargetID, DisablePostRAMachineSink); if (StandardID == &MachineCopyPropagationID) return applyDisable(TargetID, DisableCopyProp); return TargetID; } //===---------------------------------------------------------------------===// /// TargetPassConfig //===---------------------------------------------------------------------===// INITIALIZE_PASS(TargetPassConfig, "targetpassconfig", "Target Pass Configuration", false, false) char TargetPassConfig::ID = 0; namespace { struct InsertedPass { AnalysisID TargetPassID; IdentifyingPassPtr InsertedPassID; bool VerifyAfter; InsertedPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID, bool VerifyAfter) : TargetPassID(TargetPassID), InsertedPassID(InsertedPassID), VerifyAfter(VerifyAfter) {} 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 TargetPasses; /// Store the pairs of of which the second pass /// is inserted after each instance of the first one. SmallVector 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) report_fatal_error(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 getPassNameAndInstanceNum(StringRef PassName) { StringRef Name, InstanceNumStr; std::tie(Name, InstanceNumStr) = PassName.split(','); unsigned InstanceNum = 0; if (!InstanceNumStr.empty() && InstanceNumStr.getAsInteger(10, InstanceNum)) report_fatal_error("invalid pass instance specifier " + PassName); return std::make_pair(Name, InstanceNum); } void TargetPassConfig::setStartStopPasses() { StringRef StartBeforeName; std::tie(StartBeforeName, StartBeforeInstanceNum) = getPassNameAndInstanceNum(StartBeforeOpt); StringRef StartAfterName; std::tie(StartAfterName, StartAfterInstanceNum) = getPassNameAndInstanceNum(StartAfterOpt); StringRef StopBeforeName; std::tie(StopBeforeName, StopBeforeInstanceNum) = getPassNameAndInstanceNum(StopBeforeOpt); StringRef StopAfterName; std::tie(StopAfterName, StopAfterInstanceNum) = getPassNameAndInstanceNum(StopAfterOpt); StartBefore = getPassIDFromName(StartBeforeName); StartAfter = getPassIDFromName(StartAfterName); StopBefore = getPassIDFromName(StopBeforeName); StopAfter = getPassIDFromName(StopAfterName); if (StartBefore && StartAfter) report_fatal_error(Twine(StartBeforeOptName) + Twine(" and ") + Twine(StartAfterOptName) + Twine(" specified!")); if (StopBefore && StopAfter) report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") + Twine(StopAfterOptName) + Twine(" specified!")); Started = (StartAfter == nullptr) && (StartBefore == nullptr); } // Out of line constructor provides default values for pass options and // registers all common codegen passes. TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm) : ImmutablePass(ID), PM(&pm), TM(&TM) { Impl = new PassConfigImpl(); // Register all target independent codegen passes to activate their PassIDs, // including this pass itself. initializeCodeGen(*PassRegistry::getPassRegistry()); // Also register alias analysis passes required by codegen passes. initializeBasicAAWrapperPassPass(*PassRegistry::getPassRegistry()); initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry()); if (EnableIPRA.getNumOccurrences()) TM.Options.EnableIPRA = EnableIPRA; else { // If not explicitly specified, use target default. TM.Options.EnableIPRA |= TM.useIPRA(); } if (TM.Options.EnableIPRA) setRequiresCodeGenSCCOrder(); if (EnableGlobalISelAbort.getNumOccurrences()) TM.Options.GlobalISelAbort = EnableGlobalISelAbort; setStartStopPasses(); } CodeGenOpt::Level TargetPassConfig::getOptLevel() const { return TM->getOptLevel(); } /// Insert InsertedPassID pass after TargetPassID. void TargetPassConfig::insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID, bool VerifyAfter) { assert(((!InsertedPassID.isInstance() && TargetPassID != InsertedPassID.getID()) || (InsertedPassID.isInstance() && TargetPassID != InsertedPassID.getInstance()->getPassID())) && "Insert a pass after itself!"); Impl->InsertedPasses.emplace_back(TargetPassID, InsertedPassID, VerifyAfter); } /// 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) { return new TargetPassConfig(*this, PM); } TargetPassConfig::TargetPassConfig() : ImmutablePass(ID) { report_fatal_error("Trying to construct TargetPassConfig without a target " "machine. Scheduling a CodeGen pass without a target " "triple set?"); } bool TargetPassConfig::willCompleteCodeGenPipeline() { return StopBeforeOpt.empty() && StopAfterOpt.empty(); } bool TargetPassConfig::hasLimitedCodeGenPipeline() { return !StartBeforeOpt.empty() || !StartAfterOpt.empty() || !willCompleteCodeGenPipeline(); } std::string TargetPassConfig::getLimitedCodeGenPipelineReason(const char *Separator) { if (!hasLimitedCodeGenPipeline()) return std::string(); std::string Res; static cl::opt *PassNames[] = {&StartAfterOpt, &StartBeforeOpt, &StopAfterOpt, &StopBeforeOpt}; 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 += Separator; IsFirst = false; Res += OptNames[Idx]; } return Res; } // 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::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(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, bool verifyAfter) { 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) addMachinePrePasses(); std::string Banner; // Construct banner message before PM->add() as that may delete the pass. if (AddingMachinePasses && verifyAfter) Banner = std::string("After ") + std::string(P->getPassName()); PM->add(P); if (AddingMachinePasses) addMachinePostPasses(Banner, /*AllowVerify*/ verifyAfter); // Add the passes after the pass P if there is any. for (const auto &IP : Impl->InsertedPasses) { if (IP.TargetPassID == PassID) addPass(IP.getInsertedPass(), IP.VerifyAfter); } } else { delete P; } if (StopAfter == PassID && StopAfterCount++ == StopAfterInstanceNum) Stopped = true; if (StartAfter == PassID && StartAfterCount++ == StartAfterInstanceNum) Started = true; if (Stopped && !Started) report_fatal_error("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, bool verifyAfter) { IdentifyingPassPtr TargetID = getPassSubstitution(PassID); IdentifyingPassPtr FinalPtr = overridePass(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, verifyAfter); // 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 (PrintAfterISel) PM->add(createMachineFunctionPrinterPass(dbgs(), Banner)); } void TargetPassConfig::addVerifyPass(const std::string &Banner) { bool Verify = VerifyMachineCode == cl::BOU_TRUE; #ifdef EXPENSIVE_CHECKS if (VerifyMachineCode == cl::BOU_UNSET) Verify = TM->isMachineVerifierClean(); #endif if (Verify) PM->add(createMachineVerifierPass(Banner)); } void TargetPassConfig::addDebugifyPass() { PM->add(createDebugifyMachineModulePass()); } void TargetPassConfig::addStripDebugPass() { PM->add(createStripDebugMachineModulePass(/*OnlyDebugified=*/true)); } +void TargetPassConfig::addCheckDebugPass() { + PM->add(createCheckDebugMachineModulePass()); +} + void TargetPassConfig::addMachinePrePasses(bool AllowDebugify) { - if (AllowDebugify && DebugifyAndStripAll == cl::BOU_TRUE && DebugifyIsSafe) + if (AllowDebugify && DebugifyIsSafe && + (DebugifyAndStripAll == cl::BOU_TRUE || + DebugifyCheckAndStripAll == cl::BOU_TRUE)) addDebugifyPass(); } void TargetPassConfig::addMachinePostPasses(const std::string &Banner, bool AllowVerify, bool AllowStrip) { - if (DebugifyAndStripAll == cl::BOU_TRUE && DebugifyIsSafe) - addStripDebugPass(); + if (DebugifyIsSafe) { + if (DebugifyCheckAndStripAll == cl::BOU_TRUE) { + addCheckDebugPass(); + addStripDebugPass(); + } else if (DebugifyAndStripAll == cl::BOU_TRUE) + addStripDebugPass(); + } if (AllowVerify) 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() != CodeGenOpt::None) { switch (UseCFLAA) { case CFLAAType::Steensgaard: addPass(createCFLSteensAAWrapperPass()); break; case CFLAAType::Andersen: addPass(createCFLAndersAAWrapperPass()); break; case CFLAAType::Both: addPass(createCFLAndersAAWrapperPass()); addPass(createCFLSteensAAWrapperPass()); break; default: break; } // 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 (!DisableLSR) { addPass(createCanonicalizeFreezeInLoopsPass()); addPass(createLoopStrengthReducePass()); if (PrintLSR) addPass(createPrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n")); } // The MergeICmpsPass tries to create memcmp calls by grouping sequences of // loads and compares. ExpandMemCmpPass then tries to expand those calls // into optimally-sized loads and compares. The transforms are enabled by a // target lowering hook. if (!DisableMergeICmps) addPass(createMergeICmpsLegacyPass()); addPass(createExpandMemCmpPass()); } // Run GC lowering passes for builtin collectors // TODO: add a pass insertion point here addPass(createGCLoweringPass()); addPass(createShadowStackGCLoweringPass()); addPass(createLowerConstantIntrinsicsPass()); // Make sure that no unreachable blocks are instruction selected. addPass(createUnreachableBlockEliminationPass()); // Prepare expensive constants for SelectionDAG. if (getOptLevel() != CodeGenOpt::None && !DisableConstantHoisting) addPass(createConstantHoistingPass()); if (getOptLevel() != CodeGenOpt::None && !DisablePartialLibcallInlining) addPass(createPartiallyInlineLibCallsPass()); // Instrument function entry and exit, e.g. with calls to mcount(). 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 (!DisableExpandReductions) addPass(createExpandReductionsPass()); } /// Turn exception handling constructs into something the code generators can /// handle. void TargetPassConfig::addPassesToHandleExceptions() { const MCAsmInfo *MCAI = TM->getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); switch (MCAI->getExceptionHandlingType()) { case ExceptionHandling::SjLj: // 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. addPass(createSjLjEHPreparePass(TM)); LLVM_FALLTHROUGH; case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: case ExceptionHandling::AIX: addPass(createDwarfEHPass(getOptLevel())); break; case ExceptionHandling::WinEH: // We support using both GCC-style and MSVC-style exceptions on Windows, so // add both preparation passes. Each pass will only actually run if it // recognizes the personality function. addPass(createWinEHPass()); addPass(createDwarfEHPass(getOptLevel())); break; case ExceptionHandling::Wasm: // 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. addPass(createWinEHPass(/*DemoteCatchSwitchPHIOnly=*/false)); addPass(createWasmEHPass()); break; case ExceptionHandling::None: addPass(createLowerInvokePass()); // The lower invoke pass may create unreachable code. Remove it. addPass(createUnreachableBlockEliminationPass()); break; } } /// Add pass to prepare the LLVM IR for code generation. This should be done /// before exception handling preparation passes. void TargetPassConfig::addCodeGenPrepare() { if (getOptLevel() != CodeGenOpt::None && !DisableCGP) addPass(createCodeGenPreparePass()); addPass(createRewriteSymbolsPass()); } /// 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); // 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 (PrintISelInput) 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(EnableFastISelOption != cl::BOU_FALSE); // Determine an instruction selector. enum class SelectorType { SelectionDAG, FastISel, GlobalISel }; SelectorType Selector; if (EnableFastISelOption == cl::BOU_TRUE) Selector = SelectorType::FastISel; else if (EnableGlobalISelOption == cl::BOU_TRUE || (TM->Options.EnableGlobalISel && EnableGlobalISelOption != cl::BOU_FALSE)) Selector = SelectorType::GlobalISel; else if (TM->getOptLevel() == CodeGenOpt::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. 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. addPass(createResetMachineFunctionPass( reportDiagnosticWhenGlobalISelFallback(), isGlobalISelAbortEnabled())); // Provide a fallback path when we do not want to abort on // not-yet-supported input. if (!isGlobalISelAbortEnabled() && addInstSelector()) return true; } else 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()); addPass(createPreISelIntrinsicLoweringPass()); PM->add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); addIRPasses(); addCodeGenPrepare(); addPassesToHandleExceptions(); addISelPrepare(); return addCoreISelPasses(); } /// -regalloc=... command line option. static FunctionPass *useDefaultRegisterAllocator() { return nullptr; } static cl::opt> 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() != CodeGenOpt::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()); // 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; // 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(&FixupStatepointCallerSavedID); // Insert prolog/epilog code. Eliminate abstract frame index references... if (getOptLevel() != CodeGenOpt::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() != CodeGenOpt::None) addMachineLateOptimization(); // Expand pseudo instructions before second scheduling pass. addPass(&ExpandPostRAPseudosID); // Run pre-sched2 passes. addPreSched2(); if (EnableImplicitNullChecks) addPass(&ImplicitNullChecksID); // Second pass scheduler. // Let Target optionally insert this pass by itself at some other // point. if (getOptLevel() != CodeGenOpt::None && !TM->targetSchedulesPostRAScheduling()) { if (MISchedPostRA) addPass(&PostMachineSchedulerID); else addPass(&PostRASchedulerID); } // GC if (addGCPasses()) { if (PrintGCInfo) addPass(createGCInfoPrinter(dbgs()), false); } // Basic block placement. if (getOptLevel() != CodeGenOpt::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, false); addPass(&StackMapLivenessID, false); addPass(&LiveDebugValuesID, false); if (TM->Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None && EnableMachineOutliner != NeverOutline) { bool RunOnAllFunctions = (EnableMachineOutliner == AlwaysOutline); bool AddOutliner = RunOnAllFunctions || TM->Options.SupportsDefaultOutlining; if (AddOutliner) addPass(createMachineOutlinerPass(RunOnAllFunctions)); } // Machine function splitter uses the basic block sections feature. Both // cannot be enabled at the same time. if (TM->Options.EnableMachineFunctionSplitter || EnableMachineFunctionSplitter) { addPass(createMachineFunctionSplitterPass()); } else if (TM->getBBSectionsType() != llvm::BasicBlockSection::None) { addPass(llvm::createBasicBlockSectionsPass(TM->getBBSectionsFuncListBuf())); } // Add passes that directly emit MI after all other MI passes. addPreEmitPass2(); // Insert pseudo probe annotation for callsite profiling if (TM->Options.PseudoProbeForProfiling) addPass(createPseudoProbeInserter()); AddingMachinePasses = false; } /// Add passes that optimize machine instructions in SSA form. void TargetPassConfig::addMachineSSAOptimization() { // Pre-ra tail duplication. addPass(&EarlyTailDuplicateID); // Optimize PHIs before DCE: removing dead PHI cycles may make more // instructions dead. addPass(&OptimizePHIsID); // This pass merges large allocas. StackSlotColoring is a different pass // which merges spill slots. addPass(&StackColoringID); // 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(&MachineCSEID); addPass(&MachineSinkingID); addPass(&PeepholeOptimizerID); // Clean-up the dead code that may have been generated by peephole // rewriting. addPass(&DeadMachineInstructionElimID); } //===---------------------------------------------------------------------===// /// Register Allocation Pass Configuration //===---------------------------------------------------------------------===// bool TargetPassConfig::getOptimizeRegAlloc() const { switch (OptimizeRegAlloc) { case cl::BOU_UNSET: return getOptLevel() != CodeGenOpt::None; case cl::BOU_TRUE: return true; case cl::BOU_FALSE: return false; } llvm_unreachable("Invalid optimize-regalloc state"); } /// 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); } /// 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) { // Initialize the global default. llvm::call_once(InitializeDefaultRegisterAllocatorFlag, initializeDefaultRegisterAllocatorOnce); 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::addRegAssignmentFast() { if (RegAlloc != &useDefaultRegisterAllocator && RegAlloc != &createFastRegisterAllocator) report_fatal_error("Must use fast (default) register allocator for unoptimized regalloc."); addPass(createRegAllocPass(false)); return true; } bool TargetPassConfig::addRegAssignmentOptimized() { // 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); // Perform stack slot coloring and post-ra machine LICM. // // FIXME: Re-enable coloring with register when it's capable of adding // kill markers. addPass(&StackSlotColoringID); 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, false); addPass(&TwoAddressInstructionPassID, false); addRegAssignmentFast(); } /// 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, false); addPass(&ProcessImplicitDefsID, false); // LiveVariables currently requires pure SSA form. // // FIXME: Once TwoAddressInstruction pass no longer uses kill flags, // LiveVariables can be removed completely, and LiveIntervals can be directly // computed. (We still either need to regenerate kill flags after regalloc, or // preferably fix the scavenger to not depend on them). // FIXME: UnreachableMachineBlockElim is a dependant pass of LiveVariables. // When LiveVariables is removed this has to be removed/moved either. // Explicit addition of UnreachableMachineBlockElim allows stopping before or // after it with -stop-before/-stop-after. addPass(&UnreachableMachineBlockElimID, false); addPass(&LiveVariablesID, false); // Edge splitting is smarter with machine loop info. addPass(&MachineLoopInfoID, false); addPass(&PHIEliminationID, false); // Eventually, we want to run LiveIntervals before PHI elimination. if (EarlyLiveIntervals) addPass(&LiveIntervalsID, false); addPass(&TwoAddressInstructionPassID, false); 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 (addRegAssignmentOptimized()) { // 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() { // 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(&TailDuplicateID); // Copy propagation. addPass(&MachineCopyPropagationID); } /// Add standard GC passes. bool TargetPassConfig::addGCPasses() { addPass(&GCMachineCodeAnalysisID, false); return true; } /// Add standard basic block placement passes. void TargetPassConfig::addBlockPlacement() { if (addPass(&MachineBlockPlacementID)) { // Run a separate pass to collect block placement statistics. if (EnableBlockPlacementStats) addPass(&MachineBlockPlacementStatsID); } } //===---------------------------------------------------------------------===// /// GlobalISel Configuration //===---------------------------------------------------------------------===// bool TargetPassConfig::isGlobalISelAbortEnabled() const { return TM->Options.GlobalISelAbort == GlobalISelAbortMode::Enable; } bool TargetPassConfig::reportDiagnosticWhenGlobalISelFallback() const { return TM->Options.GlobalISelAbort == GlobalISelAbortMode::DisableWithDiag; } bool TargetPassConfig::isGISelCSEEnabled() const { return true; } std::unique_ptr TargetPassConfig::getCSEConfig() const { return std::make_unique(); } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/constant-mir-debugify.mir b/llvm/test/CodeGen/AArch64/GlobalISel/constant-mir-debugify.mir index 362f4511ca0d..1ba8b0043b92 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/constant-mir-debugify.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/constant-mir-debugify.mir @@ -1,33 +1,33 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -debugify-and-strip-all-safe=0 -run-pass=mir-debugify -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s ... --- name: fconstant_to_constant_s32 alignment: 4 tracksRegLiveness: true frameInfo: maxAlignment: 1 machineFunctionInfo: {} body: | bb.0: liveins: $x0 ; CHECK-LABEL: name: fconstant_to_constant_s32 ; CHECK: liveins: $x0 - ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0, debug-location !10 - ; CHECK: DBG_VALUE [[COPY]](p0), $noreg, !8, !DIExpression(), debug-location !10 - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x3FA99999A0000000, debug-location !DILocation(line: 2, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[C]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !5) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 524, debug-location !DILocation(line: 3, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[C1]](s64), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !5) - ; CHECK: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C1]](s64), debug-location !DILocation(line: 4, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[PTR_ADD]](p0), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !5) - ; CHECK: G_STORE [[C]](s32), [[PTR_ADD]](p0), debug-location !DILocation(line: 5, column: 1, scope: !5) :: (store 4) - ; CHECK: DBG_VALUE 0, $noreg, !8, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !5) - ; CHECK: RET_ReallyLR debug-location !DILocation(line: 6, column: 1, scope: !5) + ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0, debug-location !11 + ; CHECK: DBG_VALUE [[COPY]](p0), $noreg, !9, !DIExpression(), debug-location !11 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x3FA99999A0000000, debug-location !DILocation(line: 2, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[C]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !6) + ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 524, debug-location !DILocation(line: 3, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[C1]](s64), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !6) + ; CHECK: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C1]](s64), debug-location !DILocation(line: 4, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[PTR_ADD]](p0), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !6) + ; CHECK: G_STORE [[C]](s32), [[PTR_ADD]](p0), debug-location !DILocation(line: 5, column: 1, scope: !6) :: (store 4) + ; CHECK: DBG_VALUE 0, $noreg, !9, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !6) + ; CHECK: RET_ReallyLR debug-location !DILocation(line: 6, column: 1, scope: !6) %0:_(p0) = COPY $x0 %3:_(s32) = G_FCONSTANT float 0x3FA99999A0000000 %1:_(s64) = G_CONSTANT i64 524 %2:_(p0) = G_PTR_ADD %0, %1(s64) G_STORE %3(s32), %2(p0) :: (store 4) RET_ReallyLR ... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/phi-mir-debugify.mir b/llvm/test/CodeGen/AArch64/GlobalISel/phi-mir-debugify.mir index 7d85afeb3a2e..d37033aec669 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/phi-mir-debugify.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/phi-mir-debugify.mir @@ -1,106 +1,106 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -debugify-and-strip-all-safe=0 -run-pass=mir-debugify -verify-machineinstrs %s -o - | FileCheck %s --- | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64-unknown-unknown" define i32 @legalize_phi(i32 %argc) { entry: ret i32 0 } ... --- name: legalize_phi alignment: 4 exposesReturnsTwice: false legalized: false regBankSelected: false selected: false tracksRegLiveness: true registers: - { id: 0, class: _, preferred-register: '' } - { id: 1, class: _, preferred-register: '' } - { id: 2, class: _, preferred-register: '' } - { id: 3, class: _, preferred-register: '' } - { id: 4, class: _, preferred-register: '' } - { id: 5, class: _, preferred-register: '' } - { id: 6, class: _, preferred-register: '' } - { id: 7, class: _, preferred-register: '' } - { id: 8, class: _, preferred-register: '' } - { id: 9, class: _, preferred-register: '' } - { id: 10, class: _, preferred-register: '' } liveins: body: | ; CHECK-LABEL: name: legalize_phi ; CHECK: bb.0: ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) ; CHECK: liveins: $w0 - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0, debug-location !10 - ; CHECK: DBG_VALUE [[COPY]](s32), $noreg, !8, !DIExpression(), debug-location !10 - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0, debug-location !DILocation(line: 2, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[C]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !5) - ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1, debug-location !DILocation(line: 3, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[C1]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !5) - ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2, debug-location !DILocation(line: 4, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[C2]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !5) - ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), [[COPY]](s32), [[C]], debug-location !DILocation(line: 5, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[ICMP]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !5) - ; CHECK: G_BRCOND [[ICMP]](s1), %bb.1, debug-location !DILocation(line: 6, column: 1, scope: !5) - ; CHECK: G_BR %bb.2, debug-location !DILocation(line: 7, column: 1, scope: !5) + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0, debug-location !11 + ; CHECK: DBG_VALUE [[COPY]](s32), $noreg, !9, !DIExpression(), debug-location !11 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0, debug-location !DILocation(line: 2, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[C]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !6) + ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1, debug-location !DILocation(line: 3, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[C1]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !6) + ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2, debug-location !DILocation(line: 4, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[C2]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !6) + ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), [[COPY]](s32), [[C]], debug-location !DILocation(line: 5, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[ICMP]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !6) + ; CHECK: G_BRCOND [[ICMP]](s1), %bb.1, debug-location !DILocation(line: 6, column: 1, scope: !6) + ; CHECK: G_BR %bb.2, debug-location !DILocation(line: 7, column: 1, scope: !6) ; CHECK: bb.1: ; CHECK: successors: %bb.3(0x80000000) - ; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C1]], debug-location !DILocation(line: 8, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[ADD]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 8, column: 1, scope: !5) - ; CHECK: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ADD]](s32), debug-location !DILocation(line: 9, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[TRUNC]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 9, column: 1, scope: !5) - ; CHECK: G_BR %bb.3, debug-location !DILocation(line: 10, column: 1, scope: !5) + ; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C1]], debug-location !DILocation(line: 8, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[ADD]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 8, column: 1, scope: !6) + ; CHECK: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ADD]](s32), debug-location !DILocation(line: 9, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[TRUNC]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 9, column: 1, scope: !6) + ; CHECK: G_BR %bb.3, debug-location !DILocation(line: 10, column: 1, scope: !6) ; CHECK: bb.2: ; CHECK: successors: %bb.3(0x80000000) - ; CHECK: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C2]], debug-location !DILocation(line: 11, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[ADD1]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 11, column: 1, scope: !5) - ; CHECK: [[TRUNC1:%[0-9]+]]:_(s1) = G_TRUNC [[ADD1]](s32), debug-location !DILocation(line: 12, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[TRUNC1]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 12, column: 1, scope: !5) + ; CHECK: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C2]], debug-location !DILocation(line: 11, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[ADD1]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 11, column: 1, scope: !6) + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s1) = G_TRUNC [[ADD1]](s32), debug-location !DILocation(line: 12, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[TRUNC1]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 12, column: 1, scope: !6) ; CHECK: bb.3: - ; CHECK: [[PHI:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 13, column: 1, scope: !5) - ; CHECK: [[PHI1:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 14, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[PHI]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 13, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[PHI1]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 14, column: 1, scope: !5) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[PHI]](s1), debug-location !DILocation(line: 15, column: 1, scope: !5) - ; CHECK: DBG_VALUE [[ZEXT]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 15, column: 1, scope: !5) - ; CHECK: $w0 = COPY [[ZEXT]](s32), debug-location !DILocation(line: 16, column: 1, scope: !5) - ; CHECK: DBG_VALUE $w0, $noreg, !8, !DIExpression(), debug-location !DILocation(line: 16, column: 1, scope: !5) - ; CHECK: RET_ReallyLR implicit $w0, debug-location !DILocation(line: 17, column: 1, scope: !5) + ; CHECK: [[PHI:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 13, column: 1, scope: !6) + ; CHECK: [[PHI1:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 14, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[PHI]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 13, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[PHI1]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 14, column: 1, scope: !6) + ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[PHI]](s1), debug-location !DILocation(line: 15, column: 1, scope: !6) + ; CHECK: DBG_VALUE [[ZEXT]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 15, column: 1, scope: !6) + ; CHECK: $w0 = COPY [[ZEXT]](s32), debug-location !DILocation(line: 16, column: 1, scope: !6) + ; CHECK: DBG_VALUE $w0, $noreg, !9, !DIExpression(), debug-location !DILocation(line: 16, column: 1, scope: !6) + ; CHECK: RET_ReallyLR implicit $w0, debug-location !DILocation(line: 17, column: 1, scope: !6) bb.0: successors: %bb.1(0x40000000), %bb.2(0x40000000) liveins: $w0 %0(s32) = COPY $w0 %1(s32) = G_CONSTANT i32 0 %3(s32) = G_CONSTANT i32 1 %6(s32) = G_CONSTANT i32 2 %2(s1) = G_ICMP intpred(ugt), %0(s32), %1 G_BRCOND %2(s1), %bb.1 G_BR %bb.2 bb.1: successors: %bb.3(0x80000000) %4(s32) = G_ADD %0, %3 %5(s1) = G_TRUNC %4(s32) G_BR %bb.3 bb.2: successors: %bb.3(0x80000000) %7(s32) = G_ADD %0, %6 %8(s1) = G_TRUNC %7(s32) bb.3: %9(s1) = G_PHI %5(s1), %bb.1, %8(s1), %bb.2 %11:_(s1) = G_PHI %5(s1), %bb.1, %8(s1), %bb.2 %10(s32) = G_ZEXT %9(s1) $w0 = COPY %10(s32) RET_ReallyLR implicit $w0 ... diff --git a/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables-x.mir b/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables-x.mir new file mode 100644 index 000000000000..47e78bc8a3f0 --- /dev/null +++ b/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables-x.mir @@ -0,0 +1,79 @@ +# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=mir-check-debugify -o - %s 2>&1 | FileCheck %s +--- | + ; ModuleID = 'check-line-and-variables.mir' + source_filename = "check-line-and-variables.c" + + @ga = dso_local local_unnamed_addr global i32 2, align 4 + + ; Function Attrs: nofree norecurse nounwind uwtable writeonly + define dso_local i32 @foo(i32 %a, i32 %b) local_unnamed_addr #0 !dbg !9 { + entry: + %add = add nsw i32 %b, %a, !dbg !15 + call void @llvm.dbg.value(metadata i32 %add, metadata !12, metadata !DIExpression()), !dbg !15 + %mul = shl nsw i32 %add, 1, !dbg !16 + call void @llvm.dbg.value(metadata i32 %mul, metadata !14, metadata !DIExpression()), !dbg !16 + store i32 %mul, i32* @ga, align 4, !dbg !17 + ret i32 %add, !dbg !18 + } + + declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + + !llvm.module.flags = !{!0, !1} + !llvm.ident = !{!2} + !llvm.dbg.cu = !{!3} + !llvm.mir.debugify = !{!6, !7} + !llvm.debugify = !{!8, !7} + + !0 = !{i32 1, !"wchar_size", i32 4} + !1 = !{i32 2, !"Debug Info Version", i32 3} + !2 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git c0a922b3db2d39f36c0c01776cce90cc160a7d62)"} + !3 = distinct !DICompileUnit(language: DW_LANG_C, file: !4, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5) + !4 = !DIFile(filename: "main.mir", directory: "/") + !5 = !{} + !6 = !{i32 6} + !7 = !{i32 2} + !8 = !{i32 4} + !9 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !4, line: 1, type: !10, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !3, retainedNodes: !11) + !10 = !DISubroutineType(types: !5) + !11 = !{!12, !14} + !12 = !DILocalVariable(name: "1", scope: !9, file: !4, line: 1, type: !13) + !13 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned) + !14 = !DILocalVariable(name: "2", scope: !9, file: !4, line: 2, type: !13) + !15 = !DILocation(line: 1, column: 1, scope: !9) + !16 = !DILocation(line: 2, column: 1, scope: !9) + !17 = !DILocation(line: 3, column: 1, scope: !9) + !18 = !DILocation(line: 4, column: 1, scope: !9) + +... +--- +name: foo +body: | + bb.0.entry: + liveins: $edi, $esi + + %1:gr32 = COPY $esi, debug-location !15 + DBG_VALUE %1, $noreg, !12, !DIExpression(), debug-location !15 + ; Let it missing !14 and debug-location !16 + ; %0:gr32 = COPY $edi, debug-location !16 + ; DBG_VALUE %0, $noreg, !14, !DIExpression(), debug-location !16 + %0:gr32 = COPY $edi + %2:gr32 = nsw ADD32rr %1, %0, implicit-def dead $eflags, debug-location !17 + DBG_VALUE %2, $noreg, !12, !DIExpression(), debug-location !17 + DBG_VALUE $eflags, $noreg, !12, !DIExpression(), debug-location !17 + %3:gr32 = nsw ADD32rr %2, %2, implicit-def dead $eflags, debug-location !18 + DBG_VALUE %3, $noreg, !12, !DIExpression(), debug-location !18 + DBG_VALUE $eflags, $noreg, !12, !DIExpression(), debug-location !18 + MOV32mr $rip, 1, $noreg, @ga, $noreg, killed %3, debug-location !DILocation(line: 5, column: 1, scope: !9) :: (store 4 into @ga, !tbaa !18) + DBG_VALUE 0, $noreg, !12, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !9) + ; Let it miss Line 6: Change "!DILocation(line: 6, ..." to "!DILocation(line: 5, ..." + $eax = COPY %2, debug-location !DILocation(line: 5, column: 1, scope: !9) + DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !DILocation(line: 6, column: 1, scope: !9) + RET 0, $eax, debug-location !DILocation(line: 7, column: 1, scope: !9) + + ;CHECK: WARNING: Instruction with empty DebugLoc in function foo --%1:gr32 = COPY $edi + ;CHECK-NEXT: WARNING: Missing line 2 + ;CHECK-NEXT: WARNING: Missing line 6 + ;CHECK-NEXT: WARNING: Missing variable 2 + ;CHECK-NEXT: Machine IR debug info check: FAIL + +... diff --git a/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables.ll b/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables.ll new file mode 100644 index 000000000000..1b859907db0e --- /dev/null +++ b/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables.ll @@ -0,0 +1,29 @@ +; RUN: llc -debugify-check-and-strip-all-safe -o - %s 2>&1 | FileCheck %s + +; ModuleID = 'main.c' +source_filename = "main.c" + +@ga = dso_local global i32 2, align 4 + +define dso_local i32 @foo(i32 %a, i32 %b) { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %c = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + store i32 %b, i32* %b.addr, align 4 + %0 = load i32, i32* %a.addr, align 4 + %1 = load i32, i32* %b.addr, align 4 + %add = add nsw i32 %0, %1 + store i32 %add, i32* %c, align 4 + %2 = load i32, i32* %c, align 4 + %mul = mul nsw i32 %2, 2 + store i32 %mul, i32* @ga, align 4 + %3 = load i32, i32* %c, align 4 + ret i32 %3 +} + +; Different Back-Ends may have different number of passes, here we only +; check two of them to make sure -debugify-check-and-strip-all-safe works. +;CHECK: Machine IR debug info check: PASS +;CHECK: Machine IR debug info check: PASS diff --git a/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables.mir b/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables.mir new file mode 100644 index 000000000000..1deb4fe5db09 --- /dev/null +++ b/llvm/test/CodeGen/Generic/MIRDebugify/check-line-and-variables.mir @@ -0,0 +1,69 @@ +# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=mir-debugify,dead-mi-elimination,mir-check-debugify -o - %s 2>&1 | FileCheck %s +# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=mir-debugify,mir-check-debugify -o - %s 2>&1 | FileCheck %s --check-prefix=CHECK-PASS +--- | + ; ModuleID = 'check-line-and-variables.mir' + source_filename = "check-line-and-variables.ll" + + @ga = dso_local global i32 2, align 4 + + ; Function Attrs: noinline nounwind optnone uwtable + define dso_local i32 @foo(i32 %a, i32 %b) { + entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %c = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + store i32 %b, i32* %b.addr, align 4 + %0 = load i32, i32* %a.addr, align 4 + %1 = load i32, i32* %b.addr, align 4 + %add = add nsw i32 %0, %1 + store i32 %add, i32* %c, align 4 + %2 = load i32, i32* %c, align 4 + %mul = mul nsw i32 %2, 2 + store i32 %mul, i32* @ga, align 4 + %3 = load i32, i32* %c, align 4 + ; dead-mi-elimination will remove %4 = ... + %4 = load i32, i32* %a.addr, align 4 + ret i32 %3 + } + +... +--- +name: foo +alignment: 16 +stack: + - { id: 0, name: a.addr, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: b.addr, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 2, name: c, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.0.entry: + liveins: $edi, $esi + + %2:gr32 = COPY $esi + %0:gr32 = COPY $edi + %1:gr32 = COPY killed %0 + %3:gr32 = COPY killed %2 + MOV32mr %stack.0.a.addr, 1, $noreg, 0, $noreg, %1 :: (store 4 into %ir.a.addr) + MOV32mr %stack.1.b.addr, 1, $noreg, 0, $noreg, %3 :: (store 4 into %ir.b.addr) + %14:gr32 = MOV32rm %stack.0.a.addr, 1, $noreg, 0, $noreg :: (load 4 from %ir.a.addr) + %13:gr32 = ADD32rm killed %14, %stack.1.b.addr, 1, $noreg, 0, $noreg, implicit-def $eflags :: (load 4 from %ir.b.addr) + ; dead-mi-elimination will remove %15:gr32 = ... + %15:gr32 = MOV32rm %stack.0.a.addr, 1, $noreg, 0, $noreg :: (load 4 from %ir.a.addr) + MOV32mr %stack.2.c, 1, $noreg, 0, $noreg, killed %13 :: (store 4 into %ir.c) + %9:gr32 = MOV32rm %stack.2.c, 1, $noreg, 0, $noreg :: (load 4 from %ir.c) + %8:gr32 = SHL32ri killed %9, 1, implicit-def $eflags + MOV32mr $noreg, 1, $noreg, @ga, $noreg, killed %8 :: (store 4 into @ga) + %5:gr32 = MOV32rm %stack.2.c, 1, $noreg, 0, $noreg :: (load 4 from %ir.c) + $eax = COPY %5 + RETQ implicit $eax + + ;CHECK: WARNING: Missing line 9 + ;CHECK-NEXT: Machine IR debug info check: FAIL + ;CHECK-PASS: Machine IR debug info check: PASS +... diff --git a/llvm/test/CodeGen/Generic/MIRDebugify/locations-and-values.mir b/llvm/test/CodeGen/Generic/MIRDebugify/locations-and-values.mir index 84e93f9474b8..79dc90f017c1 100644 --- a/llvm/test/CodeGen/Generic/MIRDebugify/locations-and-values.mir +++ b/llvm/test/CodeGen/Generic/MIRDebugify/locations-and-values.mir @@ -1,51 +1,51 @@ # RUN: llc -run-pass=mir-debugify -o - %s | FileCheck --check-prefixes=ALL,VALUE %s # RUN: llc -run-pass=mir-debugify -debugify-level=locations -o - %s | FileCheck --check-prefixes=ALL --implicit-check-not=dbg.value %s # RUN: llc -run-pass=mir-debugify,mir-strip-debug,mir-debugify -o - %s | FileCheck --check-prefixes=ALL,VALUE %s --- | ; ModuleID = 'loc-only.ll' source_filename = "loc-only.ll" ; ALL-LABEL: @test define i32 @test(i32 %a, i32 %b) { %add = add i32 %a, 2 ; ALL-NEXT: %add = add i32 %a, 2, !dbg [[L1:![0-9]+]] ; VALUE-NEXT: call void @llvm.dbg.value(metadata i32 %add, metadata [[add:![0-9]+]], metadata !DIExpression()), !dbg [[L1]] %sub = sub i32 %add, %b ; ALL-NEXT: %sub = sub i32 %add, %b, !dbg [[L2:![0-9]+]] ; VALUE-NEXT: call void @llvm.dbg.value(metadata i32 %sub, metadata [[sub:![0-9]+]], metadata !DIExpression()), !dbg [[L2]] ; ALL-NEXT: ret i32 %sub, !dbg [[L3:![0-9]+]] ret i32 %sub } - ; ALL: !llvm.dbg.cu = !{!0} + ; ALL: !llvm.dbg.cu = !{![[CU:[0-9]+]]} ; ALL: !llvm.debugify = ; ALL: !llvm.module.flags = !{![[VERSION:[0-9]+]]} - ; ALL: !0 = distinct !DICompileUnit( + ; ALL: ![[CU]] = distinct !DICompileUnit( ; ALL: ![[VERSION]] = !{i32 2, !"Debug Info Version", i32 3} ; VALUE: [[VAR1:![0-9]+]] = !DILocalVariable(name: "1" ; VALUE: [[VAR2:![0-9]+]] = !DILocalVariable(name: "2" ... --- name: test body: | bb.1 (%ir-block.0): %0:_(s32) = IMPLICIT_DEF %1:_(s32) = IMPLICIT_DEF %2:_(s32) = G_CONSTANT i32 2 %3:_(s32) = G_ADD %0, %2 %4:_(s32) = G_SUB %3, %1 ; There's no attempt to have the locations make sense as it's an imaginary ; source file anyway. These first three coincide with IR-level information ; and therefore use metadata references. ; ALL: %0:_(s32) = IMPLICIT_DEF debug-location [[L1]] ; VALUE: DBG_VALUE %0(s32), $noreg, [[VAR1]], !DIExpression(), debug-location [[L1]] ; ALL: %1:_(s32) = IMPLICIT_DEF debug-location [[L2]] ; VALUE: DBG_VALUE %1(s32), $noreg, [[VAR2]], !DIExpression(), debug-location [[L2]] ; ALL: %2:_(s32) = G_CONSTANT i32 2, debug-location [[L3]] ; VALUE: DBG_VALUE %2(s32), $noreg, [[VAR1]], !DIExpression(), debug-location [[L3]] - ; ALL: %3:_(s32) = G_ADD %0, %2, debug-location !DILocation(line: 4, column: 1, scope: !6) + ; ALL: %3:_(s32) = G_ADD %0, %2, debug-location !DILocation(line: 4, column: 1, scope: [[SP:![0-9]+]]) ; VALUE: DBG_VALUE %3(s32), $noreg, [[VAR1]], !DIExpression(), debug-location !DILocation(line: 4 - ; ALL: %4:_(s32) = G_SUB %3, %1, debug-location !DILocation(line: 5, column: 1, scope: !6) + ; ALL: %4:_(s32) = G_SUB %3, %1, debug-location !DILocation(line: 5, column: 1, scope: [[SP]]) ; VALUE: DBG_VALUE %4(s32), $noreg, [[VAR1]], !DIExpression(), debug-location !DILocation(line: 5 ... diff --git a/llvm/utils/gn/secondary/llvm/lib/CodeGen/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/CodeGen/BUILD.gn index a1e117bb716e..961cb0b0bc46 100644 --- a/llvm/utils/gn/secondary/llvm/lib/CodeGen/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/CodeGen/BUILD.gn @@ -1,209 +1,210 @@ static_library("CodeGen") { output_name = "LLVMCodeGen" public_deps = [ # Must be a public_dep because CodeGen's headers include llvm-config.h. "//llvm/include/llvm/Config:llvm-config", ] deps = [ "//llvm/lib/Analysis", "//llvm/lib/Bitcode/Reader", "//llvm/lib/Bitcode/Writer", "//llvm/lib/IR", "//llvm/lib/MC", "//llvm/lib/ProfileData", "//llvm/lib/Support", "//llvm/lib/Target", "//llvm/lib/Transforms/Scalar", "//llvm/lib/Transforms/Utils", ] sources = [ "AggressiveAntiDepBreaker.cpp", "AllocationOrder.cpp", "Analysis.cpp", "AtomicExpandPass.cpp", "BasicBlockSections.cpp", "BasicTargetTransformInfo.cpp", "BranchFolding.cpp", "BranchRelaxation.cpp", "BreakFalseDeps.cpp", "BuiltinGCs.cpp", "CFGuardLongjmp.cpp", "CFIInstrInserter.cpp", "CalcSpillWeights.cpp", "CallingConvLower.cpp", "CodeGen.cpp", "CodeGenPrepare.cpp", "CommandFlags.cpp", "CriticalAntiDepBreaker.cpp", "DFAPacketizer.cpp", "DeadMachineInstructionElim.cpp", "DetectDeadLanes.cpp", "DwarfEHPrepare.cpp", "EarlyIfConversion.cpp", "EdgeBundles.cpp", "ExecutionDomainFix.cpp", "ExpandMemCmp.cpp", "ExpandPostRAPseudos.cpp", "ExpandReductions.cpp", "FEntryInserter.cpp", "FaultMaps.cpp", "FinalizeISel.cpp", "FixupStatepointCallerSaved.cpp", "FuncletLayout.cpp", "GCMetadata.cpp", "GCMetadataPrinter.cpp", "GCRootLowering.cpp", "GCStrategy.cpp", "GlobalMerge.cpp", "HardwareLoops.cpp", "IfConversion.cpp", "ImplicitNullChecks.cpp", "IndirectBrExpandPass.cpp", "InlineSpiller.cpp", "InterferenceCache.cpp", "InterleavedAccessPass.cpp", "InterleavedLoadCombinePass.cpp", "IntrinsicLowering.cpp", "LLVMTargetMachine.cpp", "LatencyPriorityQueue.cpp", "LazyMachineBlockFrequencyInfo.cpp", "LexicalScopes.cpp", "LiveDebugValues/InstrRefBasedImpl.cpp", "LiveDebugValues/LiveDebugValues.cpp", "LiveDebugValues/VarLocBasedImpl.cpp", "LiveDebugVariables.cpp", "LiveInterval.cpp", "LiveIntervalCalc.cpp", "LiveIntervalUnion.cpp", "LiveIntervals.cpp", "LivePhysRegs.cpp", "LiveRangeCalc.cpp", "LiveRangeEdit.cpp", "LiveRangeShrink.cpp", "LiveRegMatrix.cpp", "LiveRegUnits.cpp", "LiveStacks.cpp", "LiveVariables.cpp", "LocalStackSlotAllocation.cpp", "LoopTraversal.cpp", "LowLevelType.cpp", "LowerEmuTLS.cpp", "MBFIWrapper.cpp", "MIRCanonicalizerPass.cpp", "MIRNamerPass.cpp", "MIRPrinter.cpp", "MIRPrintingPass.cpp", "MIRVRegNamerUtils.cpp", "MachineBasicBlock.cpp", "MachineBlockFrequencyInfo.cpp", "MachineBlockPlacement.cpp", "MachineBranchProbabilityInfo.cpp", "MachineCSE.cpp", + "MachineCheckDebugify.cpp", "MachineCombiner.cpp", "MachineCopyPropagation.cpp", "MachineDebugify.cpp", "MachineDominanceFrontier.cpp", "MachineDominators.cpp", "MachineFrameInfo.cpp", "MachineFunction.cpp", "MachineFunctionPass.cpp", "MachineFunctionPrinterPass.cpp", "MachineFunctionSplitter.cpp", "MachineInstr.cpp", "MachineInstrBundle.cpp", "MachineLICM.cpp", "MachineLoopInfo.cpp", "MachineLoopUtils.cpp", "MachineModuleInfo.cpp", "MachineModuleInfoImpls.cpp", "MachineOperand.cpp", "MachineOptimizationRemarkEmitter.cpp", "MachineOutliner.cpp", "MachinePassManager.cpp", "MachinePipeliner.cpp", "MachinePostDominators.cpp", "MachineRegionInfo.cpp", "MachineRegisterInfo.cpp", "MachineSSAUpdater.cpp", "MachineScheduler.cpp", "MachineSink.cpp", "MachineSizeOpts.cpp", "MachineStableHash.cpp", "MachineStripDebug.cpp", "MachineTraceMetrics.cpp", "MachineVerifier.cpp", "MacroFusion.cpp", "ModuloSchedule.cpp", "MultiHazardRecognizer.cpp", "NonRelocatableStringpool.cpp", "OptimizePHIs.cpp", "PHIElimination.cpp", "PHIEliminationUtils.cpp", "ParallelCG.cpp", "PatchableFunction.cpp", "PeepholeOptimizer.cpp", "PostRAHazardRecognizer.cpp", "PostRASchedulerList.cpp", "PreISelIntrinsicLowering.cpp", "ProcessImplicitDefs.cpp", "PrologEpilogInserter.cpp", "PseudoProbeInserter.cpp", "PseudoSourceValue.cpp", "RDFGraph.cpp", "RDFLiveness.cpp", "RDFRegisters.cpp", "ReachingDefAnalysis.cpp", "RegAllocBase.cpp", "RegAllocBasic.cpp", "RegAllocFast.cpp", "RegAllocGreedy.cpp", "RegAllocPBQP.cpp", "RegUsageInfoCollector.cpp", "RegUsageInfoPropagate.cpp", "RegisterClassInfo.cpp", "RegisterCoalescer.cpp", "RegisterPressure.cpp", "RegisterScavenging.cpp", "RegisterUsageInfo.cpp", "RenameIndependentSubregs.cpp", "ResetMachineFunctionPass.cpp", "SafeStack.cpp", "SafeStackLayout.cpp", "ScheduleDAG.cpp", "ScheduleDAGInstrs.cpp", "ScheduleDAGPrinter.cpp", "ScoreboardHazardRecognizer.cpp", "ShadowStackGCLowering.cpp", "ShrinkWrap.cpp", "SjLjEHPrepare.cpp", "SlotIndexes.cpp", "SpillPlacement.cpp", "SplitKit.cpp", "StackColoring.cpp", "StackMapLivenessAnalysis.cpp", "StackMaps.cpp", "StackProtector.cpp", "StackSlotColoring.cpp", "SwiftErrorValueTracking.cpp", "SwitchLoweringUtils.cpp", "TailDuplication.cpp", "TailDuplicator.cpp", "TargetFrameLoweringImpl.cpp", "TargetInstrInfo.cpp", "TargetLoweringBase.cpp", "TargetLoweringObjectFileImpl.cpp", "TargetOptionsImpl.cpp", "TargetPassConfig.cpp", "TargetRegisterInfo.cpp", "TargetSchedule.cpp", "TargetSubtargetInfo.cpp", "TwoAddressInstructionPass.cpp", "TypePromotion.cpp", "UnreachableBlockElim.cpp", "ValueTypes.cpp", "VirtRegMap.cpp", "WasmEHPrepare.cpp", "WinEHPrepare.cpp", "XRayInstrumentation.cpp", ] }