diff options
Diffstat (limited to 'llvm/docs')
| -rw-r--r-- | llvm/docs/CodingStandards.rst | 46 | ||||
| -rw-r--r-- | llvm/docs/CommandGuide/index.rst | 1 | ||||
| -rw-r--r-- | llvm/docs/CommandGuide/llvm-ir2vec.rst | 170 | ||||
| -rw-r--r-- | llvm/docs/GettingInvolved.rst | 5 | ||||
| -rw-r--r-- | llvm/docs/HowToSubmitABug.rst | 13 | ||||
| -rw-r--r-- | llvm/docs/HowToUpdateDebugInfo.rst | 10 | ||||
| -rw-r--r-- | llvm/docs/KeyInstructionsDebugInfo.md | 160 | ||||
| -rw-r--r-- | llvm/docs/LangRef.rst | 60 | ||||
| -rw-r--r-- | llvm/docs/MLGO.rst | 12 | ||||
| -rw-r--r-- | llvm/docs/RISCVUsage.rst | 3 | ||||
| -rw-r--r-- | llvm/docs/ReleaseNotes.md | 17 | ||||
| -rw-r--r-- | llvm/docs/Security.rst | 76 | ||||
| -rw-r--r-- | llvm/docs/UserGuides.rst | 5 |
13 files changed, 496 insertions, 82 deletions
diff --git a/llvm/docs/CodingStandards.rst b/llvm/docs/CodingStandards.rst index c614a6d7ace9..732227b98ab9 100644 --- a/llvm/docs/CodingStandards.rst +++ b/llvm/docs/CodingStandards.rst @@ -30,7 +30,7 @@ because the naming and other conventions are dictated by the C++ standard. There are some conventions that are not uniformly followed in the code base (e.g. the naming convention). This is because they are relatively new, and a -lot of code was written before they were put in place. Our long term goal is +lot of code was written before they were put in place. Our long-term goal is for the entire codebase to follow the convention, but we explicitly *do not* want patches that do large-scale reformatting of existing code. On the other hand, it is reasonable to rename the methods of a class if you're about to @@ -50,7 +50,7 @@ code imported into the tree. Generally, our preference is for standards conforming, modern, and portable C++ code as the implementation language of choice. -For automation, build-systems and utility scripts Python is preferred and +For automation, build-systems, and utility scripts, Python is preferred and is widely used in the LLVM repository already. C++ Standard Versions @@ -92,7 +92,7 @@ LLVM support libraries (for example, `ADT <https://github.com/llvm/llvm-project/tree/main/llvm/include/llvm/ADT>`_) implement specialized data structures or functionality missing in the standard library. Such libraries are usually implemented in the ``llvm`` namespace and -follow the expected standard interface, when there is one. +follow the expected standard interface when there is one. When both C++ and the LLVM support libraries provide similar functionality, and there isn't a specific reason to favor the C++ implementation, it is generally @@ -325,8 +325,8 @@ implementation file. In any case, implementation files can include additional comments (not necessarily in Doxygen markup) to explain implementation details as needed. -Don't duplicate function or class name at the beginning of the comment. -For humans it is obvious which function or class is being documented; +Don't duplicate the function or class name at the beginning of the comment. +For humans, it is obvious which function or class is being documented; automatic documentation processing tools are smart enough to bind the comment to the correct declaration. @@ -369,7 +369,7 @@ lower-case letter, and finish the last sentence without a period, if it would end in one otherwise. Sentences which end with different punctuation, such as "did you forget ';'?", should still do so. -For example this is a good error message: +For example, this is a good error message: .. code-block:: none @@ -443,7 +443,7 @@ Write your code to fit within 80 columns. There must be some limit to the width of the code in order to allow developers to have multiple files side-by-side in windows on a modest display. If you are going to pick a width limit, it is -somewhat arbitrary but you might as well pick something standard. Going with 90 +somewhat arbitrary, but you might as well pick something standard. Going with 90 columns (for example) instead of 80 columns wouldn't add any significant value and would be detrimental to printing out code. Also many other projects have standardized on 80 columns, so some people have already configured their editors @@ -520,7 +520,7 @@ within each other and within function calls in order to build up aggregates The historically common formatting of braced initialization of aggregate variables does not mix cleanly with deep nesting, general expression contexts, function arguments, and lambdas. We suggest new code use a simple rule for -formatting braced initialization lists: act as-if the braces were parentheses +formatting braced initialization lists: act as if the braces were parentheses in a function call. The formatting rules exactly match those already well understood for formatting nested function calls. Examples: @@ -607,11 +607,11 @@ Static constructors and destructors (e.g., global variables whose types have a constructor or destructor) should not be added to the code base, and should be removed wherever possible. -Globals in different source files are initialized in `arbitrary order +Globals in different source files are initialized in an `arbitrary order <https://yosefk.com/c++fqa/ctors.html#fqa-10.12>`_, making the code more difficult to reason about. -Static constructors have negative impact on launch time of programs that use +Static constructors have a negative impact on the launch time of programs that use LLVM as a library. We would really like for there to be zero cost for linking in an additional LLVM target or other library into an application, but static constructors undermine this goal. @@ -698,7 +698,7 @@ If you use a braced initializer list when initializing a variable, use an equals Use ``auto`` Type Deduction to Make Code More Readable ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Some are advocating a policy of "almost always ``auto``" in C++11, however LLVM +Some are advocating a policy of "almost always ``auto``" in C++11; however, LLVM uses a more moderate stance. Use ``auto`` if and only if it makes the code more readable or easier to maintain. Don't "almost always" use ``auto``, but do use ``auto`` with initializers like ``cast<Foo>(...)`` or other places where the @@ -783,14 +783,14 @@ guards, and might not include their prerequisites. Name such files with the In general, a header should be implemented by one or more ``.cpp`` files. Each of these ``.cpp`` files should include the header that defines their interface -first. This ensures that all of the dependences of the header have been +first. This ensures that all of the dependencies of the header have been properly added to the header itself, and are not implicit. System headers should be included after user headers for a translation unit. Library Layering ^^^^^^^^^^^^^^^^ -A directory of header files (for example ``include/llvm/Foo``) defines a +A directory of header files (for example, ``include/llvm/Foo``) defines a library (``Foo``). One library (both its headers and implementation) should only use things from the libraries listed in its dependencies. @@ -822,7 +822,7 @@ especially in header files. But wait! Sometimes you need to have the definition of a class to use it, or to inherit from it. In these cases go ahead and ``#include`` that header file. Be -aware however that there are many cases where you don't need to have the full +aware, however, that there are many cases where you don't need to have the full definition of a class. If you are using a pointer or reference to a class, you don't need the header file. If you are simply returning a class instance from a prototyped function or method, you don't need it. In fact, for most cases, you @@ -970,7 +970,7 @@ loops. A silly example is something like this: When you have very, very small loops, this sort of structure is fine. But if it exceeds more than 10-15 lines, it becomes difficult for people to read and understand at a glance. The problem with this sort of code is that it gets very -nested very quickly. Meaning that the reader of the code has to keep a lot of +nested very quickly. This means that the reader of the code has to keep a lot of context in their brain to remember what is going immediately on in the loop, because they don't know if/when the ``if`` conditions will have ``else``\s etc. It is strongly preferred to structure the loop like this: @@ -988,7 +988,7 @@ It is strongly preferred to structure the loop like this: ... } -This has all the benefits of using early exits for functions: it reduces nesting +This has all the benefits of using early exits for functions: it reduces the nesting of the loop, it makes it easier to describe why the conditions are true, and it makes it obvious to the reader that there is no ``else`` coming up that they have to push context into their brain for. If a loop is large, this can be a @@ -1149,12 +1149,12 @@ In general, names should be in camel case (e.g. ``TextFileReader`` and nouns and start with an upper-case letter (e.g. ``TextFileReader``). * **Variable names** should be nouns (as they represent state). The name should - be camel case, and start with an upper case letter (e.g. ``Leader`` or + be camel case, and start with an upper-case letter (e.g. ``Leader`` or ``Boats``). * **Function names** should be verb phrases (as they represent actions), and command-like function should be imperative. The name should be camel case, - and start with a lower case letter (e.g. ``openFile()`` or ``isFoo()``). + and start with a lower-case letter (e.g. ``openFile()`` or ``isFoo()``). * **Enum declarations** (e.g. ``enum Foo {...}``) are types, so they should follow the naming conventions for types. A common use for enums is as a @@ -1207,7 +1207,7 @@ Assert Liberally ^^^^^^^^^^^^^^^^ Use the "``assert``" macro to its fullest. Check all of your preconditions and -assumptions, you never know when a bug (not necessarily even yours) might be +assumptions. You never know when a bug (not necessarily even yours) might be caught early by an assertion, which reduces debugging time dramatically. The "``<cassert>``" header file is probably already included by the header files you are using, so it doesn't cost anything to use it. @@ -1302,7 +1302,7 @@ preferred to write the code like this: assert(NewToSet && "The value shouldn't be in the set yet"); In C code where ``[[maybe_unused]]`` is not supported, use ``void`` cast to -suppress unused variable warning as follows: +suppress an unused variable warning as follows: .. code-block:: c @@ -1546,7 +1546,7 @@ whenever possible. The semantics of postincrement include making a copy of the value being incremented, returning it, and then preincrementing the "work value". For primitive types, this isn't a big deal. But for iterators, it can be a huge -issue (for example, some iterators contains stack and set objects in them... +issue (for example, some iterators contain stack and set objects in them... copying an iterator could invoke the copy ctor's of these as well). In general, get in the habit of always using preincrement, and you won't have a problem. @@ -1663,7 +1663,7 @@ Don't Use Braces on Simple Single-Statement Bodies of if/else/loop Statements When writing the body of an ``if``, ``else``, or for/while loop statement, we prefer to omit the braces to avoid unnecessary line noise. However, braces -should be used in cases where the omission of braces harm the readability and +should be used in cases where the omission of braces harms the readability and maintainability of the code. We consider that readability is harmed when omitting the brace in the presence @@ -1763,7 +1763,7 @@ would help to avoid running into a "dangling else" situation. handleAttrOnDecl(D, A, i); } - // Use braces on the outer block because of a nested `if`; otherwise the + // Use braces on the outer block because of a nested `if`; otherwise, the // compiler would warn: `add explicit braces to avoid dangling else` if (auto *D = dyn_cast<FunctionDecl>(D)) { if (shouldProcess(D)) diff --git a/llvm/docs/CommandGuide/index.rst b/llvm/docs/CommandGuide/index.rst index 88fc1fd326b7..f85f32a1fdd5 100644 --- a/llvm/docs/CommandGuide/index.rst +++ b/llvm/docs/CommandGuide/index.rst @@ -27,6 +27,7 @@ Basic Commands llvm-dis llvm-dwarfdump llvm-dwarfutil + llvm-ir2vec llvm-lib llvm-libtool-darwin llvm-link diff --git a/llvm/docs/CommandGuide/llvm-ir2vec.rst b/llvm/docs/CommandGuide/llvm-ir2vec.rst new file mode 100644 index 000000000000..13fe4996b968 --- /dev/null +++ b/llvm/docs/CommandGuide/llvm-ir2vec.rst @@ -0,0 +1,170 @@ +llvm-ir2vec - IR2Vec Embedding Generation Tool +============================================== + +.. program:: llvm-ir2vec + +SYNOPSIS +-------- + +:program:`llvm-ir2vec` [*options*] *input-file* + +DESCRIPTION +----------- + +:program:`llvm-ir2vec` is a standalone command-line tool for IR2Vec. It +generates IR2Vec embeddings for LLVM IR and supports triplet generation +for vocabulary training. It provides two main operation modes: + +1. **Triplet Mode**: Generates triplets (opcode, type, operands) for vocabulary + training from LLVM IR. + +2. **Embedding Mode**: Generates IR2Vec embeddings using a trained vocabulary + at different granularity levels (instruction, basic block, or function). + +The tool is designed to facilitate machine learning applications that work with +LLVM IR by converting the IR into numerical representations that can be used by +ML models. + +.. note:: + + For information about using IR2Vec programmatically within LLVM passes and + the C++ API, see the `IR2Vec Embeddings <https://llvm.org/docs/MLGO.html#ir2vec-embeddings>`_ + section in the MLGO documentation. + +OPERATION MODES +--------------- + +Triplet Generation Mode +~~~~~~~~~~~~~~~~~~~~~~~ + +In triplet mode, :program:`llvm-ir2vec` analyzes LLVM IR and extracts triplets +consisting of opcodes, types, and operands. These triplets can be used to train +vocabularies for embedding generation. + +Usage: + +.. code-block:: bash + + llvm-ir2vec --mode=triplets input.bc -o triplets.txt + +Embedding Generation Mode +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In embedding mode, :program:`llvm-ir2vec` uses a pre-trained vocabulary to +generate numerical embeddings for LLVM IR at different levels of granularity. + +Example Usage: + +.. code-block:: bash + + llvm-ir2vec --mode=embeddings --ir2vec-vocab-path=vocab.json --level=func input.bc -o embeddings.txt + +OPTIONS +------- + +.. option:: --mode=<mode> + + Specify the operation mode. Valid values are: + + * ``triplets`` - Generate triplets for vocabulary training + * ``embeddings`` - Generate embeddings using trained vocabulary (default) + +.. option:: --level=<level> + + Specify the embedding generation level. Valid values are: + + * ``inst`` - Generate instruction-level embeddings + * ``bb`` - Generate basic block-level embeddings + * ``func`` - Generate function-level embeddings (default) + +.. option:: --function=<name> + + Process only the specified function instead of all functions in the module. + +.. option:: --ir2vec-vocab-path=<path> + + Specify the path to the vocabulary file (required for embedding mode). + The vocabulary file should be in JSON format and contain the trained + vocabulary for embedding generation. See `llvm/lib/Analysis/models` + for pre-trained vocabulary files. + +.. option:: --ir2vec-opc-weight=<weight> + + Specify the weight for opcode embeddings (default: 1.0). This controls + the relative importance of instruction opcodes in the final embedding. + +.. option:: --ir2vec-type-weight=<weight> + + Specify the weight for type embeddings (default: 0.5). This controls + the relative importance of type information in the final embedding. + +.. option:: --ir2vec-arg-weight=<weight> + + Specify the weight for argument embeddings (default: 0.2). This controls + the relative importance of operand information in the final embedding. + +.. option:: -o <filename> + + Specify the output filename. Use ``-`` to write to standard output (default). + +.. option:: --help + + Print a summary of command line options. + +.. note:: + + ``--level``, ``--function``, ``--ir2vec-vocab-path``, ``--ir2vec-opc-weight``, + ``--ir2vec-type-weight``, and ``--ir2vec-arg-weight`` are only used in embedding + mode. These options are ignored in triplet mode. + +INPUT FILE FORMAT +----------------- + +:program:`llvm-ir2vec` accepts LLVM bitcode files (``.bc``) and LLVM IR files +(``.ll``) as input. The input file should contain valid LLVM IR. + +OUTPUT FORMAT +------------- + +Triplet Mode Output +~~~~~~~~~~~~~~~~~~~ + +In triplet mode, the output consists of lines containing space-separated triplets: + +.. code-block:: text + + <opcode> <type> <operand1> <operand2> ... + +Each line represents the information of one instruction, with the opcode, type, +and operands. + +Embedding Mode Output +~~~~~~~~~~~~~~~~~~~~~ + +In embedding mode, the output format depends on the specified level: + +* **Function Level**: One embedding vector per function +* **Basic Block Level**: One embedding vector per basic block, grouped by function +* **Instruction Level**: One embedding vector per instruction, grouped by basic block and function + +Each embedding is represented as a floating point vector. + +EXIT STATUS +----------- + +:program:`llvm-ir2vec` returns 0 on success, and a non-zero value on failure. + +Common failure cases include: + +* Invalid or missing input file +* Missing or invalid vocabulary file (in embedding mode) +* Specified function not found in the module +* Invalid command line options + +SEE ALSO +-------- + +:doc:`../MLGO` + +For more information about the IR2Vec algorithm and approach, see: +`IR2Vec: LLVM IR Based Scalable Program Embeddings <https://doi.org/10.1145/3418463>`_. diff --git a/llvm/docs/GettingInvolved.rst b/llvm/docs/GettingInvolved.rst index dc53072e09e3..d87a8bd81cc7 100644 --- a/llvm/docs/GettingInvolved.rst +++ b/llvm/docs/GettingInvolved.rst @@ -354,11 +354,6 @@ The :doc:`CodeOfConduct` applies to all office hours. - Every first Friday of the month, 14:00 UK time, for 60 minutes. - `Google meet <https://meet.google.com/jps-twgq-ivz>`__ - English, Portuguese - * - Rotating hosts - - Getting Started, beginner questions, new contributors. - - Every Tuesday at 2 PM ET (11 AM PT), for 30 minutes. - - `Google meet <https://meet.google.com/nga-uhpf-bbb>`__ - - English For event owners, our Discord bot also supports sending automated announcements of upcoming office hours. Please see the :ref:`discord-bot-event-pings` section diff --git a/llvm/docs/HowToSubmitABug.rst b/llvm/docs/HowToSubmitABug.rst index 1935678b1da3..002087cc55e0 100644 --- a/llvm/docs/HowToSubmitABug.rst +++ b/llvm/docs/HowToSubmitABug.rst @@ -112,15 +112,20 @@ If this does crash, then you should be able to debug this with the following Run this, then file a bug with the instructions and reduced .bc files that bugpoint emits. -If bugpoint doesn't reproduce the crash, ``llvm-reduce`` is an alternative -way to reduce LLVM IR. Create a script that repros the crash and run: +If bugpoint doesn't reproduce the crash, +:doc:`llvm-reduce <CommandGuide/llvm-reduce>` is an alternative way to reduce +LLVM IR. Create a script that repros the crash and run: .. code-block:: bash llvm-reduce --test=path/to/script foo.bc -which should produce reduced IR that reproduces the crash. Be warned the -``llvm-reduce`` is still fairly immature and may crash. +which should produce reduced IR that reproduces the crash. + +.. TIP:: + ``llvm-reduce`` is still fairly immature and may crash. On the other hand, + unlike ``bugpoint``, ``llvm-reduce -j $NUM_THREADS`` is multi-threaded and + can therefore potentially be much faster. If none of the above work, you can get the IR before a crash by running the ``opt`` command with the ``--print-before-all --print-module-scope`` flags to diff --git a/llvm/docs/HowToUpdateDebugInfo.rst b/llvm/docs/HowToUpdateDebugInfo.rst index c3262a96b62e..915e2896023c 100644 --- a/llvm/docs/HowToUpdateDebugInfo.rst +++ b/llvm/docs/HowToUpdateDebugInfo.rst @@ -169,6 +169,14 @@ See the discussion in the section about :ref:`merging locations<WhenToMergeLocation>` for examples of when the rule for dropping locations applies. +When to remap a debug location +------------------------------ + +When code paths are duplicated, during passes such as loop unrolling or jump +threading, `DILocation` attachments need to be remapped using `mapAtomInstance` +and `RemapSourceAtom`. This is to support the Key Instructions debug info feature. +See :doc:`KeyInstructionsDebugInfo` for information. + .. _NewInstLocations: Setting locations for new instructions @@ -496,7 +504,7 @@ as follows: .. code-block:: bash - $ llvm-original-di-preservation.py sample.json sample.html + $ llvm-original-di-preservation.py sample.json --report-file sample.html Testing of original debug info preservation can be invoked from front-end level as follows: diff --git a/llvm/docs/KeyInstructionsDebugInfo.md b/llvm/docs/KeyInstructionsDebugInfo.md new file mode 100644 index 000000000000..305740554c0f --- /dev/null +++ b/llvm/docs/KeyInstructionsDebugInfo.md @@ -0,0 +1,160 @@ +# Key Instructions debug info in LLVM and Clang + +Key Instructions is an LLVM feature that reduces the jumpiness of optimized code debug stepping by distinguishing the significance of instructions that make up source language statements. This document explains the feature and how it is implemented in [LLVM](#llvm) and [Clang](#clang-and-other-front-ends). + +## Status + +Feature complete except for coroutines, which fall back to not-key-instructions handling for now but will get support soon (there is no fundamental reason why they cannot be supported, we've just not got to it at time of writing). + +Tell Clang [not] to produce Key Instructions metadata with `-g[no-]key-instructions`. + +The feature improves optimized code stepping; it's intended for the feature to be used with optimisations enabled. Although the feature works at O0 it is not recommended because in some cases the effect of editing variables may not always be immediately realised. In some cases, debuggers may place a breakpoint after parts of an expression have been evaluated, which limits the ability to have variable edits affect expressions. (This is a quirk of the current implementation, rather than fundamental limitation, covered in more detail [later](#disabled-at-o0).) + +This is a DWARF-based feature. There is currently no plan to support CodeView. + +Set LLVM flag `-dwarf-use-key-instructions` to `false` to ignore Key Instructions metadata when emitting DWARF. + +# LLVM + +## Problem statement + +A lot of the noise in stepping comes from code motion and instruction scheduling. Consider a long expression on a single line. It may involve multiple operations that optimisations move, re-order, and interleave with other instructions that have different line numbers. + +DWARF provides a helpful tool the compiler can employ to mitigate this jumpiness, the `is_stmt` flag, which indicates that an instruction is a recommended breakpoint location. However, LLVM's current approach to deciding `is_stmt` placement essentially reduces down to "is the associated line number different to the previous instruction's?". + +(Note: It's up to the debugger if it wants to interpret `is_stmt` or not, and at time of writing LLDB doesn't; possibly because until now LLVM's `is_stmt`s convey no information that can't already be deduced from the rest of the line table.) + +## Solution overview + +Taking ideas from two papers [1][2] that explore the issue, especially C. Tice's: + +From the perspective of a source-level debugger user: + +* Source code is made up of interesting constructs; the level of granularity for “interesting” while stepping is typically assignments, calls, control flow. We’ll call these interesting constructs Atoms. + +* Atoms usually have one instruction that implements the functionality that a user can observe; once they step “off” that instruction, the atom is finalised. We’ll call that a Key Instruction. + +* Communicating where the key instructions are to the debugger (using DWARF’s is_stmt) avoids jumpiness introduced by scheduling non-key instructions without losing source attribution (because non-key instructions retain an associated source location, they’re just ignored for stepping). + +## Solution implementation + +1. `DILocation` has 2 new fields, `atomGroup` and `atomRank`. `DISubprogram` has a new field `keyInstructions`. +2. Clang creates `DILocations` using the new fields to communicate which instructions are "interesting", and sets `keyInstructions` true in `DISubprogram`s to tell LLVM to interpret the new metadata in those functions. +3. There’s some bookkeeping required by optimisations that duplicate control flow. +4. During DWARF emission, the new metadata is collected (linear scan over instructions) to decide `is_stmt` placements. + +Details: + +1. *The metadata* - The two new `DILocation` fields are `atomGroup` and `atomRank` and are both are unsigned integers. `atomGroup` is 61 bits and `atomRank` 3 bits. Instructions in the same function with the same `(atomGroup, inlinedAt)` pair are part of the same source atom. `atomRank` determines `is_stmt` preference within that group, where a lower number is higher precedence. Higher rank instructions act as "backup" `is_stmt` locations, providing good fallback locations if/when the primary candidate gets optimized away. The default values of 0 indicate the instruction isn’t interesting - it's not an `is_stmt` candidate. If `keyInstructions` in `DISubprogram` is false (default) then the new `DILocation` metadata is ignored for the function (including inlined instances) when emitting DWARF. + +2. *Clang annotates key instructions* with the new metadata. Variable assignments (stores, memory intrinsics), control flow (branches and their conditions, some unconditional branches), and exception handling instructions are annotated. Calls are ignored as they're unconditionally marked `is_stmt`. + +3. *Throughout optimisation*, the `DILocation` is propagated normally. Cloned instructions get the original’s `DILocation`, the new fields get merged in `getMergedLocation`, etc. However, pass writers need to intercede in cases where a code path is duplicated, e.g. unrolling, jump-threading. In these cases we want to emit key instructions in both the original and duplicated code, so the duplicated must be assigned new `atomGroup` numbers, in a similar way that instruction operands must get remapped. There are facilities to help this: `mapAtomInstance(const DebugLoc &DL, ValueToValueMapTy &VMap)` adds an entry to `VMap` which can later be used for remapping using `llvm::RemapSourceAtom(Instruction *I, ValueToValueMapTy &VM)`. `mapAtomInstance` is called from `llvm::CloneBasicBlock` and `llvm::RemapSourceAtom` is called from `llvm::RemapInstruction` so in many cases no additional work is actually needed. `mapAtomInstance` ensures `LLVMContextImpl::NextAtomGroup` is kept up to date, which is the global “next available atom number”. +The `DILocations` carry over from IR to MIR as normal, without any changes. + +4. *DWARF emission* - Iterate over all instructions in a function. For each `(atomGroup, inlinedAt)` pair we find the set of instructions sharing the lowest rank. Only the last of these instructions in each basic block is included in the set. The instructions in this set get `is_stmt` applied to their source locations. That `is_stmt` then "floats" to the top of contiguous sequence of instructions with the same line number in the same basic block. That has two benefits when optimisations are enabled. First, this floats `is_stmt` to the top of epilogue instructions (rather than applying it to the `ret` instruction itself) which is important to avoid losing variable location coverage at return statements. Second, it reduces the difference in optimized code stepping behaviour between when Key Instructions is enabled and disabled in “uninteresting” cases. I.e., it appears to generally reduce unnecessary changes in stepping.\ +We’ve used contiguous line numbers rather than atom membership as the test there because of our choice to represent source atoms with a single integer ID. We can’t have instructions belonging to multiple atom groups or represent any kind of grouping hierarchy. That means we can’t rely on all the call setup instructions being in the same group currently (e.g., if one of the argument expressions contains key functionality such as a store, it will be in its own group). + +## Limitations + +### Lack of multiple atom membership + +Using a number to represent atom membership is limiting; currently an instruction that belongs to multiple source atoms cannot belong to multiple atom groups. This does occur in practice, both in the front end and during optimisations. Consider this C code: +```c +a = b = c; +``` +Clang generates this IR: +```llvm + %0 = load i32, ptr %c.addr, align 4 + store i32 %0, ptr %b.addr, align 4 + store i32 %0, ptr %a.addr, align 4 +``` +The load of `c` is used by both stores (which are the Key Instructions for each assignment respectively). We can only use it as a backup location for one of the two atoms. + +Certain optimisations merge source locations, which presents another case where it might make sense to be able to represent an instruction belonging to multiple atoms. Currently we deterministically pick one (choosing to keep the lower rank one if there is one). + +### Disabled at O0 + +Consider the following code without optimisations: +```c +int c = + a + b; +``` +In the current implementation an `is_stmt` won't be generated for the `a + b` instruction, meaning debuggers will likely step over the `add` and stop at the `store` of the result into `c` (which does get `is_stmt`). A user might have wished to edit `a` or `b` on the previous line in order to alter the result stored to `c`, which they now won't have the chance to do (they'd need to edit the variables on a previous line instead). If the expression was all on one line then they would be able to edit the values before the `add`. For these reasons we're choosing to recommend that the feature should not be enabled at O0. + +It should be possible to fix this case if we make a few changes: add all the instructions in the statement (i.e., including the loads) to the atom, and tweak the DwarfEmission code to understand this situation (same atom, different line). So there is room to persue this in the future. Though that gets tricky in some cases due to the [other limitation mentioned above](#lack-of-multiple-atom-membership), e.g.: +```c +int e = // atom 1 + (a + b) // atom 1 + * (c = d); // - atom 2 +``` +```llvm + %0 = load i32, ptr %a.addr, align 4 ; atom 1 + %1 = load i32, ptr %b.addr, align 4 ; atom 1 + %add = add nsw i32 %0, %1 ; atom 1 + %2 = load i32, ptr %d.addr, align 4 ; - atom 2 + store i32 %2, ptr %c.addr, align 4 ; - atom 2 + %mul = mul nsw i32 %add, %2 ; atom 1 + store i32 %mul, ptr %e, align 4 ; atom 1 +``` +Without multiple-atom-membership or some kind of atom hierarchy it's not apparent how to get the `is_stmt` to stick to `a + b`, given the other rules the `is_stmt` placement follows. + +O0 isn't a key use-case so solving this is not a priority for the initial implementation. The trade off, smoother stepping at the cost of not being able to edit variables to affect an expression in some cases (and at particular stop points), becomes more attractive when optimisations are enabled (we find that editing variables in the debugger in optimized code often produces unexpected effects, so it's not a big concern that Key Instructions makes it harder sometimes). + +# Clang and other front ends + +Tell Clang [not] to produce Key Instructions metadata with `-g[no-]key-instructions`. + +## Implementation + +Clang needs to annotate key instructions with the new metadata. Variable assignments (stores, memory intrinsics), control flow (branches and their conditions, some unconditional branches), and exception handling instructions are annotated. Calls are ignored as they're unconditionally marked `is_stmt`. This is achieved with a few simple constructs: + +Class `ApplyAtomGroup` - This is a scoped helper similar to `ApplyDebugLocation` that creates a new source atom group which instructions can be added to. It's used during CodeGen to declare that a new source atom has started, e.g. in `CodeGenFunction::EmitBinaryOperatorLValue`. + +`CodeGenFunction::addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)` adds an instruction (and a backup instruction if non-null) to the current "atom group" defined with `ApplyAtomGroup`. The Key Instruction gets rank 1, and backup instructions get higher ranks (the function looks through casts, applying increasing rank as it goes). There are a lot of sites in Clang that need to call this (mostly stores and store-like instructions). Most stores created through `CGBuilderTy` are annotated, but some that don't need to be key are not. It's important to remember that if there's no active atom group, i.e. no active `ApplyAtomGroup` instance, then `addInstToCurrentSourceAtom` does not annotate the instructions. + +`CodeGenFunction::addInstToNewSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)` adds an instruction (and a backup instruction if non-null) to a new "atom group". Currently mostly used in loop handling code. + +`CodeGenFunction::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup, uint64_t Atom)` adds the instruction (and backup instruction if non-null) to the specific group `Atom`. This is currently only used for `rets` which is explored in the examples below. Special handling is needed due to the fact that an existing atom group needs to be reused in some circumstances, so neither of the other helper functions are appropriate. + +## Examples + +A simple example walk through: +```c +void fun(int a) { + int b = a; +} +``` + +There are two key instructions here, the assignment and the implicit return. We want to emit metadata that looks like this: + +```llvm +define hidden void @_Z3funi(i32 noundef %a) #0 !dbg !11 { +entry: + %a.addr = alloca i32, align 4 + %b = alloca i32, align 4 + store i32 %a, ptr %a.addr, align 4 + %0 = load i32, ptr %a.addr, align 4, !dbg !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 2) + store i32 %0, ptr %b, align 4, !dbg !DILocation(line: 2, scope: !11, atomGroup: 1, atomRank: 1) + ret void, !dbg !DILocation(line: 3, scope: !11, atomGroup: 2, atomRank: 1) +} +``` + +The store is the key instruction for the assignment (`atomGroup` 1). The instruction corresponding to the final (and in this case only) RHS value, the load from `%a.addr`, is a good backup location for `is_stmt` if the store gets optimized away. It's part of the same source atom, but has lower `is_stmt` precedence, so it gets a higher `atomRank`. This is achieved by starting an atom group with `ApplyAtomGroup` for the source atom (in this case a variable init) in `EmitAutoVarInit`. The instructions (both key and backup) are then annotated by call to `addInstToCurrentSourceAtom` called from `EmitStoreOfScalar`. + +The implicit return is also key (`atomGroup` 2) so that it's stepped on, to match existing non-key-instructions behaviour. This is achieved by calling `addInstToNewSourceAtom` from within `EmitFunctionEpilog`. + +Explicit return statements are handled uniquely. Rather than emit a `ret` for each `return` Clang, in all but the simplest cases (as in the first example) emits a branch to a dedicated block with a single `ret`. That branch is the key instruction for the return statement. If there's only one branch to that block, because there's only one `return` (as in this example), Clang folds the block into its only predecessor. Handily `EmitReturnBlock` returns the `DebugLoc` associated with the single branch in that case, which is fed into `addInstToSpecificSourceAtom` to ensure the `ret` gets the right group. + + +## Supporting Key Instructions from another front end + +Front ends that want to use the feature need to group and rank instructions according to their source atoms and interingness by attaching `DILocations` with the necessary `atomGroup` and `atomRank` values. They also need to set the `keyInstructions` field to `true` in `DISubprogram`s to tell LLVM to interpret the new metadata in those functions. + +The prototype had LLVM annotate instructions (instead of Clang) using simple heuristics (just looking at kind of instructions, e.g., annotating all stores, conditional branches, etc). This doesn't exist anywhere upstream, but could be shared if there's interest (e.g., so another front end can try it out before committing to a full implementation), feel free to reach out on Discourse (@OCHyams, @jmorse). + +--- + +**References** +* [1] Key Instructions: Solving the Code Location Problem for Optimized Code (C. Tice, S. L. Graham, 2000) +* [2] Debugging Optimized Code: Concepts and Implementation on DIGITAL Alpha Systems (R. F. Brender et al) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index d2a1821efd69..371f356c80b0 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -3240,12 +3240,24 @@ as follows: as :ref:`Non-Integral Pointer Type <nointptrtype>` s. The ``0`` address space cannot be specified as non-integral. -Unless explicitly stated otherwise, on every specification that specifies -an alignment, the value of the alignment must be in the range [1,2^16) -and must be a power of two times the width of a byte. -On every specification that takes a ``<abi>:<pref>``, specifying the -``<pref>`` alignment is optional. If omitted, the preceding ``:`` -should be omitted too and ``<pref>`` will be equal to ``<abi>``. +``<abi>`` is a lower bound on what is required for a type to be considered +aligned. This is used in various places, such as: + +- The alignment for loads and stores if none is explicitly given. +- The alignment used to compute struct layout. +- The alignment used to compute allocation sizes and thus ``getelementptr`` + offsets. +- The alignment below which accesses are considered underaligned. + +``<pref>`` allows providing a more optimal alignment that should be used when +possible, primarily for ``alloca`` and the alignment of global variables. It is +an optional value that must be greater than or equal to ``<abi>``. If omitted, +the preceding ``:`` should also be omitted and ``<pref>`` will be equal to +``<abi>``. + +Unless explicitly stated otherwise, every alignment specification is provided in +bits and must be in the range [1,2^16). The value must be a power of two times +the width of a byte (i.e. ``align = 8 * 2^N``). When constructing the data layout for a given target, LLVM starts with a default set of specifications which are then (possibly) overridden by @@ -4855,7 +4867,7 @@ to be eliminated. This is because '``poison``' is stronger than '``undef``'. %D = undef %E = icmp slt %D, 4 - %F = icmp gte %D, 4 + %F = icmp sge %D, 4 Safe: %A = undef @@ -11281,7 +11293,7 @@ If the ``load`` is marked as ``atomic``, it takes an extra :ref:`ordering Atomic loads produce :ref:`defined <memmodel>` results when they may see multiple atomic stores. The type of the pointee must be an integer, pointer, or floating-point type whose bit width is a power of two greater than or equal to -eight and less than or equal to a target-specific size limit. ``align`` must be +eight. ``align`` must be explicitly specified on atomic loads. Note: if the alignment is not greater or equal to the size of the `<value>` type, the atomic operation is likely to require a lock and have poor performance. ``!nontemporal`` does not have any @@ -11422,7 +11434,7 @@ If the ``store`` is marked as ``atomic``, it takes an extra :ref:`ordering Atomic loads produce :ref:`defined <memmodel>` results when they may see multiple atomic stores. The type of the pointee must be an integer, pointer, or floating-point type whose bit width is a power of two greater than or equal to -eight and less than or equal to a target-specific size limit. ``align`` must be +eight. ``align`` must be explicitly specified on atomic stores. Note: if the alignment is not greater or equal to the size of the `<value>` type, the atomic operation is likely to require a lock and have poor performance. ``!nontemporal`` does not have any @@ -11567,8 +11579,8 @@ There are three arguments to the '``cmpxchg``' instruction: an address to operate on, a value to compare to the value currently be at that address, and a new value to place at that address if the compared values are equal. The type of '<cmp>' must be an integer or pointer type whose -bit width is a power of two greater than or equal to eight and less -than or equal to a target-specific size limit. '<cmp>' and '<new>' must +bit width is a power of two greater than or equal to eight. +'<cmp>' and '<new>' must have the same type, and the type of '<pointer>' must be a pointer to that type. If the ``cmpxchg`` is marked as ``volatile``, then the optimizer is not allowed to modify the number or order of execution of @@ -11681,8 +11693,8 @@ operation. The operation must be one of the following keywords: - usub_sat For most of these operations, the type of '<value>' must be an integer -type whose bit width is a power of two greater than or equal to eight -and less than or equal to a target-specific size limit. For xchg, this +type whose bit width is a power of two greater than or equal to eight. +For xchg, this may also be a floating point or a pointer type with the same size constraints as integers. For fadd/fsub/fmax/fmin/fmaximum/fminimum, this must be a floating-point or fixed vector of floating-point type. The type of the '``<pointer>``' @@ -28302,9 +28314,9 @@ Overview: The '``llvm.experimental.constrained.lrint``' intrinsic returns the first argument rounded to the nearest integer. An inexact floating-point exception -will be raised if the argument is not an integer. An invalid exception is -raised if the result is too large to fit into a supported integer type, -and in this case the result is undefined. +will be raised if the argument is not an integer. If the rounded value is too +large to fit into the result type, an invalid exception is raised, and the +return value is a non-deterministic value (equivalent to `freeze poison`). Arguments: """""""""" @@ -28350,9 +28362,9 @@ Overview: The '``llvm.experimental.constrained.llrint``' intrinsic returns the first argument rounded to the nearest integer. An inexact floating-point exception -will be raised if the argument is not an integer. An invalid exception is -raised if the result is too large to fit into a supported integer type, -and in this case the result is undefined. +will be raised if the argument is not an integer. If the rounded value is too +large to fit into the result type, an invalid exception is raised, and the +return value is a non-deterministic value (equivalent to `freeze poison`). Arguments: """""""""" @@ -28701,8 +28713,9 @@ Overview: The '``llvm.experimental.constrained.lround``' intrinsic returns the first argument rounded to the nearest integer with ties away from zero. It will raise an inexact floating-point exception if the argument is not an integer. -An invalid exception is raised if the result is too large to fit into a -supported integer type, and in this case the result is undefined. +If the rounded value is too large to fit into the result type, an invalid +exception is raised, and the return value is a non-deterministic value +(equivalent to `freeze poison`). Arguments: """""""""" @@ -28739,8 +28752,9 @@ Overview: The '``llvm.experimental.constrained.llround``' intrinsic returns the first argument rounded to the nearest integer with ties away from zero. It will raise an inexact floating-point exception if the argument is not an integer. -An invalid exception is raised if the result is too large to fit into a -supported integer type, and in this case the result is undefined. +If the rounded value is too large to fit into the result type, an invalid +exception is raised, and the return value is a non-deterministic value +(equivalent to `freeze poison`). Arguments: """""""""" diff --git a/llvm/docs/MLGO.rst b/llvm/docs/MLGO.rst index ed0769bebeac..965a21b8c84b 100644 --- a/llvm/docs/MLGO.rst +++ b/llvm/docs/MLGO.rst @@ -468,6 +468,13 @@ The core components are: Using IR2Vec ------------ +.. note:: + + This section describes how to use IR2Vec within LLVM passes. A standalone + tool :doc:`CommandGuide/llvm-ir2vec` is available for generating the + embeddings and triplets from LLVM IR files, which can be useful for + training vocabularies and generating embeddings outside of compiler passes. + For generating embeddings, first the vocabulary should be obtained. Then, the embeddings can be computed and accessed via an ``ir2vec::Embedder`` instance. @@ -524,6 +531,10 @@ Further Details For more detailed information about the IR2Vec algorithm, its parameters, and advanced usage, please refer to the original paper: `IR2Vec: LLVM IR Based Scalable Program Embeddings <https://doi.org/10.1145/3418463>`_. + +For information about using IR2Vec tool for generating embeddings and +triplets from LLVM IR, see :doc:`CommandGuide/llvm-ir2vec`. + The LLVM source code for ``IR2Vec`` can also be explored to understand the implementation details. @@ -595,4 +606,3 @@ optimizations that are currently MLGO-enabled, it may be used as follows: where the ``name`` is a path fragment. We will expect to find 2 files, ``<name>.in`` (readable, data incoming from the managing process) and ``<name>.out`` (writable, the model runner sends data to the managing process) - diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index 158a20cce7f8..9f6ac558b6f7 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -516,6 +516,9 @@ The current vendor extensions supported are: ``XAndesPerf`` LLVM implements `version 5.0.0 of the Andes Performance Extension specification <https://github.com/andestech/andes-v5-isa/releases/download/ast-v5_4_0-release/AndeStar_V5_ISA_Spec_UM165-v1.5.08-20250317.pdf>`__ by Andes Technology. All instructions are prefixed with `nds.` as described in the specification. +``XAndesBFHCvt`` + LLVM implements `version 5.0.0 of the Andes Scalar BFLOAT16 Conversion Extension specification <https://github.com/andestech/andes-v5-isa/releases/download/ast-v5_4_0-release/AndeStar_V5_ISA_Spec_UM165-v1.5.08-20250317.pdf>`__ by Andes Technology. All instructions are prefixed with `nds.` as described in the specification. + ``XAndesVBFHCvt`` LLVM implements `version 5.0.0 of the Andes Vector BFLOAT16 Conversion Extension specification <https://github.com/andestech/andes-v5-isa/releases/download/ast-v5_4_0-release/AndeStar_V5_ISA_Spec_UM165-v1.5.08-20250317.pdf>`__ by Andes Technology. All instructions are prefixed with `nds.` as described in the specification. diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index daf822388a2f..5591ac619c39 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -145,6 +145,10 @@ Changes to the LoongArch Backend * Changing the default code model from `small` to `medium` for 64-bit. * Added inline asm support for the `q` constraint. +* Added the `32s` target feature for LA32S ISA extensions. +* Added codegen support for atomic-ops (`cmpxchg`, `max`, `min`, `umax`, `umin`) on LA32. +* Added codegen support for the ILP32D calling convention. +* Added several codegen and vectorization optimizations. Changes to the MIPS Backend --------------------------- @@ -214,6 +218,7 @@ Changes to the RISC-V Backend * `-mcpu=andes-ax45mpv` was added. * Removed -mattr=+no-rvc-hints that could be used to disable parsing and generation of RVC hints. * Adds assembler support for the Andes `XAndesvsintload` (Andes Vector INT4 Load extension). +* Adds assembler support for the Andes `XAndesbfhcvt` (Andes Scalar BFLOAT16 Conversion extension). Changes to the WebAssembly Backend ---------------------------------- @@ -228,6 +233,8 @@ Changes to the X86 Backend -------------------------- * `fp128` will now use `*f128` libcalls on 32-bit GNU targets as well. +* On x86-32, `fp128` and `i128` are now passed with the expected 16-byte stack + alignment. Changes to the OCaml bindings ----------------------------- @@ -306,6 +313,16 @@ Changes to LLDB stop reason = SIGSEGV: sent by tkill system call (sender pid=649752, uid=2667987) ``` * ELF Cores can now have their siginfo structures inspected using `thread siginfo`. +* LLDB now uses + [DIL](https://discourse.llvm.org/t/rfc-data-inspection-language/69893) as the + default implementation for 'frame variable'. This should not change the + behavior of 'frame variable' at all, at this time. To revert to using the + old implementation use: `settings set target.experimental.use-DIL false`. +* Disassembly of unknown instructions now produces `<unknown>` instead of + nothing at all +* Changed the format of opcode bytes to match llvm-objdump when disassembling + RISC-V code with `disassemble`'s `--byte` option. + ### Changes to lldb-dap diff --git a/llvm/docs/Security.rst b/llvm/docs/Security.rst index 8f04b6594de7..5cb8d04c0da2 100644 --- a/llvm/docs/Security.rst +++ b/llvm/docs/Security.rst @@ -157,6 +157,7 @@ Members of the LLVM Security Response Group are expected to: * Help write and review patches to address security issues. * Participate in the member nomination and removal processes. +.. _security-group-discussion-medium: Discussion Medium ================= @@ -204,6 +205,10 @@ The LLVM Security Policy may be changed by majority vote of the LLVM Security Re What is considered a security issue? ==================================== +We define "security-sensitive" to mean that a discovered bug or vulnerability +may require coordinated disclosure, and therefore should be reported to the LLVM +Security Response group rather than publishing in the public bug tracker. + The LLVM Project has a significant amount of code, and not all of it is considered security-sensitive. This is particularly true because LLVM is used in a wide variety of circumstances: there are different threat models, untrusted @@ -217,31 +222,52 @@ security-sensitive). This requires a rationale, and buy-in from the LLVM community as for any RFC. In some cases, parts of the codebase could be handled as security-sensitive but need significant work to get to the stage where that's manageable. The LLVM community will need to decide whether it wants to invest in -making these parts of the code securable, and maintain these security -properties over time. In all cases the LLVM Security Response Group should be consulted, -since they'll be responding to security issues filed against these parts of the -codebase. - -If you're not sure whether an issue is in-scope for this security process or -not, err towards assuming that it is. The Security Response Group might agree or disagree -and will explain its rationale in the report, as well as update this document -through the above process. - -The security-sensitive parts of the LLVM Project currently are the following. -Note that this list can change over time. - -* None are currently defined. Please don't let this stop you from reporting - issues to the LLVM Security Response Group that you believe are security-sensitive. - -The parts of the LLVM Project which are currently treated as non-security -sensitive are the following. Note that this list can change over time. - -* Language front-ends, such as clang, for which a malicious input file can cause - undesirable behavior. For example, a maliciously crafted C or Rust source file - can cause arbitrary code to execute in LLVM. These parts of LLVM haven't been - hardened, and compiling untrusted code usually also includes running utilities - such as `make` which can more readily perform malicious things. - +making these parts of the code securable, and maintain these security properties +over time. In all cases the LLVM Security Response Group +`should be consulted <security-group-discussion-medium_>`__, since they'll be +responding to security issues filed against these parts of the codebase. + +The security-sensitive parts of the LLVM Project currently are the following: + +* Code generation: most miscompilations are not security sensitive. However, a + miscompilation where there are clear indications that it can result in the + produced binary becoming significantly easier to exploit could be considered + security sensitive, and should be reported to the security response group. +* Run-time libraries: only parts of the run-time libraries are considered + security-sensitive. The parts that are not considered security-sensitive are + documented below. + +The following parts of the LLVM Project are currently treated as non-security +sensitive: + +* LLVM's language frontends, analyzers, optimizers, and code generators for + which a malicious input can cause undesirable behavior. For example, a + maliciously crafted C, Rust or bitcode input file can cause arbitrary code to + execute in LLVM. These parts of LLVM haven't been hardened, and handling + untrusted code usually also includes running utilities such as make which can + more readily perform malicious things. For example, vulnerabilities in clang, + clangd, or the LLVM optimizer in a JIT caused by untrusted inputs are not + security-sensitive. +* The following parts of the run-time libraries are explicitly not considered + security-sensitive: + + * parts of the run-time libraries that are not meant to be included in + production binaries. For example, most sanitizers are not considered + security-sensitive as they are meant to be used during development only, not + in production. + * for libc and libc++: if a user calls library functionality in an undefined + or otherwise incorrect way, this will most likely not be considered a + security issue, unless the libc/libc++ documentation explicitly promises to + harden or catch that specific undefined behaviour or incorrect usage. + * unwinding and exception handling: the implementations are not hardened + against malformed or malicious unwind or exception handling data. This is + not considered security sensitive. + +Note that both the explicit security-sensitive and explicit non-security +sensitive lists can change over time. If you're not sure whether an issue is +in-scope for this security process or not, err towards assuming that it is. The +Security Response Group might agree or disagree and will explain its rationale +in the report, as well as update this document through the above process. .. _CVE process: https://cve.mitre.org .. _report a vulnerability: https://github.com/llvm/llvm-security-repo/security/advisories/new diff --git a/llvm/docs/UserGuides.rst b/llvm/docs/UserGuides.rst index 3e16fe42b7d1..19f199fb462e 100644 --- a/llvm/docs/UserGuides.rst +++ b/llvm/docs/UserGuides.rst @@ -47,6 +47,7 @@ intermediate LLVM representation. InstCombineContributorGuide InstrProfileFormat InstrRefDebugInfo + KeyInstructionsDebugInfo LinkTimeOptimization LoopTerminology MarkdownQuickstartTemplate @@ -193,6 +194,10 @@ Optimizations This is a migration guide describing how to move from debug info using intrinsics such as dbg.value to using the non-instruction DbgRecord object. +:doc:`KeyInstructionsDebugInfo` + This document explains how the debug info feature Key Instructions is + implemented in LLVM. + :doc:`InstrProfileFormat` This document explains two binary formats of instrumentation-based profiles. |
