[llvm-branch-commits] [llvm] [docs] Finish MyST migration for PDB, DirectX, and GlobalISel docs (PR #217159)

Reid Kleckner via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Aug 19 11:54:39 PDT 2026


https://github.com/rnk updated https://github.com/llvm/llvm-project/pull/217159

>From 98515999a0016c51e029b5cc1934088254247d50 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Tue, 18 Aug 2026 22:09:44 +0000
Subject: [PATCH 1/3] [docs] Convert selected rst docs with rst2myst

---
 llvm/docs/DirectX/DXContainer.md          | 1126 ++++++++++-----------
 llvm/docs/DirectX/DXILArchitecture.md     |   72 +-
 llvm/docs/DirectX/DXILOpTableGenDesign.md |  646 ++++++------
 llvm/docs/DirectX/DXILResources.md        |  779 +++++++-------
 llvm/docs/DirectX/RootSignatures.md       |  315 +++---
 llvm/docs/GlobalISel/GMIR.md              |  218 ++--
 llvm/docs/GlobalISel/GenericOpcode.md     | 1060 +++++++++----------
 llvm/docs/GlobalISel/IRTranslator.md      |  144 ++-
 llvm/docs/GlobalISel/InstructionSelect.md |  100 +-
 llvm/docs/GlobalISel/KnownBits.md         |  125 +--
 llvm/docs/GlobalISel/Legalizer.md         |  334 +++---
 llvm/docs/GlobalISel/MIRPatterns.md       |  964 +++++++++---------
 llvm/docs/GlobalISel/Pipeline.md          |  153 +--
 llvm/docs/GlobalISel/Porting.md           |   26 +-
 llvm/docs/GlobalISel/RegBankSelect.md     |   59 +-
 llvm/docs/GlobalISel/Resources.md         |   18 +-
 llvm/docs/GlobalISel/index.md             |  114 +--
 llvm/docs/PDB/CodeViewSymbols.md          |  584 +++++------
 llvm/docs/PDB/CodeViewTypes.md            |  306 +++---
 llvm/docs/PDB/DbiStream.md                |  602 ++++++-----
 llvm/docs/PDB/GlobalStream.md             |    5 +-
 llvm/docs/PDB/HashTable.md                |  125 ++-
 llvm/docs/PDB/ModiStream.md               |   94 +-
 llvm/docs/PDB/MsfFile.md                  |  187 ++--
 llvm/docs/PDB/PdbStream.md                |  180 ++--
 llvm/docs/PDB/PublicStream.md             |    5 +-
 llvm/docs/PDB/TpiStream.md                |  410 ++++----
 27 files changed, 4139 insertions(+), 4612 deletions(-)

diff --git a/llvm/docs/DirectX/DXContainer.md b/llvm/docs/DirectX/DXContainer.md
index d35a2333deff9..00b860b06167f 100644
--- a/llvm/docs/DirectX/DXContainer.md
+++ b/llvm/docs/DirectX/DXContainer.md
@@ -1,13 +1,10 @@
-=================
-DirectX Container
-=================
+# DirectX Container
 
+```{toctree}
+:hidden: true
+```
 
-.. toctree::
-   :hidden:
-
-Overview
-========
+## Overview
 
 The DirectX Container (DXContainer) file format is the binary file format for
 compiled shaders targeting the DirectX runtime. The file format is also called
@@ -20,8 +17,7 @@ the DirectX runtime, profiling tools and other users. This document serves as a
 companion to the implementation in LLVM to more completely document the file
 format for its many users.
 
-Basic Structure
-===============
+## Basic Structure
 
 A DXContainer file begins with a header, and is then followed by a sequence of
 "parts", which are analogous to object file sections. Each part contains a part
@@ -31,189 +27,189 @@ DX Container data structures are encoded little-endian in the binary file.
 
 The LLVM versions of all data structures described and/or referenced in this
 file are defined in
-`llvm/include/llvm/BinaryFormat/DXContainer.h
-<https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainer.h>`_.
+[llvm/include/llvm/BinaryFormat/DXContainer.h](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainer.h).
 Some pseudo code is provided in blocks below to ease understanding of this
 document, but reading it with the header available will provide the most
 clarity.
 
-File Header
------------
-
-.. code-block:: c
+### File Header
 
-  struct Header {
-    uint8_t Magic[4];
-    uint8_t Digest[16];
-    uint16_t MajorVersion;
-    uint16_t MinorVersion;
-    uint32_t FileSize;
-    uint32_t PartCount;
-  };
+```c
+struct Header {
+  uint8_t Magic[4];
+  uint8_t Digest[16];
+  uint16_t MajorVersion;
+  uint16_t MinorVersion;
+  uint32_t FileSize;
+  uint32_t PartCount;
+};
+```
 
 The DXContainer header matches the pseudo-definition above. It begins with a
-four character code (magic number) with the value ``DXBC`` to denote the file
+four character code (magic number) with the value `DXBC` to denote the file
 format.
 
-The ``Digest`` is a 128bit hash digest computed with a proprietary algorithm and
+The `Digest` is a 128bit hash digest computed with a proprietary algorithm and
 encoded in the binary by the bytecode validator.
 
-The ``MajorVersion`` and ``MinorVersion`` encode the file format version
-``1.0``.
+The `MajorVersion` and `MinorVersion` encode the file format version
+`1.0`.
 
 The remaining fields encode 32-bit unsigned integers for the file size and
 number of parts.
 
-Following the part header is an array of ``PartCount`` 32-bit unsigned integers
+Following the part header is an array of `PartCount` 32-bit unsigned integers
 specifying the offsets of each part header.
 
-Part Data
----------
-
-.. code-block:: c
+### Part Data
 
-  struct PartHeader {
-    uint8_t Name[4];
-    uint32_t Size;
-  }
+```c
+struct PartHeader {
+  uint8_t Name[4];
+  uint32_t Size;
+}
+```
 
 Each part begins with a part header. A part header includes the 4-character part
 name, and a 32-bit unsigned integer specifying the size of the part data. The
-part header is followed by ``Size`` bytes of data comprising the part. The
+part header is followed by `Size` bytes of data comprising the part. The
 format does not explicitly require 32-bit alignment of parts, although LLVM does
 implement this restriction in the writer code (because it's a good idea). The
 LLVM object reader code does not assume inputs are correctly aligned to avoid
 undefined behavior caused by misaligned inputs generated by other compilers.
 
-The :ref:`PRIV <PRIV>` part is an exception: DXContainer writer code in LLVM may
+The {ref}`PRIV <PRIV>` part is an exception: DXContainer writer code in LLVM may
 produce a PRIV part with size which is not a multiple of four bytes.
 
-Part Formats
-============
+## Part Formats
 
 The part name indicates the format of the part data. There are 24 part headers
 used by DXC and FXC. Not all compiled shaders contain all parts. In the list
 below parts generated only by DXC are marked with †, and parts generated only by
 FXC are marked with \*.
 
-#. `DXIL`_† - Stores the DXIL bytecode.
-#. `HASH`_† - Stores the shader MD5 hash.
-#. `ILDB`_† - Stores the DXIL bytecode with LLVM Debug Information embedded in the module.
-#. `ILDN`_† - Stores shader debug name for external debug information.
-#. `ISG1`_ - Stores the input signature for Shader Model 5.1+.
-#. ISGN\* - Stores the input signature for Shader Model 4 and earlier.
-#. `OSG1`_ - Stores the output signature for Shader Model 5.1+.
-#. OSG5\* - Stores the output signature for Shader Model 5.
-#. OSGN\* - Stores the output signature for Shader Model 4 and earlier.
-#. PCSG\* - Stores the patch constant signature for Shader Model 5.1 and earlier.
-#. PDBI† - Stores PDB information.
-#. `PRIV`_† - Stores private data, including embedded companion PDB files.
-#. `PSG1`_ - Stores the patch constant signature for Shader Model 6+.
-#. `PSV0`_ - Stores Pipeline State Validation data.
-#. RDAT† - Stores Runtime Data.
-#. RDEF\* - Stores resource definitions.
-#. `RTS0`_ - Stores compiled root signature.
-#. `SFI0`_ - Stores shader feature flags.
-#. SHDR\* - Stores compiled DXBC bytecode.
-#. SHEX\* - Stores compiled DXBC bytecode.
-#. DXBC\* - Stores compiled DXBC bytecode.
-#. `SRCI`_† - Stores shader source information.
-#. STAT† - Stores shader statistics.
-#. `VERS`_† - Stores shader compiler version information.
-
-DXIL Part
----------
-.. _DXIL:
-
-The DXIL part is comprised of three data structures: the ``ProgramHeader``, the
-``BitcodeHeader`` and the bitcode serialized LLVM 3.7 IR Module.
-
-The ``ProgramHeader`` contains the shader model version and pipeline stage
+01. [DXIL]† - Stores the DXIL bytecode.
+02. [HASH]† - Stores the shader MD5 hash.
+03. [ILDB]† - Stores the DXIL bytecode with LLVM Debug Information embedded in the module.
+04. [ILDN]† - Stores shader debug name for external debug information.
+05. [ISG1] - Stores the input signature for Shader Model 5.1+.
+06. ISGN\* - Stores the input signature for Shader Model 4 and earlier.
+07. [OSG1] - Stores the output signature for Shader Model 5.1+.
+08. OSG5\* - Stores the output signature for Shader Model 5.
+09. OSGN\* - Stores the output signature for Shader Model 4 and earlier.
+10. PCSG\* - Stores the patch constant signature for Shader Model 5.1 and earlier.
+11. PDBI† - Stores PDB information.
+12. [PRIV]† - Stores private data, including embedded companion PDB files.
+13. [PSG1] - Stores the patch constant signature for Shader Model 6+.
+14. [PSV0] - Stores Pipeline State Validation data.
+15. RDAT† - Stores Runtime Data.
+16. RDEF\* - Stores resource definitions.
+17. [RTS0] - Stores compiled root signature.
+18. [SFI0] - Stores shader feature flags.
+19. SHDR\* - Stores compiled DXBC bytecode.
+20. SHEX\* - Stores compiled DXBC bytecode.
+21. DXBC\* - Stores compiled DXBC bytecode.
+22. [SRCI]† - Stores shader source information.
+23. STAT† - Stores shader statistics.
+24. [VERS]† - Stores shader compiler version information.
+
+### DXIL Part
+
+(dxil)=
+
+The DXIL part is comprised of three data structures: the `ProgramHeader`, the
+`BitcodeHeader` and the bitcode serialized LLVM 3.7 IR Module.
+
+The `ProgramHeader` contains the shader model version and pipeline stage
 enumeration value. This identifies the target profile of the contained shader
 bitcode.
 
-The ``BitcodeHeader`` contains the DXIL version information and refers to the
+The `BitcodeHeader` contains the DXIL version information and refers to the
 start of the bitcode data.
 
-HASH Part
----------
-.. _HASH:
+### HASH Part
+
+(hash)=
 
 The HASH part contains a 32-bit unsigned integer with the shader hash flags, and
-a 128-bit MD5 hash digest. The flags field can either have the value ``0`` to
-indicate no flags, or ``1`` to indicate that the file hash was computed
-including the source code that produced the binary. See :ref:`Compiler Flags
-<compiler_flags>` for how ``/Zss`` and ``/Zsb`` select the hashed bitcode.
+a 128-bit MD5 hash digest. The flags field can either have the value `0` to
+indicate no flags, or `1` to indicate that the file hash was computed
+including the source code that produced the binary. See {ref}`Compiler Flags
+<compiler_flags>` for how `/Zss` and `/Zsb` select the hashed bitcode.
+
+### ILDB Part
 
-ILDB Part
----------
-.. _ILDB:
+(ildb)=
 
-The ILDB part follows the structure of the `DXIL`_ part. It stores the
+The ILDB part follows the structure of the [DXIL] part. It stores the
 unstripped DXIL bitcode module with debug information embedded.
 
 The ILDB part is emitted when the shader is compiled with full debug information
-(``/Zi``). It is omitted from all outputs when slim debug (``/Zs``) is used.
-See :ref:`Compiler Flags <compiler_flags>` for how ``/Qembed_debug``,
-``/Qstrip_debug``, ``/Fd``, and ``/Zs`` control whether it appears in the main
+(`/Zi`). It is omitted from all outputs when slim debug (`/Zs`) is used.
+See {ref}`Compiler Flags <compiler_flags>` for how `/Qembed_debug`,
+`/Qstrip_debug`, `/Fd`, and `/Zs` control whether it appears in the main
 output, the companion PDB, or both.
 
-The stripped `DXIL`_ part has the ``Dwarf Version`` and ``Debug Info Version``
-module flags removed, and ``dx.source`` metadata nodes are stripped from it.
-Those nodes are preserved in the ILDB module when ``/Qsource_in_debug_module``
+The stripped [DXIL] part has the `Dwarf Version` and `Debug Info Version`
+module flags removed, and `dx.source` metadata nodes are stripped from it.
+Those nodes are preserved in the ILDB module when `/Qsource_in_debug_module`
 is used; otherwise they are replaced with empty placeholder values in the ILDB
 module written to the companion PDB file.
 
-.. rubric:: Reading this part
+```{rubric} Reading this part
+```
+
+When the ILDB part is present in a DXContainer file, {program}`obj2yaml` prints
+it under a `Program` mapping with the embedded DXIL bitcode. Use
+{program}`llvm-objcopy` to extract the raw bitcode, then {program}`llvm-dis` to
+disassemble it:
 
-When the ILDB part is present in a DXContainer file, :program:`obj2yaml` prints
-it under a ``Program`` mapping with the embedded DXIL bitcode. Use
-:program:`llvm-objcopy` to extract the raw bitcode, then :program:`llvm-dis` to
-disassemble it::
+```
+llvm-objcopy --dump-section=ILDB=shader.bc shader.dxbc
+llvm-dis shader.bc
+```
 
-  llvm-objcopy --dump-section=ILDB=shader.bc shader.dxbc
-  llvm-dis shader.bc
+When the ILDB part is stored in a companion PDB file, use {program}`llvm-pdbutil`
+to access it (see {doc}`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
 
-When the ILDB part is stored in a companion PDB file, use :program:`llvm-pdbutil`
-to access it (see :doc:`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
+### ILDN Part
 
-ILDN Part
----------
-.. _ILDN:
+(ildn)=
 
 The ILDN part stores the name of the companion PDB file used for external
 debug information. It is always emitted when the shader is compiled with debug
 information, and is included in both the main DXContainer output and the
 companion PDB file.
 
-The part begins with a ``DebugNameHeader`` followed by a null-terminated UTF-8
+The part begins with a `DebugNameHeader` followed by a null-terminated UTF-8
 string containing the debug file name:
 
-.. code-block:: c
+```c
+struct DebugNameHeader {
+  uint16_t Flags;
+  uint16_t NameLength;
+};
+```
 
-  struct DebugNameHeader {
-    uint16_t Flags;
-    uint16_t NameLength;
-  };
-
-The ``Flags`` field is reserved and must be zero. ``NameLength`` is the length
+The `Flags` field is reserved and must be zero. `NameLength` is the length
 of the debug file name in bytes, not including the null terminator.
 
 If no PDB output path is specified, the debug file name defaults to
-``<MD5 hash>.pdb``, where ``<MD5 hash>`` is the stringified MD5 digest from the
-`HASH`_ part. See :ref:`Compiler Flags <compiler_flags>` for how ``/Fd``, ``/Zss``,
-and ``/Zsb`` affect the debug file name and hash computation.
+`<MD5 hash>.pdb`, where `<MD5 hash>` is the stringified MD5 digest from the
+[HASH] part. See {ref}`Compiler Flags <compiler_flags>` for how `/Fd`, `/Zss`,
+and `/Zsb` affect the debug file name and hash computation.
+
+```{rubric} Reading this part
+```
 
-.. rubric:: Reading this part
+When the ILDN part is present in a DXContainer file, {program}`obj2yaml` prints
+it under a `DebugName` mapping.
 
-When the ILDN part is present in a DXContainer file, :program:`obj2yaml` prints
-it under a ``DebugName`` mapping.
+### PRIV Part
 
-PRIV Part
----------
-.. _PRIV:
+(priv)=
 
-The PRIV part stores opaque binary data. DXC may emit it when the ``/Qpdb_in_private``
+The PRIV part stores opaque binary data. DXC may emit it when the `/Qpdb_in_private`
 flag is used to embed the companion debug info PDB file in the main DXContainer output.
 
 The part data may also hold arbitrary user-provided binary blobs attached by
@@ -224,127 +220,127 @@ Unlike most other parts, the PRIV part data does not need to be padded to a
 container. LLVM enforces this constraint in both the object reader and the
 ObjectYAML writer. A DXContainer may contain at most one PRIV part.
 
-.. rubric:: Reading this part
+```{rubric} Reading this part
+```
 
-When the PRIV part is present in a DXContainer file, :program:`obj2yaml` prints
-it under a ``PrivateData`` mapping.
+When the PRIV part is present in a DXContainer file, {program}`obj2yaml` prints
+it under a `PrivateData` mapping.
 
-Use :program:`llvm-objcopy` to extract the raw part data::
+Use {program}`llvm-objcopy` to extract the raw part data:
 
-  llvm-objcopy --dump-section=PRIV=output.priv shader.dxbc
+```
+llvm-objcopy --dump-section=PRIV=output.priv shader.dxbc
+```
 
+### SRCI Part
 
-SRCI Part
----------
-.. _SRCI:
+(srci)=
 
-The SRCI part stores shader source information extracted from ``dx.source``
+The SRCI part stores shader source information extracted from `dx.source`
 metadata in the LLVM module. It is emitted when source information is available.
-See :ref:`Compiler Flags <compiler_flags>` for output placement and related flags.
+See {ref}`Compiler Flags <compiler_flags>` for output placement and related flags.
 
 The SRCI part is written only to the companion PDB file. It consists of a part
 header followed by three 4-byte aligned sections. Each section begins with a
-``SectionHeader`` and is followed by section-specific data:
-
-.. code-block:: c
-
-  struct Header {
-    uint32_t AlignedSizeInBytes;
-    uint16_t Flags;
-    uint16_t SectionCount;
-  };
-
-  struct SectionHeader {
-    uint32_t AlignedSizeInBytes;
-    uint16_t Flags;
-    uint16_t Type;
-  };
-
-The part ``Flags`` field is reserved and must be zero. ``SectionCount`` must be
-``3``. Each section ``Flags`` field is reserved and must be zero. The
-``Type`` field identifies the section. The section type values are:
-
-.. code-block:: c
-
-  SOURCE_INFO_TYPE(0, SourceContents)
-  SOURCE_INFO_TYPE(1, SourceNames)
-  SOURCE_INFO_TYPE(2, Args)
-
-Source Names Section
-~~~~~~~~~~~~~~~~~~~~~~~~~
+`SectionHeader` and is followed by section-specific data:
+
+```c
+struct Header {
+  uint32_t AlignedSizeInBytes;
+  uint16_t Flags;
+  uint16_t SectionCount;
+};
+
+struct SectionHeader {
+  uint32_t AlignedSizeInBytes;
+  uint16_t Flags;
+  uint16_t Type;
+};
+```
+
+The part `Flags` field is reserved and must be zero. `SectionCount` must be
+`3`. Each section `Flags` field is reserved and must be zero. The
+`Type` field identifies the section. The section type values are:
+
+```c
+SOURCE_INFO_TYPE(0, SourceContents)
+SOURCE_INFO_TYPE(1, SourceNames)
+SOURCE_INFO_TYPE(2, Args)
+```
+
+#### Source Names Section
 
 The source names section stores the file names of the HLSL translation units
 that contributed source to the shader. It begins with a section header of type
-``SourceNames``, followed by a section-specific header and a sequence of name
+`SourceNames`, followed by a section-specific header and a sequence of name
 entries:
 
-.. code-block:: c
-
-  struct SourceNamesHeader {
-    uint32_t Flags;
-    uint32_t Count;
-    uint16_t EntriesSizeInBytes;
-  };
-
-  struct SourceNamesEntry {
-    uint32_t AlignedSizeInBytes;
-    uint32_t Flags;
-    uint32_t NameSizeInBytes;
-    uint32_t ContentSizeInBytes;
-  };
-
-The section-specific ``Flags`` field is reserved and must be zero. ``Count`` is
-the number of entries that follow. ``EntriesSizeInBytes`` is the total size of
+```c
+struct SourceNamesHeader {
+  uint32_t Flags;
+  uint32_t Count;
+  uint16_t EntriesSizeInBytes;
+};
+
+struct SourceNamesEntry {
+  uint32_t AlignedSizeInBytes;
+  uint32_t Flags;
+  uint32_t NameSizeInBytes;
+  uint32_t ContentSizeInBytes;
+};
+```
+
+The section-specific `Flags` field is reserved and must be zero. `Count` is
+the number of entries that follow. `EntriesSizeInBytes` is the total size of
 the entry data following the section-specific header, including entry padding.
 
 Each entry is 4-byte aligned. The first entry is usually the main shader source
 file, and the remaining entries are sorted by file name.
 
 Each entry is followed by a null-terminated UTF-8 file name of length
-``NameSizeInBytes``. The ``ContentSizeInBytes`` field records the size of the
+`NameSizeInBytes`. The `ContentSizeInBytes` field records the size of the
 corresponding source content entry in the source contents section, including its
 null terminator.
 
-Source Contents Section
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#### Source Contents Section
 
 The source contents section stores the HLSL source text for each file named in
 the source names section. It begins with a section header of type
-``SourceContents``, followed by a section-specific header and the (optionally
+`SourceContents`, followed by a section-specific header and the (optionally
 compressed) entry data:
 
-.. code-block:: c
-
-  struct SourceContentsHeader {
-    uint32_t AlignedSizeInBytes;
-    uint16_t Flags;
-    uint16_t Type;
-    uint32_t EntriesSizeInBytes;
-    uint32_t UncompressedEntriesSizeInBytes;
-    uint32_t Count;
-  };
-
-  struct SourceContentsEntry {
-    uint32_t AlignedSizeInBytes;
-    uint32_t Flags;
-    uint32_t ContentSizeInBytes;
-  };
-
-The section-specific ``Flags`` field is reserved and must be zero. The
-``Type`` field specifies the compression applied to the entry data. The
+```c
+struct SourceContentsHeader {
+  uint32_t AlignedSizeInBytes;
+  uint16_t Flags;
+  uint16_t Type;
+  uint32_t EntriesSizeInBytes;
+  uint32_t UncompressedEntriesSizeInBytes;
+  uint32_t Count;
+};
+
+struct SourceContentsEntry {
+  uint32_t AlignedSizeInBytes;
+  uint32_t Flags;
+  uint32_t ContentSizeInBytes;
+};
+```
+
+The section-specific `Flags` field is reserved and must be zero. The
+`Type` field specifies the compression applied to the entry data. The
 compression type values are:
 
-.. code-block:: c
-
-  COMPRESSION_TYPE(0, None)
-  COMPRESSION_TYPE(1, Zlib)
+```c
+COMPRESSION_TYPE(0, None)
+COMPRESSION_TYPE(1, Zlib)
+```
 
-When no compression is used, ``EntriesSizeInBytes`` and
-``UncompressedEntriesSizeInBytes`` are equal.
+When no compression is used, `EntriesSizeInBytes` and
+`UncompressedEntriesSizeInBytes` are equal.
 
 When Zlib compression is used, the bytes following the section-specific header
 contain the compressed aggregate of all entries. After decompression, the data is
-a sequence of ``Count`` entries.
+a sequence of `Count` entries.
 
 Each uncompressed entry is 4-byte aligned and is followed by a null-terminated
 UTF-8 string containing the file source text.
@@ -352,125 +348,128 @@ UTF-8 string containing the file source text.
 The entries must appear in the same order as the entries in the source names
 section.
 
-Args Section
-~~~~~~~~~~~~~~~~~
+#### Args Section
 
 The args section stores the HLSL compiler command-line arguments used to produce
-the shader. It begins with a section header of type ``Args``, followed by a
+the shader. It begins with a section header of type `Args`, followed by a
 section-specific header and the argument data:
 
-.. code-block:: c
-
-  struct ArgsHeader {
-    uint32_t Flags;
-    uint32_t SizeInBytes;
-    uint32_t Count;
-  };
-
-The section-specific ``Flags`` field is reserved and must be zero.
-``SizeInBytes`` is the total size of the argument data following the
-section-specific header. ``Count`` is the number of argument pairs that
+```c
+struct ArgsHeader {
+  uint32_t Flags;
+  uint32_t SizeInBytes;
+  uint32_t Count;
+};
+```
+
+The section-specific `Flags` field is reserved and must be zero.
+`SizeInBytes` is the total size of the argument data following the
+section-specific header. `Count` is the number of argument pairs that
 follow.
 
-The header is followed by ``Count`` argument pairs. Each pair consists of two
+The header is followed by `Count` argument pairs. Each pair consists of two
 null-terminated UTF-8 strings: an argument name and an argument value.
 
 Padding is not applied between argument pairs. The section is padded with zero
 bytes at the end to a 4-byte boundary.
 
-.. rubric:: Reading this part
+```{rubric} Reading this part
+```
 
 The SRCI part is normally found in a companion PDB file rather than the main
-DXContainer output. When present, :program:`obj2yaml` prints it under a
-``SourceInfo`` mapping.
+DXContainer output. When present, {program}`obj2yaml` prints it under a
+`SourceInfo` mapping.
 
-To read SRCI part from a companion PDB file, use :program:`llvm-pdbutil`.
+To read SRCI part from a companion PDB file, use {program}`llvm-pdbutil`.
 
-VERS Part
----------
-.. _VERS:
+### VERS Part
+
+(vers)=
 
 The VERS part stores compiler version information. It is emitted when the
 shader is compiled with debug information. When a companion PDB file is produced,
 the VERS part is written to that file. When compiling a shader library, the VERS
 part is also written to the main DXContainer output.
 
-The part begins with a ``CompilerVersionHeader`` followed by two sequential
+The part begins with a `CompilerVersionHeader` followed by two sequential
 null-terminated UTF-8 strings: the compiler commit SHA and a custom version
 string:
 
-.. code-block:: c
-
-  struct CompilerVersionHeader {
-    uint16_t Major;
-    uint16_t Minor;
-    uint32_t Flags;
-    uint32_t CommitCount;
-    uint32_t ContentSizeInBytes;
-  };
+```c
+struct CompilerVersionHeader {
+  uint16_t Major;
+  uint16_t Minor;
+  uint32_t Flags;
+  uint32_t CommitCount;
+  uint32_t ContentSizeInBytes;
+};
+```
 
-``Major`` and ``Minor`` encode the compiler version.
+`Major` and `Minor` encode the compiler version.
 
-The ``Flags`` field is a bitmask. The flag values are:
+The `Flags` field is a bitmask. The flag values are:
 
-* ``Default`` (``0``) - default value
-* ``Debug`` (``1``) - indicates whether the compiler was built in debug mode
-* ``Internal`` (``2``) - indicates whether the shader was modified by a validator
+- `Default` (`0`) - default value
+- `Debug` (`1`) - indicates whether the compiler was built in debug mode
+- `Internal` (`2`) - indicates whether the shader was modified by a validator
 
-``CommitCount`` records how many commits are reachable from the compiler's HEAD
-revision. In DXC, this is the value produced by ``git rev-list --count HEAD``
+`CommitCount` records how many commits are reachable from the compiler's HEAD
+revision. In DXC, this is the value produced by `git rev-list --count HEAD`
 in the compiler repository.
-LLVM always emits ``0`` for ``CommitCount``. This is a deliberate difference
+LLVM always emits `0` for `CommitCount`. This is a deliberate difference
 from DXC; the commit SHA in the part data is considered sufficient for
 identifying the compiler build.
 
-``ContentSizeInBytes`` is the combined size of the commit SHA and custom version
+`ContentSizeInBytes` is the combined size of the commit SHA and custom version
 strings, including their null terminators but excluding any trailing part padding.
 
-.. rubric:: Reading this part
+```{rubric} Reading this part
+```
+
+When the VERS part is present in a DXContainer file, {program}`obj2yaml` prints
+it under a `CompilerVersion` mapping.
 
-When the VERS part is present in a DXContainer file, :program:`obj2yaml` prints
-it under a ``CompilerVersion`` mapping.
+To read VERS part from a companion PDB file, use {program}`llvm-pdbutil`.
 
-To read VERS part from a companion PDB file, use :program:`llvm-pdbutil`.
+### Program Signature (SG1) Parts
 
-Program Signature (SG1) Parts
------------------------------
-.. _ISG1:
-.. _OSG1:
-.. _PSG1:
+(isg1)=
 
-.. code-block:: c
+(osg1)=
 
-  struct ProgramSignatureHeader {
-    uint32_t ParamCount;
-    uint32_t FirstParamOffset;
-  }
+(psg1)=
+
+```c
+struct ProgramSignatureHeader {
+  uint32_t ParamCount;
+  uint32_t FirstParamOffset;
+}
+```
 
 The program signature parts (ISG1, OSG1, & PSG1) all use the same data
 structures to encode inputs, outputs and patch information. The
-``ProgramSignatureHeader`` includes two 32-bit unsigned integers to specify the
+`ProgramSignatureHeader` includes two 32-bit unsigned integers to specify the
 number of signature parameters and the offset of the first parameter.
 
-Beginning at ``FirstParamOffset`` bytes from the start of the
-``ProgramSignatureHeader``, ``ParamCount`` ``ProgramSignatureElement``
-structures are written. Following the ``ProgramSignatureElements`` is a string
+Beginning at `FirstParamOffset` bytes from the start of the
+`ProgramSignatureHeader`, `ParamCount` `ProgramSignatureElement`
+structures are written. Following the `ProgramSignatureElements` is a string
 table of null terminated strings padded to 32-byte alignment. This string table
 matches the DWARF string table format as implemented by LLVM.
 
-Each ``ProgramSignatureElement`` encodes a ``NameOffset`` value which specifies
-the offset into the string table. A value of ``0`` denotes no name. The offsets
-encoded here are from the beginning of the ``ProgramSignatureHeader`` not the
+Each `ProgramSignatureElement` encodes a `NameOffset` value which specifies
+the offset into the string table. A value of `0` denotes no name. The offsets
+encoded here are from the beginning of the `ProgramSignatureHeader` not the
 beginning of the string table.
 
-The ``ProgramSignatureElement`` contains several enumeration fields which are
-defined in `llvm/include/llvm/BinaryFormat/DXContainerConstants.def <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainerConstants.def>`_.
+The `ProgramSignatureElement` contains several enumeration fields which are
+defined in [llvm/include/llvm/BinaryFormat/DXContainerConstants.def](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainerConstants.def).
 These fields encode the D3D system value, the type of data and its precision
 requirements.
 
-PSV0 Part
----------
-.. _PSV0:
+### PSV0 Part
+
+(psv0)=
 
 The Pipeline State Validation data encodes versioned runtime information
 structures. These structures use a scheme where in lieu of encoding a version
@@ -481,44 +480,43 @@ size is larger than any known structure, the largest known structure can validly
 parse the data represented in the known structure.
 
 In LLVM we represent the versions of the associated data structures with
-versioned namespaces under the ``llvm::dxbc::PSV`` namespace (e.g. ``v0``,
-``v1``). Each structure in the ``v0`` namespace is the base version, the
-structures in the ``v1`` namespace inherit from the ``v0`` namespace, and the
-``v2`` structures inherit from the ``v1`` structures, and so on.
+versioned namespaces under the `llvm::dxbc::PSV` namespace (e.g. `v0`,
+`v1`). Each structure in the `v0` namespace is the base version, the
+structures in the `v1` namespace inherit from the `v0` namespace, and the
+`v2` structures inherit from the `v1` structures, and so on.
 
 The high-level structure of the PSV data is:
 
-#. ``RuntimeInfo`` structure
-#. Resource bindings
-#. Signature elements
-#. Mask Vectors (Output, Input, InputPatch, PatchOutput)
+1. `RuntimeInfo` structure
+2. Resource bindings
+3. Signature elements
+4. Mask Vectors (Output, Input, InputPatch, PatchOutput)
 
 Immediately following the part header for the PSV0 part is a 32-bit unsigned
-integer specifying the size of the ``RuntimeInfo`` structure that follows.
+integer specifying the size of the `RuntimeInfo` structure that follows.
 
-Immediately following the ``RuntimeInfo`` structure is a 32-bit unsigned integer
+Immediately following the `RuntimeInfo` structure is a 32-bit unsigned integer
 specifying the number of resource bindings. If the number of resources is
 greater than zero, another unsigned 32-bit integer follows to specify the size
-of the ``ResourceBindInfo`` structure. This is followed by the specified number
+of the `ResourceBindInfo` structure. This is followed by the specified number
 of structures of the specified size (which infers the version of the structure).
 
 For version 0 of the data this ends the part data.
 
-PSV0 Signature Elements
-~~~~~~~~~~~~~~~~~~~~~~~
+#### PSV0 Signature Elements
 
 The signature elements are conceptually a single concept but the data is encoded
 in three different blocks. The first block is a string table, the second block
 is an index table, and the third block is the elements themselves, which in turn
 are separeated by input, output and patch constant or primitive elements.
 
-Signature elements capture much of the same data captured in the :ref:`SG1
+Signature elements capture much of the same data captured in the {ref}`SG1
 <ISG1>` parts. The use of an index table allows de-duplication of data for a more
 compact final representation.
 
 The string table begins with a 32-bit unsigned integer specifying the table
 size. This string table uses the DXContainer format as implemented in LLVM. This
-format prefixes the string table with a null byte so that offset ``0`` is a null
+format prefixes the string table with a null byte so that offset `0` is a null
 string, and pads to 32-byte alignment.
 
 The index table begins with a 32-bit unsigned integer specifying the size of the
@@ -531,110 +529,110 @@ members.
 
 For example given the following code:
 
-.. code-block:: c
-
-  struct VSOut_1
-  {
-      float4 f3 : VOUT2;
-      float3 f4 : VOUT3;
-  };
+```c
+struct VSOut_1
+{
+    float4 f3 : VOUT2;
+    float3 f4 : VOUT3;
+};
 
 
-  struct VSOut
-  {
-      float4 f1 : VOUT0;
-      float2 f2[4] : VOUT1;
-      VSOut_1 s;
-      int4 f5 : VOUT4;
-  };
+struct VSOut
+{
+    float4 f1 : VOUT0;
+    float2 f2[4] : VOUT1;
+    VSOut_1 s;
+    int4 f5 : VOUT4;
+};
 
-  void main(out VSOut o1 : A) {
-  }
+void main(out VSOut o1 : A) {
+}
+```
 
-The semantic ``A`` gets expanded into 5 output signature elements. Those
+The semantic `A` gets expanded into 5 output signature elements. Those
 elements are:
 
-.. note::
-
-  In the example below, it is a coincidence that the rows match the indices, in
-  more complicated examples with multiple semantics this is not the case.
-
-#. Index 0 starts at row 0, contains 4 columns, and is float32. This represents
-   ``f1`` in the source.
-#. Index 1, 2, 3, and 4 starts at row 1, contains two columns and is float32.
-   This represents ``f2`` in the source, and it spreads across rows 1 - 4.
-#. Index 5 starts at row 5, contains 4 columns, and is float32. This represents
-   ``f3`` in the source.
-#. Index 6 starts at row 6, contains 3 columns, and is float32. This represents
-   ``f4``.
-#. Index 7 starts at row 7, contains 4 columns, and is signed 32-bit integer.
-   This represents ``f5`` in the source.
-
-The LLVM ``obj2yaml`` tool can parse this data out of the PSV and present it in
+:::{note}
+In the example below, it is a coincidence that the rows match the indices, in
+more complicated examples with multiple semantics this is not the case.
+:::
+
+1. Index 0 starts at row 0, contains 4 columns, and is float32. This represents
+   `f1` in the source.
+2. Index 1, 2, 3, and 4 starts at row 1, contains two columns and is float32.
+   This represents `f2` in the source, and it spreads across rows 1 - 4.
+3. Index 5 starts at row 5, contains 4 columns, and is float32. This represents
+   `f3` in the source.
+4. Index 6 starts at row 6, contains 3 columns, and is float32. This represents
+   `f4`.
+5. Index 7 starts at row 7, contains 4 columns, and is signed 32-bit integer.
+   This represents `f5` in the source.
+
+The LLVM `obj2yaml` tool can parse this data out of the PSV and present it in
 human-readable YAML. For the example above it produces the output:
 
-.. code-block:: YAML
-
-  SigOutputElements:
-    - Name:            A
-      Indices:         [ 0 ]
-      StartRow:        0
-      Cols:            4
-      StartCol:        0
-      Allocated:       true
-      Kind:            Arbitrary
-      ComponentType:   Float32
-      Interpolation:   Linear
-      DynamicMask:     0x0
-      Stream:          0
-    - Name:            A
-      Indices:         [ 1, 2, 3, 4 ]
-      StartRow:        1
-      Cols:            2
-      StartCol:        0
-      Allocated:       true
-      Kind:            Arbitrary
-      ComponentType:   Float32
-      Interpolation:   Linear
-      DynamicMask:     0x0
-      Stream:          0
-    - Name:            A
-      Indices:         [ 5 ]
-      StartRow:        5
-      Cols:            4
-      StartCol:        0
-      Allocated:       true
-      Kind:            Arbitrary
-      ComponentType:   Float32
-      Interpolation:   Linear
-      DynamicMask:     0x0
-      Stream:          0
-    - Name:            A
-      Indices:         [ 6 ]
-      StartRow:        6
-      Cols:            3
-      StartCol:        0
-      Allocated:       true
-      Kind:            Arbitrary
-      ComponentType:   Float32
-      Interpolation:   Linear
-      DynamicMask:     0x0
-      Stream:          0
-    - Name:            A
-      Indices:         [ 7 ]
-      StartRow:        7
-      Cols:            4
-      StartCol:        0
-      Allocated:       true
-      Kind:            Arbitrary
-      ComponentType:   SInt32
-      Interpolation:   Constant
-      DynamicMask:     0x0
-      Stream:          0
+```YAML
+SigOutputElements:
+  - Name:            A
+    Indices:         [ 0 ]
+    StartRow:        0
+    Cols:            4
+    StartCol:        0
+    Allocated:       true
+    Kind:            Arbitrary
+    ComponentType:   Float32
+    Interpolation:   Linear
+    DynamicMask:     0x0
+    Stream:          0
+  - Name:            A
+    Indices:         [ 1, 2, 3, 4 ]
+    StartRow:        1
+    Cols:            2
+    StartCol:        0
+    Allocated:       true
+    Kind:            Arbitrary
+    ComponentType:   Float32
+    Interpolation:   Linear
+    DynamicMask:     0x0
+    Stream:          0
+  - Name:            A
+    Indices:         [ 5 ]
+    StartRow:        5
+    Cols:            4
+    StartCol:        0
+    Allocated:       true
+    Kind:            Arbitrary
+    ComponentType:   Float32
+    Interpolation:   Linear
+    DynamicMask:     0x0
+    Stream:          0
+  - Name:            A
+    Indices:         [ 6 ]
+    StartRow:        6
+    Cols:            3
+    StartCol:        0
+    Allocated:       true
+    Kind:            Arbitrary
+    ComponentType:   Float32
+    Interpolation:   Linear
+    DynamicMask:     0x0
+    Stream:          0
+  - Name:            A
+    Indices:         [ 7 ]
+    StartRow:        7
+    Cols:            4
+    StartCol:        0
+    Allocated:       true
+    Kind:            Arbitrary
+    ComponentType:   SInt32
+    Interpolation:   Constant
+    DynamicMask:     0x0
+    Stream:          0
+```
 
 The number of signature elements of each type is encoded in the
-``llvm::dxbc::PSV::v1::RuntimeInfo`` structure. If any of the element count
-values are non-zero, the size of the ``ProgramSignatureElement`` structure is
+`llvm::dxbc::PSV::v1::RuntimeInfo` structure. If any of the element count
+values are non-zero, the size of the `ProgramSignatureElement` structure is
 encoded next to allow versioning of that structure. Today there is only one
 version. Following the size field is the specified number of signature elements
 in the order input, output, then patch constant or primitive.
@@ -644,16 +642,16 @@ series of 32-bit integers. Each 32-bit integer in the mask encodes values for 8
 input/output/patch or primitive elements. The mask vector is filled from least
 significant bit to most significant bit with each added element shifting the
 previous elements left. A reader needs to consult the total number of vectors
-encoded in the ``RuntimeInfo`` structure to know how to read the mask vector.
+encoded in the `RuntimeInfo` structure to know how to read the mask vector.
 
-If the shader has ``UsesViewID`` enabled in the ``RuntimeInfo`` an output mask
+If the shader has `UsesViewID` enabled in the `RuntimeInfo` an output mask
 vector will be included. The output mask vector is four arrays of 32-bit
 unsigned integers. Each of the four arrays corresponds to an output stream.
 Geometry shaders have a maximum of four output streams, all other shader stages
 only support one output stream. Each bit in the mask vector identifies one
 column of an output from the output signature depends on the ViewID.
 
-If the shader has ``UsesViewID`` enabled, it is a hull shader, and it has patch
+If the shader has `UsesViewID` enabled, it is a hull shader, and it has patch
 constant or primitive vector elements, a patch constant or primitive vector mask
 will be included. It is identical in structure to the output mask vector. Each
 bit in the mask vector identifies one column of a patch constant output which
@@ -684,104 +682,90 @@ bit in the mask vector identifies one column of a patch constant input and a
 column of an output. A value of 1 means the output is impacted by the primitive
 input.
 
-Root Signature (RTS0) Part
---------------------------
-.. _RTS0:
+### Root Signature (RTS0) Part
 
-The Root Signature data defines the shader's resource interface with Direct3D 
-12, specifying what resources the shader needs to access and how they're 
-organized and bound to the pipeline. 
+(rts0)=
 
-The RTS0 part comprises three data structures: ``RootSignatureHeader``, 
-``RootParameters`` and ``StaticSamplers``. The details of each will be described 
-in the following sections. All ``RootParameters`` will be serialized following 
+The Root Signature data defines the shader's resource interface with Direct3D
+12, specifying what resources the shader needs to access and how they're
+organized and bound to the pipeline.
+
+The RTS0 part comprises three data structures: `RootSignatureHeader`,
+`RootParameters` and `StaticSamplers`. The details of each will be described
+in the following sections. All `RootParameters` will be serialized following
 the order they were defined in the metadata representation.
 
-The table below summarizes the data being serialized as well as it's size. The 
-details of it part will be discussed in further details on the next sections 
+The table below summarizes the data being serialized as well as it's size. The
+details of it part will be discussed in further details on the next sections
 of this document.
 
-======================== =========================================== =============================
-Part Name                Size In Bytes                                 Maximum number of Instances 
-======================== =========================================== =============================
-Root Signature Header    24                                          1               
-Root Parameter Headers   12                                          Many              
-Root Parameter           ================================ ===        Many
-                         Root Constants                   12                                      
-                         Root Descriptor Version 1.0      8                                      
-                         Root Descriptor Version 1.1      12                                      
-                         Descriptors Tables Version 1.0   20                                     
-                         Descriptors Tables Version 1.1   24                                      
-                         ================================ ===       
-                                             
-Static Samplers          52                                          Many              
-======================== =========================================== =============================
-
-
-Root Signature Header
-~~~~~~~~~~~~~~~~~~~~~
+| Part Name              | Size In Bytes | Maximum number of Instances |
+| ---------------------- | ------------- | --------------------------- |
+| Root Signature Header  | 24            | 1                           |
+| Root Parameter Headers | 12            | Many                        |
+| Root Parameter         | ```{eval-rst}
+================================ === Root Constants                   12 Root Descriptor Version 1.0      8 Root Descriptor Version 1.1      12 Descriptors Tables Version 1.0   20 Descriptors Tables Version 1.1   24 ================================ === ```               | Many                        |
+| Static Samplers        | 52            | Many                        |
+
+#### Root Signature Header
 
 The root signature header is 24 bytes long, consisting of six 32-bit values
-representing the version, number and offset of parameters, number and offset 
+representing the version, number and offset of parameters, number and offset
 of static samplers, and a flags field for global behaviours:
 
-.. code-block:: c
+```c
+struct RootSignatureHeader {
+  uint32_t Version;
+  uint32_t NumParameters;
+  uint32_t ParametersOffset;
+  uint32_t NumStaticSamplers;
+  uint32_t StaticSamplerOffset;
+  uint32_t Flags;
+}
+```
 
-   struct RootSignatureHeader {
-     uint32_t Version;
-     uint32_t NumParameters;
-     uint32_t ParametersOffset;
-     uint32_t NumStaticSamplers;
-     uint32_t StaticSamplerOffset;
-     uint32_t Flags;
-   }
+#### Root Parameters
 
+Root parameters define how resources are bound to the shader pipeline, each
+type having different size and fields.
 
-Root Parameters
-~~~~~~~~~~~~~~~
-
-Root parameters define how resources are bound to the shader pipeline, each 
-type having different size and fields. 
-
-The slot of root parameters is preceded by a variable size section containing 
-the header information for such parameters. Such structure is 12 bytes long, 
+The slot of root parameters is preceded by a variable size section containing
+the header information for such parameters. Such structure is 12 bytes long,
 composed of three 32-bit values, representing the parameter type, a flag
-encoding the pipeline stages where the data is visible, and an offset 
+encoding the pipeline stages where the data is visible, and an offset
 calculated from the start of RTS0 section.
 
-.. code-block:: c
-
-   struct RootParameterHeader {
-     uint32_t ParameterType;
-     uint32_t ShaderVisibility;
-     uint32_t ParameterOffset;
-   };
+```c
+struct RootParameterHeader {
+  uint32_t ParameterType;
+  uint32_t ShaderVisibility;
+  uint32_t ParameterOffset;
+};
+```
 
 After the header information has been serialized, the actual data for each of the
-root parameters is layout in a single continuous blob. The parameters can be fetch 
+root parameters is layout in a single continuous blob. The parameters can be fetch
 from such using the offset information, present in the header.
 
-The following sections will describe each of the root parameters types and their 
+The following sections will describe each of the root parameters types and their
 encodings.
 
-Root Constants
-''''''''''''''
+##### Root Constants
 
-The root constants are inline 32-bit values that show up in the shader 
+The root constants are inline 32-bit values that show up in the shader
 as a constant buffer. It is a 12 bytes long structure, two 32-bit values
-encoding the register and space the constant is assigned to, and 
+encoding the register and space the constant is assigned to, and
 the last 32 bits encode the number of constants being defined in the buffer.
 
-.. code-block:: c
+```c
+struct RootConstants {
+  uint32_t Register;
+  uint32_t Space;
+  uint32_t NumOfConstants;
+};
+```
 
-  struct RootConstants {
-    uint32_t Register;
-    uint32_t Space;
-    uint32_t NumOfConstants;
-  };
-
-Root Descriptor
-'''''''''''''''
+##### Root Descriptor
 
 Root descriptors provide direct GPU memory addresses to resources.
 
@@ -791,153 +775,150 @@ space as 2 32-bit values.
 In version 1.1, the root descriptor is 12 bytes. It matches the 1.0 descriptor
 but adds a 32-bit access flag.
 
-.. code-block:: c
+```c
+struct RootDescriptor_V1_0 {
+   uint32_t ShaderRegister;
+   uint32_t RegisterSpace;
+};
 
-   struct RootDescriptor_V1_0 {
-      uint32_t ShaderRegister;
-      uint32_t RegisterSpace;
-   };
-   
-   struct RootDescriptor_V1_1 {
-      uint32_t ShaderRegister;
-      uint32_t RegisterSpace;      
-      uint32_t Flags;
-   };
+struct RootDescriptor_V1_1 {
+   uint32_t ShaderRegister;
+   uint32_t RegisterSpace;
+   uint32_t Flags;
+};
+```
 
-Root Descriptor Table
-'''''''''''''''''''''
+##### Root Descriptor Table
 
-Descriptor tables let shaders access multiple resources through a single pointer 
-to a descriptor heap. 
+Descriptor tables let shaders access multiple resources through a single pointer
+to a descriptor heap.
 
-The tables are made of a collection of descriptor ranges. In Version 1.0, the 
+The tables are made of a collection of descriptor ranges. In Version 1.0, the
 descriptor range is 20 bytes, containing five 32-bit values. It encodes a range
-of registers, including the register type, range length, register numbers and 
+of registers, including the register type, range length, register numbers and
 space within range and the offset locating each range inside the table.
 
 In version 1.1, the descriptor range is 24 bytes. It matches the 1.0 descriptor
 but adds a 32-bit access flag.
 
-.. code-block:: c
-
-   struct DescriptorRange_V1_0 {
-      dxil::ResourceClass RangeType;
-      uint32_t NumDescriptors;
-      uint32_t BaseShaderRegister;
-      uint32_t RegisterSpace;
-      uint32_t OffsetInDescriptorsFromTableStart;
-   };
-
-   struct DescriptorRange_V1_1 {
-      dxil::ResourceClass RangeType;
-      uint32_t NumDescriptors;
-      uint32_t BaseShaderRegister;
-      uint32_t RegisterSpace;
-      uint32_t Flags;
-      uint32_t OffsetInDescriptorsFromTableStart;      
-   };
-
-Static Samplers
-~~~~~~~~~~~~~~~
-
-Static samplers are predefined filtering settings built into the root signature, 
-avoiding descriptor heap lookups. 
-
-This section also has a variable size, since it can contain multiple static 
-samplers definitions. However, the definition is a fixed sized struct, 
-containing 13 32-byte fields of various enum, float, and integer values. 
+```c
+struct DescriptorRange_V1_0 {
+   dxil::ResourceClass RangeType;
+   uint32_t NumDescriptors;
+   uint32_t BaseShaderRegister;
+   uint32_t RegisterSpace;
+   uint32_t OffsetInDescriptorsFromTableStart;
+};
+
+struct DescriptorRange_V1_1 {
+   dxil::ResourceClass RangeType;
+   uint32_t NumDescriptors;
+   uint32_t BaseShaderRegister;
+   uint32_t RegisterSpace;
+   uint32_t Flags;
+   uint32_t OffsetInDescriptorsFromTableStart;
+};
+```
+
+#### Static Samplers
+
+Static samplers are predefined filtering settings built into the root signature,
+avoiding descriptor heap lookups.
+
+This section also has a variable size, since it can contain multiple static
+samplers definitions. However, the definition is a fixed sized struct,
+containing 13 32-byte fields of various enum, float, and integer values.
 
 In version 1.2, the static sampler is 17 bytes. It matches the 1.0 static sampler
-but adds a 32-bit access flag. In Version 1.1, it matches static sampler 
+but adds a 32-bit access flag. In Version 1.1, it matches static sampler
 version 1.0.
 
-.. code-block:: c
-
-   struct StaticSamplerDesc {
-      dxbc::FilterMode Filter; 
-      dxbc::TextureAddressMode AddressU;
-      dxbc::TextureAddressMode AddressV;
-      dxbc::TextureAddressMode AddressW;
-      float MipLODBias;
-      uint32_t MaxAnisotropy;
-      dxbc::ComparisonFunc ComparisonFunc; 
-      dxbc::StaticBorderColor BorderColor;
-      float MinLOD;
-      float MaxLOD;
-      uint32_t ShaderRegister;
-      uint32_t RegisterSpace;
-      dxbc::ShaderVisibility ShaderVisibility;
-   };
-
-SFI0 Part
----------
-.. _SFI0:
+```c
+struct StaticSamplerDesc {
+   dxbc::FilterMode Filter;
+   dxbc::TextureAddressMode AddressU;
+   dxbc::TextureAddressMode AddressV;
+   dxbc::TextureAddressMode AddressW;
+   float MipLODBias;
+   uint32_t MaxAnisotropy;
+   dxbc::ComparisonFunc ComparisonFunc;
+   dxbc::StaticBorderColor BorderColor;
+   float MinLOD;
+   float MaxLOD;
+   uint32_t ShaderRegister;
+   uint32_t RegisterSpace;
+   dxbc::ShaderVisibility ShaderVisibility;
+};
+```
+
+### SFI0 Part
+
+(sfi0)=
 
 The SFI0 part encodes a 64-bit unsigned integer bitmask of the feature flags.
 This denotes which optional features the shader requires. The flag values are
-defined in `llvm/include/llvm/BinaryFormat/DXContainerConstants.def <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainerConstants.def>`_.
+defined in [llvm/include/llvm/BinaryFormat/DXContainerConstants.def](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainerConstants.def).
 
-Compiler Flags
-==============
+## Compiler Flags
 
-.. _compiler_flags:
+(compiler-flags-1)=
 
-When compiling HLSL with :program:`dxc`, several flags control whether
+When compiling HLSL with {program}`dxc`, several flags control whether
 debug information is embedded in the main DXContainer output, written to a
-companion PDB file, or both. Use ``/Zi`` for full debug output or ``/Zs`` for
-slim debug output without an `ILDB`_ part. In :program:`clang-dxc`, most
-dxc-style flags are forwarded to :program:`llc` as ``-mllvm`` options.
+companion PDB file, or both. Use `/Zi` for full debug output or `/Zs` for
+slim debug output without an [ILDB] part. In {program}`clang-dxc`, most
+dxc-style flags are forwarded to {program}`llc` as `-mllvm` options.
 
-Debug Output Locations
-----------------------
+### Debug Output Locations
 
-Debug information is enabled with either ``/Zi`` (full debug) or ``/Zs`` (slim
+Debug information is enabled with either `/Zi` (full debug) or `/Zs` (slim
 debug). The two flags are mutually exclusive.
 
-**Full debug with ``/Zi``**
+**Full debug with \`\`/Zi\`\`**
 
-When ``/Zi`` is enabled, the `ILDB`_ part can appear in the main DXContainer
+When `/Zi` is enabled, the [ILDB] part can appear in the main DXContainer
 output, in a companion PDB, or both:
 
-* **Embedded in the main DXContainer output.** The `ILDB`_ part holds the
+- **Embedded in the main DXContainer output.** The [ILDB] part holds the
   unstripped DXIL module with debug information. It is included when
-  ``/Qembed_debug`` is used. The main output always contains the stripped `DXIL`_
-  part alongside other parts such as `HASH`_, `ILDN`_, and `VERS`_.
-* **Omitted from the main DXContainer output.** When ``/Qstrip_debug`` is used,
-  the `ILDB`_ part is not written to the main output. Other debug-related parts
-  such as `ILDN`_ are still emitted. If ``/Fd`` is also specified, the `ILDB`_
-  part is still written to the companion PDB. ``/Qstrip_debug`` takes precedence
-  over the default ``/Qembed_debug`` behavior when ``/Zi`` is used without
-  ``/Fd``. If both ``/Qstrip_debug`` and ``/Qembed_debug`` are specified,
-  ``/Qstrip_debug`` is ignored and the `ILDB`_ part is embedded.
-* **In a companion PDB file.** A sidecar ``.pdb`` stores a DXContainer stream
-  with debug-related parts including `ILDB`_, `SRCI`_, and `VERS`_. This is
-  produced when ``/Fd`` names an output path. Use :program:`llvm-pdbutil` to
+  `/Qembed_debug` is used. The main output always contains the stripped [DXIL]
+  part alongside other parts such as [HASH], [ILDN], and [VERS].
+- **Omitted from the main DXContainer output.** When `/Qstrip_debug` is used,
+  the [ILDB] part is not written to the main output. Other debug-related parts
+  such as [ILDN] are still emitted. If `/Fd` is also specified, the [ILDB]
+  part is still written to the companion PDB. `/Qstrip_debug` takes precedence
+  over the default `/Qembed_debug` behavior when `/Zi` is used without
+  `/Fd`. If both `/Qstrip_debug` and `/Qembed_debug` are specified,
+  `/Qstrip_debug` is ignored and the [ILDB] part is embedded.
+- **In a companion PDB file.** A sidecar `.pdb` stores a DXContainer stream
+  with debug-related parts including [ILDB], [SRCI], and [VERS]. This is
+  produced when `/Fd` names an output path. Use {program}`llvm-pdbutil` to
   inspect or extract that stream (see
-  :doc:`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
-* **Embedded in the private data of the main output.** When
-  ``/Qpdb_in_private`` is used, a copy of the companion PDB file is stored as
-  opaque bytes in `PRIV`_. This can be used with or without ``/Fd``; without
-  ``/Fd``, the PDB is not retained as a separate file on disk. After extraction,
-  tools treat the bytes as a standalone ``.pdb`` file.
-
-``/Fd`` can be combined with ``/Qembed_debug`` or ``/Qpdb_in_private`` to
+  {doc}`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
+- **Embedded in the private data of the main output.** When
+  `/Qpdb_in_private` is used, a copy of the companion PDB file is stored as
+  opaque bytes in [PRIV]. This can be used with or without `/Fd`; without
+  `/Fd`, the PDB is not retained as a separate file on disk. After extraction,
+  tools treat the bytes as a standalone `.pdb` file.
+
+`/Fd` can be combined with `/Qembed_debug` or `/Qpdb_in_private` to
 write full debug information to more than one location.
 
-**Slim debug with ``/Zs``**
+**Slim debug with \`\`/Zs\`\`**
 
-When ``/Zs`` is enabled, slim debug information is emitted. The `ILDB`_ part is
-omitted from the main DXContainer output and from any companion PDB or `PRIV`_
-embedding, but other debug-related parts such as `HASH`_, `ILDN`_, `SRCI`_, and
-`VERS`_ are still emitted. A companion PDB from ``/Fd`` or a `PRIV`_ embedding
-from ``/Qpdb_in_private`` therefore contains slim debug data only.
+When `/Zs` is enabled, slim debug information is emitted. The [ILDB] part is
+omitted from the main DXContainer output and from any companion PDB or [PRIV]
+embedding, but other debug-related parts such as [HASH], [ILDN], [SRCI], and
+[VERS] are still emitted. A companion PDB from `/Fd` or a [PRIV] embedding
+from `/Qpdb_in_private` therefore contains slim debug data only.
 
-``/Zs`` cannot be combined with ``/Qembed_debug`` or ``/Qsource_in_debug_module``.
+`/Zs` cannot be combined with `/Qembed_debug` or `/Qsource_in_debug_module`.
 
-The table below summarizes the :program:`dxc` flags that affect this behavior.
-The **llc flag** column lists the ``-mllvm`` option the driver forwards when
+The table below summarizes the {program}`dxc` flags that affect this behavior.
+The **llc flag** column lists the `-mllvm` option the driver forwards when
 invoking the backend.
 
+```{eval-rst}
 .. list-table::
    :header-rows: 1
    :widths: 20 20 20 40
@@ -1011,14 +992,15 @@ invoking the backend.
      -
      - Do not embed ``dx.source`` metadata in the LLVM module, which prevents
        `SRCI`_ generation.
+```
 
-Part Placement
---------------
+### Part Placement
 
 The table below shows where each debug-related part is written for a typical
-shader compile. ``Yes`` means the part is present in that output whenever its
+shader compile. `Yes` means the part is present in that output whenever its
 preconditions are met.
 
+```{eval-rst}
 .. list-table::
    :header-rows: 1
    :widths: 12 28 28 32
@@ -1059,3 +1041,5 @@ preconditions are met.
      - If ``/Qpdb_in_private``
      - No
      - Holds a copy of the companion PDB file.
+```
+
diff --git a/llvm/docs/DirectX/DXILArchitecture.md b/llvm/docs/DirectX/DXILArchitecture.md
index 1d7b96c35fc3e..a89563d1a992d 100644
--- a/llvm/docs/DirectX/DXILArchitecture.md
+++ b/llvm/docs/DirectX/DXILArchitecture.md
@@ -1,16 +1,12 @@
-===============================================
-Architecture and Design of DXIL Support in LLVM
-===============================================
+# Architecture and Design of DXIL Support in LLVM
 
+```{toctree}
+:hidden: true
+```
 
-.. toctree::
-   :hidden:
+## Introduction
 
-Introduction
-============
-
-LLVM supports reading and writing the `DirectX Intermediate Language.
-<https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst>`_,
+LLVM supports reading and writing the [DirectX Intermediate Language.](https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst),
 or DXIL. DXIL is essentially LLVM 3.7 era bitcode with some
 restrictions and various semantically important operations and
 metadata.
@@ -26,8 +22,7 @@ There are three places to look for DXIL related code in LLVM: The
 reading; and in library code that is shared between writing and
 reading. We'll describe these in reverse order.
 
-Common Code for Reading and Writing
-===================================
+## Common Code for Reading and Writing
 
 There's quite a bit of logic that needs to be shared between reading
 and writing DXIL in order to avoid code duplication. While we don't
@@ -39,8 +34,7 @@ DXIL and modern LLVM constructs live in `lib/Transforms/Utils`, and
 more analyses that are needed to derive or preserve information are
 implemented as typical `lib/Analysis` passes.
 
-The DXILUpgrade Pass
-====================
+## The DXILUpgrade Pass
 
 Translating DXIL to LLVM IR takes advantage of the fact that DXIL is
 compatible with LLVM 3.7 bitcode, and that modern LLVM is capable of
@@ -59,21 +53,19 @@ on the utilities described in "Common Code" above in order to share
 logic with both the DirectX backend and with Clang's codegen of HLSL
 support as much as possible.
 
-The DirectX Intrinsic Expansion Pass
-====================================
+## The DirectX Intrinsic Expansion Pass
+
 There are intrinsics that don't map directly to DXIL Ops. In some cases
 an intrinsic needs to be expanded to a set of LLVM IR instructions. In
 other cases an intrinsic needs modifications to the arguments or return
-values of a DXIL Op. The `DXILIntrinsicExpansion` pass handles all 
-the cases where our intrinsics don't have a one to one mapping. This 
-pass may also be used when the expansion is specific to DXIL to keep 
-implementation details out of CodeGen. Finally, there is an expectation 
-that we maintain vector types through this pass. Therefore, best 
+values of a DXIL Op. The `DXILIntrinsicExpansion` pass handles all
+the cases where our intrinsics don't have a one to one mapping. This
+pass may also be used when the expansion is specific to DXIL to keep
+implementation details out of CodeGen. Finally, there is an expectation
+that we maintain vector types through this pass. Therefore, best
 practice would be to avoid scalarization in this pass.
 
-
-The DirectX Backend
-===================
+## The DirectX Backend
 
 The DirectX backend lowers LLVM IR into DXIL. As we're transforming to
 an intermediate format rather than a specific ISA, this backend does
@@ -100,55 +92,52 @@ leverage LLVM's current bitcode libraries to do a lot of the work, but
 it's possible that at some point in the future it will need to be
 completely separate as modern LLVM bitcode evolves.
 
-DirectX Backend Flow
---------------------
+### DirectX Backend Flow
 
 The code generation flow for DXIL is broken into a series of passes. The passes
 are grouped into two flows:
 
-#. Generating DXIL IR.
-#. Generating DXIL Binary.
+1. Generating DXIL IR.
+2. Generating DXIL Binary.
 
 The passes to generate DXIL IR follow the flow:
 
-  DXILOpLowering -> DXILPrepare -> DXILTranslateMetadata
+> DXILOpLowering -> DXILPrepare -> DXILTranslateMetadata
 
 Each of these passes has a defined responsibility:
 
-#. DXILOpLowering translates LLVM intrinsic calls to dx.op calls.
-#. DXILPrepare updates functions in the DXIL IR to be compatible with LLVM 3.7,
+1. DXILOpLowering translates LLVM intrinsic calls to dx.op calls.
+2. DXILPrepare updates functions in the DXIL IR to be compatible with LLVM 3.7,
    namely removing attributes, and inserting bitcasts to allow typed pointers
    to be inserted.
-#. DXILTranslateMetadata transforms and emits all recognized DXIL Metadata.
+3. DXILTranslateMetadata transforms and emits all recognized DXIL Metadata.
 
 The passes to encode DXIL to binary in the DX Container follow the flow:
 
-  DXILEmbedder -> DXContainerGlobals -> AsmPrinter
+> DXILEmbedder -> DXContainerGlobals -> AsmPrinter
 
 Each of these passes have the following defined responsibilities:
 
-#. DXILEmbedder runs the DXIL bitcode writer to generate a bitcode stream and
+1. DXILEmbedder runs the DXIL bitcode writer to generate a bitcode stream and
    embeds the binary data inside a global in the original module.
-#. DXContainerGlobals generates binary data globals for the other DX Container
+2. DXContainerGlobals generates binary data globals for the other DX Container
    parts based on computed analysis passes.
-#. AsmPrinter is the standard LLVM infrastructure for emitting object files.
+3. AsmPrinter is the standard LLVM infrastructure for emitting object files.
 
 When emitting DXIL into a DX Container file the MC layer is used in a similar
-way to how the Clang ``-fembed-bitcode`` option operates. The DX Container
+way to how the Clang `-fembed-bitcode` option operates. The DX Container
 object writer knows how to construct the headers and structural fields of the
 container, and reads global variables from the module to fill in the remaining
 part data.
 
-DirectX Container
------------------
+### DirectX Container
 
 The DirectX container format is treated in LLVM as an object file format.
 Reading is implemented between the BinaryFormat and Object libraries, and
 writing is implemented in the MC layer. Additional testing and inspection
 support are implemented in the ObjectYAML library and tools.
 
-Testing
-=======
+## Testing
 
 A lot of DXIL testing can be done with typical IR to IR tests using
 `opt` and `FileCheck`, since a lot of the support is implemented in
@@ -168,3 +157,4 @@ DXIL reading path.
 As soon as we are able, we will also want to round trip using the DXIL
 writing and reading paths in order to ensure self consistency and to
 get test coverage when `dxil-dis` isn't available.
+
diff --git a/llvm/docs/DirectX/DXILOpTableGenDesign.md b/llvm/docs/DirectX/DXILOpTableGenDesign.md
index 2673bda7463cf..e58f26fd20e75 100644
--- a/llvm/docs/DirectX/DXILOpTableGenDesign.md
+++ b/llvm/docs/DirectX/DXILOpTableGenDesign.md
@@ -1,314 +1,316 @@
-==============================================================
-Specification of DXIL Operations using TableGen Representation
-==============================================================
+# Specification of DXIL Operations using TableGen Representation
 
-.. toctree
-   :hidden
+% toctree
+% :hidden
 
-Introduction
-============
+## Introduction
 
-`DirectXShaderCompiler <https://github.com/microsoft/DirectXShaderCompiler>`_
+[DirectXShaderCompiler](https://github.com/microsoft/DirectXShaderCompiler)
 encapsulates, among other information, various DXIL Operations in
-`hctdb.py <https://github.com/microsoft/DirectXShaderCompiler/blob/main/utils/hct/hctdb.py>`_.
-DXIL Operations are represented in one of the following `two ways
-<https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#operations>`_:
+[hctdb.py](https://github.com/microsoft/DirectXShaderCompiler/blob/main/utils/hct/hctdb.py).
+DXIL Operations are represented in one of the following [two ways](https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#operations):
 
-#. Using LLVM instructions.
-#. Using LLVM External functions. These are represented in LLVM IR as follows:
+1. Using LLVM instructions.
 
-   * "Standard" LLVM intrinsics (e.g., ``llvm.sin.*``) and
-   * HLSL intrinsics (defined as LLVM intrinsics in ``llvm/include/llvm/IR/IntrinsicsDirectX.td``, e.g., ``llvm.dx.*``)
+2. Using LLVM External functions. These are represented in LLVM IR as follows:
 
-   These are  collectively referred to as `LLVM Intrinsics` in this note.
+   - "Standard" LLVM intrinsics (e.g., `llvm.sin.*`) and
+   - HLSL intrinsics (defined as LLVM intrinsics in `llvm/include/llvm/IR/IntrinsicsDirectX.td`, e.g., `llvm.dx.*`)
+
+   These are collectively referred to as `LLVM Intrinsics` in this note.
 
 Following is the complete list of properties of DXIL Ops with the corresponding field name
-as used in ``hctdb.py``. A DXIL Op is represented by a set of associated properties. These
+as used in `hctdb.py`. A DXIL Op is represented by a set of associated properties. These
 are consumed in DXIL backend passes as well as in other usage scenarios such as validation,
 DXIL reader, etc.
 
-A. Properties consumed in DXIL backend passes
-
-   1. Name of operation (``dxil_op``)
-   2. A string that documents the operation (``doc``) - This is not strictly necessary but is included
-      for readability and documentation of the operation.
-   3. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name``).
-   4. Unique Integer ID (``dxil_opid``)
-   5. Operation Class signifying the name and function signature of the operation (``dxil_class``).
-      This string is an integral part of the DXIL Op function name and is constructed in
-      the format ``dx.op.<class-name>.<overload-type>``. Each DXIL Op call target function name
-      is required to conform to this format per existing contract with the driver.
-   6. List of valid overload types for the operation (``oload_types``).
-   7. Required DXIL Version with support for the operation.
-   8. Required minimum Shader Model (``shader_model``).
-   9. Minimum shader model required with translation by linker (``shader_model_translated``)
-   10.  List of shader stages applicable to (``shader_stages``), empty, if applicable to all stages.
-   11.  Memory access attributes of the operation (``fn_attr``).
-   12.  Boolean attributes of operation to indicate if it
-
-        * is some kind of a derivative (``is_derivative``)
-        * requires gradient calculation (``is_gradient``)
-        * is a sampler feedback (``is_feedback``)
-        * requires in-wave, cross-lane functionality (``is_wave``)
-        * requires that all of its inputs are uniform across the wave (``requires_uniform_inputs``).
-        * is a barrier operation (``is_barrier``).
-
-Motivation
-==========
-
-DXIL backend passes depend on various properties of DXIL Operations. For example, ``DXILOpLowering``
+1. Properties consumed in DXIL backend passes
+
+   01. Name of operation (`dxil_op`)
+
+   02. A string that documents the operation (`doc`) - This is not strictly necessary but is included
+       for readability and documentation of the operation.
+
+   03. The generic or HLSL-specific intrinsic that maps to the operation (`llvm_name`).
+
+   04. Unique Integer ID (`dxil_opid`)
+
+   05. Operation Class signifying the name and function signature of the operation (`dxil_class`).
+       This string is an integral part of the DXIL Op function name and is constructed in
+       the format `dx.op.<class-name>.<overload-type>`. Each DXIL Op call target function name
+       is required to conform to this format per existing contract with the driver.
+
+   06. List of valid overload types for the operation (`oload_types`).
+
+   07. Required DXIL Version with support for the operation.
+
+   08. Required minimum Shader Model (`shader_model`).
+
+   09. Minimum shader model required with translation by linker (`shader_model_translated`)
+
+   10. List of shader stages applicable to (`shader_stages`), empty, if applicable to all stages.
+
+   11. Memory access attributes of the operation (`fn_attr`).
+
+   12. Boolean attributes of operation to indicate if it
+
+       - is some kind of a derivative (`is_derivative`)
+       - requires gradient calculation (`is_gradient`)
+       - is a sampler feedback (`is_feedback`)
+       - requires in-wave, cross-lane functionality (`is_wave`)
+       - requires that all of its inputs are uniform across the wave (`requires_uniform_inputs`).
+       - is a barrier operation (`is_barrier`).
+
+## Motivation
+
+DXIL backend passes depend on various properties of DXIL Operations. For example, `DXILOpLowering`
 pass will need information such as the DXIL operation an LLVM intrinsic is to be lowered to,
 along with valid overload and argument types etc. The TableGen file -
-``llvm/lib/Target/DirectX/DXIL.td`` - is used to represent DXIL Operations
-by specifying their properties listed above. ``DXIL.td`` is designed to be the single source
+`llvm/lib/Target/DirectX/DXIL.td` - is used to represent DXIL Operations
+by specifying their properties listed above. `DXIL.td` is designed to be the single source
 of reference of DXIL Operations primarily for the implementation of passes in DXIL backend in
-``llvm-project`` repo - analogous to ``hctdb.py`` for ``DirectXShadeCompiler`` repo. However,
-the current design does not intend to encapsulate various validation rules, present in ``hctdb.py``,
+`llvm-project` repo - analogous to `hctdb.py` for `DirectXShadeCompiler` repo. However,
+the current design does not intend to encapsulate various validation rules, present in `hctdb.py`,
 but do not pertain to DXIL Operations. It needs to have a rich representation capabilities that
-TableGen backends (such as ``DXILEmitter``) can rely on. Additionally, the DXIL Op specification
+TableGen backends (such as `DXILEmitter`) can rely on. Additionally, the DXIL Op specification
 should be easy to read and comprehend.
 
-This note provides the design of the specification DXIL Ops as TableGen class ``DXILOp``
+This note provides the design of the specification DXIL Ops as TableGen class `DXILOp`
 by specifying its properties identified above.
 
-DXIL Operation Specification
-============================
-
-The DXIL Operation is represented using the TableGen class ``DXILOp``. The DXIL operation
-properties are specified as fields of the ``DXILOp`` class as described below.
-
-1. Each DXIL Operation is represented as a TableGen record. The name of each of the records
-   signifies operation name.
-2. A documentation string for the operation.
-3. The LLVM Intrinsic that maps to the operation is represented as ``Intrinsic`` defined in
-   `Intrinsics.td <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/Intrinsics.td>`_.
-4. The unique operation id is represented by an integer.
-5. DXIL Operation Class is represented as follows
-
-   .. code-block::
-
-        // Abstraction of DXIL Operation class.
-        class DXILOpClass;
-
-   Concrete operation records, such as ``unary`` are defined by inheriting from ``DXILOpClass``.
-6. A set of type names are defined that represent return and argument types,
-   which all inherit from ``DXILOpParamType``. These represent simple types
-   like ``int32Ty``, DXIL types like ``dx.types.Handle``, and a special
-   ``overloadTy`` which can be any type allowed by ``Overloads``, described
-   below.
-7. Operation return type is represented as a ``DXILOpParamType``, and arguments
-   are represented as a list of the same. An operation with no return value
-   shall specify ``VoidTy`` as its return.
-8. Valid operation overload types predicated on DXIL version are specified as
-   a list of ``Overloads`` records. Representation of ``Overloads``
-   class is described in a later section.
-9.  Valid shader stages predicated on DXIL version are specified as a list of
-    ``Stages`` records. Representation of ``Stages`` class is
+## DXIL Operation Specification
+
+The DXIL Operation is represented using the TableGen class `DXILOp`. The DXIL operation
+properties are specified as fields of the `DXILOp` class as described below.
+
+01. Each DXIL Operation is represented as a TableGen record. The name of each of the records
+    signifies operation name.
+
+02. A documentation string for the operation.
+
+03. The LLVM Intrinsic that maps to the operation is represented as `Intrinsic` defined in
+    [Intrinsics.td](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/Intrinsics.td).
+
+04. The unique operation id is represented by an integer.
+
+05. DXIL Operation Class is represented as follows
+
+    ```
+    // Abstraction of DXIL Operation class.
+    class DXILOpClass;
+    ```
+
+    Concrete operation records, such as `unary` are defined by inheriting from `DXILOpClass`.
+
+06. A set of type names are defined that represent return and argument types,
+    which all inherit from `DXILOpParamType`. These represent simple types
+    like `int32Ty`, DXIL types like `dx.types.Handle`, and a special
+    `overloadTy` which can be any type allowed by `Overloads`, described
+    below.
+
+07. Operation return type is represented as a `DXILOpParamType`, and arguments
+    are represented as a list of the same. An operation with no return value
+    shall specify `VoidTy` as its return.
+
+08. Valid operation overload types predicated on DXIL version are specified as
+    a list of `Overloads` records. Representation of `Overloads`
+    class is described in a later section.
+
+09. Valid shader stages predicated on DXIL version are specified as a list of
+    `Stages` records. Representation of `Stages` class is
     described in a later section.
-10. Various attributes of the DXIL Operation are represented as a ``list`` of
-    ``Attributes`` class records. Representation of ``Attributes``
+
+10. Various attributes of the DXIL Operation are represented as a `list` of
+    `Attributes` class records. Representation of `Attributes`
     class is described in a later section.
 
-Types specific to DXIL
-----------------------
+### Types specific to DXIL
 
-Type notation used in this document viz., ``<size>Ty`` corresponds to TableGen records for
-LLVM types ``llvm_<size>_ty``. Apart from ``overloadTy`` described above, ``resRetF32Ty`` is
-used to denote resource return type and ``handleTy`` is used to denote handle type.
+Type notation used in this document viz., `<size>Ty` corresponds to TableGen records for
+LLVM types `llvm_<size>_ty`. Apart from `overloadTy` described above, `resRetF32Ty` is
+used to denote resource return type and `handleTy` is used to denote handle type.
 
-Specification of DXIL Operation
-================================
+## Specification of DXIL Operation
 
 A DXIL Operation is represented by the following TableGen class that encapsulates the various
 TableGen representations of its properties described above.
 
-.. code-block::
-
-   // Abstraction DXIL Operation
-   class DXILOp<int opcode, DXILOpClass opclass> {
-     // A short description of the operation
-     string Doc = "";
+```
+// Abstraction DXIL Operation
+class DXILOp<int opcode, DXILOpClass opclass> {
+  // A short description of the operation
+  string Doc = "";
 
-     // Opcode of DXIL Operation
-     int OpCode = opcode;
+  // Opcode of DXIL Operation
+  int OpCode = opcode;
 
-     // Class of DXIL Operation.
-     DXILOpClass OpClass = opclass;
+  // Class of DXIL Operation.
+  DXILOpClass OpClass = opclass;
 
-     // LLVM Intrinsic DXIL Operation maps to
-     Intrinsic LLVMIntrinsic = ?;
+  // LLVM Intrinsic DXIL Operation maps to
+  Intrinsic LLVMIntrinsic = ?;
 
-     // Result type of the op.
-     DXILOpParamType result;
+  // Result type of the op.
+  DXILOpParamType result;
 
-     // List of argument types of the op. Default to 0 arguments.
-     list<DXILOpParamType> arguments = [];
+  // List of argument types of the op. Default to 0 arguments.
+  list<DXILOpParamType> arguments = [];
 
-     // List of valid overload types predicated by DXIL version
-     list<Overloads> overloads;
+  // List of valid overload types predicated by DXIL version
+  list<Overloads> overloads;
 
-     // List of valid shader stages predicated by DXIL version
-    list<Stages> stages;
+  // List of valid shader stages predicated by DXIL version
+ list<Stages> stages;
 
-     // List of valid attributes predicated by DXIL version
-     list<Attributes> attributes = [];
-   }
+  // List of valid attributes predicated by DXIL version
+  list<Attributes> attributes = [];
+}
+```
 
-Version Specification
-=====================
+## Version Specification
 
 DXIL version is used to specify various version-dependent operation properties in
 place of Shader Model version.
 
-A ``Version`` class encapsulating ``Major`` and ``Minor`` version number is defined
+A `Version` class encapsulating `Major` and `Minor` version number is defined
 as follows:
 
-.. code-block::
-
-   // Abstract class to represent major and minor version values
-   class Version<int major, int minor> {
-     int Major = major;
-     int Minor = minor;
-   }
-
+```
+// Abstract class to represent major and minor version values
+class Version<int major, int minor> {
+  int Major = major;
+  int Minor = minor;
+}
+```
 
 Concrete representations of valid DXIL versions are defined as follows:
 
-.. code-block::
+```
+// Definition of DXIL Version 1.0 - 1.8
+foreach i = 0...8 in {
+  def DXIL1_#i : Version<1, i>;
+}
+```
 
-   // Definition of DXIL Version 1.0 - 1.8
-   foreach i = 0...8 in {
-     def DXIL1_#i : Version<1, i>;
-   }
+## Shader Stage Specification
 
-Shader Stage Specification
-==========================
-
-Various shader stages such as ``compute``, ``pixel``, ``vertex``, etc., are represented
+Various shader stages such as `compute`, `pixel`, `vertex`, etc., are represented
 as follows
 
-.. code-block::
-
-   // Shader stages
-   class DXILShaderStage;
+```
+// Shader stages
+class DXILShaderStage;
 
-   def compute : DXILShaderStage;
-   def pixel : DXILShaderStage;
-   def vertex : DXILShaderStage;
-   ...
+def compute : DXILShaderStage;
+def pixel : DXILShaderStage;
+def vertex : DXILShaderStage;
+...
+```
 
-Shader Attribute Specification
-==============================
+## Shader Attribute Specification
 
-Various operation memory access and boolean attributes such as ``ReadNone``,
-``IsWave`` etc., are represented as follows
+Various operation memory access and boolean attributes such as `ReadNone`,
+`IsWave` etc., are represented as follows
 
-.. code-block::
+```
+class DXILAttribute;
 
-  class DXILAttribute;
+def ReadOnly : DXILOpAttributes;
+def ReadNone : DXILOpAttributes;
+def IsWave : DXILOpAttributes;
+...
+```
 
-  def ReadOnly : DXILOpAttributes;
-  def ReadNone : DXILOpAttributes;
-  def IsWave : DXILOpAttributes;
-  ...
-
-Versioned Property Specification
-================================
+## Versioned Property Specification
 
 DXIL Operation properties such as valid overload types, shader stages and
 attributes are predicated on DXIL version. These are represented as list of
 versioned properties.
 
-Overload Type Specification
----------------------------
+### Overload Type Specification
 
-``overloads`` field of ``class DXILOp`` is used to represent valid operation
+`overloads` field of `class DXILOp` is used to represent valid operation
 overloads predicated on DXIL version as list of records of the following class
 
-.. code-block::
-
-   class Overloads<Version minver, list<DXILOpParamType> ols> {
-     Version dxil_version = minver;
-     list<DXILOpParamType> overload_types = ols;
-   }
+```
+class Overloads<Version minver, list<DXILOpParamType> ols> {
+  Version dxil_version = minver;
+  list<DXILOpParamType> overload_types = ols;
+}
+```
 
-Following is an example specification of valid overload types for ``DXIL1_0`` and
-``DXIL1_2``.
+Following is an example specification of valid overload types for `DXIL1_0` and
+`DXIL1_2`.
 
-.. code-block::
-
-   overloads = [
-                 Overloads<DXIL1_0, [halfTy, floatTy]>,
-                 Overloads<DXIL1_2, [halfTy, floatTy, doubleTy]>
-               ];
+```
+overloads = [
+              Overloads<DXIL1_0, [halfTy, floatTy]>,
+              Overloads<DXIL1_2, [halfTy, floatTy, doubleTy]>
+            ];
+```
 
 An empty list signifies that the operation supports no overload types.
 
+### Stages Specification
 
-Stages Specification
---------------------
-
-``stages`` field of ``class DXILOp`` is used to represent valid operation
+`stages` field of `class DXILOp` is used to represent valid operation
 stages predicated on DXIL version as list of records of the following class
 
-.. code-block::
-
-   class Stages<Version minver, list<DXILShaderStage> sts> {
-     Version dxil_version = minver;
-     list<DXILShaderStage> shader_stages = sts;
-   }
-
-Following is an example specification of valid stages for ``DXIL1_0``,
-``DXIL1_2``, ``DXIL1_4`` and ``DXIL1_6``.
-
-.. code-block::
-
-   stages = [
-             Stages<DXIL1_0, [compute, pixel]>,
-             Stages<DXIL1_2, [compute, pixel, mesh]>,
-             Stages<DXIL1_4, [all_stages]>,
-             Stages<DXIL1_6, [removed]>
-            ];
+```
+class Stages<Version minver, list<DXILShaderStage> sts> {
+  Version dxil_version = minver;
+  list<DXILShaderStage> shader_stages = sts;
+}
+```
+
+Following is an example specification of valid stages for `DXIL1_0`,
+`DXIL1_2`, `DXIL1_4` and `DXIL1_6`.
+
+```
+stages = [
+          Stages<DXIL1_0, [compute, pixel]>,
+          Stages<DXIL1_2, [compute, pixel, mesh]>,
+          Stages<DXIL1_4, [all_stages]>,
+          Stages<DXIL1_6, [removed]>
+         ];
+```
 
 The following two pseudo stage records in addition to standard shader stages
 are defined.
 
-1. ``all_stages`` signifies that the operation is valid for all stages in the
+1. `all_stages` signifies that the operation is valid for all stages in the
    specified DXIL version and later.
-2. ``removed`` signifies removal of support for the operation in the specified
+2. `removed` signifies removal of support for the operation in the specified
    DXIL version and later.
 
 A non-empty list of supported stages is required to be specified. If an operation
 is supported in all DXIL versions and all stages it is required to be specified as
 
-.. code-block::
-
-   stages = [Stages<DXIL1_0, [all_stages]>];
+```
+stages = [Stages<DXIL1_0, [all_stages]>];
+```
 
+### Attribute Specification
 
-Attribute Specification
------------------------
-
-``attributes`` field of ``class DXILOp`` is used to represent valid operation
+`attributes` field of `class DXILOp` is used to represent valid operation
 attributes predicated on DXIL version as list of records of the following class
 
-.. code-block::
-
-  class Attributes<MinVersion minver, list<DXILAttribute> attrs> {
-    MinVersion dxil_version = ver;
-    list<DXILAttribute> attributes = attrs;
-  }
+```
+class Attributes<MinVersion minver, list<DXILAttribute> attrs> {
+  MinVersion dxil_version = ver;
+  list<DXILAttribute> attributes = attrs;
+}
+```
 
-Following is an example specification of valid attributes for ``DXIL1_0``.
+Following is an example specification of valid attributes for `DXIL1_0`.
 
-.. code-block::
+```
+attributes = [Attributes<DXIL1_0, [ReadNone]];
+```
 
-   attributes = [Attributes<DXIL1_0, [ReadNone]];
+A null list of `attributes` signifies no operation attributes.
 
-A null list of ``attributes`` signifies no operation attributes.
-
-Interpretation of Multiple Versioned Properties
------------------------------------------------
+### Interpretation of Multiple Versioned Properties
 
 Each of the versioned properties states that the specified overload type, stage or
 attribute records are valid for the predicated DXIL version. Only
@@ -317,130 +319,128 @@ Note as in the above example, any overload types, stages or attributes,
 that remain valid in a later DXIL version need to be specified in full.
 For example, consider the following specification of valid overload types:
 
-.. code-block::
-
-   overloads = [
-                Overloads<DXIL1_0, [halfTy, floatTy]>,
-                Overloads<DXIL1_2, [halfTy, floatTy, doubleTy]>
-               ];
+```
+overloads = [
+             Overloads<DXIL1_0, [halfTy, floatTy]>,
+             Overloads<DXIL1_2, [halfTy, floatTy, doubleTy]>
+            ];
+```
 
-It specifies that the overload types ``halfTy`` and ``floatTy`` are valid for DXIL
-version 1.0 and later. It also specifies that  ``doubleTy`` is additionally supported
+It specifies that the overload types `halfTy` and `floatTy` are valid for DXIL
+version 1.0 and later. It also specifies that `doubleTy` is additionally supported
 in DXIL version 1.2 and later.
 
 This provides the flexibility to specify properties independent of other
 versioned specifications in the list.
 
-
-DXIL Operation Specification Examples
-=====================================
+## DXIL Operation Specification Examples
 
 Following examples illustrate the specification of some of the DXIL Ops.
 
-``Sin`` operation - an operation valid in all DXIL versions and all stages
+`Sin` operation - an operation valid in all DXIL versions and all stages
 and has valid overload types predicated on DXIL version.
 
-.. code-block::
-
-  def Sin : DXILOp<13, unary> {
-    let Doc = "Returns sine(theta) for theta in radians.";
-    let LLVMIntrinsic = int_sin;
-    let result = overloadTy;
-    let arguments = [overloadTy];
-    let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
-    let stages = [Stages<DXIL1_0, [all_stages]>];
-    let attributes = [Attributes<DXIL1_0, [ReadNone]>];
-  }
-
-``FlattenedThreadIdInGroup`` - an operation with no arguments, no
+```
+def Sin : DXILOp<13, unary> {
+  let Doc = "Returns sine(theta) for theta in radians.";
+  let LLVMIntrinsic = int_sin;
+  let result = overloadTy;
+  let arguments = [overloadTy];
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
+}
+```
+
+`FlattenedThreadIdInGroup` - an operation with no arguments, no
 overload types, and valid stages and attributes predicated by DXIL Version.
 
-.. code-block::
-
-   def FlattenedThreadIdInGroup :  DXILOp<96, flattenedThreadIdInGroup> {
-    let Doc = "Provides a flattened index for a given thread within a given "
-              "group (SV_GroupIndex)";
-    let LLVMIntrinsic = int_dx_flattened_thread_id_in_group;
-    let result = i32Ty;
-    let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
-    let attributes = [Attributes<DXIL1_0, [ReadNone]>];
-   }
-
-``RawBufferStore`` - an operation with ``void`` return type, valid overload types
+```
+def FlattenedThreadIdInGroup :  DXILOp<96, flattenedThreadIdInGroup> {
+ let Doc = "Provides a flattened index for a given thread within a given "
+           "group (SV_GroupIndex)";
+ let LLVMIntrinsic = int_dx_flattened_thread_id_in_group;
+ let result = i32Ty;
+ let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
+ let attributes = [Attributes<DXIL1_0, [ReadNone]>];
+}
+```
+
+`RawBufferStore` - an operation with `void` return type, valid overload types
 predicated by DXIL Version and valid in all DXIL versions and stages.
 
-.. code-block::
-
-   def RawBufferStore : DXILOp<140, rawBufferStore> {
-     let Doc = "Writes to a RWByteAddressBuffer or RWStructuredBuffer.";
-     let result = voidTy;
-     let arguments = [dxil_resource_ty, i32Ty, i32Ty, overloadTy,
-                      overloadTy, overloadTy, overloadTy, i8Ty, i32Ty];
-     let overloads = [
-                      Overloads<DXIL1_2, [halfTy, floatTy, i16Ty, i32Ty]>,
-                      Overloads<DXIL1_3>,[halfTy, floatTy, doubleTy,
-                                                   i16Ty, i32Ty, i64Ty]>
-                     ];
-      let stages = [Stages<DXIL1_2, all_stages>];
-      let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
-   }
-
-``DerivCoarseX`` - an operation with no overload types and stages predicated
+```
+def RawBufferStore : DXILOp<140, rawBufferStore> {
+  let Doc = "Writes to a RWByteAddressBuffer or RWStructuredBuffer.";
+  let result = voidTy;
+  let arguments = [dxil_resource_ty, i32Ty, i32Ty, overloadTy,
+                   overloadTy, overloadTy, overloadTy, i8Ty, i32Ty];
+  let overloads = [
+                   Overloads<DXIL1_2, [halfTy, floatTy, i16Ty, i32Ty]>,
+                   Overloads<DXIL1_3>,[halfTy, floatTy, doubleTy,
+                                                i16Ty, i32Ty, i64Ty]>
+                  ];
+   let stages = [Stages<DXIL1_2, all_stages>];
+   let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
+}
+```
+
+`DerivCoarseX` - an operation with no overload types and stages predicated
 by DXIL Version.
 
-.. code-block::
-
-   def DerivCoarseX : DXILOp<83, unary> {
-    let doc = "Computes the rate of change per stamp in x direction.";
-    let LLVMIntrinsic = int_dx_ddx;
-    let result = overloadTy;
-    let arguments = [overloadTy];
-    let stages = [
-                   Stages<DXIL1_0, [library, pixel]>,
-                   Stages<DXIL1_6, [library, pixel, amplification, compute, mesh]>
-                 ];
-    let attributes = [Attributes<DXIL1_0, [ReadNone]>];
-   }
-
-``CreateHandle`` - an operation with no overload types, no associated ``LLVMIntrinsic``
-and stages predicated  by DXIL Version.
-
-.. code-block::
-
-   def CreateHandle : DXILOp<57, createHandle> {
-     let doc = "Creates the handle to a resource";
-     let result = i32Ty;
-     let arguments = [i8Ty, i32Ty, i32Ty, i1Ty];
-     let stages = [
-                   Stages<DXIL1_0, [all_stages]>,
-                   Stages<DXIL1_6, [removed]
-                  ];
-     let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
-   }
+```
+def DerivCoarseX : DXILOp<83, unary> {
+ let doc = "Computes the rate of change per stamp in x direction.";
+ let LLVMIntrinsic = int_dx_ddx;
+ let result = overloadTy;
+ let arguments = [overloadTy];
+ let stages = [
+                Stages<DXIL1_0, [library, pixel]>,
+                Stages<DXIL1_6, [library, pixel, amplification, compute, mesh]>
+              ];
+ let attributes = [Attributes<DXIL1_0, [ReadNone]>];
+}
+```
+
+`CreateHandle` - an operation with no overload types, no associated `LLVMIntrinsic`
+and stages predicated by DXIL Version.
+
+```
+def CreateHandle : DXILOp<57, createHandle> {
+  let doc = "Creates the handle to a resource";
+  let result = i32Ty;
+  let arguments = [i8Ty, i32Ty, i32Ty, i1Ty];
+  let stages = [
+                Stages<DXIL1_0, [all_stages]>,
+                Stages<DXIL1_6, [removed]
+               ];
+  let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
+}
+```
 
-``Sample`` - an operation with valid overload types, stages and attributes
+`Sample` - an operation with valid overload types, stages and attributes
 predicated by DXIL version.
 
-.. code-block::
-
-   def Sample : DXILOp<60, sample> {
-     let Doc = "Samples a texture";
-     let LLVMIntrinsic = int_dx_sample;
-     let result = resRetF32Ty;
-     let arguments = [handleTy, handleTy, floatTy, floatTy, floatTy, floatTy,
-                      i32Ty, i32Ty, i32Ty, floatTy];
-     let overloads = [Overloads<DXIL1_0, [halfTy, floatTy, i16Ty, i32Ty]>];
-     let stages = [
-                   Stages<DXIL1_0, [library, pixel]>,
-                   Stages<DXIL1_6, [library, pixel, amplification, compute, mesh]>
-                  ];
-     let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
-   }
+```
+def Sample : DXILOp<60, sample> {
+  let Doc = "Samples a texture";
+  let LLVMIntrinsic = int_dx_sample;
+  let result = resRetF32Ty;
+  let arguments = [handleTy, handleTy, floatTy, floatTy, floatTy, floatTy,
+                   i32Ty, i32Ty, i32Ty, floatTy];
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy, i16Ty, i32Ty]>];
+  let stages = [
+                Stages<DXIL1_0, [library, pixel]>,
+                Stages<DXIL1_6, [library, pixel, amplification, compute, mesh]>
+               ];
+  let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
+}
+```
 
-Summary
-=======
+## Summary
 
 This note sketches the design of a readable and maintainable TableGen specification of
-DXIL Ops in ``DXIL.td`` intended to serve as a single source of reference for TableGen
-backends (such as ``DXILEmitter``) that generate C++ representations used in DXIL
+DXIL Ops in `DXIL.td` intended to serve as a single source of reference for TableGen
+backends (such as `DXILEmitter`) that generate C++ representations used in DXIL
 backend passes.
+
diff --git a/llvm/docs/DirectX/DXILResources.md b/llvm/docs/DirectX/DXILResources.md
index 1f969841009a9..f27bc56f86ea3 100644
--- a/llvm/docs/DirectX/DXILResources.md
+++ b/llvm/docs/DirectX/DXILResources.md
@@ -1,15 +1,12 @@
-======================
-DXIL Resource Handling
-======================
+# DXIL Resource Handling
 
+```{toctree}
+:hidden: true
+```
 
-.. toctree::
-   :hidden:
+## Introduction
 
-Introduction
-============
-
-Resources in DXIL are represented via ``TargetExtType`` in LLVM IR and
+Resources in DXIL are represented via `TargetExtType` in LLVM IR and
 eventually lowered by the DirectX backend into metadata in DXIL.
 
 In DXC and DXIL, static resources are represented as lists of SRVs (Shader
@@ -17,89 +14,92 @@ Resource Views), UAVs (Uniform Access Views), CBVs (Constant Bffer Views), and
 Samplers. This metadata consists of a "resource record ID" which uniquely
 identifies a resource and type information. As of shader model 6.6, there are
 also dynamic resources, which forgo the metadata and are described via
-``annotateHandle`` operations in the instruction stream instead.
+`annotateHandle` operations in the instruction stream instead.
 
 In LLVM we attempt to unify some of the alternative representations that are
 present in DXC, with the aim of making handling of resources in the middle end
 of the compiler simpler and more consistent.
 
-Resource Type Information and Properties
-========================================
+## Resource Type Information and Properties
 
 There are a number of properties associated with a resource in DXIL.
 
 `Resource ID`
-   An arbitrary ID that must be unique per resource type (SRV, UAV, etc).
 
-   In LLVM we don't bother representing this, instead opting to generate it at
-   DXIL lowering time.
+: An arbitrary ID that must be unique per resource type (SRV, UAV, etc).
+
+  In LLVM we don't bother representing this, instead opting to generate it at
+  DXIL lowering time.
 
 `Binding information`
-   Information about where the resource comes from. This is either (a) a
-   register space, lower bound in that space, and size of the binding, or (b)
-   an index into a dynamic resource heap.
 
-   In LLVM we represent binding information in the arguments of the
-   :ref:`handle creation intrinsics <dxil-resources-handles>`. When generating
-   DXIL we transform these calls to metadata, ``dx.op.createHandle``,
-   ``dx.op.createHandleFromBinding``, ``dx.op.createHandleFromHeap``, and
-   ``dx.op.createHandleForLib`` as needed.
+: Information about where the resource comes from. This is either (a) a
+  register space, lower bound in that space, and size of the binding, or (b)
+  an index into a dynamic resource heap.
+
+  In LLVM we represent binding information in the arguments of the
+  {ref}`handle creation intrinsics <dxil-resources-handles>`. When generating
+  DXIL we transform these calls to metadata, `dx.op.createHandle`,
+  `dx.op.createHandleFromBinding`, `dx.op.createHandleFromHeap`, and
+  `dx.op.createHandleForLib` as needed.
 
 `Type information`
-   The type of data that's accessible via the resource. For buffers and
-   textures this can be a simple type like ``float`` or ``float4``, a struct,
-   or raw bytes. For constant buffers this is just a size. For samplers this is
-   the kind of sampler.
 
-   In LLVM we embed this information as a parameter on the ``target()`` type of
-   the resource. See :ref:`dxil-resources-types-of-resource`.
+: The type of data that's accessible via the resource. For buffers and
+  textures this can be a simple type like `float` or `float4`, a struct,
+  or raw bytes. For constant buffers this is just a size. For samplers this is
+  the kind of sampler.
+
+  In LLVM we embed this information as a parameter on the `target()` type of
+  the resource. See {ref}`dxil-resources-types-of-resource`.
 
 `Resource kind information`
-   The kind of resource. In HLSL we have things like ``ByteAddressBuffer``,
-   ``RWTexture2D``, and ``RasterizerOrderedStructuredBuffer``. These map to a
-   set of DXIL kinds like ``RawBuffer`` and ``Texture2D`` with fields for
-   certain properties such as ``IsUAV`` and ``IsROV``.
 
-   In LLVM we represent this in the ``target()`` type. We omit information
-   that's deriveable from the type information, but we do have fields to encode
-   ``IsWriteable``, ``IsROV``, and ``SampleCount`` when needed.
+: The kind of resource. In HLSL we have things like `ByteAddressBuffer`,
+  `RWTexture2D`, and `RasterizerOrderedStructuredBuffer`. These map to a
+  set of DXIL kinds like `RawBuffer` and `Texture2D` with fields for
+  certain properties such as `IsUAV` and `IsROV`.
 
-.. note:: TODO: There are two fields in the DXIL metadata that are not
-   represented as part of the target type: ``IsGloballyCoherent`` and
-   ``HasCounter``.
+  In LLVM we represent this in the `target()` type. We omit information
+  that's deriveable from the type information, but we do have fields to encode
+  `IsWriteable`, `IsROV`, and `SampleCount` when needed.
 
-   Since these are derived from analysis, storing them on the type would mean
-   we need to change the type during the compiler pipeline. That just isn't
-   practical. It isn't entirely clear to me that we need to serialize this info
-   into the IR during the compiler pipeline anyway - we can probably get away
-   with an analysis pass that can calculate the information when we need it.
+:::{note}
+TODO: There are two fields in the DXIL metadata that are not
+represented as part of the target type: `IsGloballyCoherent` and
+`HasCounter`.
 
-   If analysis is insufficient we'll need something akin to ``annotateHandle``
-   (but limited to these two properties) or to encode these in the handle
-   creation.
+Since these are derived from analysis, storing them on the type would mean
+we need to change the type during the compiler pipeline. That just isn't
+practical. It isn't entirely clear to me that we need to serialize this info
+into the IR during the compiler pipeline anyway - we can probably get away
+with an analysis pass that can calculate the information when we need it.
 
-.. _dxil-resources-types-of-resource:
+If analysis is insufficient we'll need something akin to `annotateHandle`
+(but limited to these two properties) or to encode these in the handle
+creation.
+:::
 
-Types of Resource
-=================
+(dxil-resources-types-of-resource)=
 
-We define a set of ``TargetExtTypes`` that is similar to the HLSL
+## Types of Resource
+
+We define a set of `TargetExtTypes` that is similar to the HLSL
 representations for the various resources, albeit with a few things
 parameterized. This is different than DXIL, as simplifying the types to
 something like "dx.srv" and "dx.uav" types would mean the operations on these
 types would have to be overly generic.
 
-Buffers
--------
-
-.. code-block:: llvm
+### Buffers
 
-   target("dx.TypedBuffer", ElementType, IsWriteable, IsROV, IsSigned)
-   target("dx.RawBuffer", ElementType, IsWriteable, IsROV)
+```llvm
+target("dx.TypedBuffer", ElementType, IsWriteable, IsROV, IsSigned)
+target("dx.RawBuffer", ElementType, IsWriteable, IsROV)
+```
 
 We need two separate buffer types to account for the differences between the
-16-byte `bufferLoad`_ / `bufferStore`_ operations that work on DXIL's
-TypedBuffers and the `rawBufferLoad`_ / `rawBufferStore`_ operations that are
+16-byte [bufferLoad][bufferload] / [bufferStore][bufferstore] operations that work on DXIL's
+TypedBuffers and the [rawBufferLoad][rawbufferload] / [rawBufferStore][rawbufferstore] operations that are
 used for DXIL's RawBuffers and StructuredBuffers. We call the latter
 "RawBuffer" to match the naming of the operations, but it can represent both
 the Raw and Structured variants.
@@ -118,6 +118,7 @@ well as atomics.
 
 There are a few fields to describe variants of all of these types:
 
+```{eval-rst}
 .. list-table:: Buffer Fields
    :header-rows: 1
 
@@ -133,31 +134,25 @@ There are a few fields to describe variants of all of these types:
      - Whether the UAV is a rasterizer ordered view. Always ``0`` for SRVs.
    * - IsSigned
      - Whether an int element type is signed ("dx.TypedBuffer" only)
+```
 
-.. _bufferLoad: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#bufferload
-.. _bufferStore: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#bufferstore
-.. _rawBufferLoad: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#rawbufferload
-.. _rawBufferStore: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#rawbufferstore
+## Resource Operations
 
-Resource Operations
-===================
+(dxil-resources-handles)=
 
-.. _dxil-resources-handles:
-
-Resource Handles
-----------------
+### Resource Handles
 
 We provide a few different ways to instantiate resources in the IR via the
-``llvm.dx.handle.*`` intrinsics. These intrinsics are overloaded on return
+`llvm.dx.handle.*` intrinsics. These intrinsics are overloaded on return
 type, returning an appropriate handle for the resource, and represent binding
 information in the arguments to the intrinsic.
 
-The three operations we need are ``llvm.dx.resource.handlefrombinding``,
-``llvm.dx.handle.fromHeap``, and ``llvm.dx.handle.fromPointer``. These are
-rougly equivalent to the DXIL operations ``dx.op.createHandleFromBinding``,
-``dx.op.createHandleFromHeap``, and ``dx.op.createHandleForLib``, but they fold
-the subsequent ``dx.op.annotateHandle`` operation in. Note that we don't have
-an analogue for `dx.op.createHandle`_, since ``dx.op.createHandleFromBinding``
+The three operations we need are `llvm.dx.resource.handlefrombinding`,
+`llvm.dx.handle.fromHeap`, and `llvm.dx.handle.fromPointer`. These are
+rougly equivalent to the DXIL operations `dx.op.createHandleFromBinding`,
+`dx.op.createHandleFromHeap`, and `dx.op.createHandleForLib`, but they fold
+the subsequent `dx.op.annotateHandle` operation in. Note that we don't have
+an analogue for [dx.op.createHandle][dx.op.createhandle], since `dx.op.createHandleFromBinding`
 subsumes it.
 
 We diverge from DXIL and index from the beginning of the binding rather than
@@ -165,8 +160,7 @@ indexing from the beginning of the binding space. This matches the semantics
 more clearly and avoids a non-obvious invariant in what constitutes valid
 arguments.
 
-.. _dx.op.createHandle: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#resource-handles
-
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.handlefrombinding``
    :header-rows: 1
 
@@ -198,46 +192,50 @@ arguments.
      - 5
      - i1
      - Must be ``true`` if the resource index may be non-uniform.
+```
 
-.. note:: TODO: Can we drop the uniformity bit? I suspect we can derive it from
-          uniformity analysis...
+:::{note}
+TODO: Can we drop the uniformity bit? I suspect we can derive it from
+uniformity analysis...
+:::
 
 Examples:
 
-.. code-block:: llvm
-
-   ; RWBuffer<float4> Buf : register(u5, space3)
-   %buf = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
-        @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
-            i32 3, i32 5, i32 1, i32 0, i1 false)
-
-   ; RWBuffer<int> Buf : register(u7, space2)
-   %buf = call target("dx.TypedBuffer", i32, 1, 0, 1)
-        @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0t(
-            i32 2, i32 7, i32 1, i32 0, i1 false)
-
-   ; Buffer<uint4> Buf[24] : register(t3, space5)
-   %buf = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
-        @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_0_0t(
-            i32 2, i32 7, i32 24, i32 0, i1 false)
-
-   ; struct S { float4 a; uint4 b; };
-   ; StructuredBuffer<S> Buf : register(t2, space4)
-   %buf = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
-       @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
-           i32 4, i32 2, i32 1, i32 0, i1 false)
-
-   ; ByteAddressBuffer Buf : register(t8, space1)
-   %buf = call target("dx.RawBuffer", i8, 0, 0)
-       @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
-           i32 1, i32 8, i32 1, i32 0, i1 false)
-
-   ; RWBuffer<float4> Global[3] : register(u6, space5)
-   ; RWBuffer<float4> Buf = Global[2];
-   %buf = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
-       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
-           i32 5, i32 6, i32 3, i32 2, i1 false)
-
+```llvm
+; RWBuffer<float4> Buf : register(u5, space3)
+%buf = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+     @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
+         i32 3, i32 5, i32 1, i32 0, i1 false)
+
+; RWBuffer<int> Buf : register(u7, space2)
+%buf = call target("dx.TypedBuffer", i32, 1, 0, 1)
+     @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0t(
+         i32 2, i32 7, i32 1, i32 0, i1 false)
+
+; Buffer<uint4> Buf[24] : register(t3, space5)
+%buf = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
+     @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_0_0t(
+         i32 2, i32 7, i32 24, i32 0, i1 false)
+
+; struct S { float4 a; uint4 b; };
+; StructuredBuffer<S> Buf : register(t2, space4)
+%buf = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
+    @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
+        i32 4, i32 2, i32 1, i32 0, i1 false)
+
+; ByteAddressBuffer Buf : register(t8, space1)
+%buf = call target("dx.RawBuffer", i8, 0, 0)
+    @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
+        i32 1, i32 8, i32 1, i32 0, i1 false)
+
+; RWBuffer<float4> Global[3] : register(u6, space5)
+; RWBuffer<float4> Buf = Global[2];
+%buf = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+    @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
+        i32 5, i32 6, i32 3, i32 2, i1 false)
+```
+
+```{eval-rst}
 .. list-table:: ``@llvm.dx.handle.fromHeap``
    :header-rows: 1
 
@@ -257,23 +255,23 @@ Examples:
      - 1
      - i1
      - Must be ``true`` if the resource index may be non-uniform.
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   ; RWStructuredBuffer<float4> Buf = ResourceDescriptorHeap[2];
-   declare
-     target("dx.RawBuffer", <4 x float>, 1, 0)
-     @llvm.dx.handle.fromHeap.tdx.RawBuffer_v4f32_1_0(
-         i32 %index, i1 %non_uniform)
-   ; ...
-   %buf = call target("dx.RawBuffer", <4 x f32>, 1, 0)
-               @llvm.dx.handle.fromHeap.tdx.RawBuffer_v4f32_1_0(
-                   i32 2, i1 false)
+```llvm
+; RWStructuredBuffer<float4> Buf = ResourceDescriptorHeap[2];
+declare
+  target("dx.RawBuffer", <4 x float>, 1, 0)
+  @llvm.dx.handle.fromHeap.tdx.RawBuffer_v4f32_1_0(
+      i32 %index, i1 %non_uniform)
+; ...
+%buf = call target("dx.RawBuffer", <4 x f32>, 1, 0)
+            @llvm.dx.handle.fromHeap.tdx.RawBuffer_v4f32_1_0(
+                i32 2, i1 false)
+```
 
-Accessing Resources as Memory
------------------------------
+### Accessing Resources as Memory
 
 *relevant types: Buffers, Textures, and CBuffers*
 
@@ -286,9 +284,12 @@ Accesses using `llvm.dx.resource.getpointer` are replaced with direct load and
 store operations in the `DXILResourceAccess` pass. These direct loads and
 stores are described later in this document.
 
-.. note:: Currently the pointers returned by `dx.resource.getpointer` are in
-          the default address space, but that will likely change in the future.
+:::{note}
+Currently the pointers returned by `dx.resource.getpointer` are in
+the default address space, but that will likely change in the future.
+:::
 
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.getpointer``
    :header-rows: 1
 
@@ -308,23 +309,23 @@ stores are described later in this document.
      - 1
      - ``i32``
      - Index into the resource
+```
 
 Examples:
 
-.. code-block:: llvm
+```llvm
+%ptr = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4f32_0_0_0t(
+    target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 %index)
+```
 
-   %ptr = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4f32_0_0_0t(
-       target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 %index)
-
-Loads, Samples, and Gathers
----------------------------
+### Loads, Samples, and Gathers
 
 *relevant types: Buffers and Textures*
 
-All load, sample, and gather operations in DXIL return a `ResRet`_ type. These
+All load, sample, and gather operations in DXIL return a [ResRet][resret] type. These
 types are structs containing 4 elements of some basic type, and a 5th element
-that is used by the `CheckAccessFullyMapped`_ operation. Some of these
-operations, like `RawBufferLoad`_ include a mask and/or alignment that tell us
+that is used by the [CheckAccessFullyMapped][checkaccessfullymapped] operation. Some of these
+operations, like [RawBufferLoad][rawbufferload] include a mask and/or alignment that tell us
 some information about how to interpret those four values.
 
 In the LLVM IR representations of these operations we instead return scalars or
@@ -334,8 +335,8 @@ the intermediate format while also keeping lowering to DXIL straightforward.
 
 LLVM intrinsics that map to operations returning `ResRet` return an anonymous
 struct with element-0 being the scalar or vector type, and element-1 being the
-``i1`` result of a ``CheckAccessFullyMapped`` call. We don't have a separate
-call to ``CheckAccessFullyMapped`` at all, since that's the only operation that
+`i1` result of a `CheckAccessFullyMapped` call. We don't have a separate
+call to `CheckAccessFullyMapped` at all, since that's the only operation that
 can possibly be done on this value. In practice this may mean we insert a DXIL
 operation for the check when this was missing in the HLSL source, but this
 actually matches DXC's behaviour in practice.
@@ -346,13 +347,9 @@ constrained to contain only scalars and vectors of up to 4 elements, the
 lowering to DXIL ops is generally straightforward. The one exception we have
 here is that `double` types in the elements are special - these are allowed in
 the LLVM intrinsics, but are lowered to pairs of `i32` followed by
-``MakeDouble`` operations for DXIL.
-
-.. _ResRet: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#resource-operation-return-types
-.. _CBufRet: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#cbufferloadlegacy
-.. _CheckAccessFullyMapped: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/checkaccessfullymapped
-.. _RawBufferLoad: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#rawbufferload
+`MakeDouble` operations for DXIL.
 
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.load.typedbuffer``
    :header-rows: 1
 
@@ -372,41 +369,41 @@ the LLVM intrinsics, but are lowered to pairs of `i32` followed by
      - 1
      - ``i32``
      - Index into the buffer
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   %ret = call {<4 x float>, i1}
-       @llvm.dx.resource.load.typedbuffer.v4f32.tdx.TypedBuffer_v4f32_0_0_0t(
-           target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 %index)
-   %ret = call {float, i1}
-       @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_0_0_0t(
-           target("dx.TypedBuffer", float, 0, 0, 0) %buffer, i32 %index)
-   %ret = call {<4 x i32>, i1}
-       @llvm.dx.resource.load.typedbuffer.v4i32.tdx.TypedBuffer_v4i32_0_0_0t(
-           target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) %buffer, i32 %index)
-   %ret = call {<4 x half>, i1}
-       @llvm.dx.resource.load.typedbuffer.v4f16.tdx.TypedBuffer_v4f16_0_0_0t(
-           target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %buffer, i32 %index)
-   %ret = call {<2 x double>, i1}
-       @llvm.dx.resource.load.typedbuffer.v2f64.tdx.TypedBuffer_v2f64_0_0t(
-           target("dx.TypedBuffer", <2 x double>, 0, 0, 0) %buffer, i32 %index)
+```llvm
+%ret = call {<4 x float>, i1}
+    @llvm.dx.resource.load.typedbuffer.v4f32.tdx.TypedBuffer_v4f32_0_0_0t(
+        target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 %index)
+%ret = call {float, i1}
+    @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_0_0_0t(
+        target("dx.TypedBuffer", float, 0, 0, 0) %buffer, i32 %index)
+%ret = call {<4 x i32>, i1}
+    @llvm.dx.resource.load.typedbuffer.v4i32.tdx.TypedBuffer_v4i32_0_0_0t(
+        target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) %buffer, i32 %index)
+%ret = call {<4 x half>, i1}
+    @llvm.dx.resource.load.typedbuffer.v4f16.tdx.TypedBuffer_v4f16_0_0_0t(
+        target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %buffer, i32 %index)
+%ret = call {<2 x double>, i1}
+    @llvm.dx.resource.load.typedbuffer.v2f64.tdx.TypedBuffer_v2f64_0_0t(
+        target("dx.TypedBuffer", <2 x double>, 0, 0, 0) %buffer, i32 %index)
+```
 
 For RawBuffer, an HLSL load operation may return an arbitrarily sized result,
 but we still constrain the LLVM intrinsic to return only up to 4 elements of a
 basic type. This means that larger loads are represented as a series of loads,
-which matches DXIL. Unlike in the `RawBufferLoad`_ operation, we do not need
+which matches DXIL. Unlike in the [RawBufferLoad][rawbufferload] operation, we do not need
 arguments for the mask/type size and alignment, since we can calculate these
 from the return type of the load during lowering.
 
 Note that RawBuffer loads represent either "structured" accesses, as in HLSL's
-StructuredBuffer<T>, or a "raw" access, as in HLSL's "ByteAddressBuffer". The
+StructuredBuffer\<T>, or a "raw" access, as in HLSL's "ByteAddressBuffer". The
 `%offset` parameter is only used for structured accesses, and *must* be
 `poison` for raw accesses.
 
-.. _RawBufferLoad: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#rawbufferload
-
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.load.rawbuffer``
    :header-rows: 1
 
@@ -430,75 +427,75 @@ StructuredBuffer<T>, or a "raw" access, as in HLSL's "ByteAddressBuffer". The
      - 2
      - ``i32``
      - Offset into the structure at the given index
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   ; float
-   %ret = call {float, i1}
-       @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_0_0_0t(
-           target("dx.RawBuffer", float, 0, 0, 0) %buffer,
-           i32 %index,
-           i32 0)
-   %ret = call {float, i1}
-       @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_i8_0_0_0t(
-           target("dx.RawBuffer", i8, 0, 0, 0) %buffer,
-           i32 %byte_offset,
-           i32 poison)
-
-   ; float4
-   %ret = call {<4 x float>, i1}
-       @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_v4f32_0_0_0t(
-           target("dx.RawBuffer", float, 0, 0, 0) %buffer,
-           i32 %index,
-           i32 0)
-   %ret = call {float, i1}
-       @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_i8_0_0_0t(
-           target("dx.RawBuffer", i8, 0, 0, 0) %buffer,
-           i32 %byte_offset,
-           i32 poison)
-
-   ; struct S0 { float4 f; int4 i; };
-   %ret = call {<4 x float>, i1}
-       @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
-           target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0, 0) %buffer,
-           i32 %index,
-           i32 0)
-   %ret = call {<4 x i32>, i1}
-       @llvm.dx.resource.load.rawbuffer.v4i32.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
-           target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0, 0) %buffer,
-           i32 %index,
-           i32 1)
-
-   ; struct Q { float4 f; int3 i; }
-   ; struct R { int z; S x; }
-   %ret = call {i32, i1}
-       @llvm.dx.resource.load.rawbuffer.i32(
-           target("dx.RawBuffer", {i32, {<4 x float>, <3 x i32>}}, 0, 0, 0)
-               %buffer, i32 %index, i32 0)
-   %ret = call {<4 x float>, i1}
-       @llvm.dx.resource.load.rawbuffer.i32(
-           target("dx.RawBuffer", {i32, {<4 x float>, <3 x i32>}}, 0, 0, 0)
-               %buffer, i32 %index, i32 4)
-   %ret = call {<3 x i32>, i1}
-       @llvm.dx.resource.load.rawbuffer.i32(
-           target("dx.RawBuffer", {i32, {<4 x float>, <3 x i32>}}, 0, 0, 0)
-               %buffer, i32 %index, i32 20)
-
-   ; byteaddressbuf.Load<int64_t4>
-   %ret = call {<4 x i64>, i1}
-       @llvm.dx.resource.load.rawbuffer.v4i64.tdx.RawBuffer_i8_0_0t(
-           target("dx.RawBuffer", i8, 0, 0, 0) %buffer,
-           i32 %byte_offset,
-           i32 poison)
-
-Stores
-------
+```llvm
+; float
+%ret = call {float, i1}
+    @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_0_0_0t(
+        target("dx.RawBuffer", float, 0, 0, 0) %buffer,
+        i32 %index,
+        i32 0)
+%ret = call {float, i1}
+    @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_i8_0_0_0t(
+        target("dx.RawBuffer", i8, 0, 0, 0) %buffer,
+        i32 %byte_offset,
+        i32 poison)
+
+; float4
+%ret = call {<4 x float>, i1}
+    @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_v4f32_0_0_0t(
+        target("dx.RawBuffer", float, 0, 0, 0) %buffer,
+        i32 %index,
+        i32 0)
+%ret = call {float, i1}
+    @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_i8_0_0_0t(
+        target("dx.RawBuffer", i8, 0, 0, 0) %buffer,
+        i32 %byte_offset,
+        i32 poison)
+
+; struct S0 { float4 f; int4 i; };
+%ret = call {<4 x float>, i1}
+    @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
+        target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0, 0) %buffer,
+        i32 %index,
+        i32 0)
+%ret = call {<4 x i32>, i1}
+    @llvm.dx.resource.load.rawbuffer.v4i32.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
+        target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0, 0) %buffer,
+        i32 %index,
+        i32 1)
+
+; struct Q { float4 f; int3 i; }
+; struct R { int z; S x; }
+%ret = call {i32, i1}
+    @llvm.dx.resource.load.rawbuffer.i32(
+        target("dx.RawBuffer", {i32, {<4 x float>, <3 x i32>}}, 0, 0, 0)
+            %buffer, i32 %index, i32 0)
+%ret = call {<4 x float>, i1}
+    @llvm.dx.resource.load.rawbuffer.i32(
+        target("dx.RawBuffer", {i32, {<4 x float>, <3 x i32>}}, 0, 0, 0)
+            %buffer, i32 %index, i32 4)
+%ret = call {<3 x i32>, i1}
+    @llvm.dx.resource.load.rawbuffer.i32(
+        target("dx.RawBuffer", {i32, {<4 x float>, <3 x i32>}}, 0, 0, 0)
+            %buffer, i32 %index, i32 20)
+
+; byteaddressbuf.Load<int64_t4>
+%ret = call {<4 x i64>, i1}
+    @llvm.dx.resource.load.rawbuffer.v4i64.tdx.RawBuffer_i8_0_0t(
+        target("dx.RawBuffer", i8, 0, 0, 0) %buffer,
+        i32 %byte_offset,
+        i32 poison)
+```
+
+### Stores
 
 *relevant types: Textures and Buffer*
 
-The `TextureStore`_, `BufferStore`_, and `RawBufferStore`_ DXIL operations
+The [TextureStore][texturestore], [BufferStore][bufferstore], and [RawBufferStore][rawbufferstore] DXIL operations
 write four components to a texture or a buffer. These include a mask argument
 that is used when fewer than 4 components are written, but notably this only
 takes on the contiguous x, xy, xyz, and xyzw values.
@@ -507,10 +504,6 @@ We define the LLVM store intrinsics to accept vectors when storing multiple
 components rather than using `undef` and a mask, but otherwise match the DXIL
 ops fairly closely.
 
-.. _TextureStore: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#texturestore
-.. _BufferStore: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#bufferstore
-.. _RawBufferStore: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#rawbufferstore
-
 For TypedBuffer, we only need one coordinate, and we must always write a vector
 since partial writes aren't possible. Similarly to the load operations
 described above, we handle 64-bit types specially and only handle 2-element
@@ -518,6 +511,7 @@ vectors rather than 4.
 
 Examples:
 
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.store.typedbuffer``
    :header-rows: 1
 
@@ -541,17 +535,18 @@ Examples:
      - 2
      - A 4- or 2-element vector of the type of the buffer
      - The data to store
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   call void @llvm.dx.resource.store.typedbuffer.tdx.Buffer_v4f32_1_0_0t(
-       target("dx.TypedBuffer", f32, 1, 0) %buf, i32 %index, <4 x f32> %data)
-   call void @llvm.dx.resource.store.typedbuffer.tdx.Buffer_v4f16_1_0_0t(
-       target("dx.TypedBuffer", f16, 1, 0) %buf, i32 %index, <4 x f16> %data)
-   call void @llvm.dx.resource.store.typedbuffer.tdx.Buffer_v2f64_1_0_0t(
-       target("dx.TypedBuffer", f64, 1, 0) %buf, i32 %index, <2 x f64> %data)
+```llvm
+call void @llvm.dx.resource.store.typedbuffer.tdx.Buffer_v4f32_1_0_0t(
+    target("dx.TypedBuffer", f32, 1, 0) %buf, i32 %index, <4 x f32> %data)
+call void @llvm.dx.resource.store.typedbuffer.tdx.Buffer_v4f16_1_0_0t(
+    target("dx.TypedBuffer", f16, 1, 0) %buf, i32 %index, <4 x f16> %data)
+call void @llvm.dx.resource.store.typedbuffer.tdx.Buffer_v2f64_1_0_0t(
+    target("dx.TypedBuffer", f64, 1, 0) %buf, i32 %index, <2 x f64> %data)
+```
 
 For Textures, the coordinates are a scalar for 1D textures and a vector of 2 or
 3 elements for the higher dimensional and array textures. Like TypedBuffer, a
@@ -560,6 +555,7 @@ read-modify-write of the full value.
 
 Examples:
 
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.store.texture``
    :header-rows: 1
 
@@ -583,26 +579,28 @@ Examples:
      - 2
      - Scalar or vector of the type of the texture
      - The data to store
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   call void @llvm.dx.resource.store.texture.tdx.Texture_v4f32_1_0_0_1t.i32.v4f32(
-       target("dx.Texture", <4 x float>, 1, 0, 0, 1) %tex,
-       i32 %coord, <4 x float> %data)
-   call void @llvm.dx.resource.store.texture.tdx.Texture_v4f32_1_0_0_2t.v2i32.v4f32(
-       target("dx.Texture", <4 x float>, 1, 0, 0, 2) %tex,
-       <2 x i32> %coords, <4 x float> %data)
-   call void @llvm.dx.resource.store.texture.tdx.Texture_v4f32_1_0_0_4t.v3i32.v4f32(
-       target("dx.Texture", <4 x float>, 1, 0, 0, 4) %tex,
-       <3 x i32> %coords, <4 x float> %data)
+```llvm
+call void @llvm.dx.resource.store.texture.tdx.Texture_v4f32_1_0_0_1t.i32.v4f32(
+    target("dx.Texture", <4 x float>, 1, 0, 0, 1) %tex,
+    i32 %coord, <4 x float> %data)
+call void @llvm.dx.resource.store.texture.tdx.Texture_v4f32_1_0_0_2t.v2i32.v4f32(
+    target("dx.Texture", <4 x float>, 1, 0, 0, 2) %tex,
+    <2 x i32> %coords, <4 x float> %data)
+call void @llvm.dx.resource.store.texture.tdx.Texture_v4f32_1_0_0_4t.v3i32.v4f32(
+    target("dx.Texture", <4 x float>, 1, 0, 0, 4) %tex,
+    <3 x i32> %coords, <4 x float> %data)
+```
 
 For RawBuffer, we need two indices and we accept scalars and vectors of 4 or
 fewer elements. Note that we do allow vectors of 4 64-bit elements here.
 
 Examples:
 
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.store.rawbuffer``
    :header-rows: 1
 
@@ -630,72 +628,70 @@ Examples:
      - 3
      - Scalar or vector
      - The data to store
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   ; float
-   call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f32_1_0_0t.f32(
-       target("dx.RawBuffer", float, 1, 0, 0) %buffer,
-       i32 %index, i32 0, float %data)
-   call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i8_1_0_0t.f32(
-       target("dx.RawBuffer", i8, 1, 0, 0) %buffer,
-       i32 %index, i32 0, float %data)
-
-   ; float4
-   call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_v4f32_1_0_0t.v4f32(
-       target("dx.RawBuffer", <4 x float>, 1, 0, 0) %buffer,
-       i32 %index, i32 0, <4 x float> %data)
-   call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i8_1_0_0t.v4f32(
-       target("dx.RawBuffer", i8, 1, 0, 0) %buffer,
-       i32 %index, i32 0, <4 x float> %data)
-
-   ; struct S0 { float4 f; int4 i; }
-   call void @llvm.dx.resource.store.rawbuffer.v4f32(
-       target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 1, 0, 0) %buffer,
-       i32 %index, i32 0, <4 x float> %data0)
-   call void @llvm.dx.resource.store.rawbuffer.v4i32(
-       target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 1, 0, 0) %buffer,
-       i32 %index, i32 16, <4 x i32> %data1)
-
-   ; struct Q { float4 f; int3 i; }
-   ; struct R { int z; S x; }
-   call void @llvm.dx.resource.store.rawbuffer.i32(
-       target("dx.RawBuffer", {i32, {<4 x float>, <3 x half>}}, 1, 0, 0)
-           %buffer,
-       i32 %index, i32 0, i32 %data0)
-   call void @llvm.dx.resource.store.rawbuffer.v4f32(
-       target("dx.RawBuffer", {i32, {<4 x float>, <3 x half>}}, 1, 0, 0)
-           %buffer,
-       i32 %index, i32 4, <4 x float> %data1)
-   call void @llvm.dx.resource.store.rawbuffer.v3f16(
-       target("dx.RawBuffer", {i32, {<4 x float>, <3 x half>}}, 1, 0, 0)
-           %buffer,
-       i32 %index, i32 20, <3 x half> %data2)
-
-   ; byteaddressbuf.Store<int64_t4>
-   call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i8_1_0_0t.v4f64(
-       target("dx.RawBuffer", i8, 1, 0, 0) %buffer,
-       i32 %index, i32 0, <4 x double> %data)
-
-Constant Buffer Loads
----------------------
+```llvm
+; float
+call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f32_1_0_0t.f32(
+    target("dx.RawBuffer", float, 1, 0, 0) %buffer,
+    i32 %index, i32 0, float %data)
+call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i8_1_0_0t.f32(
+    target("dx.RawBuffer", i8, 1, 0, 0) %buffer,
+    i32 %index, i32 0, float %data)
+
+; float4
+call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_v4f32_1_0_0t.v4f32(
+    target("dx.RawBuffer", <4 x float>, 1, 0, 0) %buffer,
+    i32 %index, i32 0, <4 x float> %data)
+call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i8_1_0_0t.v4f32(
+    target("dx.RawBuffer", i8, 1, 0, 0) %buffer,
+    i32 %index, i32 0, <4 x float> %data)
+
+; struct S0 { float4 f; int4 i; }
+call void @llvm.dx.resource.store.rawbuffer.v4f32(
+    target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 1, 0, 0) %buffer,
+    i32 %index, i32 0, <4 x float> %data0)
+call void @llvm.dx.resource.store.rawbuffer.v4i32(
+    target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 1, 0, 0) %buffer,
+    i32 %index, i32 16, <4 x i32> %data1)
+
+; struct Q { float4 f; int3 i; }
+; struct R { int z; S x; }
+call void @llvm.dx.resource.store.rawbuffer.i32(
+    target("dx.RawBuffer", {i32, {<4 x float>, <3 x half>}}, 1, 0, 0)
+        %buffer,
+    i32 %index, i32 0, i32 %data0)
+call void @llvm.dx.resource.store.rawbuffer.v4f32(
+    target("dx.RawBuffer", {i32, {<4 x float>, <3 x half>}}, 1, 0, 0)
+        %buffer,
+    i32 %index, i32 4, <4 x float> %data1)
+call void @llvm.dx.resource.store.rawbuffer.v3f16(
+    target("dx.RawBuffer", {i32, {<4 x float>, <3 x half>}}, 1, 0, 0)
+        %buffer,
+    i32 %index, i32 20, <3 x half> %data2)
+
+; byteaddressbuf.Store<int64_t4>
+call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i8_1_0_0t.v4f64(
+    target("dx.RawBuffer", i8, 1, 0, 0) %buffer,
+    i32 %index, i32 0, <4 x double> %data)
+```
+
+### Constant Buffer Loads
 
 *relevant types: CBuffers*
 
-The `CBufferLoadLegacy`_ operation, which despite the name is the only
+The [CBufferLoadLegacy][cbufferloadlegacy] operation, which despite the name is the only
 supported way to load from a cbuffer in any DXIL version, loads a single "row"
 of a cbuffer, which is exactly 16 bytes. The return value of the operation is
-represented by a `CBufRet`_ type, which has variants for 2 64-bit values, 4
+represented by a [CBufRet][cbufret] type, which has variants for 2 64-bit values, 4
 32-bit values, and 8 16-bit values.
 
 We represent these in LLVM IR with 3 separate operations, which return a
 2-element, 4-element, or 8-element struct respectively.
 
-.. _CBufferLoadLegacy: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#cbufferLoadLegacy
-.. _CBufRet: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#cbufferloadlegacy
-
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.load.cbufferrow.4``
    :header-rows: 1
 
@@ -715,20 +711,22 @@ We represent these in LLVM IR with 3 separate operations, which return a
      - 1
      - ``i32``
      - Index into the buffer
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   %ret = call {float, float, float, float}
-       @llvm.dx.resource.load.cbufferrow.4(
-           target("dx.CBuffer", target("dx.Layout", {float}, 4, 0)) %buffer,
-           i32 %index)
-   %ret = call {i32, i32, i32, i32}
-       @llvm.dx.resource.load.cbufferrow.4(
-           target("dx.CBuffer", target("dx.Layout", {i32}, 4, 0)) %buffer,
-           i32 %index)
-
+```llvm
+%ret = call {float, float, float, float}
+    @llvm.dx.resource.load.cbufferrow.4(
+        target("dx.CBuffer", target("dx.Layout", {float}, 4, 0)) %buffer,
+        i32 %index)
+%ret = call {i32, i32, i32, i32}
+    @llvm.dx.resource.load.cbufferrow.4(
+        target("dx.CBuffer", target("dx.Layout", {i32}, 4, 0)) %buffer,
+        i32 %index)
+```
+
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.load.cbufferrow.2``
    :header-rows: 1
 
@@ -748,20 +746,22 @@ Examples:
      - 1
      - ``i32``
      - Index into the buffer
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   %ret = call {double, double}
-       @llvm.dx.resource.load.cbufferrow.2(
-           target("dx.CBuffer", target("dx.Layout", {double}, 8, 0)) %buffer,
-           i32 %index)
-   %ret = call {i64, i64}
-       @llvm.dx.resource.load.cbufferrow.2(
-           target("dx.CBuffer", target("dx.Layout", {i64}, 4, 0)) %buffer,
-           i32 %index)
-
+```llvm
+%ret = call {double, double}
+    @llvm.dx.resource.load.cbufferrow.2(
+        target("dx.CBuffer", target("dx.Layout", {double}, 8, 0)) %buffer,
+        i32 %index)
+%ret = call {i64, i64}
+    @llvm.dx.resource.load.cbufferrow.2(
+        target("dx.CBuffer", target("dx.Layout", {i64}, 4, 0)) %buffer,
+        i32 %index)
+```
+
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.load.cbufferrow.8``
    :header-rows: 1
 
@@ -781,34 +781,34 @@ Examples:
      - 1
      - ``i32``
      - Index into the buffer
+```
 
 Examples:
 
-.. code-block:: llvm
-
-   %ret = call {half, half, half, half, half, half, half, half}
-       @llvm.dx.resource.load.cbufferrow.8(
-           target("dx.CBuffer", target("dx.Layout", {half}, 2, 0)) %buffer,
-           i32 %index)
-   %ret = call {i16, i16, i16, i16, i16, i16, i16, i16}
-       @llvm.dx.resource.load.cbufferrow.8(
-           target("dx.CBuffer", target("dx.Layout", {i16}, 2, 0)) %buffer,
-           i32 %index)
+```llvm
+%ret = call {half, half, half, half, half, half, half, half}
+    @llvm.dx.resource.load.cbufferrow.8(
+        target("dx.CBuffer", target("dx.Layout", {half}, 2, 0)) %buffer,
+        i32 %index)
+%ret = call {i16, i16, i16, i16, i16, i16, i16, i16}
+    @llvm.dx.resource.load.cbufferrow.8(
+        target("dx.CBuffer", target("dx.Layout", {i16}, 2, 0)) %buffer,
+        i32 %index)
+```
 
-Resource dimensions
--------------------
+### Resource dimensions
 
 *relevant types: Textures and Buffer*
 
-The `getDimensions`_ DXIL operation returns the dimensions of a texture or
-buffer resource. It returns a `Dimensions`_ type, which is a struct
-containing four ``i32`` values. The values in the struct represent the size
+The [getDimensions][getdimensions] DXIL operation returns the dimensions of a texture or
+buffer resource. It returns a [Dimensions][dimensions] type, which is a struct
+containing four `i32` values. The values in the struct represent the size
 of each dimension of the resource, and when aplicable the number of array
 elements or number of samples. The mapping is defined in the
-`getDimensions`_ documentation.
+[getDimensions][getdimensions] documentation.
 
 The LLVM IR representation of this operation has several forms
-depending on the resource type and the specific ``getDimensions`` query.
+depending on the resource type and the specific `getDimensions` query.
 The intrinsics return a scalar or anonymous struct with up to 4 `i32`
 elements. The intrinsic names include suffixes to indicate the number of
 elements in the return value. The suffix `.x` indicates a single `i32`
@@ -823,17 +823,18 @@ Intrinsics with `mip_level` argument and `.levels.` in their name are used
 for texture resources with multiple MIP levels. Their return
 struct includes an additional `i32` for the number of levels the resource has.
 
-.. code-block:: llvm
-
-   i32 @llvm.dx.resource.getdimensions.x( target("dx.*") handle )
-   {i32, i32} @llvm.dx.resource.getdimensions.xy( target("dx.*") handle )
-   {i32, i32, i32} @llvm.dx.resource.getdimensions.xyz( target("dx.*") handle )
-   {i32, i32} @llvm.dx.resource.getdimensions.levels.x( target("dx.*") handle, i32 mip_level )
-   {i32, i32, i32} @llvm.dx.resource.getdimensions.levels.xy( target("dx.*") handle, i32 mip_level )
-   {i32, i32, i32, i32} @llvm.dx.resource.getdimensions.levels.xyz( target("dx.*") handle, i32 mip_level )
-   {i32, i32, i32} @llvm.dx.resource.getdimensions.ms.xy( target("dx.*") handle )
-   {i32, i32, i32, i32} @llvm.dx.resource.getdimensions.ms.xyz( target("dx.*") handle )
-
+```llvm
+i32 @llvm.dx.resource.getdimensions.x( target("dx.*") handle )
+{i32, i32} @llvm.dx.resource.getdimensions.xy( target("dx.*") handle )
+{i32, i32, i32} @llvm.dx.resource.getdimensions.xyz( target("dx.*") handle )
+{i32, i32} @llvm.dx.resource.getdimensions.levels.x( target("dx.*") handle, i32 mip_level )
+{i32, i32, i32} @llvm.dx.resource.getdimensions.levels.xy( target("dx.*") handle, i32 mip_level )
+{i32, i32, i32, i32} @llvm.dx.resource.getdimensions.levels.xyz( target("dx.*") handle, i32 mip_level )
+{i32, i32, i32} @llvm.dx.resource.getdimensions.ms.xy( target("dx.*") handle )
+{i32, i32, i32, i32} @llvm.dx.resource.getdimensions.ms.xyz( target("dx.*") handle )
+```
+
+```{eval-rst}
 .. list-table:: ``@llvm.dx.resource.getdimensions.*``
    :header-rows: 1
 
@@ -853,33 +854,45 @@ struct includes an additional `i32` for the number of levels the resource has.
      - 1
      - ``i32``
      - MIP level for the requested dimensions.
+```
 
 Examples:
 
-.. code-block:: llvm
-
-  ; RWBuffer<float4>
-  %dim = call i32 @llvm.dx.resource.getdimensions.x(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %handle)
-
-  ; Texture2D
-  %0 = call {i32, i32} @llvm.dx.resource.getdimensions.xy(target("dx.Texture", ...) %tex2d)
-  %tex2d_width = extractvalue {i32, i32} %0, 0
-  %tex2d_height = extractvalue {i32, i32} %0, 1
-
-  ; Texture2DArray with levels
-  %1 = call {i32, i32, i32, i32} @llvm.dx.resource.getdimensions.levels.xyz(
-     target("dx.Texture", ...) %tex2darray, i32 1)
-  %tex2darray_width = extractvalue {i32, i32, i32, i32} %1, 0
-  %tex2darray_height = extractvalue {i32, i32, i32, i32} %1, 1
-  %tex2darray_elem_count = extractvalue {i32, i32, i32, i32} %1, 2
-  %tex2darray_levels_count = extractvalue {i32, i32, i32, i32} %1, 3
-
-  ; Texture2DMS
-  %2 = call {i32, i32, i32} @llvm.dx.resource.getdimensions.ms.xy(
-     target("dx.Texture", ...) %tex2dms)
-  %tex2dms_width = extractvalue {i32, i32, i32} %2, 0
-  %tex2dms_height = extractvalue {i32, i32, i32} %2, 1
-  %tex2dms_samples_count = extractvalue {i32, i32, i32} %2, 2
-
-.. _Dimensions: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#resource-operation-return-types
-.. _getDimensions: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#getdimensions
+```llvm
+; RWBuffer<float4>
+%dim = call i32 @llvm.dx.resource.getdimensions.x(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %handle)
+
+; Texture2D
+%0 = call {i32, i32} @llvm.dx.resource.getdimensions.xy(target("dx.Texture", ...) %tex2d)
+%tex2d_width = extractvalue {i32, i32} %0, 0
+%tex2d_height = extractvalue {i32, i32} %0, 1
+
+; Texture2DArray with levels
+%1 = call {i32, i32, i32, i32} @llvm.dx.resource.getdimensions.levels.xyz(
+   target("dx.Texture", ...) %tex2darray, i32 1)
+%tex2darray_width = extractvalue {i32, i32, i32, i32} %1, 0
+%tex2darray_height = extractvalue {i32, i32, i32, i32} %1, 1
+%tex2darray_elem_count = extractvalue {i32, i32, i32, i32} %1, 2
+%tex2darray_levels_count = extractvalue {i32, i32, i32, i32} %1, 3
+
+; Texture2DMS
+%2 = call {i32, i32, i32} @llvm.dx.resource.getdimensions.ms.xy(
+   target("dx.Texture", ...) %tex2dms)
+%tex2dms_width = extractvalue {i32, i32, i32} %2, 0
+%tex2dms_height = extractvalue {i32, i32, i32} %2, 1
+%tex2dms_samples_count = extractvalue {i32, i32, i32} %2, 2
+```
+
+[bufferload]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#bufferload
+[bufferstore]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#bufferstore
+[cbufferloadlegacy]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#cbufferLoadLegacy
+[cbufret]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#cbufferloadlegacy
+[checkaccessfullymapped]: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/checkaccessfullymapped
+[dimensions]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#resource-operation-return-types
+[dx.op.createhandle]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#resource-handles
+[getdimensions]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#getdimensions
+[rawbufferload]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#rawbufferload
+[rawbufferstore]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#rawbufferstore
+[resret]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#resource-operation-return-types
+[texturestore]: https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#texturestore
+
diff --git a/llvm/docs/DirectX/RootSignatures.md b/llvm/docs/DirectX/RootSignatures.md
index 9341100d80ff2..48c5f9e41717c 100644
--- a/llvm/docs/DirectX/RootSignatures.md
+++ b/llvm/docs/DirectX/RootSignatures.md
@@ -1,220 +1,179 @@
-===============
-Root Signatures
-===============
+# Root Signatures
 
+```{toctree}
+:hidden: true
+```
 
-.. toctree::
-   :hidden:
-
-Overview
-========
+## Overview
 
 A root signature is used to describe what resources a shader needs access to
 and how they're organized and bound in the pipeline. The DirectX Container
 (DXContainer) contains a root signature part (RTS0), which stores this
 information in a binary format. To assist with the construction of, and
 interaction with, a root signature is represented as metadata
-(``dx.rootsignatures`` ) in the LLVM IR. The metadata can then be converted to
+(`dx.rootsignatures` ) in the LLVM IR. The metadata can then be converted to
 its binary form, as defined in
-`llvm/include/llvm/llvm/Frontend/HLSL/RootSignatureMetadata.h
-<https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h>`_.
+[llvm/include/llvm/llvm/Frontend/HLSL/RootSignatureMetadata.h](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h).
 This document serves as a reference for the metadata representation of a root
 signature for users to interface with.
 
-Metadata Representation
-=======================
+## Metadata Representation
 
 Consider the reference root signature, then the following sections describe the
 metadata representation of this root signature and the corresponding operands.
 
-.. code-block:: HLSL
-
-  RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),
-  RootConstants(b0, space = 1, num32Constants = 3),
-  CBV(b1, flags = 0),
-  StaticSampler(
-    filter = FILTER_MIN_MAG_POINT_MIP_LINEAR,
-    addressU = TEXTURE_ADDRESS_BORDER,
-  ),
-  DescriptorTable(
-    visibility = VISIBILITY_ALL,
-    SRV(t0, flags = DATA_STATIC_WHILE_SET_AT_EXECUTE),
-    UAV(
-      numDescriptors = 5, u1, space = 10, offset = 5,
-      flags = DATA_VOLATILE
-    )
+```HLSL
+RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),
+RootConstants(b0, space = 1, num32Constants = 3),
+CBV(b1, flags = 0),
+StaticSampler(
+  filter = FILTER_MIN_MAG_POINT_MIP_LINEAR,
+  addressU = TEXTURE_ADDRESS_BORDER,
+),
+DescriptorTable(
+  visibility = VISIBILITY_ALL,
+  SRV(t0, flags = DATA_STATIC_WHILE_SET_AT_EXECUTE),
+  UAV(
+    numDescriptors = 5, u1, space = 10, offset = 5,
+    flags = DATA_VOLATILE
   )
+)
+```
 
-.. note::
-
-  A root signature does not necessarily have a unique metadata representation.
-  Futher, a malformed root signature can be represented in the metadata format,
-  (eg. mixing Sampler and non-Sampler descriptor ranges), and so it is the
-  user's responsibility to verify that it is a well-formed root signature.
+:::{note}
+A root signature does not necessarily have a unique metadata representation.
+Futher, a malformed root signature can be represented in the metadata format,
+(eg. mixing Sampler and non-Sampler descriptor ranges), and so it is the
+user's responsibility to verify that it is a well-formed root signature.
+:::
 
-Named Root Signature Table
-==========================
+## Named Root Signature Table
 
-.. code-block:: LLVM
+```LLVM
+!dx.rootsignatures = !{!0}
+```
 
-  !dx.rootsignatures = !{!0}
-
-A named metadata node, ``dx.rootsignatures``` is used to identify the root
+A named metadata node, `` dx.rootsignatures` `` is used to identify the root
 signature table. The table itself is a list of references to function/root
 signature pairs.
 
-Function/Root Signature Pair
-============================
-
-.. code-block:: LLVM
+## Function/Root Signature Pair
 
-  !1 = !{ptr @main, !2, i32 2 }
+```LLVM
+!1 = !{ptr @main, !2, i32 2 }
+```
 
 The function/root signature associates a function (the first operand) with a
 reference to a root signature (the second operand). The root signature version
 (the third operand) used for validation logic and binary format follows.
 
-Root Signature
-==============
+## Root Signature
 
-.. code-block:: LLVM
-
-  !2 = !{ !3, !4, !5, !6, !7 }
+```LLVM
+!2 = !{ !3, !4, !5, !6, !7 }
+```
 
 The root signature itself simply consists of a list of references to its root
 signature elements.
 
-Root Signature Element
-======================
+## Root Signature Element
 
 A root signature element is identified by the first operand, which is a string.
 The following root signature elements are defined:
 
-================= ======================
-Identifier String Root Signature Element
-================= ======================
-"RootFlags"       Root Flags
-"RootConstants"   Root Constants
-"RootCBV"         Root Descriptor
-"RootSRV"         Root Descriptor
-"RootUAV"         Root Descriptor
-"StaticSampler"   Static Sampler
-"DescriptorTable" Descriptor Table
-================= ======================
+| Identifier String | Root Signature Element |
+| ----------------- | ---------------------- |
+| "RootFlags"       | Root Flags             |
+| "RootConstants"   | Root Constants         |
+| "RootCBV"         | Root Descriptor        |
+| "RootSRV"         | Root Descriptor        |
+| "RootUAV"         | Root Descriptor        |
+| "StaticSampler"   | Static Sampler         |
+| "DescriptorTable" | Descriptor Table       |
 
 Below is listed the representation for each type of root signature element.
 
-Root Flags
-==========
-
-.. code-block:: LLVM
-
-  !3 = { !"RootFlags", i32 1 }
+## Root Flags
 
-======================= ====
-Description             Type
-======================= ====
-`Root Signature Flags`_ i32
-======================= ====
+```LLVM
+!3 = { !"RootFlags", i32 1 }
+```
 
-.. _Root Signature Flags: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_root_signature_flags
+| Description                                  | Type |
+| -------------------------------------------- | ---- |
+| [Root Signature Flags][root signature flags] | i32  |
 
-Root Constants
-==============
+## Root Constants
 
-.. code-block:: LLVM
+```LLVM
+!4 = { !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
+```
 
-  !4 = { !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
+| Description                            | Type |
+| -------------------------------------- | ---- |
+| [Shader Visibility][shader visibility] | i32  |
+| Shader Register                        | i32  |
+| Register Space                         | i32  |
+| Number 32-bit Values                   | i32  |
 
-==================== ====
-Description          Type
-==================== ====
-`Shader Visibility`_ i32
-Shader Register      i32
-Register Space       i32
-Number 32-bit Values i32
-==================== ====
-
-.. _Shader Visibility: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shader_visibility
-
-Root Descriptor
-===============
+## Root Descriptor
 
 As noted in the table above, the first operand will denote the type of
 root descriptor.
 
-.. code-block:: LLVM
-
-  !5 = { !"RootCBV", i32 0, i32 1, i32 0, i32 0 }
-
-======================== ====
-Description              Type
-======================== ====
-`Shader Visibility`_     i32
-Shader Register          i32
-Register Space           i32
-`Root Descriptor Flags`_ i32
-======================== ====
-
-.. _Root Descriptor Flags: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_root_descriptor_flags
-
-Static Sampler
-==============
-
-.. code-block:: LLVM
-
-  !6 = !{ !"StaticSampler", i32 1, i32 4, ... }; remaining operands omitted for space
-
-==================== =====
-Description          Type
-==================== =====
-`Filter`_            i32
-`AddressU`_          i32
-`AddressV`_          i32
-`AddressW`_          i32
-MipLODBias           float
-MaxAnisotropy        i32
-`ComparisonFunc`_    i32
-`BorderColor`_       i32
-MinLOD               float
-MaxLOD               float
-ShaderRegister       i32
-RegisterSpace        i32
-`Shader Visibility`_ i32
-==================== =====
-
-.. _Filter: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_filter
-.. _AddressU: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
-.. _AddressV: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
-.. _AddressW: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
-.. _ComparisonFunc: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_comparison_func>
-.. _BorderColor: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_static_border_color>
-
-Descriptor Table
-================
+```LLVM
+!5 = { !"RootCBV", i32 0, i32 1, i32 0, i32 0 }
+```
+
+| Description                                    | Type |
+| ---------------------------------------------- | ---- |
+| [Shader Visibility][shader visibility]         | i32  |
+| Shader Register                                | i32  |
+| Register Space                                 | i32  |
+| [Root Descriptor Flags][root descriptor flags] | i32  |
+
+## Static Sampler
+
+```LLVM
+!6 = !{ !"StaticSampler", i32 1, i32 4, ... }; remaining operands omitted for space
+```
+
+| Description                            | Type  |
+| -------------------------------------- | ----- |
+| [Filter][filter]                       | i32   |
+| [AddressU][addressu]                   | i32   |
+| [AddressV][addressv]                   | i32   |
+| [AddressW][addressw]                   | i32   |
+| MipLODBias                             | float |
+| MaxAnisotropy                          | i32   |
+| [ComparisonFunc][comparisonfunc]       | i32   |
+| [BorderColor][bordercolor]             | i32   |
+| MinLOD                                 | float |
+| MaxLOD                                 | float |
+| ShaderRegister                         | i32   |
+| RegisterSpace                          | i32   |
+| [Shader Visibility][shader visibility] | i32   |
+
+## Descriptor Table
 
 A descriptor table consists of a visibility and the remaining operands are a
 list of references to its descriptor ranges.
 
-.. note::
-
-  The term Descriptor Table Clause is synonymous with Descriptor Range when
-  referencing the implementation details.
-
-.. code-block:: LLVM
+:::{note}
+The term Descriptor Table Clause is synonymous with Descriptor Range when
+referencing the implementation details.
+:::
 
-  !7 = { !"DescriptorTable", i32 0, !8, !9 }
+```LLVM
+!7 = { !"DescriptorTable", i32 0, !8, !9 }
+```
 
-========================= ================
-Description               Type
-========================= ================
-`Shader Visibility`_      i32
-Descriptor Range Elements Descriptor Range
-========================= ================
+| Description                            | Type             |
+| -------------------------------------- | ---------------- |
+| [Shader Visibility][shader visibility] | i32              |
+| Descriptor Range Elements              | Descriptor Range |
 
-
-Descriptor Range
-================
+## Descriptor Range
 
 Similar to a root descriptor, the first operand will denote the type of
 descriptor range. It is one of the following types:
@@ -224,20 +183,28 @@ descriptor range. It is one of the following types:
 - "UAV"
 - "Sampler"
 
-.. code-block:: LLVM
-
-  !8 = !{ !"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4 }
-  !9 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 2 }
-
-============================== ====
-Description                    Type
-============================== ====
-Number of Descriptors in Range i32
-Shader Register                i32
-Register Space                 i32
-`Offset`_                      i32
-`Descriptor Range Flags`_      i32
-============================== ====
+```LLVM
+!8 = !{ !"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4 }
+!9 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 2 }
+```
+
+| Description                                      | Type |
+| ------------------------------------------------ | ---- |
+| Number of Descriptors in Range                   | i32  |
+| Shader Register                                  | i32  |
+| Register Space                                   | i32  |
+| [Offset][offset]                                 | i32  |
+| [Descriptor Range Flags][descriptor range flags] | i32  |
+
+[addressu]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
+[addressv]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
+[addressw]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
+[bordercolor]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_static_border_color>
+[comparisonfunc]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_comparison_func>
+[descriptor range flags]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_descriptor_range_flags
+[filter]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_filter
+[offset]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_descriptor_range
+[root descriptor flags]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_root_descriptor_flags
+[root signature flags]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_root_signature_flags
+[shader visibility]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shader_visibility
 
-.. _Offset: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_descriptor_range
-.. _Descriptor Range Flags: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_descriptor_range_flags
diff --git a/llvm/docs/GlobalISel/GMIR.md b/llvm/docs/GlobalISel/GMIR.md
index 0364ab0937569..e2cf2c7e4a6ff 100644
--- a/llvm/docs/GlobalISel/GMIR.md
+++ b/llvm/docs/GlobalISel/GMIR.md
@@ -1,86 +1,81 @@
-.. _gmir:
-
-Generic Machine IR
-==================
+(gmir)=
 
+# Generic Machine IR
 
 Generic MIR (gMIR) is an intermediate representation that shares the same data
-structures as :doc:`MachineIR (MIR) <../MIRLangRef>` but has more relaxed
+structures as {doc}`MachineIR (MIR) <../MIRLangRef>` but has more relaxed
 constraints. As the compilation pipeline proceeds, these constraints are
 gradually tightened until gMIR has become MIR.
 
 The rest of this document will assume that you are familiar with the concepts
-in :doc:`MachineIR (MIR) <../MIRLangRef>` and will highlight the differences
+in {doc}`MachineIR (MIR) <../MIRLangRef>` and will highlight the differences
 between MIR and gMIR.
 
-.. _gmir-instructions:
-
-Generic Machine Instructions
-----------------------------
+(gmir-instructions)=
 
-.. note::
+## Generic Machine Instructions
 
-  This section expands on :ref:`mir-instructions` from the MIR Language
-  Reference.
+:::{note}
+This section expands on {ref}`mir-instructions` from the MIR Language
+Reference.
+:::
 
 Whereas MIR deals largely in Target Instructions and only has a small set of
-target-independent opcodes such as ``COPY``, ``PHI``, and ``REG_SEQUENCE``,
-gMIR defines a rich collection of ``Generic Opcodes`` which are target
+target-independent opcodes such as `COPY`, `PHI`, and `REG_SEQUENCE`,
+gMIR defines a rich collection of `Generic Opcodes` which are target
 independent and describe operations which are typically supported by targets.
-One example is ``G_ADD`` which is the generic opcode for an integer addition.
+One example is `G_ADD` which is the generic opcode for an integer addition.
 More information on each of the generic opcodes can be found at
-:doc:`GenericOpcode`.
+{doc}`GenericOpcode`.
 
-The ``MachineIRBuilder`` class wraps the ``MachineInstrBuilder`` and provides
+The `MachineIRBuilder` class wraps the `MachineInstrBuilder` and provides
 a convenient way to create these generic instructions.
 
-.. _gmir-gvregs:
-
-Generic Virtual Registers
--------------------------
+(gmir-gvregs)=
 
-.. note::
+## Generic Virtual Registers
 
-  This section expands on :ref:`mir-registers` from the MIR Language
-  Reference.
+:::{note}
+This section expands on {ref}`mir-registers` from the MIR Language
+Reference.
+:::
 
 Generic virtual registers are like virtual registers but they are not assigned a
 Register Class constraint. Instead, generic virtual registers have less strict
-constraints starting with a :ref:`gmir-llt` and then further constrained to a
-:ref:`gmir-regbank`. Eventually they will be constrained to a register class
+constraints starting with a {ref}`gmir-llt` and then further constrained to a
+{ref}`gmir-regbank`. Eventually they will be constrained to a register class
 at which point they become normal virtual registers.
 
 Generic virtual registers can be used with all the virtual register API's
-provided by ``MachineRegisterInfo``. In particular, the def-use chain API's can
+provided by `MachineRegisterInfo`. In particular, the def-use chain API's can
 be used without needing to distinguish them from non-generic virtual registers.
 
 For simplicity, most generic instructions only accept virtual registers (both
 generic and non-generic). There are some exceptions to this but in general:
 
-* instead of immediates, they use a generic virtual register defined by an
+- instead of immediates, they use a generic virtual register defined by an
   instruction that materializes the immediate value (see
-  :ref:`irtranslator-constants`). Typically this is a G_CONSTANT or a
+  {ref}`irtranslator-constants`). Typically this is a G_CONSTANT or a
   G_FCONSTANT. One example of an exception to this rule is G_SEXT_INREG where
   having an immediate is mandatory.
-* instead of physical register, they use a generic virtual register that is
-  either defined by a ``COPY`` from the physical register or used by a ``COPY``
+- instead of physical register, they use a generic virtual register that is
+  either defined by a `COPY` from the physical register or used by a `COPY`
   that defines the physical register.
 
-.. admonition:: Historical Note
+:::{admonition} Historical Note
+We started with an alternative representation, where MRI tracks a size for
+each generic virtual register, and instructions have lists of types.
+That had two flaws: the type and size are redundant, and there was no generic
+way of getting a given operand's type (as there was no 1:1 mapping between
+instruction types and operands).
+We considered putting the type in some variant of MCInstrDesc instead:
+See [PR26576](https://llvm.org/PR26576): [GlobalISel] Generic MachineInstrs
+need a type but this increases the memory footprint of the related objects
+:::
 
-  We started with an alternative representation, where MRI tracks a size for
-  each generic virtual register, and instructions have lists of types.
-  That had two flaws: the type and size are redundant, and there was no generic
-  way of getting a given operand's type (as there was no 1:1 mapping between
-  instruction types and operands).
-  We considered putting the type in some variant of MCInstrDesc instead:
-  See `PR26576 <https://llvm.org/PR26576>`_: [GlobalISel] Generic MachineInstrs
-  need a type but this increases the memory footprint of the related objects
+(gmir-regbank)=
 
-.. _gmir-regbank:
-
-Register Bank
--------------
+## Register Bank
 
 A Register Bank is a set of register classes defined by the target. This
 definition is rather loose so let's talk about what they can achieve.
@@ -121,102 +116,101 @@ To give some concrete examples:
 
 AArch64
 
-  AArch64 has three main banks. GPR for integer operations, FPR for floating
-  point and also for the NEON vector instruction set. The third is CCR and
-  describes the condition code register used for predication.
+> AArch64 has three main banks. GPR for integer operations, FPR for floating
+> point and also for the NEON vector instruction set. The third is CCR and
+> describes the condition code register used for predication.
 
 MIPS
 
-  MIPS has five main banks of which many programs only really use one or two.
-  GPR is the general purpose bank for integer operations. FGR or CP1 is for
-  the floating point operations as well as the MSA vector instructions and a
-  few other application specific extensions. CP0 is for system registers and
-  few programs will use it. CP2 and CP3 are for any application specific
-  coprocessors that may be present in the chip. Arguably, there is also a sixth
-  for the LO and HI registers but these are only used for the result of a few
-  operations and it's of questionable value to model distinctly from GPR.
+> MIPS has five main banks of which many programs only really use one or two.
+> GPR is the general purpose bank for integer operations. FGR or CP1 is for
+> the floating point operations as well as the MSA vector instructions and a
+> few other application specific extensions. CP0 is for system registers and
+> few programs will use it. CP2 and CP3 are for any application specific
+> coprocessors that may be present in the chip. Arguably, there is also a sixth
+> for the LO and HI registers but these are only used for the result of a few
+> operations and it's of questionable value to model distinctly from GPR.
 
 X86
 
-  X86 can be seen as having 3 main banks: general-purpose, x87, and
-  vector (which could be further split into a bank per domain for single vs
-  double precision instructions). It also looks like there's arguably a few
-  more potential banks such as one for the AVX512 Mask Registers.
+> X86 can be seen as having 3 main banks: general-purpose, x87, and
+> vector (which could be further split into a bank per domain for single vs
+> double precision instructions). It also looks like there's arguably a few
+> more potential banks such as one for the AVX512 Mask Registers.
 
 Register banks are described by a target-provided API,
-:ref:`RegisterBankInfo <api-registerbankinfo>`.
+{ref}`RegisterBankInfo <api-registerbankinfo>`.
 
-.. _gmir-llt:
+(gmir-llt)=
 
-Low Level Type
---------------
+## Low Level Type
 
 Additionally, every generic virtual register has a type, represented by an
-instance of the ``LLT`` class.
+instance of the `LLT` class.
 
-Like ``EVT``/``MVT``/``Type``, it has no distinction between unsigned and signed
-integer types.  Furthermore, it also has no distinction between integer and
+Like `EVT`/`MVT`/`Type`, it has no distinction between unsigned and signed
+integer types. Furthermore, it also has no distinction between integer and
 floating-point types: it mainly conveys absolutely necessary information, such
 as size and number of vector lanes:
 
-* ``sN`` for scalars
-* ``pN`` for pointers
-* ``<N x sM>`` for vectors
-
-``LLT`` is intended to replace the usage of ``EVT`` in SelectionDAG.
-
-Here are some LLT examples and their ``EVT`` and ``Type`` equivalents:
-
-   =============  =========  ======================================
-   LLT            EVT        IR Type
-   =============  =========  ======================================
-   ``s1``         ``i1``     ``i1``
-   ``s8``         ``i8``     ``i8``
-   ``s8``         ``i8``     ``b8`` [#byte-as-integer]_
-   ``s32``        ``i32``    ``i32``
-   ``s32``        ``i32``    ``b32`` [#byte-as-integer]_
-   ``s32``        ``f32``    ``float``
-   ``s17``        ``i17``    ``i17``
-   ``s16``        N/A        ``{i8, i8}`` [#abi-dependent]_
-   ``s32``        N/A        ``[4 x i8]`` [#abi-dependent]_
-   ``p0``         ``iPTR``   ``i8*``, ``i32*``, ``%opaque*``
-   ``p2``         ``iPTR``   ``i8 addrspace(2)*``
-   ``<4 x s32>``  ``v4f32``  ``<4 x float>``
-   ``<4 x s8>``   ``v4i8``   ``<4 x b8>`` [#byte-as-integer]_
-   ``s64``        ``v1f64``  ``<1 x double>``
-   ``<3 x s32>``  ``v3i32``  ``<3 x i32>``
-   =============  =========  ======================================
-
+- `sN` for scalars
+- `pN` for pointers
+- `<N x sM>` for vectors
+
+`LLT` is intended to replace the usage of `EVT` in SelectionDAG.
+
+Here are some LLT examples and their `EVT` and `Type` equivalents:
+
+> | LLT         | EVT     | IR Type                       |
+> | ----------- | ------- | ----------------------------- |
+> | `s1`        | `i1`    | `i1`                          |
+> | `s8`        | `i8`    | `i8`                          |
+> | `s8`        | `i8`    | `b8` [^byte-as-integer]       |
+> | `s32`       | `i32`   | `i32`                         |
+> | `s32`       | `i32`   | `b32` [^byte-as-integer]      |
+> | `s32`       | `f32`   | `float`                       |
+> | `s17`       | `i17`   | `i17`                         |
+> | `s16`       | N/A     | `{i8, i8}` [^abi-dependent]   |
+> | `s32`       | N/A     | `[4 x i8]` [^abi-dependent]   |
+> | `p0`        | `iPTR`  | `i8*`, `i32*`, `%opaque*`     |
+> | `p2`        | `iPTR`  | `i8 addrspace(2)*`            |
+> | `<4 x s32>` | `v4f32` | `<4 x float>`                 |
+> | `<4 x s8>`  | `v4i8`  | `<4 x b8>` [^byte-as-integer] |
+> | `s64`       | `v1f64` | `<1 x double>`                |
+> | `<3 x s32>` | `v3i32` | `<3 x i32>`                   |
 
 Rationale: instructions already encode a specific interpretation of types
-(e.g., ``add`` vs. ``fadd``, or ``sdiv`` vs. ``udiv``).  Also encoding that
+(e.g., `add` vs. `fadd`, or `sdiv` vs. `udiv`). Also encoding that
 information in the type system requires introducing bitcast with no real
 advantage for the selector.
 
-Pointer types are distinguished by address space.  This matches IR, as opposed
+Pointer types are distinguished by address space. This matches IR, as opposed
 to SelectionDAG where address space is an attribute on operations.
 This representation better supports pointers having different sizes depending
 on their addressspace.
 
-.. note::
+::::{note}
+
+:::{caution}
+Is this still true? I thought we'd removed the 1-element vector concept.
+Hypothetically, it could be distinct from a scalar but I think we failed to
+find a real occurrence.
+:::
 
-  .. caution::
+Currently, LLT requires at least 2 elements in vectors, but some targets have
+the concept of a '1-element vector'. Representing them as their underlying
+scalar type is a nice simplification.
+::::
 
-    Is this still true? I thought we'd removed the 1-element vector concept.
-    Hypothetically, it could be distinct from a scalar but I think we failed to
-    find a real occurrence.
+```{rubric} Footnotes
+```
 
-  Currently, LLT requires at least 2 elements in vectors, but some targets have
-  the concept of a '1-element vector'.  Representing them as their underlying
-  scalar type is a nice simplification.
+[^abi-dependent]: This mapping is ABI dependent. Here we've assumed no additional padding is required.
 
-.. rubric:: Footnotes
+[^byte-as-integer]: The {ref}`byte type <t_byte>` `bN` is translated as the
+    equi-sized integer scalar `sN`. See {ref}`irtranslator-byte-type`.
 
-.. [#abi-dependent] This mapping is ABI dependent. Here we've assumed no additional padding is required.
-.. [#byte-as-integer] The :ref:`byte type <t_byte>` ``bN`` is translated as the
-   equi-sized integer scalar ``sN``. See :ref:`irtranslator-byte-type`.
+## Generic Opcode Reference
 
-Generic Opcode Reference
-------------------------
+The Generic Opcodes that are available are described at {doc}`GenericOpcode`.
 
-The Generic Opcodes that are available are described at :doc:`GenericOpcode`.
diff --git a/llvm/docs/GlobalISel/GenericOpcode.md b/llvm/docs/GlobalISel/GenericOpcode.md
index d2552b6c3a3f3..de6251167fdc4 100644
--- a/llvm/docs/GlobalISel/GenericOpcode.md
+++ b/llvm/docs/GlobalISel/GenericOpcode.md
@@ -1,293 +1,275 @@
-
-.. _gmir-opcodes:
-
-Generic Opcodes
-===============
-
-
-.. note::
-
-  This documentation does not yet fully account for vectors. Many of the
-  scalar/integer/floating-point operations can also take vectors.
-
-Constants
----------
-
-G_IMPLICIT_DEF
-^^^^^^^^^^^^^^
+---
+substitutions:
+  all_g_atomicrmw: |-
+    G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD,
+    G_ATOMICRMW_SUB, G_ATOMICRMW_AND,
+    G_ATOMICRMW_NAND, G_ATOMICRMW_OR,
+    G_ATOMICRMW_XOR, G_ATOMICRMW_MAX,
+    G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
+    G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD,
+    G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX,
+    G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAXIMUM,
+    G_ATOMICRMW_FMINIMUM, G_ATOMICRMW_UINC_WRAP,
+    G_ATOMICRMW_UDEC_WRAP, G_ATOMICRMW_USUB_COND,
+    G_ATOMICRMW_USUB_SAT
+---
+
+(gmir-opcodes)=
+
+# Generic Opcodes
+
+:::{note}
+This documentation does not yet fully account for vectors. Many of the
+scalar/integer/floating-point operations can also take vectors.
+:::
+
+## Constants
+
+### G_IMPLICIT_DEF
 
 An undefined value.
 
-.. code-block:: none
+```none
+%0:_(s32) = G_IMPLICIT_DEF
+```
 
-  %0:_(s32) = G_IMPLICIT_DEF
-
-G_CONSTANT
-^^^^^^^^^^
+### G_CONSTANT
 
 An integer constant.
 
-.. code-block:: none
-
-  %0:_(s32) = G_CONSTANT i32 1
+```none
+%0:_(s32) = G_CONSTANT i32 1
+```
 
-G_FCONSTANT
-^^^^^^^^^^^
+### G_FCONSTANT
 
 A floating point constant.
 
-.. code-block:: none
-
-  %0:_(s32) = G_FCONSTANT float 1.0
+```none
+%0:_(s32) = G_FCONSTANT float 1.0
+```
 
-G_FRAME_INDEX
-^^^^^^^^^^^^^
+### G_FRAME_INDEX
 
 The address of an object in the stack frame.
 
-.. code-block:: none
+```none
+%1:_(p0) = G_FRAME_INDEX %stack.0.ptr0
+```
 
-  %1:_(p0) = G_FRAME_INDEX %stack.0.ptr0
-
-G_GLOBAL_VALUE
-^^^^^^^^^^^^^^
+### G_GLOBAL_VALUE
 
 The address of a global value.
 
-.. code-block:: none
-
-  %0(p0) = G_GLOBAL_VALUE @var_local
+```none
+%0(p0) = G_GLOBAL_VALUE @var_local
+```
 
-G_PTRAUTH_GLOBAL_VALUE
-^^^^^^^^^^^^^^^^^^^^^^
+### G_PTRAUTH_GLOBAL_VALUE
 
 The signed address of a global value. Operands: address to be signed (pointer),
 key (32-bit imm), address for address discrimination (zero if not needed) and
 an extra discriminator (64-bit imm).
 
-.. code-block:: none
-
-  %0:_(p0) = G_PTRAUTH_GLOBAL_VALUE %1:_(p0), s32, %2:_(p0), s64
+```none
+%0:_(p0) = G_PTRAUTH_GLOBAL_VALUE %1:_(p0), s32, %2:_(p0), s64
+```
 
-G_BLOCK_ADDR
-^^^^^^^^^^^^
+### G_BLOCK_ADDR
 
 The address of a basic block.
 
-.. code-block:: none
+```none
+%0:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
+```
 
-  %0:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
-
-G_CONSTANT_POOL
-^^^^^^^^^^^^^^^
+### G_CONSTANT_POOL
 
 The address of an object in the constant pool.
 
-.. code-block:: none
-
-  %0:_(p0) = G_CONSTANT_POOL %const.0
+```none
+%0:_(p0) = G_CONSTANT_POOL %const.0
+```
 
-Integer Extension and Truncation
---------------------------------
+## Integer Extension and Truncation
 
-G_ANYEXT
-^^^^^^^^
+### G_ANYEXT
 
 Extend the underlying scalar type of an operation, leaving the high bits
 unspecified.
 
-.. code-block:: none
-
-  %1:_(s32) = G_ANYEXT %0:_(s16)
+```none
+%1:_(s32) = G_ANYEXT %0:_(s16)
+```
 
-G_SEXT
-^^^^^^
+### G_SEXT
 
 Sign extend the underlying scalar type of an operation, copying the sign bit
 into the newly-created space.
 
-.. code-block:: none
+```none
+%1:_(s32) = G_SEXT %0:_(s16)
+```
 
-  %1:_(s32) = G_SEXT %0:_(s16)
-
-G_SEXT_INREG
-^^^^^^^^^^^^
+### G_SEXT_INREG
 
 Sign extend the value from an arbitrary bit position, copying the sign bit
 into all bits above it. This is equivalent to a shl + ashr pair with an
-appropriate shift amount. $sz is an immediate (MachineOperand::isImm()
+appropriate shift amount. \$sz is an immediate (MachineOperand::isImm()
 returns true) to allow targets to have some bitwidths legal and others
 lowered. This opcode is particularly useful if the target has sign-extension
 instructions that are cheaper than the constituent shifts as the optimizer is
 able to make decisions on whether it's better to hang on to the G_SEXT_INREG
 or to lower it and optimize the individual shifts.
 
-.. code-block:: none
-
-  %1:_(s32) = G_SEXT_INREG %0:_(s32), 16
+```none
+%1:_(s32) = G_SEXT_INREG %0:_(s32), 16
+```
 
-G_ZEXT
-^^^^^^
+### G_ZEXT
 
 Zero extend the underlying scalar type of an operation, putting zero bits
 into the newly-created space.
 
-.. code-block:: none
-
-  %1:_(s32) = G_ZEXT %0:_(s16)
+```none
+%1:_(s32) = G_ZEXT %0:_(s16)
+```
 
-G_TRUNC
-^^^^^^^
+### G_TRUNC
 
 Truncate the underlying scalar type of an operation. This is equivalent to
 G_EXTRACT for scalar types, but acts elementwise on vectors.
 
-.. code-block:: none
+```none
+%1:_(s16) = G_TRUNC %0:_(s32)
+```
 
-  %1:_(s16) = G_TRUNC %0:_(s32)
-
-G_TRUNC_SSAT_S
-^^^^^^^^^^^^^^
+### G_TRUNC_SSAT_S
 
 Truncate a signed input to a signed result with saturation.
 
-.. code-block:: none
-
-  %1:_(s16) = G_TRUNC_SSAT_S %0:_(s32)
+```none
+%1:_(s16) = G_TRUNC_SSAT_S %0:_(s32)
+```
 
-G_TRUNC_SSAT_U
-^^^^^^^^^^^^^^
+### G_TRUNC_SSAT_U
 
 Truncate a signed input to an unsigned result with saturation.
 
-.. code-block:: none
-
-  %1:_(s16) = G_TRUNC_SSAT_U %0:_(s32)
+```none
+%1:_(s16) = G_TRUNC_SSAT_U %0:_(s32)
+```
 
-G_TRUNC_USAT_U
-^^^^^^^^^^^^^^
+### G_TRUNC_USAT_U
 
 Truncate a unsigned input to an unsigned result with saturation.
 
-.. code-block:: none
+```none
+%1:_(s16) = G_TRUNC_USAT_U %0:_(s32)
+```
 
-  %1:_(s16) = G_TRUNC_USAT_U %0:_(s32)
+## Type Conversions
 
-Type Conversions
-----------------
-
-G_INTTOPTR
-^^^^^^^^^^
+### G_INTTOPTR
 
 Convert an integer to a pointer.
 
-.. code-block:: none
-
-  %1:_(p0) = G_INTTOPTR %0:_(s32)
+```none
+%1:_(p0) = G_INTTOPTR %0:_(s32)
+```
 
-G_PTRTOINT
-^^^^^^^^^^
+### G_PTRTOINT
 
 Convert a pointer to an integer.
 
-.. code-block:: none
-
-  %1:_(s32) = G_PTRTOINT %0:_(p0)
+```none
+%1:_(s32) = G_PTRTOINT %0:_(p0)
+```
 
-G_BITCAST
-^^^^^^^^^
+### G_BITCAST
 
 Reinterpret a value as a new type. This is usually done without
 changing any bits but this is not always the case due a subtlety in the
-definition of the :ref:`LLVM-IR Bitcast Instruction <i_bitcast>`. It
+definition of the {ref}`LLVM-IR Bitcast Instruction <i_bitcast>`. It
 is allowed to bitcast between pointers with the same size, but
 different address spaces.
 
-.. code-block:: none
+```none
+%1:_(s64) = G_BITCAST %0:_(<2 x s32>)
+```
 
-  %1:_(s64) = G_BITCAST %0:_(<2 x s32>)
-
-G_ADDRSPACE_CAST
-^^^^^^^^^^^^^^^^
+### G_ADDRSPACE_CAST
 
 Convert a pointer to an address space to a pointer to another address space.
 
-.. code-block:: none
-
-  %1:_(p1) = G_ADDRSPACE_CAST %0:_(p0)
-
-.. caution::
+```none
+%1:_(p1) = G_ADDRSPACE_CAST %0:_(p0)
+```
 
-  :ref:`i_addrspacecast` doesn't mention what happens if the cast is simply
-  invalid (i.e. if the address spaces are disjoint).
+:::{caution}
+{ref}`i_addrspacecast` doesn't mention what happens if the cast is simply
+invalid (i.e. if the address spaces are disjoint).
+:::
 
-Scalar Operations
------------------
+## Scalar Operations
 
-G_EXTRACT
-^^^^^^^^^
+### G_EXTRACT
 
 Extract a register of the specified size, starting from the block given by
 index. This will almost certainly be mapped to sub-register COPYs after
 register banks have been selected.
 
-.. code-block:: none
+```none
+%3:_(s32) = G_EXTRACT %2:_(s64), 32
+```
 
-  %3:_(s32) = G_EXTRACT %2:_(s64), 32
-
-G_INSERT
-^^^^^^^^
+### G_INSERT
 
 Insert a smaller register into a larger one at the specified bit-index.
 
-.. code-block:: none
-
-  %2:_(s64) = G_INSERT %0:(_s64), %1:_(s32), 0
+```none
+%2:_(s64) = G_INSERT %0:(_s64), %1:_(s32), 0
+```
 
-G_MERGE_VALUES
-^^^^^^^^^^^^^^
+### G_MERGE_VALUES
 
 Concatenate multiple registers of the same size into a wider register.
 The input operands are always ordered from lowest bits to highest:
 
-.. code-block:: none
-
-  %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
-                            %bits_16_23:(s8), %bits_24_31:(s8)
+```none
+%0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
+                          %bits_16_23:(s8), %bits_24_31:(s8)
+```
 
-G_UNMERGE_VALUES
-^^^^^^^^^^^^^^^^
+### G_UNMERGE_VALUES
 
 Extract multiple registers of the specified size, starting from blocks given by
 indexes. This will almost certainly be mapped to sub-register COPYs after
 register banks have been selected.
 The output operands are always ordered from lowest bits to highest:
 
-.. code-block:: none
+```none
+%bits_0_7:(s8), %bits_8_15:(s8),
+    %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
+```
 
-  %bits_0_7:(s8), %bits_8_15:(s8),
-      %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
-
-G_BSWAP
-^^^^^^^
+### G_BSWAP
 
 Reverse the order of the bytes in a scalar.
 
-.. code-block:: none
-
-  %1:_(s32) = G_BSWAP %0:_(s32)
+```none
+%1:_(s32) = G_BSWAP %0:_(s32)
+```
 
-G_BITREVERSE
-^^^^^^^^^^^^
+### G_BITREVERSE
 
 Reverse the order of the bits in a scalar.
 
-.. code-block:: none
-
-  %1:_(s32) = G_BITREVERSE %0:_(s32)
+```none
+%1:_(s32) = G_BITREVERSE %0:_(s32)
+```
 
-G_SBFX, G_UBFX
-^^^^^^^^^^^^^^
+### G_SBFX, G_UBFX
 
 Extract a range of bits from a register.
 
@@ -299,302 +281,266 @@ The source operands are registers as follows:
 
 The least-significant bit (lsb) and width operands are in the range:
 
-::
-
-      0 <= lsb < lsb + width <= source bitwidth, where all values are unsigned
+```
+0 <= lsb < lsb + width <= source bitwidth, where all values are unsigned
+```
 
 G_SBFX sign-extends the result, while G_UBFX zero-extends the result.
 
-.. code-block:: none
-
-  ; Extract 5 bits starting at bit 1 from %x and store them in %a.
-  ; Sign-extend the result.
-  ;
-  ; Example:
-  ; %x = 0...0000[10110]1 ---> %a = 1...111111[10110]
-  %lsb_one = G_CONSTANT i32 1
-  %width_five = G_CONSTANT i32 5
-  %a:_(s32) = G_SBFX %x, %lsb_one, %width_five
-
-  ; Extract 3 bits starting at bit 2 from %x and store them in %b. Zero-extend
-  ; the result.
-  ;
-  ; Example:
-  ; %x = 1...11111[100]11 ---> %b = 0...00000[100]
-  %lsb_two = G_CONSTANT i32 2
-  %width_three = G_CONSTANT i32 3
-  %b:_(s32) = G_UBFX %x, %lsb_two, %width_three
-
-Integer Operations
--------------------
-
-G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SDIV, G_UDIV, G_SREM, G_UREM
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+```none
+; Extract 5 bits starting at bit 1 from %x and store them in %a.
+; Sign-extend the result.
+;
+; Example:
+; %x = 0...0000[10110]1 ---> %a = 1...111111[10110]
+%lsb_one = G_CONSTANT i32 1
+%width_five = G_CONSTANT i32 5
+%a:_(s32) = G_SBFX %x, %lsb_one, %width_five
+
+; Extract 3 bits starting at bit 2 from %x and store them in %b. Zero-extend
+; the result.
+;
+; Example:
+; %x = 1...11111[100]11 ---> %b = 0...00000[100]
+%lsb_two = G_CONSTANT i32 2
+%width_three = G_CONSTANT i32 3
+%b:_(s32) = G_UBFX %x, %lsb_two, %width_three
+```
+
+## Integer Operations
+
+### G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SDIV, G_UDIV, G_SREM, G_UREM
 
 These each perform their respective integer arithmetic on a scalar.
 
-.. code-block:: none
-
-  %dst:_(s32) = G_ADD %src0:_(s32), %src1:_(s32)
+```none
+%dst:_(s32) = G_ADD %src0:_(s32), %src1:_(s32)
+```
 
 The above example adds %src1 to %src0 and stores the result in %dst.
 
-G_CLMUL
-^^^^^^^
+### G_CLMUL
 
 Perform integer carry-less multiplication.
 
-.. code-block:: none
+```none
+%dst:_(s32) = G_CLMUL %src_0:_(s32), %src1:_(32)
+```
 
-  %dst:_(s32) = G_CLMUL %src_0:_(s32), %src1:_(32)
-
-G_SDIVREM, G_UDIVREM
-^^^^^^^^^^^^^^^^^^^^
+### G_SDIVREM, G_UDIVREM
 
 Perform integer division and remainder thereby producing two results.
 
-.. code-block:: none
-
-  %div:_(s32), %rem:_(s32) = G_SDIVREM %0:_(s32), %1:_(s32)
+```none
+%div:_(s32), %rem:_(s32) = G_SDIVREM %0:_(s32), %1:_(s32)
+```
 
-G_SADDSAT, G_UADDSAT, G_SSUBSAT, G_USUBSAT, G_SSHLSAT, G_USHLSAT
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_SADDSAT, G_UADDSAT, G_SSUBSAT, G_USUBSAT, G_SSHLSAT, G_USHLSAT
 
 Signed and unsigned addition, subtraction and left shift with saturation.
 
-.. code-block:: none
-
-  %2:_(s32) = G_SADDSAT %0:_(s32), %1:_(s32)
+```none
+%2:_(s32) = G_SADDSAT %0:_(s32), %1:_(s32)
+```
 
-G_SHL, G_LSHR, G_ASHR
-^^^^^^^^^^^^^^^^^^^^^
+### G_SHL, G_LSHR, G_ASHR
 
 Shift the bits of a scalar left or right inserting zeros (sign-bit for G_ASHR).
 
-G_ROTR, G_ROTL
-^^^^^^^^^^^^^^
+### G_ROTR, G_ROTL
 
 Rotate the bits right (G_ROTR) or left (G_ROTL).
 
-G_ICMP
-^^^^^^
+### G_ICMP
 
 Perform integer comparison producing non-zero (true) or zero (false). It's
 target specific whether a true value is 1, ~0U, or some other non-zero value.
 
-G_SCMP
-^^^^^^
+### G_SCMP
 
 Perform signed 3-way integer comparison producing -1 (smaller), 0 (equal), or 1 (larger).
 
-.. code-block:: none
+```none
+%5:_(s32) = G_SCMP %6, %2
+```
 
-  %5:_(s32) = G_SCMP %6, %2
-
-
-G_UCMP
-^^^^^^
+### G_UCMP
 
 Perform unsigned 3-way integer comparison producing -1 (smaller), 0 (equal), or 1 (larger).
 
-.. code-block:: none
-
-  %7:_(s32) = G_UCMP %2, %6
+```none
+%7:_(s32) = G_UCMP %2, %6
+```
 
-
-G_SELECT
-^^^^^^^^
+### G_SELECT
 
 Select between two values depending on a zero/non-zero value.
 
-.. code-block:: none
-
-  %5:_(s32) = G_SELECT %4(s1), %6, %2
+```none
+%5:_(s32) = G_SELECT %4(s1), %6, %2
+```
 
-G_PTR_ADD
-^^^^^^^^^
+### G_PTR_ADD
 
 Add a scalar offset in addressible units to a pointer. Addressible units are
 typically bytes but this may vary between targets.
 
-.. code-block:: none
-
-  %1:_(p0) = G_PTR_ADD %0:_(p0), %1:_(s32)
+```none
+%1:_(p0) = G_PTR_ADD %0:_(p0), %1:_(s32)
+```
 
-.. caution::
+:::{caution}
+There are currently no in-tree targets that use this with addressable units
+not equal to 8 bit.
+:::
 
-  There are currently no in-tree targets that use this with addressable units
-  not equal to 8 bit.
-
-G_PTRMASK
-^^^^^^^^^^
+### G_PTRMASK
 
 Zero out an arbitrary mask of bits of a pointer. The mask type must be
 an integer, and the number of vector elements must match for all
 operands. This corresponds to `i_intr_llvm_ptrmask`.
 
-.. code-block:: none
-
-  %2:_(p0) = G_PTRMASK %0, %1
+```none
+%2:_(p0) = G_PTRMASK %0, %1
+```
 
-G_SMIN, G_SMAX, G_UMIN, G_UMAX
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_SMIN, G_SMAX, G_UMIN, G_UMAX
 
 Take the minimum/maximum of two values.
 
-.. code-block:: none
-
-  %5:_(s32) = G_SMIN %6, %2
+```none
+%5:_(s32) = G_SMIN %6, %2
+```
 
-G_ABS
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_ABS
 
 Take the absolute value of a signed integer. The absolute value of the minimum
 negative value (e.g. the 8-bit value `0x80`) is defined to be itself.
 
-.. code-block:: none
+```none
+%1:_(s32) = G_ABS %0
+```
 
-  %1:_(s32) = G_ABS %0
-
-G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_SMULO, G_UMULO
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_SMULO, G_UMULO
 
 Perform the requested arithmetic and produce a carry output in addition to the
 normal result.
 
-.. code-block:: none
-
-  %3:_(s32), %4:_(s1) = G_UADDO %0, %1
+```none
+%3:_(s32), %4:_(s1) = G_UADDO %0, %1
+```
 
-G_UADDE, G_SADDE, G_USUBE, G_SSUBE
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_UADDE, G_SADDE, G_USUBE, G_SSUBE
 
 Perform the requested arithmetic and consume a carry input in addition to the
 normal input. Also produce a carry output in addition to the normal result.
 
-.. code-block:: none
-
-  %4:_(s32), %5:_(s1) = G_UADDE %0, %1, %3:_(s1)
+```none
+%4:_(s32), %5:_(s1) = G_UADDE %0, %1, %3:_(s1)
+```
 
-G_UMULH, G_SMULH
-^^^^^^^^^^^^^^^^
+### G_UMULH, G_SMULH
 
 Multiply two numbers at twice the incoming bit width (unsigned or signed) and
 return the high half of the result.
 
-.. code-block:: none
+```none
+%3:_(s32) = G_UMULH %0, %1
+```
 
-  %3:_(s32) = G_UMULH %0, %1
-
-G_CTLZ, G_CTTZ, G_CTPOP
-^^^^^^^^^^^^^^^^^^^^^^^
+### G_CTLZ, G_CTTZ, G_CTPOP
 
 Count leading zeros, trailing zeros, or number of set bits.
 
-.. code-block:: none
-
-  %2:_(s33) = G_CTLZ_ZERO_POISON %1
-  %2:_(s33) = G_CTTZ_ZERO_POISON %1
-  %2:_(s33) = G_CTPOP %1
+```none
+%2:_(s33) = G_CTLZ_ZERO_POISON %1
+%2:_(s33) = G_CTTZ_ZERO_POISON %1
+%2:_(s33) = G_CTPOP %1
+```
 
-G_CTLZ_ZERO_POISON, G_CTTZ_ZERO_POISON
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_CTLZ_ZERO_POISON, G_CTTZ_ZERO_POISON
 
 Count leading zeros or trailing zeros. If the value is zero then the result is
 poison.
 
-.. code-block:: none
-
-  %2:_(s33) = G_CTLZ_ZERO_POISON %1
-  %2:_(s33) = G_CTTZ_ZERO_POISON %1
+```none
+%2:_(s33) = G_CTLZ_ZERO_POISON %1
+%2:_(s33) = G_CTTZ_ZERO_POISON %1
+```
 
-G_CTLS
-^^^^^^
+### G_CTLS
 
 Count leading redundant sign bits. If the value is positive then the result is
 the number of extra leading zeros. If the value is negative then the result is
 the number of extra leading ones.
 
-.. code-block:: none
+```none
+%2:_(s32) = G_CTLS %1
+```
 
-  %2:_(s32) = G_CTLS %1
-
-G_ABDS, G_ABDU
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_ABDS, G_ABDU
 
 Compute the absolute difference (signed and unsigned), e.g. trunc(abs(ext(x)-ext(y)).
 
-.. code-block:: none
-
-  %0:_(s33) = G_ABDS %2, %3
-  %1:_(s33) = G_ABDU %4, %5
+```none
+%0:_(s33) = G_ABDS %2, %3
+%1:_(s33) = G_ABDU %4, %5
+```
 
-G_UAVGFLOOR, G_UAVGCEIL, G_SAVGFLOOR, G_SAVGCEIL
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_UAVGFLOOR, G_UAVGCEIL, G_SAVGFLOOR, G_SAVGCEIL
 
 Computes the average of corresponding elements in two vectors (signed and unsigned).
 Resulting vector contains values that are either rounded or truncated. e.g. trunc(shr(add(ext(a),ext(b)),1)).
 
-.. code-block:: none
-
-  %0:_(<4 x i16>) = G_UAVGFLOOR %4:_(<4 x i16>), %5:_(<4 x i16>)
-  %1:_(<4 x i16>) = G_UAVGCEIL %6:_(<4 x i16>), %7:_(<4 x i16>)
-  %2:_(<4 x i16>) = G_SAVGFLOOR %8:_(<4 x i16>), %9:_(<4 x i16>)
-  %3:_(<4 x i16>) = G_SAVGCEIL %10:_(<4 x i16>), %11:_(<4 x i16>)
+```none
+%0:_(<4 x i16>) = G_UAVGFLOOR %4:_(<4 x i16>), %5:_(<4 x i16>)
+%1:_(<4 x i16>) = G_UAVGCEIL %6:_(<4 x i16>), %7:_(<4 x i16>)
+%2:_(<4 x i16>) = G_SAVGFLOOR %8:_(<4 x i16>), %9:_(<4 x i16>)
+%3:_(<4 x i16>) = G_SAVGCEIL %10:_(<4 x i16>), %11:_(<4 x i16>)
+```
 
-Floating Point Operations
--------------------------
+## Floating Point Operations
 
-G_FCMP
-^^^^^^
+### G_FCMP
 
 Perform floating point comparison producing non-zero (true) or zero
 (false). It's target specific whether a true value is 1, ~0U, or some other
 non-zero value.
 
-G_FNEG
-^^^^^^
+### G_FNEG
 
 Floating point negation.
 
-G_FPEXT
-^^^^^^^
+### G_FPEXT
 
 Convert a floating point value to a larger type.
 
-G_FPTRUNC
-^^^^^^^^^
+### G_FPTRUNC
 
 Convert a floating point value to a narrower type.
 
-G_FPTOSI, G_FPTOUI, G_SITOFP, G_UITOFP
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_FPTOSI, G_FPTOUI, G_SITOFP, G_UITOFP
 
 Convert between integer and floating point.
 
-G_FPTOSI_SAT, G_FPTOUI_SAT
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_FPTOSI_SAT, G_FPTOUI_SAT
 
 Saturating convert between integer and floating point.
 
-G_FABS
-^^^^^^
+### G_FABS
 
 Take the absolute value of a floating point value.
 
-G_FCOPYSIGN
-^^^^^^^^^^^
+### G_FCOPYSIGN
 
 Copy the value of the first operand, replacing the sign bit with that of the
 second operand.
 
-G_FCANONICALIZE
-^^^^^^^^^^^^^^^
+### G_FCANONICALIZE
 
-See :ref:`i_intr_llvm_canonicalize`.
+See {ref}`i_intr_llvm_canonicalize`.
 
-G_IS_FPCLASS
-^^^^^^^^^^^^
+### G_IS_FPCLASS
 
 Tests if the first operand, which must be floating-point scalar or vector, has
 floating-point class specified by the second operand. Returns non-zero (true)
@@ -602,8 +548,7 @@ or zero (false). It's target specific whether a true value is 1, ~0U, or some
 other non-zero value. If the first operand is a vector, the returned value is a
 vector of the same length.
 
-G_FMINNUM
-^^^^^^^^^
+### G_FMINNUM
 
 Perform floating-point minimum on two values.
 
@@ -612,8 +557,7 @@ the non-NaN input is returned.
 
 The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
 
-G_FMAXNUM
-^^^^^^^^^
+### G_FMAXNUM
 
 Perform floating-point maximum on two values.
 
@@ -622,8 +566,7 @@ the non-NaN input is returned.
 
 The return value of (FMAXNUM 0.0, -0.0) could be either 0.0 or -0.0.
 
-G_FMINNUM_IEEE
-^^^^^^^^^^^^^^
+### G_FMINNUM_IEEE
 
 Perform floating-point minimum on two values, following IEEE-754
 definitions. This differs from FMINNUM in the handling of signaling
@@ -637,8 +580,7 @@ These treat -0 as ordered less than +0, matching the behavior of
 IEEE-754 2019's minimumNumber/maximumNumber (which was unspecified in
 2008).
 
-G_FMAXNUM_IEEE
-^^^^^^^^^^^^^^
+### G_FMAXNUM_IEEE
 
 Perform floating-point maximum on two values, following IEEE-754
 definitions. This differs from FMAXNUM in the handling of signaling
@@ -652,109 +594,91 @@ These treat -0 as ordered less than +0, matching the behavior of
 IEEE-754 2019's minimumNumber/maximumNumber (which was unspecified in
 2008).
 
-G_FMINIMUM
-^^^^^^^^^^
+### G_FMINIMUM
 
 NaN-propagating minimum that also treat -0.0 as less than 0.0. While
 FMINNUM_IEEE follow IEEE 754-2008 semantics, FMINIMUM follows IEEE
 754-2019 semantics.
 
-G_FMAXIMUM
-^^^^^^^^^^
+### G_FMAXIMUM
 
 NaN-propagating maximum that also treat -0.0 as less than 0.0. While
 FMAXNUM_IEEE follow IEEE 754-2008 semantics, FMAXIMUM follows IEEE
 754-2019 semantics.
 
-G_FMINIMUMNUM
-^^^^^^^^^^^^^
+### G_FMINIMUMNUM
 
 IEEE-754 2019 minimumNumber
 
-G_FMAXIMUMNUM
-^^^^^^^^^^^^^
+### G_FMAXIMUMNUM
 
 IEEE-754 2019 maximumNumber
 
-G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FREM
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FREM
 
 Perform the specified floating point arithmetic.
 
-G_FMA
-^^^^^
+### G_FMA
 
 Perform a fused multiply add (i.e. without the intermediate rounding step).
 
-G_FMAD
-^^^^^^
+### G_FMAD
 
 Perform a non-fused multiply add (i.e. with the intermediate rounding step).
 
-G_FPOW
-^^^^^^
+### G_FPOW
 
 Raise the first operand to the power of the second.
 
-G_FEXP, G_FEXP2
-^^^^^^^^^^^^^^^
+### G_FEXP, G_FEXP2
 
 Calculate the base-e or base-2 exponential of a value
 
-G_FLOG, G_FLOG2, G_FLOG10
-^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_FLOG, G_FLOG2, G_FLOG10
 
 Calculate the base-e, base-2, or base-10 respectively.
 
-G_FCEIL, G_FSQRT, G_FFLOOR, G_FRINT, G_FNEARBYINT
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_FCEIL, G_FSQRT, G_FFLOOR, G_FRINT, G_FNEARBYINT
 
 These correspond to the standard C functions of the same name.
 
-G_FCOS, G_FSIN, G_FSINCOS, G_FTAN, G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH, G_FTANH
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_FCOS, G_FSIN, G_FSINCOS, G_FTAN, G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH, G_FTANH
 
 These correspond to the standard C trigonometry functions of the same name.
 
-G_INTRINSIC_TRUNC
-^^^^^^^^^^^^^^^^^
+### G_INTRINSIC_TRUNC
 
 Returns the operand rounded to the nearest integer not larger in magnitude than the operand.
 
-G_INTRINSIC_ROUND
-^^^^^^^^^^^^^^^^^
+### G_INTRINSIC_ROUND
 
 Returns the operand rounded to the nearest integer.
 
-G_LROUND, G_LLROUND
-^^^^^^^^^^^^^^^^^^^
+### G_LROUND, G_LLROUND
 
 Returns the source operand rounded to the nearest integer with ties away from
 zero.
 
-See the LLVM LangRef entry on '``llvm.lround.*'`` for details on behaviour.
+See the LLVM LangRef entry on '`llvm.lround.*'` for details on behaviour.
 
-.. code-block:: none
+```none
+%rounded_32:_(s32) = G_LROUND %round_me:_(s64)
+%rounded_64:_(s64) = G_LLROUND %round_me:_(s64)
+```
 
-  %rounded_32:_(s32) = G_LROUND %round_me:_(s64)
-  %rounded_64:_(s64) = G_LLROUND %round_me:_(s64)
+## Vector Specific Operations
 
-Vector Specific Operations
---------------------------
+### G_VSCALE
 
-G_VSCALE
-^^^^^^^^
-
-Puts the value of the runtime ``vscale`` multiplied by the value in the source
+Puts the value of the runtime `vscale` multiplied by the value in the source
 operand into the destination register. This can be useful in determining the
 actual runtime number of elements in a vector.
 
-.. code-block::
-
-  %0:_(s32) = G_VSCALE 4
+```
+%0:_(s32) = G_VSCALE 4
+```
 
-G_INSERT_SUBVECTOR
-^^^^^^^^^^^^^^^^^^
+### G_INSERT_SUBVECTOR
 
 Insert the second source vector into the first source vector. The index operand
 represents the starting index in the first source vector at which the second
@@ -769,12 +693,11 @@ but is false at runtime, then the result vector is undefined.
 This operation supports inserting a fixed vector into a scalable vector, but not
 the other way around.
 
-.. code-block:: none
-
-  %2:_(<vscale x 4 x i64>) = G_INSERT_SUBVECTOR %0:_(<vscale x 4 x i64>), %1:_(<vscale x 2 x i64>), 0
+```none
+%2:_(<vscale x 4 x i64>) = G_INSERT_SUBVECTOR %0:_(<vscale x 4 x i64>), %1:_(<vscale x 2 x i64>), 0
+```
 
-G_EXTRACT_SUBVECTOR
-^^^^^^^^^^^^^^^^^^^
+### G_EXTRACT_SUBVECTOR
 
 Extract a vector of destination type from the source vector. The index operand
 represents the starting index from which a subvector is extracted from
@@ -790,68 +713,57 @@ undefined.
 This operation supports extracting a fixed vector from a scalable vector, but
 not the other way around.
 
-.. code-block:: none
+```none
+%3:_(<vscale x 4 x i64>) = G_EXTRACT_SUBVECTOR %2:_(<vscale x 8 x i64>), 4
+```
 
-  %3:_(<vscale x 4 x i64>) = G_EXTRACT_SUBVECTOR %2:_(<vscale x 8 x i64>), 4
-
-G_CONCAT_VECTORS
-^^^^^^^^^^^^^^^^
+### G_CONCAT_VECTORS
 
 Concatenate vectors to form a longer vector.
 
-.. code-block:: none
-
-  %4:_(<16 x i32>) = G_CONCAT_VECTORS %0:_(<4 x i32>), %1:_(<4 x i32>),
-                                      %2:_(<4 x i32>), %3:_(<4 x i32>)
-
+```none
+%4:_(<16 x i32>) = G_CONCAT_VECTORS %0:_(<4 x i32>), %1:_(<4 x i32>),
+                                    %2:_(<4 x i32>), %3:_(<4 x i32>)
+```
 
-G_BUILD_VECTOR, G_BUILD_VECTOR_TRUNC
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_BUILD_VECTOR, G_BUILD_VECTOR_TRUNC
 
 Create a vector from multiple scalar registers. No implicit
 conversion is performed (i.e. the result element type must be the
 same as all source operands)
 
-The _TRUNC version truncates the larger operand types to fit the
+The \_TRUNC version truncates the larger operand types to fit the
 destination vector elt type.
 
-.. code-block:: none
+```none
+%4:_(<4 x i32>) = G_BUILD_VECTOR %0:_(i32), %1:_(i32), %2:_(i32), %3:_(i32)
 
-  %4:_(<4 x i32>) = G_BUILD_VECTOR %0:_(i32), %1:_(i32), %2:_(i32), %3:_(i32)
+%4:_(<4 x i32>) = G_BUILD_VECTOR_TRUNC %0:_(i64), %1:_(i64), %2:_(i64), %3:_(i64)
+```
 
-  %4:_(<4 x i32>) = G_BUILD_VECTOR_TRUNC %0:_(i64), %1:_(i64), %2:_(i64), %3:_(i64)
-
-
-G_INSERT_VECTOR_ELT
-^^^^^^^^^^^^^^^^^^^
+### G_INSERT_VECTOR_ELT
 
 Insert an element into a vector
 
-.. code-block:: none
-
-  %4:_(<16 x i32>) = G_INSERT_VECTOR_ELT %vec:_(<16 x i32>), %elt:_(i32), %idx:_(s64)
+```none
+%4:_(<16 x i32>) = G_INSERT_VECTOR_ELT %vec:_(<16 x i32>), %elt:_(i32), %idx:_(s64)
+```
 
-
-
-G_EXTRACT_VECTOR_ELT
-^^^^^^^^^^^^^^^^^^^^
+### G_EXTRACT_VECTOR_ELT
 
 Extract an element from a vector
 
-.. code-block:: none
-
-  %elt:_(i32) = G_EXTRACT_VECTOR_ELT %vec:_(<16 x i32>), %idx:_(s64)
+```none
+%elt:_(i32) = G_EXTRACT_VECTOR_ELT %vec:_(<16 x i32>), %idx:_(s64)
+```
 
-
-G_SHUFFLE_VECTOR
-^^^^^^^^^^^^^^^^
+### G_SHUFFLE_VECTOR
 
 Concatenate two vectors and shuffle the elements according to the mask operand.
 The mask operand should be an IR Constant which exactly matches the
 corresponding mask for the IR shufflevector instruction.
 
-G_SPLAT_VECTOR
-^^^^^^^^^^^^^^^^
+### G_SPLAT_VECTOR
 
 Create a vector where all elements are the scalar from the source operand.
 
@@ -859,8 +771,7 @@ The type of the operand must be equal to or larger than the vector element
 type. If the operand is larger than the vector element type, the scalar is
 implicitly truncated to the vector element type.
 
-G_STEP_VECTOR
-^^^^^^^^^^^^^
+### G_STEP_VECTOR
 
 Create a scalable vector where all lanes are linear sequences starting at 0
 with a given unsigned step.
@@ -869,65 +780,56 @@ The type of the operand must be equal to the vector element type. Arithmetic
 is performed modulo the bitwidth of the element. The step must be > 0.
 Otherwise the vector is zero.
 
-.. code-block::
-
-  %0:_(<vscale x 2 x s64>) = G_STEP_VECTOR i64 4
+```
+%0:_(<vscale x 2 x s64>) = G_STEP_VECTOR i64 4
 
-  %1:_(<vscale x s32>) = G_STEP_VECTOR i32 4
+%1:_(<vscale x s32>) = G_STEP_VECTOR i32 4
 
-  0, 1*Step, 2*Step, 3*Step, 4*Step, ...
+0, 1*Step, 2*Step, 3*Step, 4*Step, ...
+```
 
-G_VECTOR_COMPRESS
-^^^^^^^^^^^^^^^^^
+### G_VECTOR_COMPRESS
 
 Given an input vector, a mask vector, and a passthru vector, continuously place
 all selected (i.e., where mask[i] = true) input lanes in an output vector. All
 remaining lanes in the output are taken from passthru, which may be undef.
 
-Vector Reduction Operations
----------------------------
+## Vector Reduction Operations
 
 These operations represent horizontal vector reduction, producing a scalar result.
 
-G_VECREDUCE_SEQ_FADD, G_VECREDUCE_SEQ_FMUL
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_VECREDUCE_SEQ_FADD, G_VECREDUCE_SEQ_FMUL
 
 The SEQ variants perform reductions in sequential order. The first operand is
 an initial scalar accumulator value, and the second operand is the vector to reduce.
 
-G_VECREDUCE_FADD, G_VECREDUCE_FMUL
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_VECREDUCE_FADD, G_VECREDUCE_FMUL
 
 These reductions are relaxed variants which may reduce the elements in any order.
 
-G_VECREDUCE_FMAX, G_VECREDUCE_FMIN, G_VECREDUCE_FMAXIMUM, G_VECREDUCE_FMINIMUM
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_VECREDUCE_FMAX, G_VECREDUCE_FMIN, G_VECREDUCE_FMAXIMUM, G_VECREDUCE_FMINIMUM
 
 FMIN/FMAX/FMINIMUM/FMAXIMUM nodes can have flags, for NaN/NoNaN variants.
 
+### Integer/bitwise reductions
 
-Integer/bitwise reductions
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-* G_VECREDUCE_ADD
-* G_VECREDUCE_MUL
-* G_VECREDUCE_AND
-* G_VECREDUCE_OR
-* G_VECREDUCE_XOR
-* G_VECREDUCE_SMAX
-* G_VECREDUCE_SMIN
-* G_VECREDUCE_UMAX
-* G_VECREDUCE_UMIN
+- G_VECREDUCE_ADD
+- G_VECREDUCE_MUL
+- G_VECREDUCE_AND
+- G_VECREDUCE_OR
+- G_VECREDUCE_XOR
+- G_VECREDUCE_SMAX
+- G_VECREDUCE_SMIN
+- G_VECREDUCE_UMAX
+- G_VECREDUCE_UMIN
 
 Integer reductions may have a result type larger than the vector element type.
 However, the reduction is performed using the vector element type and the value
 in the top bits is unspecified.
 
-Memory Operations
------------------
+## Memory Operations
 
-G_LOAD, G_SEXTLOAD, G_ZEXTLOAD
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_LOAD, G_SEXTLOAD, G_ZEXTLOAD
 
 Generic load. Expects a MachineMemOperand in addition to explicit
 operands. If the result size is larger than the memory size, the
@@ -941,8 +843,7 @@ Unlike in SelectionDAG, atomic loads are expressed with the same
 opcodes as regular loads. G_LOAD, G_SEXTLOAD and G_ZEXTLOAD may all
 have atomic memory operands.
 
-G_FPEXTLOAD
-^^^^^^^^^^^
+### G_FPEXTLOAD
 
 Generic floating-point extending load. Expects a MachineMemOperand in addition
 to explicit operands. Loads a floating-point value from memory and extends it
@@ -952,29 +853,25 @@ The memory size must be smaller than the result type. For example, loading an
 f32 value from memory and extending it to f64, or loading an f16 value and
 extending it to f32.
 
-.. code-block:: none
+```none
+%1:_(s64) = G_FPEXTLOAD %0:_(p0) :: (load (s32))
+```
 
-  %1:_(s64) = G_FPEXTLOAD %0:_(p0) :: (load (s32))
+### G_INDEXED_LOAD
 
-G_INDEXED_LOAD
-^^^^^^^^^^^^^^
+Generic indexed load. Combines a GEP with a load. \$newaddr is set to \$base + \$offset.
+If \$am is 0 (post-indexed), then the value is loaded from \$base; if \$am is 1 (pre-indexed)
+then the value is loaded from \$newaddr.
 
-Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
-If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
-then the value is loaded from $newaddr.
-
-G_INDEXED_SEXTLOAD
-^^^^^^^^^^^^^^^^^^
+### G_INDEXED_SEXTLOAD
 
 Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
 
-G_INDEXED_ZEXTLOAD
-^^^^^^^^^^^^^^^^^^
+### G_INDEXED_ZEXTLOAD
 
 Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
 
-G_STORE
-^^^^^^^
+### G_STORE
 
 Generic store. Expects a MachineMemOperand in addition to explicit
 operands. If the stored value size is greater than the memory size,
@@ -982,8 +879,7 @@ the high bits are implicitly truncated. If this is a vector store, the
 high elements are discarded (i.e. this does not function as a per-lane
 vector, truncating store)
 
-G_FPTRUNCSTORE
-^^^^^^^^^^^^^^
+### G_FPTRUNCSTORE
 
 Generic floating-point truncating store. Expects a MachineMemOperand in
 addition to explicit operands. Truncates a floating-point value to a smaller
@@ -993,147 +889,117 @@ The memory size must be smaller than the source value type. For example,
 truncating an f64 value to f32 and storing it, or truncating an f32 value
 to f16 and storing it.
 
-.. code-block:: none
-
-  G_FPTRUNCSTORE %0:_(s64), %1:_(p0) :: (store (s32))
+```none
+G_FPTRUNCSTORE %0:_(s64), %1:_(p0) :: (store (s32))
+```
 
-G_INDEXED_STORE
-^^^^^^^^^^^^^^^
+### G_INDEXED_STORE
 
 Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
 
-G_ATOMIC_CMPXCHG_WITH_SUCCESS
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_ATOMIC_CMPXCHG_WITH_SUCCESS
 
 Generic atomic cmpxchg with internal success check. Expects a
 MachineMemOperand in addition to explicit operands.
 
-G_ATOMIC_CMPXCHG
-^^^^^^^^^^^^^^^^
+### G_ATOMIC_CMPXCHG
 
 Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
 operands.
 
-|all_g_atomicrmw|
-^^^^^^^^^^^^^^^^^
-
-.. |all_g_atomicrmw| replace:: G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD,
-                               G_ATOMICRMW_SUB, G_ATOMICRMW_AND,
-                               G_ATOMICRMW_NAND, G_ATOMICRMW_OR,
-                               G_ATOMICRMW_XOR, G_ATOMICRMW_MAX,
-                               G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
-                               G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD,
-                               G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX,
-                               G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAXIMUM,
-                               G_ATOMICRMW_FMINIMUM, G_ATOMICRMW_UINC_WRAP,
-			       G_ATOMICRMW_UDEC_WRAP, G_ATOMICRMW_USUB_COND,
-			       G_ATOMICRMW_USUB_SAT
+### {{ all_g_atomicrmw }}
 
 Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
 operands.
 
-G_FENCE
-^^^^^^^
+### G_FENCE
 
 Generic fence. The first operand is the memory ordering. The second operand is
 the syncscope.
 
-See the LLVM LangRef entry on the '``fence'`` instruction for more details.
+See the LLVM LangRef entry on the '`fence'` instruction for more details.
 
-G_MEMCPY
-^^^^^^^^
+### G_MEMCPY
 
 Generic memcpy. Expects two MachineMemOperands covering the store and load
 respectively, in addition to explicit operands.
 
-G_MEMCPY_INLINE
-^^^^^^^^^^^^^^^
+### G_MEMCPY_INLINE
 
 Generic inlined memcpy. Like G_MEMCPY, but it is guaranteed that this version
 will not be lowered as a call to an external function. Currently the size
 operand is required to evaluate as a constant (not an immediate), though that is
 expected to change when llvm.memcpy.inline is taught to support dynamic sizes.
 
-G_MEMMOVE
-^^^^^^^^^
+### G_MEMMOVE
 
 Generic memmove. Similar to G_MEMCPY, but the source and destination memory
 ranges are allowed to overlap.
 
-G_MEMSET
-^^^^^^^^
+### G_MEMSET
 
 Generic memset. Expects a MachineMemOperand in addition to explicit operands.
 
-G_BZERO
-^^^^^^^
+### G_BZERO
 
 Generic bzero. Expects a MachineMemOperand in addition to explicit operands.
 
-Control Flow
-------------
+## Control Flow
 
-G_PHI
-^^^^^
+### G_PHI
 
 Implement the φ node in the SSA graph representing the function.
 
-.. code-block:: none
-
-  %dst(s8) = G_PHI %src1(s8), %bb.<id1>, %src2(s8), %bb.<id2>
+```none
+%dst(s8) = G_PHI %src1(s8), %bb.<id1>, %src2(s8), %bb.<id2>
+```
 
-G_BR
-^^^^
+### G_BR
 
 Unconditional branch
 
-.. code-block:: none
+```none
+G_BR %bb.<id>
+```
 
-  G_BR %bb.<id>
-
-G_BRCOND
-^^^^^^^^
+### G_BRCOND
 
 Conditional branch
 
-.. code-block:: none
-
-  G_BRCOND %condition, %basicblock.<id>
+```none
+G_BRCOND %condition, %basicblock.<id>
+```
 
-G_BRINDIRECT
-^^^^^^^^^^^^
+### G_BRINDIRECT
 
 Indirect branch
 
-.. code-block:: none
-
-  G_BRINDIRECT %src(p0)
+```none
+G_BRINDIRECT %src(p0)
+```
 
-G_BRJT
-^^^^^^
+### G_BRJT
 
 Indirect branch to jump table entry
 
-.. code-block:: none
+```none
+G_BRJT %ptr(p0), %jti, %idx(s64)
+```
 
-  G_BRJT %ptr(p0), %jti, %idx(s64)
-
-G_JUMP_TABLE
-^^^^^^^^^^^^
+### G_JUMP_TABLE
 
 Generates a pointer to the address of the jump table specified by the source
 operand. The source operand is a jump table index.
 G_JUMP_TABLE can be used in conjunction with G_BRJT to support jump table
 codegen with GlobalISel.
 
-.. code-block:: none
-
-  %dst:_(p0) = G_JUMP_TABLE %jump-table.0
+```none
+%dst:_(p0) = G_JUMP_TABLE %jump-table.0
+```
 
 The above example generates a pointer to the source jump table index.
 
-G_INVOKE_REGION_START
-^^^^^^^^^^^^^^^^^^^^^
+### G_INVOKE_REGION_START
 
 A marker instruction that acts as a pseudo-terminator for regions of code that may
 throw exceptions. Being a terminator, it prevents code from being inserted after
@@ -1141,97 +1007,86 @@ it during passes like legalization. This is needed because calls to exception
 throw routines do not return, so no code that must be on an executable path must
 be placed after throwing.
 
-G_INTRINSIC, G_INTRINSIC_CONVERGENT
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_INTRINSIC, G_INTRINSIC_CONVERGENT
 
 Call an intrinsic that has no side-effects.
 
-The _CONVERGENT variant corresponds to an LLVM IR intrinsic marked `convergent`.
-
-.. note::
+The \_CONVERGENT variant corresponds to an LLVM IR intrinsic marked `convergent`.
 
-  Unlike SelectionDAG, there is no _VOID variant. Both of these are permitted
-  to have zero, one, or multiple results.
+:::{note}
+Unlike SelectionDAG, there is no \_VOID variant. Both of these are permitted
+to have zero, one, or multiple results.
+:::
 
-G_INTRINSIC_W_SIDE_EFFECTS, G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_INTRINSIC_W_SIDE_EFFECTS, G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS
 
 Call an intrinsic that is considered to have unknown side-effects and as such
 cannot be reordered across other side-effecting instructions.
 
-The _CONVERGENT variant corresponds to an LLVM IR intrinsic marked `convergent`.
+The \_CONVERGENT variant corresponds to an LLVM IR intrinsic marked `convergent`.
 
-.. note::
+:::{note}
+Unlike SelectionDAG, there is no \_VOID variant. Both of these are permitted
+to have zero, one, or multiple results.
+:::
 
-  Unlike SelectionDAG, there is no _VOID variant. Both of these are permitted
-  to have zero, one, or multiple results.
+### G_TRAP, G_DEBUGTRAP, G_UBSANTRAP
 
-G_TRAP, G_DEBUGTRAP, G_UBSANTRAP
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Represents :ref:`llvm.trap <llvm.trap>`, :ref:`llvm.debugtrap <llvm.debugtrap>`
-and :ref:`llvm.ubsantrap <llvm.ubsantrap>` that generate a target-dependent
+Represents {ref}`llvm.trap <llvm.trap>`, {ref}`llvm.debugtrap <llvm.debugtrap>`
+and {ref}`llvm.ubsantrap <llvm.ubsantrap>` that generate a target-dependent
 trap instructions.
 
-.. code-block:: none
-
-  G_TRAP
-
-.. code-block:: none
-
-  G_DEBUGTRAP
-
-.. code-block:: none
-
-  G_UBSANTRAP 12
+```none
+G_TRAP
+```
 
-Variadic Arguments
-------------------
+```none
+G_DEBUGTRAP
+```
 
-G_VASTART
-^^^^^^^^^
+```none
+G_UBSANTRAP 12
+```
 
-.. caution::
+## Variadic Arguments
 
-  I found no documentation for this instruction at the time of writing.
+### G_VASTART
 
-G_VAARG
-^^^^^^^
+:::{caution}
+I found no documentation for this instruction at the time of writing.
+:::
 
-.. caution::
+### G_VAARG
 
-  I found no documentation for this instruction at the time of writing.
+:::{caution}
+I found no documentation for this instruction at the time of writing.
+:::
 
-Other Operations
-----------------
+## Other Operations
 
-G_DYN_STACKALLOC
-^^^^^^^^^^^^^^^^
+### G_DYN_STACKALLOC
 
 Dynamically realigns the stack pointer to the specified size and alignment.
 An alignment value of `0` or `1` means no specific alignment.
 
-.. code-block:: none
+```none
+%8:_(p0) = G_DYN_STACKALLOC %7(s64), 32
+```
 
-  %8:_(p0) = G_DYN_STACKALLOC %7(s64), 32
-
-G_FREEZE
-^^^^^^^^
+### G_FREEZE
 
 G_FREEZE is used to stop propagation of undef and poison values.
 
-.. code-block:: none
-
-  %1:_(s32) = G_FREEZE %0(s32)
+```none
+%1:_(s32) = G_FREEZE %0(s32)
+```
 
-Optimization Hints
-------------------
+## Optimization Hints
 
 These instructions do not correspond to any target instructions. They act as
 hints for various combines.
 
-G_ASSERT_SEXT, G_ASSERT_ZEXT
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### G_ASSERT_SEXT, G_ASSERT_ZEXT
 
 This signifies that the contents of a register were previously extended from a
 smaller type.
@@ -1240,12 +1095,12 @@ The smaller type is denoted using an immediate operand. For scalars, this is the
 width of the entire smaller type. For vectors, this is the width of the smaller
 element type.
 
-.. code-block:: none
-
-  %x_was_zexted:_(s32) = G_ASSERT_ZEXT %x(s32), 16
-  %y_was_zexted:_(<2 x s32>) = G_ASSERT_ZEXT %y(<2 x s32>), 16
+```none
+%x_was_zexted:_(s32) = G_ASSERT_ZEXT %x(s32), 16
+%y_was_zexted:_(<2 x s32>) = G_ASSERT_ZEXT %y(<2 x s32>), 16
 
-  %z_was_sexted:_(s32) = G_ASSERT_SEXT %z(s32), 8
+%z_was_sexted:_(s32) = G_ASSERT_SEXT %z(s32), 8
+```
 
 G_ASSERT_SEXT and G_ASSERT_ZEXT act like copies, albeit with some restrictions.
 
@@ -1260,16 +1115,13 @@ It should always be safe to
 - Look through the source register
 - Replace the destination register with the source register
 
+## Miscellaneous
 
-Miscellaneous
--------------
-
-G_CONSTANT_FOLD_BARRIER
-^^^^^^^^^^^^^^^^^^^^^^^
+### G_CONSTANT_FOLD_BARRIER
 
 This operation is used as an opaque barrier to prevent constant folding. Combines
 and other transformations should not look through this. These have no other
 semantics and can be safely eliminated if a target chooses.
 
-
 Unlisted: G_STACKSAVE, G_STACKRESTORE, G_FSHL, G_FSHR, G_SMULFIX, G_UMULFIX, G_SMULFIXSAT, G_UMULFIXSAT, G_SDIVFIX, G_UDIVFIX, G_SDIVFIXSAT, G_UDIVFIXSAT, G_FPOWI, G_FEXP10, G_FLDEXP, G_FFREXP, G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV, G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE, G_INTRINSIC_FPTRUNC_ROUND, G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT, G_INTRINSIC_ROUNDEVEN, G_READCYCLECOUNTER, G_READSTEADYCOUNTER, G_PREFETCH, G_READ_REGISTER, G_WRITE_REGISTER, G_STRICT_FADD, G_STRICT_FSUB, G_STRICT_FMUL, G_STRICT_FDIV, G_STRICT_FREM, G_STRICT_FMA, G_STRICT_FSQRT, G_STRICT_FLDEXP, G_ASSERT_ALIGN
+
diff --git a/llvm/docs/GlobalISel/IRTranslator.md b/llvm/docs/GlobalISel/IRTranslator.md
index 7858dfdc31251..ef40644a1d6c8 100644
--- a/llvm/docs/GlobalISel/IRTranslator.md
+++ b/llvm/docs/GlobalISel/IRTranslator.md
@@ -1,40 +1,37 @@
-.. _irtranslator:
+(irtranslator)=
 
-IRTranslator
-============
+# IRTranslator
 
-
-This pass translates the input LLVM-IR ``Function`` to a :doc:`GMIR`
-``MachineFunction``. This is typically a direct translation but does
+This pass translates the input LLVM-IR `Function` to a {doc}`GMIR`
+`MachineFunction`. This is typically a direct translation but does
 occasionally get a bit more involved. For example:
 
-.. code-block:: llvm
-
-  %2 = add i32 %0, %1
+```llvm
+%2 = add i32 %0, %1
+```
 
 becomes:
 
-.. code-block:: none
-
-  %2:_(s32) = G_ADD %0:_(s32), %1:_(s32)
+```none
+%2:_(s32) = G_ADD %0:_(s32), %1:_(s32)
+```
 
 whereas
 
-.. code-block:: llvm
-
-  call i32 @puts(i8* %cast210)
+```llvm
+call i32 @puts(i8* %cast210)
+```
 
 is translated according to the ABI rules of the target.
 
-.. note::
-
-  The currently implemented portion of the :doc:`../LangRef` is sufficient for
-  many compilations but it is not 100% complete. Users seeking to compile
-  LLVM-IR containing some of the rarer features may need to implement the
-  translation.
+:::{note}
+The currently implemented portion of the {doc}`../LangRef` is sufficient for
+many compilations but it is not 100% complete. Users seeking to compile
+LLVM-IR containing some of the rarer features may need to implement the
+translation.
+:::
 
-Target Intrinsics
------------------
+## Target Intrinsics
 
 There has been some (off-list) debate about whether to add target hooks for
 translating target intrinsics. Among those who discussed it, it was generally
@@ -42,101 +39,94 @@ agreed that the IRTranslator should be able to lower target intrinsics in a
 customizable way but no work has happened to implement this at the time of
 writing.
 
-.. _translator-call-lower:
+(translator-call-lower)=
 
-Translating Function Calls
---------------------------
+## Translating Function Calls
 
-The ``IRTranslator`` also implements the ABI's calling convention by lowering
+The `IRTranslator` also implements the ABI's calling convention by lowering
 calls, returns, and arguments to the appropriate physical register usage and
-instruction sequences. This is achieved using the ``CallLowering`` interface,
+instruction sequences. This is achieved using the `CallLowering` interface,
 which provides several hooks that targets should implement:
-``lowerFormalArguments``, ``lowerReturn``, ``lowerCall`` etc.
+`lowerFormalArguments`, `lowerReturn`, `lowerCall` etc.
 
 In essence, all of these hooks need to find a way to move the argument/return
 values between the virtual registers used in the rest of the function and either
 physical registers or the stack, as dictated by the ABI. This may involve
 splitting large types into smaller ones, introducing sign/zero extensions etc.
 In order to share as much of this code as possible between the different
-backends, ``CallLowering`` makes available a few helpers and interfaces:
+backends, `CallLowering` makes available a few helpers and interfaces:
 
-* ``ArgInfo`` - used for formal arguments, but also return values, actual
+- `ArgInfo` - used for formal arguments, but also return values, actual
   arguments and call results; contains info such as the IR type, the virtual
   registers etc; large values will likely have to be split into several
-  ``ArgInfo`` objects (``CallLowering::splitToValueTypes`` can help with that);
-
-* ``ValueAssigner`` - uses a ``CCAssignFn``, usually generated by TableGen (see
-  :ref:`backend-calling-convs`), to decide where to put each
-  ``ArgInfo`` (physical register or stack); backends can use the provided
-  ``IncomingValueAssigner`` (for formal arguments and call results) and
-  ``OutgoingValueAssigner`` (for actual arguments and function returns), but
+  `ArgInfo` objects (`CallLowering::splitToValueTypes` can help with that);
+- `ValueAssigner` - uses a `CCAssignFn`, usually generated by TableGen (see
+  {ref}`backend-calling-convs`), to decide where to put each
+  `ArgInfo` (physical register or stack); backends can use the provided
+  `IncomingValueAssigner` (for formal arguments and call results) and
+  `OutgoingValueAssigner` (for actual arguments and function returns), but
   it's also possible to subclass them;
-
-* ``ValueHandler`` - inserts the necessary instructions for putting each value
+- `ValueHandler` - inserts the necessary instructions for putting each value
   where it belongs; it has pure virtual methods for assigning values to
   registers or to addresses, and a host of other helpers;
+- `determineAndHandleAssignments` (or for more fine grained control,
+  `determineAssignments` and `handleAssignments`) - contains some boilerplate
+  for invoking a given `ValueAssigner` and `ValueHandler` on a series of
+  `ArgInfo` objects.
 
-* ``determineAndHandleAssignments`` (or for more fine grained control,
-  ``determineAssignments`` and ``handleAssignments``) - contains some boilerplate
-  for invoking a given ``ValueAssigner`` and ``ValueHandler`` on a series of
-  ``ArgInfo`` objects.
-
-.. _irtranslator-aggregates:
-
-Aggregates
-^^^^^^^^^^
+(irtranslator-aggregates)=
 
-.. caution::
+### Aggregates
 
-  This has changed since it was written and is no longer accurate. It has not
-  been refreshed in this pass of improving the documentation as I haven't
-  worked much in this part of the codebase and it should have attention from
-  someone more knowledgeable about it.
+:::{caution}
+This has changed since it was written and is no longer accurate. It has not
+been refreshed in this pass of improving the documentation as I haven't
+worked much in this part of the codebase and it should have attention from
+someone more knowledgeable about it.
+:::
 
 Aggregates are lowered into multiple virtual registers, similar to
-SelectionDAG's multiple vregs via ``GetValueVTs``.
+SelectionDAG's multiple vregs via `GetValueVTs`.
 
-``TODO``:
+`TODO`:
 As some of the bits are undef (padding), we should consider augmenting the
 representation with additional metadata (in effect, caching computeKnownBits
 information on vregs).
-See `PR26161 <https://llvm.org/PR26161>`_: [GlobalISel] Value to vreg during
+See [PR26161](https://llvm.org/PR26161): [GlobalISel] Value to vreg during
 IR to MachineInstr translation for aggregate type
 
-.. _irtranslator-constants:
+(irtranslator-constants)=
 
-Translation of Constants
-------------------------
+## Translation of Constants
 
 Constant operands are translated as a use of a virtual register that is defined
-by a ``G_CONSTANT`` or ``G_FCONSTANT`` instruction. These instructions are
+by a `G_CONSTANT` or `G_FCONSTANT` instruction. These instructions are
 placed in the entry block to allow them to be subject to the continuous CSE
-implementation (``CSEMIRBuilder``). Their debug location information is removed
+implementation (`CSEMIRBuilder`). Their debug location information is removed
 to prevent this from confusing debuggers.
 
 This is beneficial as it allows us to fold constants into immediate operands
-during :ref:`instructionselect`, while still avoiding redundant materializations
+during {ref}`instructionselect`, while still avoiding redundant materializations
 for expensive non-foldable constants. However, this can lead to unnecessary
 spills and reloads in an -O0 pipeline, as these virtual registers can have long
-live ranges. This can be mitigated by running a `localizer <https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/GlobalISel/Localizer.cpp>`_
+live ranges. This can be mitigated by running a [localizer](https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/GlobalISel/Localizer.cpp)
 after the translator.
 
-.. _irtranslator-byte-type:
+(irtranslator-byte-type)=
 
-Translation of the Byte Type
-----------------------------
+## Translation of the Byte Type
 
-The :ref:`byte type <t_byte>` (``bN``) has no distinct GMIR representation and
-is translated as the ``LLT::integer(N)``. This mirrors the
-SelectionDAG behaviour, where ``bN`` maps to the same ``EVT`` as ``iN``.
+The {ref}`byte type <t_byte>` (`bN`) has no distinct GMIR representation and
+is translated as the `LLT::integer(N)`. This mirrors the
+SelectionDAG behaviour, where `bN` maps to the same `EVT` as `iN`.
 
-* ``getLLTForType`` lowers ``ByteType`` to ``LLT::integer(N)``.
-* ``ConstantByte`` is materialised via ``G_CONSTANT`` using the underlying
-  ``APInt``, the same path as ``ConstantInt``.
-* A ``bitcast`` between a byte type and a pointer (the only ptr/non-ptr
-  ``bitcast`` IR permits with byte) is lowered to ``G_INTTOPTR`` or
-  ``G_PTRTOINT`` rather than ``G_BITCAST``, since ``G_BITCAST`` cannot cross
-  the pointer/non-pointer boundary under ``MachineVerifier``.
+- `getLLTForType` lowers `ByteType` to `LLT::integer(N)`.
+- `ConstantByte` is materialised via `G_CONSTANT` using the underlying
+  `APInt`, the same path as `ConstantInt`.
+- A `bitcast` between a byte type and a pointer (the only ptr/non-ptr
+  `bitcast` IR permits with byte) is lowered to `G_INTTOPTR` or
+  `G_PTRTOINT` rather than `G_BITCAST`, since `G_BITCAST` cannot cross
+  the pointer/non-pointer boundary under `MachineVerifier`.
 
 The mid-end semantics of the byte type (per-bit poison, conditional pointer
 provenance preservation) are not representable in MIR and are not consumed by
diff --git a/llvm/docs/GlobalISel/InstructionSelect.md b/llvm/docs/GlobalISel/InstructionSelect.md
index 5513824cf190c..1c74017752019 100644
--- a/llvm/docs/GlobalISel/InstructionSelect.md
+++ b/llvm/docs/GlobalISel/InstructionSelect.md
@@ -1,33 +1,30 @@
+(instructionselect)=
 
-.. _instructionselect:
-
-InstructionSelect
------------------
+# InstructionSelect
 
 This pass transforms generic machine instructions into equivalent
-target-specific instructions.  
-
-The legacy instruction selector, SelectionDAG, iterated over each function's 
-basic block and constructed a dataflow graph. Every backend defines 
-tree patterns in the ``XXXInstrInfo.td``. The legacy selector started
-at the bottom and replaced the SDNodes greedily. 
-
-The GlobalISel's instruction selector traverses the ``MachineFunction`` 
-bottom-up, selecting uses before definitions, enabling trivial dead code 
-elimination. It does that by iterating over the basic blocks in post-order. 
-Each gMIR instruction is then replaced by a MIR instruction when a matching 
-pattern is found. So, when there is a 1:1 mapping between gMIR and MIR, where 
-is the benefit of the global scope? Even in the case of a 1:1 mapping, 
-GlobalISel includes a combiner that can match and fuse multiple gMIR 
-instructions. The scope of the combination is not limited to a basic block, 
+target-specific instructions.
+
+The legacy instruction selector, SelectionDAG, iterated over each function's
+basic block and constructed a dataflow graph. Every backend defines
+tree patterns in the `XXXInstrInfo.td`. The legacy selector started
+at the bottom and replaced the SDNodes greedily.
+
+The GlobalISel's instruction selector traverses the `MachineFunction`
+bottom-up, selecting uses before definitions, enabling trivial dead code
+elimination. It does that by iterating over the basic blocks in post-order.
+Each gMIR instruction is then replaced by a MIR instruction when a matching
+pattern is found. So, when there is a 1:1 mapping between gMIR and MIR, where
+is the benefit of the global scope? Even in the case of a 1:1 mapping,
+GlobalISel includes a combiner that can match and fuse multiple gMIR
+instructions. The scope of the combination is not limited to a basic block,
 but can extend across the entire function.
 
-.. _api-instructionselector:
+(api-instructionselector)=
 
-API: InstructionSelector
-^^^^^^^^^^^^^^^^^^^^^^^^
+## API: InstructionSelector
 
-The target implements the ``InstructionSelector`` class, containing the
+The target implements the `InstructionSelector` class, containing the
 target-specific selection logic proper.
 
 The instance is provided by the subtarget, so that it can specialize the
@@ -38,9 +35,9 @@ variants based on function attributes like optsize.
 
 The simple API consists of:
 
-  .. code-block:: c++
-
-    virtual bool select(MachineInstr &MI)
+> ```c++
+> virtual bool select(MachineInstr &MI)
+> ```
 
 This target-provided method is responsible for mutating (or replacing) a
 possibly-generic MI into a fully target-specific equivalent.
@@ -48,65 +45,60 @@ It is also responsible for doing the necessary constraining of gvregs into the
 appropriate register classes as well as passing through COPY instructions to
 the register allocator.
 
-The ``InstructionSelector`` can fold other instructions into the selected MI,
+The `InstructionSelector` can fold other instructions into the selected MI,
 by walking the use-def chain of the vreg operands.
 As GlobalISel is Global, this folding can occur across basic blocks.
 
-SelectionDAG Rule Imports
-^^^^^^^^^^^^^^^^^^^^^^^^^
+## SelectionDAG Rule Imports
 
 TableGen will import SelectionDAG rules and provide the following function to
 execute them:
 
-  .. code-block:: c++
+> ```c++
+> bool selectImpl(MachineInstr &MI)
+> ```
 
-    bool selectImpl(MachineInstr &MI)
-
-The ``--stats`` option can be used to determine what proportion of rules were
+The `--stats` option can be used to determine what proportion of rules were
 successfully imported. The easiest way to use this is to copy the
-``-gen-globalisel`` tablegen command from ``ninja -v`` and modify it.
+`-gen-globalisel` tablegen command from `ninja -v` and modify it.
 
-Similarly, the ``--warn-on-skipped-patterns`` option can be used to obtain the
+Similarly, the `--warn-on-skipped-patterns` option can be used to obtain the
 reasons that rules weren't imported. This can be used to focus on the most
 important rejection reasons.
 
-PatLeaf Predicates
-^^^^^^^^^^^^^^^^^^
+## PatLeaf Predicates
 
 PatLeafs cannot be imported because their C++ is implemented in terms of
-``SDNode`` objects. PatLeafs that handle immediate predicates should be
-replaced by ``ImmLeaf``, ``IntImmLeaf``, or ``FPImmLeaf`` as appropriate.
+`SDNode` objects. PatLeafs that handle immediate predicates should be
+replaced by `ImmLeaf`, `IntImmLeaf`, or `FPImmLeaf` as appropriate.
 
 There's no standard answer for other PatLeafs. Some standard predicates have
 been baked into TableGen but this should not generally be done.
 
-Custom SDNodes
-^^^^^^^^^^^^^^
+## Custom SDNodes
 
-Custom SDNodes should be mapped to Target Pseudos using ``GINodeEquiv``. This
+Custom SDNodes should be mapped to Target Pseudos using `GINodeEquiv`. This
 will cause the instruction selector to import them but you will also need to
 ensure the target pseudo is introduced to the MIR before the instruction
 selector. Any preceding pass is suitable but the legalizer will be a
 particularly common choice.
 
-ComplexPatterns
-^^^^^^^^^^^^^^^
+## ComplexPatterns
 
 ComplexPatterns cannot be imported because their C++ is implemented in terms of
-``SDNode`` objects. GlobalISel versions should be defined with
-``GIComplexOperandMatcher`` and mapped to ComplexPattern with
-``GIComplexPatternEquiv``.
+`SDNode` objects. GlobalISel versions should be defined with
+`GIComplexOperandMatcher` and mapped to ComplexPattern with
+`GIComplexPatternEquiv`.
 
 The following predicates are useful for porting ComplexPattern:
 
-* isBaseWithConstantOffset() - Check for base+offset structures
-* isOperandImmEqual() - Check for a particular constant
-* isObviouslySafeToFold() - Check for reasons an instruction can't be sunk and folded into another.
+- isBaseWithConstantOffset() - Check for base+offset structures
+- isOperandImmEqual() - Check for a particular constant
+- isObviouslySafeToFold() - Check for reasons an instruction can't be sunk and folded into another.
 
 There are some important points for the C++ implementation:
 
-* Don't modify MIR in the predicate
-* Renderer lambdas should capture by value to avoid use-after-free. They will be used after the predicate returns.
-* Only create instructions in a renderer lambda. GlobalISel won't clean up things you create but don't use.
-
+- Don't modify MIR in the predicate
+- Renderer lambdas should capture by value to avoid use-after-free. They will be used after the predicate returns.
+- Only create instructions in a renderer lambda. GlobalISel won't clean up things you create but don't use.
 
diff --git a/llvm/docs/GlobalISel/KnownBits.md b/llvm/docs/GlobalISel/KnownBits.md
index 0a16a7d2825cb..6b734bcd12a43 100644
--- a/llvm/docs/GlobalISel/KnownBits.md
+++ b/llvm/docs/GlobalISel/KnownBits.md
@@ -1,100 +1,101 @@
-Known Bits Analysis
-===================
+# Known Bits Analysis
 
 The Known Bits Analysis pass makes information about the known values of bits
 available to other passes to enable transformations like those in the examples
 below. The information is lazily computed so you should only pay for what you
 use.
 
-Examples
---------
+## Examples
 
-A simple example is that transforming::
+A simple example is that transforming:
 
-  a + 1
+```
+a + 1
+```
 
-into::
+into:
 
-  a | 1
+```
+a | 1
+```
 
 is only valid when the addition doesn't carry. In other words it's only valid
-if ``a & 1`` is zero.
+if `a & 1` is zero.
 
 Another example is:
 
-.. code-block:: none
+```none
+%1:(s32) = G_CONSTANT i32 0xFF0
+%2:(s32) = G_AND %0, %1
+%3:(s32) = G_CONSTANT i32 0x0FF
+%4:(s32) = G_AND %2, %3
+```
 
-  %1:(s32) = G_CONSTANT i32 0xFF0
-  %2:(s32) = G_AND %0, %1
-  %3:(s32) = G_CONSTANT i32 0x0FF
-  %4:(s32) = G_AND %2, %3
-
-We can use the constants and the definition of ``G_AND`` to determine the known
+We can use the constants and the definition of `G_AND` to determine the known
 bits:
 
-.. code-block:: none
-
-                                   ; %0 = 0x????????
-  %1:(s32) = G_CONSTANT i32 0xFF0  ; %1 = 0x00000FF0
-  %2:(s32) = G_AND %0, %1          ; %2 = 0x00000??0
-  %3:(s32) = G_CONSTANT i32 0x0FF  ; %3 = 0x000000FF
-  %4:(s32) = G_AND %2, %3          ; %4 = 0x000000?0
+```none
+                                 ; %0 = 0x????????
+%1:(s32) = G_CONSTANT i32 0xFF0  ; %1 = 0x00000FF0
+%2:(s32) = G_AND %0, %1          ; %2 = 0x00000??0
+%3:(s32) = G_CONSTANT i32 0x0FF  ; %3 = 0x000000FF
+%4:(s32) = G_AND %2, %3          ; %4 = 0x000000?0
+```
 
 and then use this to simplify the expression:
 
-.. code-block:: none
-
-                                   ; %0 = 0x????????
-  %5:(s32) = G_CONSTANT i32 0x0F0  ; %5 = 0x000000F0
-  %4:(s32) = G_AND %0, %5          ; %4 = 0x000000?0
+```none
+                                 ; %0 = 0x????????
+%5:(s32) = G_CONSTANT i32 0x0F0  ; %5 = 0x000000F0
+%4:(s32) = G_AND %0, %5          ; %4 = 0x000000?0
+```
 
-Note that ``%4`` still has the same known bits as before the transformation.
+Note that `%4` still has the same known bits as before the transformation.
 Many transformations share this property. The main exception being when the
 transform causes undefined bits to become defined to either zero, one, or
 defined but unknown.
 
-Usage
------
+## Usage
 
 To use Known Bits Analysis in a pass, first include the header and register the
-dependency with ``INITIALIZE_PASS_DEPENDENCY``.
+dependency with `INITIALIZE_PASS_DEPENDENCY`.
 
-.. code-block:: c++
+```c++
+#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
 
-  #include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
+...
 
-  ...
-
-  INITIALIZE_PASS_BEGIN(...)
-  INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
-  INITIALIZE_PASS_END(...)
+INITIALIZE_PASS_BEGIN(...)
+INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
+INITIALIZE_PASS_END(...)
+```
 
-and require the pass in ``getAnalysisUsage``.
+and require the pass in `getAnalysisUsage`.
 
-.. code-block:: c++
-
-  void MyPass::getAnalysisUsage(AnalysisUsage &AU) const {
-    AU.addRequired<GISelValueTrackingAnalysisLegacy>();
-    // Optional: If your pass preserves known bits analysis (many do) then
-    //           indicate that it's preserved for re-use by another pass here.
-    AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
-  }
+```c++
+void MyPass::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<GISelValueTrackingAnalysisLegacy>();
+  // Optional: If your pass preserves known bits analysis (many do) then
+  //           indicate that it's preserved for re-use by another pass here.
+  AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
+}
+```
 
 Then it's just a matter of fetching the analysis and using it:
 
-.. code-block:: c++
-
-  bool MyPass::runOnMachineFunction(MachineFunction &MF) {
-    ...
-    GISelValueTracking &VT = getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
-    ...
-    MachineInstr *MI = ...;
-    KnownBits Known = VT.getKnownBits(MI->getOperand(0).getReg());
-    if (Known.Zero[0]) {
-      // Bit 0 is known to be zero
-    }
-    ...
+```c++
+bool MyPass::runOnMachineFunction(MachineFunction &MF) {
+  ...
+  GISelValueTracking &VT = getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
+  ...
+  MachineInstr *MI = ...;
+  KnownBits Known = VT.getKnownBits(MI->getOperand(0).getReg());
+  if (Known.Zero[0]) {
+    // Bit 0 is known to be zero
   }
+  ...
+}
+```
+
+There are many more API's beyond `getKnownBits()`. See the [API reference](https://llvm.org/doxygen) for more information
 
-There are many more API's beyond ``getKnownBits()``. See the `API reference
-<https://llvm.org/doxygen>`_ for more information
diff --git a/llvm/docs/GlobalISel/Legalizer.md b/llvm/docs/GlobalISel/Legalizer.md
index 0f35574b441ab..3f063eb9a5930 100644
--- a/llvm/docs/GlobalISel/Legalizer.md
+++ b/llvm/docs/GlobalISel/Legalizer.md
@@ -1,37 +1,33 @@
-.. _milegalizer:
+(milegalizer)=
 
-Legalizer
----------
+# Legalizer
 
 This pass transforms the generic machine instructions such that they are legal.
 
 A legal instruction is defined as:
 
-* **selectable** --- the target will later be able to select it to a
+- **selectable** --- the target will later be able to select it to a
   target-specific (non-generic) instruction. This doesn't necessarily mean that
-  :doc:`InstructionSelect` has to handle it though. It just means that
+  {doc}`InstructionSelect` has to handle it though. It just means that
   **something** must handle it.
+- operating on **vregs that can be loaded and stored** -- if necessary, the
+  target can select a `G_LOAD`/`G_STORE` of each gvreg operand.
 
-* operating on **vregs that can be loaded and stored** -- if necessary, the
-  target can select a ``G_LOAD``/``G_STORE`` of each gvreg operand.
-
-Unlike SelectionDAG, there are no legalization phases.  In particular,
+Unlike SelectionDAG, there are no legalization phases. In particular,
 'type' and 'operation' legalization are not separate.
 
-Legalization is iterative, and all state is contained in GMIR.  To maintain the
+Legalization is iterative, and all state is contained in GMIR. To maintain the
 validity of the intermediate code, instructions are introduced:
 
-* ``G_MERGE_VALUES`` --- concatenate multiple registers of the same
+- `G_MERGE_VALUES` --- concatenate multiple registers of the same
   size into a single wider register.
-
-* ``G_UNMERGE_VALUES`` --- extract multiple registers of the same size
+- `G_UNMERGE_VALUES` --- extract multiple registers of the same size
   from a single wider register.
-
-* ``G_EXTRACT`` --- extract a simple register (as contiguous sequences of bits)
+- `G_EXTRACT` --- extract a simple register (as contiguous sequences of bits)
   from a single wider register.
 
 As they are expected to be temporary byproducts of the legalization process,
-they are combined at the end of the :ref:`milegalizer` pass.
+they are combined at the end of the {ref}`milegalizer` pass.
 If any remain, they are expected to always be selectable, using loads and stores
 if necessary.
 
@@ -39,68 +35,71 @@ The legality of an instruction may only depend on the instruction itself and
 must not depend on any context in which the instruction is used. However, after
 deciding that an instruction is not legal, using the context of the instruction
 to decide how to legalize the instruction is permitted. As an example, if we
-have a ``G_FOO`` instruction of the form::
+have a `G_FOO` instruction of the form:
 
-  %1:_(s32) = G_CONSTANT i32 1
-  %2:_(s32) = G_FOO %0:_(s32), %1:_(s32)
+```
+%1:_(s32) = G_CONSTANT i32 1
+%2:_(s32) = G_FOO %0:_(s32), %1:_(s32)
+```
 
-it's impossible to say that ``G_FOO`` is legal iff %1 is a ``G_CONSTANT`` with
-value ``1``. However, the following::
+it's impossible to say that `G_FOO` is legal iff %1 is a `G_CONSTANT` with
+value `1`. However, the following:
 
-  %2:_(s32) = G_FOO %0:_(s32), i32 1
+```
+%2:_(s32) = G_FOO %0:_(s32), i32 1
+```
 
-can say that it's legal iff operand 2 is an immediate with value ``1`` because
+can say that it's legal iff operand 2 is an immediate with value `1` because
 that information is entirely contained within the single instruction.
 
-.. _api-legalizerinfo:
+(api-legalizerinfo)=
 
-API: LegalizerInfo
-^^^^^^^^^^^^^^^^^^
+## API: LegalizerInfo
 
-The recommended [#legalizer-legacy-footnote]_ API looks like this::
+The recommended [^legalizer-legacy-footnote] API looks like this:
 
-  getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL})
-      .legalFor({s32, s64, v2s32, v4s32, v2s64})
-      .clampScalar(0, s32, s64)
-      .widenScalarToNextPow2(0)
-      .clampNumElements(0, v2s32, v4s32)
-      .clampNumElements(0, v2s64, v2s64)
-      .moreElementsToNextPow2(0);
+```
+getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL})
+    .legalFor({s32, s64, v2s32, v4s32, v2s64})
+    .clampScalar(0, s32, s64)
+    .widenScalarToNextPow2(0)
+    .clampNumElements(0, v2s32, v4s32)
+    .clampNumElements(0, v2s64, v2s64)
+    .moreElementsToNextPow2(0);
+```
 
 and describes a set of rules by which we can either declare an instruction legal
 or decide which action to take to make it more legal.
 
-At the core of this ruleset is the ``LegalityQuery`` which describes the
+At the core of this ruleset is the `LegalityQuery` which describes the
 instruction. We use a description rather than the instruction to both allow other
 passes to determine legality without having to create an instruction and also to
 limit the information available to the predicates to that which is safe to rely
 on. Currently, the information available to the predicates that determine
 legality contains:
 
-* The opcode for the instruction
-
-* The type of each type index (see ``type0``, ``type1``, etc.)
+- The opcode for the instruction
+- The type of each type index (see `type0`, `type1`, etc.)
+- The size in bytes and atomic ordering for each MachineMemOperand
 
-* The size in bytes and atomic ordering for each MachineMemOperand
+:::{note}
+An alternative worth investigating is to generalize the API to represent
+actions using `std::function` that implements the action, instead of explicit
+enum tokens (`Legal`, `WidenScalar`, ...) that instruct it to call a
+function. This would have some benefits, most notable being that Custom could
+be removed.
+:::
 
-.. note::
+```{rubric} Footnotes
+```
 
-  An alternative worth investigating is to generalize the API to represent
-  actions using ``std::function`` that implements the action, instead of explicit
-  enum tokens (``Legal``, ``WidenScalar``, ...) that instruct it to call a
-  function. This would have some benefits, most notable being that Custom could
-  be removed.
+[^legalizer-legacy-footnote]: An API that is broadly similar to
+    SelectionDAG/TargetLowering is available, but is not recommended as a more
+    powerful API is available.
 
-.. rubric:: Footnotes
+### Rule Processing and Declaring Rules
 
-.. [#legalizer-legacy-footnote] An API that is broadly similar to
-   SelectionDAG/TargetLowering is available, but is not recommended as a more
-   powerful API is available.
-
-Rule Processing and Declaring Rules
-"""""""""""""""""""""""""""""""""""
-
-The ``getActionDefinitionsBuilder`` function generates a ruleset for the given
+The `getActionDefinitionsBuilder` function generates a ruleset for the given
 opcode(s) that rules can be added to. If multiple opcodes are given, they are
 all permanently bound to the same ruleset. The rules in a ruleset are executed
 from top to bottom and will start again from the top if an instruction is
@@ -119,138 +118,126 @@ the rule as possible and to place any expensive rules as low as possible. This
 helps with performance as testing for legality happens more often than
 legalization and legalization can require multiple passes over the rules.
 
-As a concrete example, consider the rule::
+As a concrete example, consider the rule:
 
-  getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL})
-      .legalFor({s32, s64, v2s32, v4s32, v2s64})
-      .clampScalar(0, s32, s64)
-      .widenScalarToNextPow2(0);
+```
+getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL})
+    .legalFor({s32, s64, v2s32, v4s32, v2s64})
+    .clampScalar(0, s32, s64)
+    .widenScalarToNextPow2(0);
+```
 
-and the instruction::
+and the instruction:
 
-  %2:_(s7) = G_ADD %0:_(s7), %1:_(s7)
+```
+%2:_(s7) = G_ADD %0:_(s7), %1:_(s7)
+```
 
-This doesn't meet the predicate for the :ref:`.legalFor() <legalfor>` as ``s7``
+This doesn't meet the predicate for the {ref}`.legalFor() <legalfor>` as `s7`
 is not one of the listed types so it falls through to the
-:ref:`.clampScalar() <clampscalar>`. It does meet the predicate for this rule
-as the type is smaller than the ``s32`` and this rule instructs the legalizer
-to change type 0 to ``s32``. It then restarts from the top. This time it does
-satisfy ``.legalFor()`` and the resulting output is::
-
-  %3:_(s32) = G_ANYEXT %0:_(s7)
-  %4:_(s32) = G_ANYEXT %1:_(s7)
-  %5:_(s32) = G_ADD %3:_(s32), %4:_(s32)
-  %2:_(s7) = G_TRUNC %5:_(s32)
-
-where the ``G_ADD`` is legal and the other instructions are scheduled for
+{ref}`.clampScalar() <clampscalar>`. It does meet the predicate for this rule
+as the type is smaller than the `s32` and this rule instructs the legalizer
+to change type 0 to `s32`. It then restarts from the top. This time it does
+satisfy `.legalFor()` and the resulting output is:
+
+```
+%3:_(s32) = G_ANYEXT %0:_(s7)
+%4:_(s32) = G_ANYEXT %1:_(s7)
+%5:_(s32) = G_ADD %3:_(s32), %4:_(s32)
+%2:_(s7) = G_TRUNC %5:_(s32)
+```
+
+where the `G_ADD` is legal and the other instructions are scheduled for
 processing by the legalizer.
 
-Rule Actions
-""""""""""""
+### Rule Actions
 
 There are various rule factories that append rules to a ruleset, but they have a
 few actions in common:
 
-.. _legalfor:
+(legalfor)=
 
-* ``legalIf()``, ``legalFor()``, etc. declare an instruction to be legal if the
+- `legalIf()`, `legalFor()`, etc. declare an instruction to be legal if the
   predicate is satisfied.
-
-* ``narrowScalarIf()``, ``narrowScalarFor()``, etc. declare an instruction to be illegal
+- `narrowScalarIf()`, `narrowScalarFor()`, etc. declare an instruction to be illegal
   if the predicate is satisfied and indicates that narrowing the scalars in one
   of the types to a specific type would make it more legal. This action supports
   both scalars and vectors.
-
-* ``widenScalarIf()``, ``widenScalarFor()``, etc. declare an instruction to be illegal
+- `widenScalarIf()`, `widenScalarFor()`, etc. declare an instruction to be illegal
   if the predicate is satisfied and indicates that widening the scalars in one
   of the types to a specific type would make it more legal. This action supports
   both scalars and vectors.
-
-* ``fewerElementsIf()``, ``fewerElementsFor()``, etc. declare an instruction to be
+- `fewerElementsIf()`, `fewerElementsFor()`, etc. declare an instruction to be
   illegal if the predicate is satisfied and indicates reducing the number of
   vector elements in one of the types to a specific type would make it more
   legal. This action supports vectors.
-
-* ``moreElementsIf()``, ``moreElementsFor()``, etc. declare an instruction to be illegal
+- `moreElementsIf()`, `moreElementsFor()`, etc. declare an instruction to be illegal
   if the predicate is satisfied and indicates increasing the number of vector
   elements in one of the types to a specific type would make it more legal.
   This action supports vectors.
-
-* ``lowerIf()``, ``lowerFor()``, etc. declare an instruction to be
+- `lowerIf()`, `lowerFor()`, etc. declare an instruction to be
   illegal if the predicate is satisfied and indicates that replacing
   it with equivalent instruction(s) would make it more legal. Support
   for this action differs for each opcode. These may provide an
   optional LegalizeMutation containing a type to attempt to perform
   the expansion in a different type.
-
-* ``libcallIf()``, ``libcallFor()``, etc. declare an instruction to be illegal if the
+- `libcallIf()`, `libcallFor()`, etc. declare an instruction to be illegal if the
   predicate is satisfied and indicates that replacing it with a libcall would
   make it more legal. Support for this action differs for
   each opcode.
-
-* ``customIf()``, ``customFor()``, etc. declare an instruction to be illegal if the
+- `customIf()`, `customFor()`, etc. declare an instruction to be illegal if the
   predicate is satisfied and indicates that the backend developer will supply
   a means of making it more legal.
-
-* ``unsupportedIf()``, ``unsupportedFor()``, etc. declare an instruction to be illegal
+- `unsupportedIf()`, `unsupportedFor()`, etc. declare an instruction to be illegal
   if the predicate is satisfied and indicates that there is no way to make it
   legal and the compiler should fail.
 
-Rule Predicates
-"""""""""""""""
+### Rule Predicates
 
 The rule factories also have the following predicates in common:
 
-* ``legal()``, ``lower()``, etc. are always satisfied.
-
-* ``legalIf()``, ``narrowScalarIf()``, etc. are satisfied if the user-supplied
-  ``LegalityPredicate`` function returns true. This predicate has access to the
-  information in the ``LegalityQuery`` to make its decision.
-  User-supplied predicates can also be combined using ``all(P0, P1, ...)``.
-
-* ``legalFor()``, ``narrowScalarFor()``, etc. are satisfied if the type matches one in
-  a given set of types. For example ``.legalFor({s16, s32})`` declares the
+- `legal()`, `lower()`, etc. are always satisfied.
+- `legalIf()`, `narrowScalarIf()`, etc. are satisfied if the user-supplied
+  `LegalityPredicate` function returns true. This predicate has access to the
+  information in the `LegalityQuery` to make its decision.
+  User-supplied predicates can also be combined using `all(P0, P1, ...)`.
+- `legalFor()`, `narrowScalarFor()`, etc. are satisfied if the type matches one in
+  a given set of types. For example `.legalFor({s16, s32})` declares the
   instruction legal if type 0 is either s16 or s32. Additional versions for two
   and three type indices are generally available. For these, all the type
   indices considered together must match all the types in one of the tuples. So
-  ``.legalFor({{s16, s32}, {s32, s64}})`` will only accept ``{s16, s32}``, or
-  ``{s32, s64}`` but will not accept ``{s16, s64}``.
-
-* ``legalForTypesWithMemSize()``, ``narrowScalarForTypesWithMemSize()``, etc. are
-  similar to ``legalFor()``, ``narrowScalarFor()``, etc. but additionally require a
+  `.legalFor({{s16, s32}, {s32, s64}})` will only accept `{s16, s32}`, or
+  `{s32, s64}` but will not accept `{s16, s64}`.
+- `legalForTypesWithMemSize()`, `narrowScalarForTypesWithMemSize()`, etc. are
+  similar to `legalFor()`, `narrowScalarFor()`, etc. but additionally require a
   MachineMemOperand to have a given size in each tuple.
-
-* ``legalForCartesianProduct()``, ``narrowScalarForCartesianProduct()``, etc. are
+- `legalForCartesianProduct()`, `narrowScalarForCartesianProduct()`, etc. are
   satisfied if each type index matches one element in each of the independent
-  sets. So ``.legalForCartesianProduct({s16, s32}, {s32, s64})`` will accept
-  ``{s16, s32}``, ``{s16, s64}``, ``{s32, s32}``, and ``{s32, s64}``.
+  sets. So `.legalForCartesianProduct({s16, s32}, {s32, s64})` will accept
+  `{s16, s32}`, `{s16, s64}`, `{s32, s32}`, and `{s32, s64}`.
 
-Composite Rules
-"""""""""""""""
+### Composite Rules
 
 There are some composite rules for common situations built out of the above facilities:
 
-* ``widenScalarToNextPow2()`` is like ``widenScalarIf()`` but is satisfied iff the type
+- `widenScalarToNextPow2()` is like `widenScalarIf()` but is satisfied iff the type
   size in bits is not a power of 2 and selects a target type that is the next
   largest power of 2.
 
-.. _clampscalar:
+(clampscalar)=
 
-* ``minScalar()`` is like ``widenScalarIf()`` but is satisfied iff the type
+- `minScalar()` is like `widenScalarIf()` but is satisfied iff the type
   size in bits is smaller than the given minimum and selects the minimum as the
-  target type. Similarly, there is also a ``maxScalar()`` for the maximum and a
-  ``clampScalar()`` to do both at once.
-
-* ``minScalarSameAs()`` is like ``minScalar()`` but the minimum is taken from another
+  target type. Similarly, there is also a `maxScalar()` for the maximum and a
+  `clampScalar()` to do both at once.
+- `minScalarSameAs()` is like `minScalar()` but the minimum is taken from another
   type index.
-
-* ``moreElementsToNextMultiple()`` is like ``moreElementsToNextPow2()`` but is based on
+- `moreElementsToNextMultiple()` is like `moreElementsToNextPow2()` but is based on
   multiples of X rather than powers of 2.
 
-.. _min-legalizerinfo:
+(min-legalizerinfo)=
 
-Minimum Rule Set
-^^^^^^^^^^^^^^^^
+## Minimum Rule Set
 
 GlobalISel's legalizer has a great deal of flexibility in how a given target
 shapes the GMIR that the rest of the backend must handle. However, there are
@@ -259,88 +246,89 @@ a small number of requirements that all targets must meet.
 Before discussing the minimum requirements, we'll need some terminology:
 
 Producer Type Set
-  The set of types which is the union of all possible types produced by at
+
+: The set of types which is the union of all possible types produced by at
   least one legal instruction.
 
 Consumer Type Set
-  The set of types which is the union of all possible types consumed by at
+
+: The set of types which is the union of all possible types consumed by at
   least one legal instruction.
 
 Both sets are often identical, but there's no guarantee of that. For example,
 it's not uncommon to be unable to consume s64 but still be able to produce it
 for a few specific instructions.
 
-Minimum Rules For Scalars
-"""""""""""""""""""""""""
+### Minimum Rules For Scalars
 
-* ``G_ANYEXT`` must be legal for all inputs from the producer type set and all larger
+- `G_ANYEXT` must be legal for all inputs from the producer type set and all larger
   outputs from the consumer type set.
-* ``G_TRUNC`` must be legal for all inputs from the producer type set and all
+- `G_TRUNC` must be legal for all inputs from the producer type set and all
   smaller outputs from the consumer type set.
 
-``G_ANYEXT`` and ``G_TRUNC`` have mandatory legality since the GMIR requires a means to
+`G_ANYEXT` and `G_TRUNC` have mandatory legality since the GMIR requires a means to
 connect operations with different type sizes. They are usually trivial to support
-since ``G_ANYEXT`` doesn't define the value of the additional bits and ``G_TRUNC`` is
-discarding bits. The other conversions can be lowered into ``G_ANYEXT``/``G_TRUNC``
+since `G_ANYEXT` doesn't define the value of the additional bits and `G_TRUNC` is
+discarding bits. The other conversions can be lowered into `G_ANYEXT`/`G_TRUNC`
 with some additional operations that are subject to further legalization. For
-example, ``G_SEXT`` can lower to::
+example, `G_SEXT` can lower to:
 
-  %1 = G_ANYEXT %0
-  %2 = G_CONSTANT ...
-  %3 = G_SHL %1, %2
-  %4 = G_ASHR %3, %2
+```
+%1 = G_ANYEXT %0
+%2 = G_CONSTANT ...
+%3 = G_SHL %1, %2
+%4 = G_ASHR %3, %2
+```
 
-and the ``G_CONSTANT``/``G_SHL``/``G_ASHR`` can further lower to other operations or target
-instructions. Similarly, ``G_FPEXT`` has no legality requirement since it can lower
-to a ``G_ANYEXT`` followed by a target instruction.
+and the `G_CONSTANT`/`G_SHL`/`G_ASHR` can further lower to other operations or target
+instructions. Similarly, `G_FPEXT` has no legality requirement since it can lower
+to a `G_ANYEXT` followed by a target instruction.
 
-``G_MERGE_VALUES`` and ``G_UNMERGE_VALUES`` do not have legality requirements since the
-former can lower to ``G_ANYEXT`` and some other legalizable instructions, while the
-latter can lower to some legalizable instructions followed by ``G_TRUNC``.
+`G_MERGE_VALUES` and `G_UNMERGE_VALUES` do not have legality requirements since the
+former can lower to `G_ANYEXT` and some other legalizable instructions, while the
+latter can lower to some legalizable instructions followed by `G_TRUNC`.
 
-Minimum Legality For Vectors
-""""""""""""""""""""""""""""
+### Minimum Legality For Vectors
 
 Within the vector types, there aren't any defined conversions in LLVM IR as
 vectors are often converted by reinterpreting the bits or by decomposing the
-vector and reconstituting it as a different type. As such, ``G_BITCAST`` is the
+vector and reconstituting it as a different type. As such, `G_BITCAST` is the
 only operation to account for. We generally don't require that it's legal
-because it can usually be lowered to ``COPY`` (or to nothing using
-``replaceAllUses()``). However, there are situations where ``G_BITCAST`` is non-trivial
+because it can usually be lowered to `COPY` (or to nothing using
+`replaceAllUses()`). However, there are situations where `G_BITCAST` is non-trivial
 (e.g. little-endian vectors of big-endian data such as on big-endian MIPS MSA and
-big-endian ARM NEON, see `_i_bitcast`). To account for this, ``G_BITCAST`` must be
+big-endian ARM NEON, see `_i_bitcast`). To account for this, `G_BITCAST` must be
 legal for all type combinations that change the bit pattern in the value.
 
-There are no legality requirements for ``G_BUILD_VECTOR``, or ``G_BUILD_VECTOR_TRUNC``
+There are no legality requirements for `G_BUILD_VECTOR`, or `G_BUILD_VECTOR_TRUNC`
 since these can be handled by:
-* Declaring them legal.
-* Scalarizing them.
-* Lowering them to ``G_TRUNC``+``G_ANYEXT`` and some legalizable instructions.
-* Lowering them to target instructions which are legal by definition.
+\* Declaring them legal.
+\* Scalarizing them.
+\* Lowering them to ``` G_TRUNC``+``G_ANYEXT ``` and some legalizable instructions.
+\* Lowering them to target instructions which are legal by definition.
 
-The same reasoning also allows ``G_UNMERGE_VALUES`` to lack legality requirements
+The same reasoning also allows `G_UNMERGE_VALUES` to lack legality requirements
 for vector inputs.
 
-Minimum Legality for Pointers
-"""""""""""""""""""""""""""""
+### Minimum Legality for Pointers
 
-There are no minimum rules for pointers since ``G_INTTOPTR`` and ``G_PTRTOINT`` can
-be selected to a ``COPY`` from register class to another by the legalizer.
+There are no minimum rules for pointers since `G_INTTOPTR` and `G_PTRTOINT` can
+be selected to a `COPY` from register class to another by the legalizer.
 
-Minimum Legality For Operations
-"""""""""""""""""""""""""""""""
+### Minimum Legality For Operations
 
-The rules for ``G_ANYEXT``, ``G_MERGE_VALUES``, ``G_BITCAST``, ``G_BUILD_VECTOR``,
-``G_BUILD_VECTOR_TRUNC``, ``G_CONCAT_VECTORS``, ``G_UNMERGE_VALUES``, ``G_PTRTOINT``, and
-``G_INTTOPTR`` have already been noted above. In addition to those, the following
+The rules for `G_ANYEXT`, `G_MERGE_VALUES`, `G_BITCAST`, `G_BUILD_VECTOR`,
+`G_BUILD_VECTOR_TRUNC`, `G_CONCAT_VECTORS`, `G_UNMERGE_VALUES`, `G_PTRTOINT`, and
+`G_INTTOPTR` have already been noted above. In addition to those, the following
 operations have requirements:
 
-* ``G_IMPLICIT_DEF`` must be legal for every type that can be produced
-   by any instruction.
-* ``G_PHI`` must be legal for all types in the producer and consumer typesets. This
+- `G_IMPLICIT_DEF` must be legal for every type that can be produced
+  : by any instruction.
+- `G_PHI` must be legal for all types in the producer and consumer typesets. This
   is usually trivial as it requires no code to be selected.
-* At least one ``G_FRAME_INDEX`` must be legal
-* At least one ``G_BLOCK_ADDR`` must be legal
+- At least one `G_FRAME_INDEX` must be legal
+- At least one `G_BLOCK_ADDR` must be legal
 
 There are many other operations you'd expect to have legality requirements, but
 they can be lowered to target instructions which are legal by definition.
+
diff --git a/llvm/docs/GlobalISel/MIRPatterns.md b/llvm/docs/GlobalISel/MIRPatterns.md
index a7974eca55ebc..8253edf463562 100644
--- a/llvm/docs/GlobalISel/MIRPatterns.md
+++ b/llvm/docs/GlobalISel/MIRPatterns.md
@@ -1,683 +1,675 @@
+(tblgen-mirpats)=
 
-.. _tblgen-mirpats:
+# MIR Patterns in TableGen
 
-========================
-MIR Patterns in TableGen
-========================
-
-
-
-User's Guide
-============
+## User's Guide
 
 This section is intended for developers who want to use MIR patterns in their
 TableGen files.
 
-``NOTE``:
+`NOTE`:
 This feature is still in active development. This document may become outdated
 over time. If you see something that's incorrect, please update it.
 
-Use Cases
----------
+### Use Cases
 
 MIR patterns are supported in the following places:
 
-* GlobalISel ``GICombineRule``
-* GlobalISel ``GICombinePatFrag``
+- GlobalISel `GICombineRule`
+- GlobalISel `GICombinePatFrag`
 
-Syntax
-------
+### Syntax
 
 MIR patterns use the DAG datatype in TableGen.
 
-.. code-block:: text
+```text
+(inst operand0, operand1, ...)
+```
 
-  (inst operand0, operand1, ...)
-
-``inst`` must be a def which inherits from ``Instruction`` (e.g. ``G_FADD``),
-``Intrinsic`` or ``GICombinePatFrag``.
+`inst` must be a def which inherits from `Instruction` (e.g. `G_FADD`),
+`Intrinsic` or `GICombinePatFrag`.
 
 Operands essentially fall into one of two categories:
 
-* immediates
+- immediates
 
-  * untyped, unnamed: ``0``
-  * untyped, named: ``0:$y``
-  * typed, unnamed: ``(i32 0)``
-  * typed, named: ``(i32 0):$y``
+  - untyped, unnamed: `0`
+  - untyped, named: `0:$y`
+  - typed, unnamed: `(i32 0)`
+  - typed, named: `(i32 0):$y`
 
-* machine operands
+- machine operands
 
-  * untyped: ``$x``
-  * typed: ``i32:$x``
+  - untyped: `$x`
+  - typed: `i32:$x`
 
 Semantics:
 
-* A typed operand always adds an operand type check to the matcher.
-* There is a trivial type inference system to propagate types.
+- A typed operand always adds an operand type check to the matcher.
+
+- There is a trivial type inference system to propagate types.
 
-  * e.g. You only need to use ``i32:$x`` once in any pattern of a
-    ``GICombinePatFrag`` alternative or ``GICombineRule``, then all
-    other patterns in that rule/alternative can simply use ``$x``
-    (``i32:$x`` is redundant).
+  - e.g. You only need to use `i32:$x` once in any pattern of a
+    `GICombinePatFrag` alternative or `GICombineRule`, then all
+    other patterns in that rule/alternative can simply use `$x`
+    (`i32:$x` is redundant).
 
-* A named operand's behavior depends on whether the name has been seen before.
+- A named operand's behavior depends on whether the name has been seen before.
 
-  * For match patterns, reusing an operand name checks that the operands
+  - For match patterns, reusing an operand name checks that the operands
     are identical (see example 2 below).
-  * For apply patterns, reusing an operand name simply copies that operand into
+  - For apply patterns, reusing an operand name simply copies that operand into
     the new instruction (see example 2 below).
 
 Operands are ordered just like they would be in a MachineInstr: the defs (outs)
 come first, then the uses (ins).
 
 Patterns are generally grouped into another DAG datatype with a dummy operator
-such as ``match``, ``apply``, ``combine`` or ``pattern``.
+such as `match`, `apply`, `combine` or `pattern`.
 
 Finally, any DAG datatype in TableGen can be named. This also holds for
-patterns. e.g. the following is valid: ``(G_FOO $root, (i32 0):$cst):$mypat``.
+patterns. e.g. the following is valid: `(G_FOO $root, (i32 0):$cst):$mypat`.
 This may also be helpful to debug issues. Patterns are *always* named, and if
 they don't have a name, an "anonymous" one is given to them. If you're trying
 to debug an error related to a MIR pattern, but the error mentions an anonymous
 pattern, you can try naming your patterns to see exactly where the issue is.
 
-.. code-block:: text
-  :caption: Pattern Example 1
+```{code-block} text
+:caption: Pattern Example 1
 
-  // Match
-  //    %imp = G_IMPLICIT_DEF
-  //    %root = G_MUL %x, %imp
-  (match (G_IMPLICIT_DEF $imp),
-         (G_MUL $root, $x, $imp))
+// Match
+//    %imp = G_IMPLICIT_DEF
+//    %root = G_MUL %x, %imp
+(match (G_IMPLICIT_DEF $imp),
+       (G_MUL $root, $x, $imp))
+```
 
-.. code-block:: text
-  :caption: Pattern Example 2
+```{code-block} text
+:caption: Pattern Example 2
 
-  // using $x twice here checks that the operand 1 and 2 of the G_AND are
-  // identical.
-  (match (G_AND $root, $x, $x))
-  // using $x again here copies operand 1 from G_AND into the new inst.
-  (apply (COPY $root, $x))
+// using $x twice here checks that the operand 1 and 2 of the G_AND are
+// identical.
+(match (G_AND $root, $x, $x))
+// using $x again here copies operand 1 from G_AND into the new inst.
+(apply (COPY $root, $x))
+```
 
-Types
------
+### Types
 
-ValueType
-~~~~~~~~~
+#### ValueType
 
-Subclasses of ``ValueType`` are valid types, e.g. ``i32``.
+Subclasses of `ValueType` are valid types, e.g. `i32`.
 
-GITypeOf
-~~~~~~~~
+#### GITypeOf
 
-``GITypeOf<"$x">`` is a ``GISpecialType`` that allows for the creation of a
+`GITypeOf<"$x">` is a `GISpecialType` that allows for the creation of a
 register or immediate with the same type as another (register) operand.
 
 Type Parameters:
 
-* An operand name as a string, prefixed by ``$``.
+- An operand name as a string, prefixed by `$`.
 
 Semantics:
 
-* Can only appear in an 'apply' pattern.
-* The operand name used must appear in the 'match' pattern of the
-  same ``GICombineRule``.
+- Can only appear in an 'apply' pattern.
+- The operand name used must appear in the 'match' pattern of the
+  same `GICombineRule`.
 
-.. code-block:: text
-  :caption: Example: Immediate
+```{code-block} text
+:caption: 'Example: Immediate'
 
-  def mul_by_neg_one: GICombineRule <
-    (defs root:$root),
-    (match (G_MUL $dst, $x, -1)),
-    (apply (G_SUB $dst, (GITypeOf<"$x"> 0), $x))
-  >;
+def mul_by_neg_one: GICombineRule <
+  (defs root:$root),
+  (match (G_MUL $dst, $x, -1)),
+  (apply (G_SUB $dst, (GITypeOf<"$x"> 0), $x))
+>;
+```
 
-.. code-block:: text
-  :caption: Example: Temp Reg
+```{code-block} text
+:caption: 'Example: Temp Reg'
 
-  def Test0 : GICombineRule<
-    (defs root:$dst),
-    (match (G_FMUL $dst, $src, -1)),
-    (apply (G_FSUB $dst, $src, $tmp),
-           (G_FNEG GITypeOf<"$dst">:$tmp, $src))>;
+def Test0 : GICombineRule<
+  (defs root:$dst),
+  (match (G_FMUL $dst, $src, -1)),
+  (apply (G_FSUB $dst, $src, $tmp),
+         (G_FNEG GITypeOf<"$dst">:$tmp, $src))>;
+```
 
-GIVariadic
-~~~~~~~~~~
+#### GIVariadic
 
-``GIVariadic<>`` is a ``GISpecialType`` that allows for matching 1 or
+`GIVariadic<>` is a `GISpecialType` that allows for matching 1 or
 more operands remaining on an instruction.
 
 Type Parameters:
 
-* The minimum number of additional operands to match. Must be greater than zero.
+- The minimum number of additional operands to match. Must be greater than zero.
 
-  * Default is 1.
+  - Default is 1.
 
-* The maximum number of additional operands to match. Must be strictly greater
+- The maximum number of additional operands to match. Must be strictly greater
   than the minimum.
 
-  * 0 can be used to indicate there is no upper limit.
-  * Default is 0.
+  - 0 can be used to indicate there is no upper limit.
+  - Default is 0.
 
 Semantics:
 
-* ``GIVariadic<>`` operands can only appear on variadic instructions.
-* ``GIVariadic<>`` operands cannot be defs.
-* ``GIVariadic<>`` operands can only appear as the last operand in a 'match' pattern.
-* Each instance within a 'match' pattern must be uniquely named.
-* Re-using a ``GIVariadic<>`` operand in an 'apply' pattern will result in all
+- `GIVariadic<>` operands can only appear on variadic instructions.
+- `GIVariadic<>` operands cannot be defs.
+- `GIVariadic<>` operands can only appear as the last operand in a 'match' pattern.
+- Each instance within a 'match' pattern must be uniquely named.
+- Re-using a `GIVariadic<>` operand in an 'apply' pattern will result in all
   the matched operands being copied from the original instruction.
-* The min/max operands will result in the matcher checking that the number of operands
+- The min/max operands will result in the matcher checking that the number of operands
   falls within that range.
-* ``GIVariadic<>`` operands can be used in C++ code within a rule, which will
-  result in the operand name being expanded to a value of type ``ArrayRef<MachineOperand>``.
-
-.. code-block:: text
-
-  // bool checkBuildVectorToUnmerge(ArrayRef<MachineOperand>);
-
-  def build_vector_to_unmerge: GICombineRule <
-    (defs root:$root),
-    (match (G_BUILD_VECTOR $root, GIVariadic<>:$args),
-           [{ return checkBuildVectorToUnmerge(${args}); }]),
-    (apply (G_UNMERGE_VALUES $root, $args))
-  >;
-
-.. code-block:: text
-
-  // Will additionally check the number of operands is >= 3 and <= 5.
-  // ($root is one operand, then 2 to 4 variadic operands).
-  def build_vector_to_unmerge: GICombineRule <
-    (defs root:$root),
-    (match (G_BUILD_VECTOR $root, GIVariadic<2, 4>:$two_to_four),
-           [{ return checkBuildVectorToUnmerge(${two_to_four}); }]),
-    (apply (G_UNMERGE_VALUES $root, $two_to_four))
-  >;
-
-Builtin Operations
-------------------
+- `GIVariadic<>` operands can be used in C++ code within a rule, which will
+  result in the operand name being expanded to a value of type `ArrayRef<MachineOperand>`.
+
+```text
+// bool checkBuildVectorToUnmerge(ArrayRef<MachineOperand>);
+
+def build_vector_to_unmerge: GICombineRule <
+  (defs root:$root),
+  (match (G_BUILD_VECTOR $root, GIVariadic<>:$args),
+         [{ return checkBuildVectorToUnmerge(${args}); }]),
+  (apply (G_UNMERGE_VALUES $root, $args))
+>;
+```
+
+```text
+// Will additionally check the number of operands is >= 3 and <= 5.
+// ($root is one operand, then 2 to 4 variadic operands).
+def build_vector_to_unmerge: GICombineRule <
+  (defs root:$root),
+  (match (G_BUILD_VECTOR $root, GIVariadic<2, 4>:$two_to_four),
+         [{ return checkBuildVectorToUnmerge(${two_to_four}); }]),
+  (apply (G_UNMERGE_VALUES $root, $two_to_four))
+>;
+```
+
+### Builtin Operations
 
 MIR Patterns also offer builtin operations, also called "builtin instructions".
 They offer some powerful features that would otherwise require use of C++ code.
 
-GIReplaceReg
-~~~~~~~~~~~~
+#### GIReplaceReg
 
-.. code-block:: text
-  :caption: Usage
+```{code-block} text
+:caption: Usage
 
-  (apply (GIReplaceReg $old, $new))
+(apply (GIReplaceReg $old, $new))
+```
 
 Operands:
 
-* ``$old`` (out) register defined by a matched instruction
-* ``$new`` (in)  register
+- `$old` (out) register defined by a matched instruction
+- `$new` (in) register
 
 Semantics:
 
-* Can only appear in an 'apply' pattern.
-* If both old/new are operands of matched instructions,
-  ``canReplaceReg`` is checked before applying the rule.
+- Can only appear in an 'apply' pattern.
+- If both old/new are operands of matched instructions,
+  `canReplaceReg` is checked before applying the rule.
 
+#### GIEraseRoot
 
-GIEraseRoot
-~~~~~~~~~~~
+```{code-block} text
+:caption: Usage
 
-.. code-block:: text
-  :caption: Usage
-
-  (apply (GIEraseRoot))
+(apply (GIEraseRoot))
+```
 
 Semantics:
 
-* Can only appear as the only pattern of an 'apply' pattern list.
-* The root cannot have any output operands.
-* The root must be a CodeGenInstruction
+- Can only appear as the only pattern of an 'apply' pattern list.
+- The root cannot have any output operands.
+- The root must be a CodeGenInstruction
 
-Instruction Flags
------------------
+### Instruction Flags
 
-MIR Patterns support both matching & writing ``MIFlags``.
+MIR Patterns support both matching & writing `MIFlags`.
 
-.. code-block:: text
-  :caption: Example
+```{code-block} text
+:caption: Example
 
-  def Test : GICombineRule<
-    (defs root:$dst),
-    (match (G_FOO $dst, $src, (MIFlags FmNoNans, FmNoInfs))),
-    (apply (G_BAR $dst, $src, (MIFlags FmReassoc)))>;
+def Test : GICombineRule<
+  (defs root:$dst),
+  (match (G_FOO $dst, $src, (MIFlags FmNoNans, FmNoInfs))),
+  (apply (G_BAR $dst, $src, (MIFlags FmReassoc)))>;
+```
 
-In ``apply`` patterns, we also support referring to a matched instruction to
+In `apply` patterns, we also support referring to a matched instruction to
 "take" its MIFlags.
 
-.. code-block:: text
-  :caption: Example
+```{code-block} text
+:caption: Example
 
-  ; We match NoNans/NoInfs, but $zext may have more flags.
-  ; Copy them all into the output instruction, and set Reassoc on the output inst.
-  def TestCpyFlags : GICombineRule<
-    (defs root:$dst),
-    (match (G_FOO $dst, $src, (MIFlags FmNoNans, FmNoInfs)):$zext),
-    (apply (G_BAR $dst, $src, (MIFlags $zext, FmReassoc)))>;
+; We match NoNans/NoInfs, but $zext may have more flags.
+; Copy them all into the output instruction, and set Reassoc on the output inst.
+def TestCpyFlags : GICombineRule<
+  (defs root:$dst),
+  (match (G_FOO $dst, $src, (MIFlags FmNoNans, FmNoInfs)):$zext),
+  (apply (G_BAR $dst, $src, (MIFlags $zext, FmReassoc)))>;
+```
 
-The ``not`` operator can be used to check that a flag is NOT present
+The `not` operator can be used to check that a flag is NOT present
 on a matched instruction, and to remove a flag from a generated instruction.
 
-.. code-block:: text
-  :caption: Example
+```{code-block} text
+:caption: Example
 
-  ; We match NoInfs but we don't want NoNans/Reassoc to be set. $zext may have more flags.
-  ; Copy them all into the output instruction but remove NoInfs on the output inst.
-  def TestNot : GICombineRule<
-    (defs root:$dst),
-    (match (G_FOO $dst, $src, (MIFlags FmNoInfs, (not FmNoNans, FmReassoc))):$zext),
-    (apply (G_BAR $dst, $src, (MIFlags $zext, (not FmNoInfs))))>;
+; We match NoInfs but we don't want NoNans/Reassoc to be set. $zext may have more flags.
+; Copy them all into the output instruction but remove NoInfs on the output inst.
+def TestNot : GICombineRule<
+  (defs root:$dst),
+  (match (G_FOO $dst, $src, (MIFlags FmNoInfs, (not FmNoNans, FmReassoc))):$zext),
+  (apply (G_BAR $dst, $src, (MIFlags $zext, (not FmNoInfs))))>;
+```
 
-Limitations
------------
+### Limitations
 
 This a non-exhaustive list of known issues with MIR patterns at this time.
 
-* Using ``GICombinePatFrag`` within another ``GICombinePatFrag`` is not
+- Using `GICombinePatFrag` within another `GICombinePatFrag` is not
   supported.
-* ``GICombinePatFrag`` can only have a single root.
-* Instructions with multiple defs cannot be the root of a ``GICombinePatFrag``.
-* Using ``GICombinePatFrag`` in the ``apply`` pattern of a ``GICombineRule``
+- `GICombinePatFrag` can only have a single root.
+- Instructions with multiple defs cannot be the root of a `GICombinePatFrag`.
+- Using `GICombinePatFrag` in the `apply` pattern of a `GICombineRule`
   is not supported.
-* We cannot rewrite a matched instruction other than the root.
-* Matching/creating a (CImm) immediate >64 bits is not supported
-  (see comment in ``GIM_CheckConstantInt``)
-* There is currently no way to constrain two register/immediate types to
+- We cannot rewrite a matched instruction other than the root.
+- Matching/creating a (CImm) immediate >64 bits is not supported
+  (see comment in `GIM_CheckConstantInt`)
+- There is currently no way to constrain two register/immediate types to
   match. e.g. if a pattern needs to work on both i32 and i64, you either
   need to leave it untyped and check the type in C++, or duplicate the
   pattern.
-* ``GISpecialType`` operands are not allowed within a ``GICombinePatFrag``.
-* ``GIVariadic<>`` matched operands must each have a unique name.
+- `GISpecialType` operands are not allowed within a `GICombinePatFrag`.
+- `GIVariadic<>` matched operands must each have a unique name.
 
-GICombineRule
--------------
+### GICombineRule
 
-MIR patterns can appear in the ``match`` or ``apply`` patterns of a
-``GICombineRule``.
+MIR patterns can appear in the `match` or `apply` patterns of a
+`GICombineRule`.
 
-The ``root`` of the rule can either be a def of an instruction, or a
+The `root` of the rule can either be a def of an instruction, or a
 named pattern. The latter is helpful when the instruction you want
 to match has no defs. The former is generally preferred because
 it's less verbose.
 
-.. code-block:: text
-  :caption: Combine Rule root is a def
-
-  // Fold x op 1 -> x
-  def right_identity_one: GICombineRule<
-    (defs root:$dst),
-    (match (G_MUL $dst, $x, 1)),
-    // Note: Patterns always need to create something, we can't just replace $dst with $x, so we need a COPY.
-    (apply (COPY $dst, $x))
-  >;
+```{code-block} text
+:caption: Combine Rule root is a def
 
-.. code-block:: text
-  :caption: Combine Rule root is a named pattern
+// Fold x op 1 -> x
+def right_identity_one: GICombineRule<
+  (defs root:$dst),
+  (match (G_MUL $dst, $x, 1)),
+  // Note: Patterns always need to create something, we can't just replace $dst with $x, so we need a COPY.
+  (apply (COPY $dst, $x))
+>;
+```
 
-  def Foo : GICombineRule<
-    (defs root:$root),
-    (match (G_ZEXT $tmp, (i32 0)),
-           (G_STORE $tmp, $ptr):$root),
-    (apply (G_STORE (i32 0), $ptr):$root)>;
+```{code-block} text
+:caption: Combine Rule root is a named pattern
 
+def Foo : GICombineRule<
+  (defs root:$root),
+  (match (G_ZEXT $tmp, (i32 0)),
+         (G_STORE $tmp, $ptr):$root),
+  (apply (G_STORE (i32 0), $ptr):$root)>;
+```
 
 Combine Rules also allow mixing C++ code with MIR patterns, so that you
 may perform additional checks when matching, or run a C++ action after
 matching.
 
-Note that C++ code in ``apply`` pattern is mutually exclusive with
+Note that C++ code in `apply` pattern is mutually exclusive with
 other patterns. However, you can freely mix C++ code with other
-types of patterns in ``match`` patterns.
-C++ code in ``match`` patterns is always run last, after all other
+types of patterns in `match` patterns.
+C++ code in `match` patterns is always run last, after all other
 patterns matched.
 
-.. code-block:: text
-  :caption: Apply Pattern Examples with C++ code
-
-  // Valid
-  def Foo : GICombineRule<
-    (defs root:$root),
-    (match (G_ZEXT $tmp, (i32 0)),
-           (G_STORE $tmp, $ptr):$root,
-           "return myFinalCheck()"),
-    (apply "runMyAction(${root})")>;
-
-  // error: 'apply' patterns cannot mix C++ code with other types of patterns
-  def Bar : GICombineRule<
-    (defs root:$dst),
-    (match (G_ZEXT $dst, $src):$mi),
-    (apply (G_MUL $dst, $src, $src),
-           "runMyAction(${root})")>;
+```{code-block} text
+:caption: Apply Pattern Examples with C++ code
+
+// Valid
+def Foo : GICombineRule<
+  (defs root:$root),
+  (match (G_ZEXT $tmp, (i32 0)),
+         (G_STORE $tmp, $ptr):$root,
+         "return myFinalCheck()"),
+  (apply "runMyAction(${root})")>;
+
+// error: 'apply' patterns cannot mix C++ code with other types of patterns
+def Bar : GICombineRule<
+  (defs root:$dst),
+  (match (G_ZEXT $dst, $src):$mi),
+  (apply (G_MUL $dst, $src, $src),
+         "runMyAction(${root})")>;
+```
 
 The following expansions are available for MIR patterns:
 
-* operand names (``MachineOperand &``)
-* pattern names (``MachineInstr *`` for ``match``,
-  ``MachineInstrBuilder &`` for apply)
+- operand names (`MachineOperand &`)
+- pattern names (`MachineInstr *` for `match`,
+  `MachineInstrBuilder &` for apply)
 
-.. code-block:: text
-  :caption: Example C++ Expansions
+```{code-block} text
+:caption: Example C++ Expansions
 
-  def Foo : GICombineRule<
-    (defs root:$root),
-    (match (G_ZEXT $root, $src):$mi),
-    (apply "foobar(${root}.getReg(), ${src}.getReg(), ${mi}->hasImplicitDef())")>;
+def Foo : GICombineRule<
+  (defs root:$root),
+  (match (G_ZEXT $root, $src):$mi),
+  (apply "foobar(${root}.getReg(), ${src}.getReg(), ${mi}->hasImplicitDef())")>;
+```
 
-``combine`` Operator
-~~~~~~~~~~~~~~~~~~~~
+#### `combine` Operator
 
-``GICombineRule`` also supports a single ``combine`` pattern, which is a shorter way to
+`GICombineRule` also supports a single `combine` pattern, which is a shorter way to
 declare patterns that just match one or more instructions, then defer all remaining matching
 and rewriting logic to C++ code.
 
-.. code-block:: text
-  :caption: Example usage of the combine operator.
+```{code-block} text
+:caption: Example usage of the combine operator.
 
-  // match + apply
-  def FooLong : GICombineRule<
-    (defs root:$root),
-    (match (G_ZEXT $root, $src):$mi, "return matchFoo(${mi});"),
-    (apply "applyFoo(${mi});")>;
+// match + apply
+def FooLong : GICombineRule<
+  (defs root:$root),
+  (match (G_ZEXT $root, $src):$mi, "return matchFoo(${mi});"),
+  (apply "applyFoo(${mi});")>;
 
-  // combine
-  def FooShort : GICombineRule<
-    (defs root:$root),
-    (combine (G_ZEXT $root, $src):$mi, "return combineFoo(${mi});")>;
+// combine
+def FooShort : GICombineRule<
+  (defs root:$root),
+  (combine (G_ZEXT $root, $src):$mi, "return combineFoo(${mi});")>;
+```
 
 This has a couple of advantages:
 
-* We only need one C++ function, not two.
-* We no longer need to use ``GIDefMatchData`` to pass information between the match/apply functions.
-
-As described above, this is syntactic sugar for the match+apply form. In a ``combine`` pattern:
+- We only need one C++ function, not two.
+- We no longer need to use `GIDefMatchData` to pass information between the match/apply functions.
 
-* Everything except C++ code is considered the ``match`` part.
-* The C++ code is the ``apply`` part. C++ code is emitted in order of appearance.
+As described above, this is syntactic sugar for the match+apply form. In a `combine` pattern:
 
-.. note::
+- Everything except C++ code is considered the `match` part.
+- The C++ code is the `apply` part. C++ code is emitted in order of appearance.
 
-  The C++ code **must** return true if it changed any instruction. Returning false when changing
-  instructions is undefined behavior.
+:::{note}
+The C++ code **must** return true if it changed any instruction. Returning false when changing
+instructions is undefined behavior.
+:::
 
-Common Pattern #1: Replace a Register with Another
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#### Common Pattern #1: Replace a Register with Another
 
 The 'apply' pattern must always redefine all operands defined by the match root.
 Sometimes, we do not need to create instructions, simply replace a def with
-another matched register. The ``GIReplaceReg`` builtin can do just that.
-
-.. code-block:: text
+another matched register. The `GIReplaceReg` builtin can do just that.
 
-  def Foo : GICombineRule<
-    (defs root:$dst),
-    (match (G_FNEG $tmp, $src), (G_FNEG $dst, $tmp)),
-    (apply (GIReplaceReg $dst, $src))>;
+```text
+def Foo : GICombineRule<
+  (defs root:$dst),
+  (match (G_FNEG $tmp, $src), (G_FNEG $dst, $tmp)),
+  (apply (GIReplaceReg $dst, $src))>;
+```
 
 This also works if the replacement register is a temporary register from the
-``apply`` pattern.
+`apply` pattern.
 
-.. code-block:: text
+```text
+def ReplaceTemp : GICombineRule<
+  (defs root:$a),
+  (match    (G_BUILD_VECTOR $tmp, $x, $y),
+            (G_UNMERGE_VALUES $a, $b, $tmp)),
+  (apply  (G_UNMERGE_VALUES $a, i32:$new, $y),
+          (GIReplaceReg $b, $new))>
+```
 
-  def ReplaceTemp : GICombineRule<
-    (defs root:$a),
-    (match    (G_BUILD_VECTOR $tmp, $x, $y),
-              (G_UNMERGE_VALUES $a, $b, $tmp)),
-    (apply  (G_UNMERGE_VALUES $a, i32:$new, $y),
-            (GIReplaceReg $b, $new))>
-
-Common Pattern #2: Erasing a Def-less Root
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#### Common Pattern #2: Erasing a Def-less Root
 
 If we simply want to erase a def-less match root, we can use the
-``GIEraseRoot`` builtin.
-
-.. code-block:: text
+`GIEraseRoot` builtin.
 
-  def Foo : GICombineRule<
-    (defs root:$mi),
-    (match (G_STORE $a, $b):$mi),
-    (apply (GIEraseRoot))>;
+```text
+def Foo : GICombineRule<
+  (defs root:$mi),
+  (match (G_STORE $a, $b):$mi),
+  (apply (GIEraseRoot))>;
+```
 
-Common Pattern #3: Emitting a Constant Value
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#### Common Pattern #3: Emitting a Constant Value
 
 When an immediate operand appears in an 'apply' pattern, the behavior
 depends on whether it's typed or not.
 
-* If the immediate is typed, ``MachineIRBuilder::buildConstant`` is used
-  to create a ``G_CONSTANT``. A ``G_BUILD_VECTOR`` will be used for vectors.
-* If the immediate is untyped, a simple immediate is added
-  (``MachineInstrBuilder::addImm``).
-
-There is of course a special case for ``G_CONSTANT``. Immediates for
-``G_CONSTANT`` must always be typed, and a CImm is added
-(``MachineInstrBuilder::addCImm``).
-
-.. code-block:: text
-  :caption: Constant Emission Examples:
-
-  // Example output:
-  //    %0 = G_CONSTANT i32 0
-  //    %dst = COPY %0
-  def Foo : GICombineRule<
-    (defs root:$dst),
-    (match (G_FOO $dst, $src)),
-    (apply (COPY $dst, (i32 0)))>;
-
-  // Example output:
-  //    %dst = COPY 0
-  // Note that this would be ill-formed because COPY
-  // expects a register operand!
-  def Bar : GICombineRule<
-    (defs root:$dst),
-    (match (G_FOO $dst, $src)),
-    (apply (COPY $dst, (i32 0)))>;
-
-  // Example output:
-  //    %dst = G_CONSTANT i32 0
-  def Bux : GICombineRule<
-    (defs root:$dst),
-    (match (G_FOO $dst, $src)),
-    (apply (G_CONSTANT $dst, (i32 0)))>;
-
-GICombinePatFrag
-----------------
-
-``GICombinePatFrag`` is an equivalent of ``PatFrags`` for MIR patterns.
+- If the immediate is typed, `MachineIRBuilder::buildConstant` is used
+  to create a `G_CONSTANT`. A `G_BUILD_VECTOR` will be used for vectors.
+- If the immediate is untyped, a simple immediate is added
+  (`MachineInstrBuilder::addImm`).
+
+There is of course a special case for `G_CONSTANT`. Immediates for
+`G_CONSTANT` must always be typed, and a CImm is added
+(`MachineInstrBuilder::addCImm`).
+
+```{code-block} text
+:caption: 'Constant Emission Examples:'
+
+// Example output:
+//    %0 = G_CONSTANT i32 0
+//    %dst = COPY %0
+def Foo : GICombineRule<
+  (defs root:$dst),
+  (match (G_FOO $dst, $src)),
+  (apply (COPY $dst, (i32 0)))>;
+
+// Example output:
+//    %dst = COPY 0
+// Note that this would be ill-formed because COPY
+// expects a register operand!
+def Bar : GICombineRule<
+  (defs root:$dst),
+  (match (G_FOO $dst, $src)),
+  (apply (COPY $dst, (i32 0)))>;
+
+// Example output:
+//    %dst = G_CONSTANT i32 0
+def Bux : GICombineRule<
+  (defs root:$dst),
+  (match (G_FOO $dst, $src)),
+  (apply (G_CONSTANT $dst, (i32 0)))>;
+```
+
+### GICombinePatFrag
+
+`GICombinePatFrag` is an equivalent of `PatFrags` for MIR patterns.
 They have two main usecases:
 
-* Reduce repetition by creating a ``GICombinePatFrag`` for common
+- Reduce repetition by creating a `GICombinePatFrag` for common
   patterns (see example 1).
-* Implicitly duplicate a CombineRule for multiple variants of a
+- Implicitly duplicate a CombineRule for multiple variants of a
   pattern (see example 2).
 
-A ``GICombinePatFrag`` is composed of three elements:
+A `GICombinePatFrag` is composed of three elements:
+
+- zero or more `in` (def) parameter
 
-* zero or more ``in`` (def) parameter
-* zero or more ``out`` parameter
-* A list of MIR patterns that can match.
+- zero or more `out` parameter
 
-  * When a ``GICombinePatFrag`` is used within a pattern, the pattern is
+- A list of MIR patterns that can match.
+
+  - When a `GICombinePatFrag` is used within a pattern, the pattern is
     cloned once for each alternative that can match.
 
 Parameters can have the following types:
 
-* ``gi_mo``, which is the implicit default (no type = ``gi_mo``).
+- `gi_mo`, which is the implicit default (no type = `gi_mo`).
 
-  * Refers to any operand of an instruction (register, BB ref, imm, etc.).
-  * Can be used in both ``in`` and ``out`` parameters.
-  * Users of the PatFrag can only use an operand name for this
-    parameter (e.g. ``(my_pat_frag $foo)``).
+  - Refers to any operand of an instruction (register, BB ref, imm, etc.).
+  - Can be used in both `in` and `out` parameters.
+  - Users of the PatFrag can only use an operand name for this
+    parameter (e.g. `(my_pat_frag $foo)`).
 
-* ``root``
+- `root`
 
-  * This is identical to ``gi_mo``.
-  * Can only be used in ``out`` parameters to declare the root of the
+  - This is identical to `gi_mo`.
+  - Can only be used in `out` parameters to declare the root of the
     pattern.
-  * Non-empty ``out`` parameter lists must always have exactly one ``root``.
+  - Non-empty `out` parameter lists must always have exactly one `root`.
 
-* ``gi_imm``
+- `gi_imm`
 
-  * Refers to an (potentially typed) immediate.
-  * Can only be used in ``in`` parameters.
-  * Users of the PatFrag can only use an immediate for this parameter
-    (e.g. ``(my_pat_frag 0)`` or ``(my_pat_frag (i32 0))``)
+  - Refers to an (potentially typed) immediate.
+  - Can only be used in `in` parameters.
+  - Users of the PatFrag can only use an immediate for this parameter
+    (e.g. `(my_pat_frag 0)` or `(my_pat_frag (i32 0))`)
 
-``out`` operands can only be empty if the ``GICombinePatFrag`` only contains
+`out` operands can only be empty if the `GICombinePatFrag` only contains
 C++ code. If the fragment contains instruction patterns, it has to have at
-least one ``out`` operand of type ``root``.
+least one `out` operand of type `root`.
 
-``in`` operands are less restricted, but there is one important concept to
+`in` operands are less restricted, but there is one important concept to
 remember: you can pass "unbound" operand names, but only if the
-``GICombinePatFrag`` binds it. See example 3 below.
+`GICombinePatFrag` binds it. See example 3 below.
 
-``GICombinePatFrag`` are used just like any other instructions.
-Note that the ``out`` operands are defs, so they come first in the list
+`GICombinePatFrag` are used just like any other instructions.
+Note that the `out` operands are defs, so they come first in the list
 of operands.
 
-.. code-block:: text
-  :caption: Example 1: Reduce Repetition
-
-  def zext_cst : GICombinePatFrag<(outs root:$dst, $cst), (ins gi_imm:$val),
-    [(pattern (G_CONSTANT $cst, $val),
-              (G_ZEXT $dst, $cst))]
-  >;
-
-  def foo_to_impdef : GICombineRule<
-   (defs root:$dst),
-   (match (zext_cst $y, $cst, (i32 0))
-          (G_FOO $dst, $y)),
-   (apply (G_IMPLICIT_DEF $dst))>;
-
-  def store_ext_zero : GICombineRule<
-   (defs root:$root),
-   (match (zext_cst $y, $cst, (i32 0))
-          (G_STORE $y, $ptr):$root),
-   (apply (G_STORE $cst, $ptr):$root)>;
-
-.. code-block:: text
-  :caption: Example 2: Generate Multiple Rules at Once
-
-  // Fold (freeze (freeze x)) -> (freeze x).
-  // Fold (fabs (fabs x)) -> (fabs x).
-  // Fold (fcanonicalize (fcanonicalize x)) -> (fcanonicalize x).
-  def idempotent_prop_frags : GICombinePatFrag<(outs root:$dst, $src), (ins),
-    [
-      (pattern (G_FREEZE $dst, $src), (G_FREEZE $src, $x)),
-      (pattern (G_FABS $dst, $src), (G_FABS $src, $x)),
-      (pattern (G_FCANONICALIZE $dst, $src), (G_FCANONICALIZE $src, $x))
-    ]
-  >;
-
-  def idempotent_prop : GICombineRule<
-    (defs root:$dst),
-    (match (idempotent_prop_frags $dst, $src)),
-    (apply (COPY $dst, $src))>;
-
-
-
-.. code-block:: text
-  :caption: Example 3: Unbound Operand Names
-
-  // This fragment binds $x to an operand in all of its
-  // alternative patterns.
-  def always_binds : GICombinePatFrag<
-    (outs root:$dst), (ins $x),
-    [
-      (pattern (G_FREEZE $dst, $x)),
-      (pattern (G_FABS $dst, $x)),
-    ]
-  >;
-
-  // This fragment does not bind $x to an operand in any
-  // of its alternative patterns.
-  def does_not_bind : GICombinePatFrag<
-    (outs root:$dst), (ins $x),
-    [
-      (pattern (G_FREEZE $dst, $x)), // binds $x
-      (pattern (G_FOO $dst (i32 0))), // does not bind $x
-      (pattern "return myCheck(${x}.getReg())"), // does not bind $x
-    ]
-  >;
-
-  // Here we pass $x, which is unbound, to always_binds.
-  // This works because if $x is unbound, always_binds will bind it for us.
-  def test0 : GICombineRule<
-    (defs root:$dst),
-    (match (always_binds $dst, $x)),
-    (apply (COPY $dst, $x))>;
-
-  // Here we pass $x, which is unbound, to does_not_bind.
-  // This cannot work because $x may not have been initialized in 'apply'.
-  // error: operand 'x' (for parameter 'src' of 'does_not_bind') cannot be unbound
-  def test1 : GICombineRule<
-    (defs root:$dst),
-    (match (does_not_bind $dst, $x)),
-    (apply (COPY $dst, $x))>;
-
-  // Here we pass $x, which is bound, to does_not_bind.
-  // This is fine because $x will always be bound when emitting does_not_bind
-  def test2 : GICombineRule<
-    (defs root:$dst),
-    (match (does_not_bind $tmp, $x)
-           (G_MUL $dst, $x, $tmp)),
-    (apply (COPY $dst, $x))>;
-
-
-
-
-Gallery
-=======
+```{code-block} text
+:caption: 'Example 1: Reduce Repetition'
+
+def zext_cst : GICombinePatFrag<(outs root:$dst, $cst), (ins gi_imm:$val),
+  [(pattern (G_CONSTANT $cst, $val),
+            (G_ZEXT $dst, $cst))]
+>;
+
+def foo_to_impdef : GICombineRule<
+ (defs root:$dst),
+ (match (zext_cst $y, $cst, (i32 0))
+        (G_FOO $dst, $y)),
+ (apply (G_IMPLICIT_DEF $dst))>;
+
+def store_ext_zero : GICombineRule<
+ (defs root:$root),
+ (match (zext_cst $y, $cst, (i32 0))
+        (G_STORE $y, $ptr):$root),
+ (apply (G_STORE $cst, $ptr):$root)>;
+```
+
+```{code-block} text
+:caption: 'Example 2: Generate Multiple Rules at Once'
+
+// Fold (freeze (freeze x)) -> (freeze x).
+// Fold (fabs (fabs x)) -> (fabs x).
+// Fold (fcanonicalize (fcanonicalize x)) -> (fcanonicalize x).
+def idempotent_prop_frags : GICombinePatFrag<(outs root:$dst, $src), (ins),
+  [
+    (pattern (G_FREEZE $dst, $src), (G_FREEZE $src, $x)),
+    (pattern (G_FABS $dst, $src), (G_FABS $src, $x)),
+    (pattern (G_FCANONICALIZE $dst, $src), (G_FCANONICALIZE $src, $x))
+  ]
+>;
+
+def idempotent_prop : GICombineRule<
+  (defs root:$dst),
+  (match (idempotent_prop_frags $dst, $src)),
+  (apply (COPY $dst, $src))>;
+```
+
+```{code-block} text
+:caption: 'Example 3: Unbound Operand Names'
+
+// This fragment binds $x to an operand in all of its
+// alternative patterns.
+def always_binds : GICombinePatFrag<
+  (outs root:$dst), (ins $x),
+  [
+    (pattern (G_FREEZE $dst, $x)),
+    (pattern (G_FABS $dst, $x)),
+  ]
+>;
+
+// This fragment does not bind $x to an operand in any
+// of its alternative patterns.
+def does_not_bind : GICombinePatFrag<
+  (outs root:$dst), (ins $x),
+  [
+    (pattern (G_FREEZE $dst, $x)), // binds $x
+    (pattern (G_FOO $dst (i32 0))), // does not bind $x
+    (pattern "return myCheck(${x}.getReg())"), // does not bind $x
+  ]
+>;
+
+// Here we pass $x, which is unbound, to always_binds.
+// This works because if $x is unbound, always_binds will bind it for us.
+def test0 : GICombineRule<
+  (defs root:$dst),
+  (match (always_binds $dst, $x)),
+  (apply (COPY $dst, $x))>;
+
+// Here we pass $x, which is unbound, to does_not_bind.
+// This cannot work because $x may not have been initialized in 'apply'.
+// error: operand 'x' (for parameter 'src' of 'does_not_bind') cannot be unbound
+def test1 : GICombineRule<
+  (defs root:$dst),
+  (match (does_not_bind $dst, $x)),
+  (apply (COPY $dst, $x))>;
+
+// Here we pass $x, which is bound, to does_not_bind.
+// This is fine because $x will always be bound when emitting does_not_bind
+def test2 : GICombineRule<
+  (defs root:$dst),
+  (match (does_not_bind $tmp, $x)
+         (G_MUL $dst, $x, $tmp)),
+  (apply (COPY $dst, $x))>;
+```
+
+## Gallery
 
 We should use precise patterns that state our intentions. Please avoid
 using wip_match_opcode in patterns. It can lead to imprecise patterns.
 
-.. code-block:: text
-  :caption: Example fold zext(trunc:nuw)
-
-  // Imprecise: matches any G_ZEXT
-  def zext : GICombineRule<
-    (defs root:$root),
-    (match (wip_match_opcode G_ZEXT):$root,
-    [{ return Helper.matchZextOfTrunc(*${root}, ${matchinfo}); }]),
-    (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
-
-
-  // Imprecise: matches G_ZEXT of G_TRUNC
-  def zext_of_trunc : GICombineRule<
-    (defs root:$root),
-    (match (G_TRUNC $src, $x),
-           (G_ZEXT $root, $src),
-    [{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
-    (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
-
-
-  // Precise: matches G_ZEXT of G_TRUNC with nuw flag
-  def zext_of_trunc_nuw : GICombineRule<
-    (defs root:$root),
-    (match (G_TRUNC $src, $x, (MIFlags NoUWrap)),
-           (G_ZEXT $root, $src),
-    [{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
-    (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
-
-
-  // Precise: lists all combine combinations
-  class ext_of_ext_opcodes<Instruction ext1Opcode, Instruction ext2Opcode> : GICombineRule <
-    (defs root:$root, build_fn_matchinfo:$matchinfo),
-    (match (ext2Opcode $second, $src):$Second,
-           (ext1Opcode $root, $second):$First,
-           [{ return Helper.matchExtOfExt(*${First}, *${Second}, ${matchinfo}); }]),
-    (apply [{ Helper.applyBuildFn(*${First}, ${matchinfo}); }])>;
-
-  def zext_of_zext : ext_of_ext_opcodes<G_ZEXT, G_ZEXT>;
-  def zext_of_anyext : ext_of_ext_opcodes<G_ZEXT, G_ANYEXT>;
-  def sext_of_sext : ext_of_ext_opcodes<G_SEXT, G_SEXT>;
-  def sext_of_anyext : ext_of_ext_opcodes<G_SEXT, G_ANYEXT>;
-  def anyext_of_anyext : ext_of_ext_opcodes<G_ANYEXT, G_ANYEXT>;
-  def anyext_of_zext : ext_of_ext_opcodes<G_ANYEXT, G_ZEXT>;
-  def anyext_of_sext : ext_of_ext_opcodes<G_ANYEXT, G_SEXT>;
+```{code-block} text
+:caption: Example fold zext(trunc:nuw)
+
+// Imprecise: matches any G_ZEXT
+def zext : GICombineRule<
+  (defs root:$root),
+  (match (wip_match_opcode G_ZEXT):$root,
+  [{ return Helper.matchZextOfTrunc(*${root}, ${matchinfo}); }]),
+  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
+
+// Imprecise: matches G_ZEXT of G_TRUNC
+def zext_of_trunc : GICombineRule<
+  (defs root:$root),
+  (match (G_TRUNC $src, $x),
+         (G_ZEXT $root, $src),
+  [{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
+  (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
+
+
+// Precise: matches G_ZEXT of G_TRUNC with nuw flag
+def zext_of_trunc_nuw : GICombineRule<
+  (defs root:$root),
+  (match (G_TRUNC $src, $x, (MIFlags NoUWrap)),
+         (G_ZEXT $root, $src),
+  [{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
+  (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
+
+
+// Precise: lists all combine combinations
+class ext_of_ext_opcodes<Instruction ext1Opcode, Instruction ext2Opcode> : GICombineRule <
+  (defs root:$root, build_fn_matchinfo:$matchinfo),
+  (match (ext2Opcode $second, $src):$Second,
+         (ext1Opcode $root, $second):$First,
+         [{ return Helper.matchExtOfExt(*${First}, *${Second}, ${matchinfo}); }]),
+  (apply [{ Helper.applyBuildFn(*${First}, ${matchinfo}); }])>;
+
+def zext_of_zext : ext_of_ext_opcodes<G_ZEXT, G_ZEXT>;
+def zext_of_anyext : ext_of_ext_opcodes<G_ZEXT, G_ANYEXT>;
+def sext_of_sext : ext_of_ext_opcodes<G_SEXT, G_SEXT>;
+def sext_of_anyext : ext_of_ext_opcodes<G_SEXT, G_ANYEXT>;
+def anyext_of_anyext : ext_of_ext_opcodes<G_ANYEXT, G_ANYEXT>;
+def anyext_of_zext : ext_of_ext_opcodes<G_ANYEXT, G_ZEXT>;
+def anyext_of_sext : ext_of_ext_opcodes<G_ANYEXT, G_SEXT>;
+```
+
diff --git a/llvm/docs/GlobalISel/Pipeline.md b/llvm/docs/GlobalISel/Pipeline.md
index 8565c8c95178b..da18e84272040 100644
--- a/llvm/docs/GlobalISel/Pipeline.md
+++ b/llvm/docs/GlobalISel/Pipeline.md
@@ -1,40 +1,40 @@
-.. _pipeline:
+(pipeline)=
 
-Core Pipeline
-=============
+# Core Pipeline
 
 The core pipeline of GlobalISel is:
 
-.. image:: pipeline-overview.png
+```{image} pipeline-overview.png
+```
 
 The four passes shown in the diagram consist of:
 
-:doc:`IRTranslator`
+{doc}`IRTranslator`
 
-  Converts :doc:`LLVM-IR <../LangRef>` into :doc:`gMIR (Generic MIR) <GMIR>`.
-  This is largely a direct translation and has little target customization.
-  It's somewhat analogous to SelectionDAGBuilder but builds a flavour of MIR
-  called gMIR instead of a specialized representation. gMIR uses exactly the
-  same data structures as MIR but has more relaxed constraints. For example,
-  a virtual register may be constrained to a particular type without also
-  constraining it to a specific register class.
+> Converts {doc}`LLVM-IR <../LangRef>` into {doc}`gMIR (Generic MIR) <GMIR>`.
+> This is largely a direct translation and has little target customization.
+> It's somewhat analogous to SelectionDAGBuilder but builds a flavour of MIR
+> called gMIR instead of a specialized representation. gMIR uses exactly the
+> same data structures as MIR but has more relaxed constraints. For example,
+> a virtual register may be constrained to a particular type without also
+> constraining it to a specific register class.
 
-:doc:`Legalizer`
+{doc}`Legalizer`
 
-  Replaces unsupported operations with supported ones. In other words, it shapes
-  the gMIR to suit what the backend can support. There is a very small set of
-  operations which targets are required to support but aside from that targets
-  can shape the MIR as they wish.
+> Replaces unsupported operations with supported ones. In other words, it shapes
+> the gMIR to suit what the backend can support. There is a very small set of
+> operations which targets are required to support but aside from that targets
+> can shape the MIR as they wish.
 
-:doc:`Register Bank Selector <RegBankSelect>`
+{doc}`Register Bank Selector <RegBankSelect>`
 
-  Binds virtual registers to register banks. This pass is intended to minimize
-  cross-register-bank copies by clustering portions of the MIR together.
+> Binds virtual registers to register banks. This pass is intended to minimize
+> cross-register-bank copies by clustering portions of the MIR together.
 
-:doc:`Instruction Select <InstructionSelect>`
+{doc}`Instruction Select <InstructionSelect>`
 
-  Select target instructions using the gMIR. At this point, the gMIR has been
-  constrained enough that it becomes MIR.
+> Select target instructions using the gMIR. At this point, the gMIR has been
+> constrained enough that it becomes MIR.
 
 Although we tend to talk about them as distinct passes, it should be noted that
 there's a good deal of flexibility here and it's ok for things to happen
@@ -45,91 +45,92 @@ each of these passes:
 
 IRTranslator
 
-  The representation must be gMIR, MIR, or a mixture of the two after this pass.
-  The majority will typically be gMIR to begin with but later passes will
-  gradually transition the gMIR to MIR.
+> The representation must be gMIR, MIR, or a mixture of the two after this pass.
+> The majority will typically be gMIR to begin with but later passes will
+> gradually transition the gMIR to MIR.
 
 Legalizer
 
-  No illegal operations must remain or be introduced after this pass.
+> No illegal operations must remain or be introduced after this pass.
 
 Register Bank Selector
 
-  All virtual registers must have a register bank assigned after this pass.
+> All virtual registers must have a register bank assigned after this pass.
 
 Instruction Select
 
-  No gMIR must remain or be introduced after this pass. In other words, we must
-  have completed the conversion from gMIR to MIR.
+> No gMIR must remain or be introduced after this pass. In other words, we must
+> have completed the conversion from gMIR to MIR.
 
 In addition to these passes, there are also some optional passes that perform
 an optimization. The current optional passes are:
 
 Combiner
 
-  Replaces patterns of instructions with a better alternative. Typically, this
-  means improving run time performance by replacing instructions with faster
-  alternatives but Combiners can also focus on code size or other metrics.
+> Replaces patterns of instructions with a better alternative. Typically, this
+> means improving run time performance by replacing instructions with faster
+> alternatives but Combiners can also focus on code size or other metrics.
 
 Additional passes such as these can be inserted to support higher optimization
 levels or target-specific needs. A likely pipeline is:
 
-.. image:: pipeline-overview-with-combiners.png
+```{image} pipeline-overview-with-combiners.png
+```
 
 Of course, combiners can be inserted in other places too. Also passes can be
 replaced entirely so long as their task is complete as shown in this (more
 customized) example pipeline.
 
-.. image:: pipeline-overview-customized.png
+```{image} pipeline-overview-customized.png
+```
 
-.. _maintainability-verifier:
+(maintainability-verifier)=
 
-MachineVerifier
----------------
+## MachineVerifier
 
-The pass approach lets us use the ``MachineVerifier`` to enforce invariants
+The pass approach lets us use the `MachineVerifier` to enforce invariants
 that are required beyond certain points of the pipeline. For example, a
-function with the ``legalized`` property can have the ``MachineVerifier``
+function with the `legalized` property can have the `MachineVerifier`
 enforce that no illegal instructions occur. Similarly, a
-``regBankSelected`` function may not have virtual registers without a register
+`regBankSelected` function may not have virtual registers without a register
 bank assigned.
 
-.. note::
+:::{note}
+For layering reasons, `MachineVerifier` isn't able to be the sole verifier
+in GlobalISel. Currently some of the passes also perform verification while
+we find a way to solve this problem.
 
-  For layering reasons, ``MachineVerifier`` isn't able to be the sole verifier
-  in GlobalISel. Currently some of the passes also perform verification while
-  we find a way to solve this problem.
+The main issue is that GlobalISel is a separate library, so we can't
+directly reference it from CodeGen.
+:::
 
-  The main issue is that GlobalISel is a separate library, so we can't
-  directly reference it from CodeGen.
-
-Testing
--------
+## Testing
 
 The ability to test GlobalISel is significantly improved over SelectionDAG.
 SelectionDAG is something of a black box and there's a lot going on inside it.
 This makes it difficult to write a test that reliably tests a particular aspect
 of its behaviour. For comparison, see the following diagram:
 
-.. image:: testing-pass-level.png
+```{image} testing-pass-level.png
+```
 
 Each of the grey boxes indicates an opportunity to serialize the current state
 and test the behaviour between two points in the pipeline. The current state
-can be serialized using ``-stop-before`` or ``-stop-after`` and loaded using
-``-start-before``, ``-start-after``, and ``-run-pass``.
+can be serialized using `-stop-before` or `-stop-after` and loaded using
+`-start-before`, `-start-after`, and `-run-pass`.
 
 We can also go further still, as many of GlobalISel's passes are readily unit
 testable:
 
-.. image:: testing-unit-level.png
+```{image} testing-unit-level.png
+```
 
-It's possible to create an imaginary target such as in `LegalizerHelperTest.cpp <https://github.com/llvm/llvm-project/blob/93b29d3882baf7df42e4e9bc26b977b00373ef56/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp#L28-L57>`_
+It's possible to create an imaginary target such as in [LegalizerHelperTest.cpp](https://github.com/llvm/llvm-project/blob/93b29d3882baf7df42e4e9bc26b977b00373ef56/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp#L28-L57)
 and perform a single step of the algorithm and check the result. The MIR and
 FileCheck directives can be embedded using strings so you still have access to
 the convenience available in llvm-lit.
 
-Debugging
----------
+## Debugging
 
 One debugging technique that's proven particularly valuable is to use the
 BlockExtractor to extract basic blocks into new functions. This can be used
@@ -137,16 +138,17 @@ to track down correctness bugs and can also be used to track down performance
 regressions. It can also be coupled with function attributes to disable
 GlobalISel for one or more of the extracted functions.
 
-.. image:: block-extract.png
+```{image} block-extract.png
+```
 
 The command to do the extraction is:
 
-.. code-block:: shell
-
-  ./bin/llvm-extract -o - -S -b ‘foo:bb1;bb4’ <input> > extracted.ll
+```shell
+./bin/llvm-extract -o - -S -b ‘foo:bb1;bb4’ <input> > extracted.ll
+```
 
-This particular example extracts two basic blocks from a function named ``foo``.
-The new LLVM-IR can then be modified to add the ``failedISel`` attribute to the
+This particular example extracts two basic blocks from a function named `foo`.
+The new LLVM-IR can then be modified to add the `failedISel` attribute to the
 extracted function containing bb4 to make that function use SelectionDAG.
 
 This can prevent some optimizations as GlobalISel is generally able to work on a
@@ -157,22 +159,22 @@ involved in a bug.
 Once the critical blocks have been identified, you can further increase the
 resolution to the critical instructions by splitting the blocks like from:
 
-.. code-block:: none
-
-  bb1:
-    ... instructions group 1 ...
-    ... instructions group 2 ...
+```none
+bb1:
+  ... instructions group 1 ...
+  ... instructions group 2 ...
+```
 
 into:
 
-.. code-block:: none
+```none
+bb1:
+  ... instructions group 1 ...
+  br %bb2
 
-  bb1:
-    ... instructions group 1 ...
-    br %bb2
-
-  bb2:
-    ... instructions group 2 ...
+bb2:
+  ... instructions group 2 ...
+```
 
 and then repeating the process for the new blocks.
 
@@ -182,3 +184,4 @@ SelectionDAG (or the other way around) to leverage the existing quality of
 another code generator to track down bugs. This technique can also be used to
 improve the similarity between fast and slow code when tracking down performance
 regressions and help you zero in on a particular cause of the regression.
+
diff --git a/llvm/docs/GlobalISel/Porting.md b/llvm/docs/GlobalISel/Porting.md
index 89aeeb5f53fcb..6b06a89cc03f9 100644
--- a/llvm/docs/GlobalISel/Porting.md
+++ b/llvm/docs/GlobalISel/Porting.md
@@ -1,28 +1,26 @@
-.. _porting:
+(porting)=
 
-Porting GlobalISel to A New Target
-==================================
+# Porting GlobalISel to A New Target
 
 There are four major classes to implement by the target:
 
-* :ref:`CallLowering <translator-call-lower>` --- lower calls, returns, and
+- {ref}`CallLowering <translator-call-lower>` --- lower calls, returns, and
   arguments according to the ABI.
-* :ref:`RegisterBankInfo <api-registerbankinfo>` --- describe
-  :ref:`gmir-regbank` coverage, cross-bank copy cost, and the mapping of
+- {ref}`RegisterBankInfo <api-registerbankinfo>` --- describe
+  {ref}`gmir-regbank` coverage, cross-bank copy cost, and the mapping of
   operands onto banks for each instruction.
-* :ref:`LegalizerInfo <api-legalizerinfo>` --- describe what is legal, and how
+- {ref}`LegalizerInfo <api-legalizerinfo>` --- describe what is legal, and how
   to legalize what isn't.
-* :ref:`InstructionSelector <api-instructionselector>` --- select generic MIR
+- {ref}`InstructionSelector <api-instructionselector>` --- select generic MIR
   to target-specific MIR.
 
 Additionally:
 
-* ``TargetPassConfig`` --- create the passes constituting the pipeline,
-  including additional passes not included in the :ref:`pipeline`.
+- `TargetPassConfig` --- create the passes constituting the pipeline,
+  including additional passes not included in the {ref}`pipeline`.
 
-Tutorials
----------
+## Tutorials
 
-We'd recommend watching `this tutorial
-<https://www.llvm.org/devmtg/2017-10/#tutorial2>`_ from the 2017 LLVM DevMeeting
+We'd recommend watching [this tutorial](https://www.llvm.org/devmtg/2017-10/#tutorial2) from the 2017 LLVM DevMeeting
 which gave an overview of how to bring up a new backend in GlobalISel.
+
diff --git a/llvm/docs/GlobalISel/RegBankSelect.md b/llvm/docs/GlobalISel/RegBankSelect.md
index 2702d689b84a2..94a7129c0a01d 100644
--- a/llvm/docs/GlobalISel/RegBankSelect.md
+++ b/llvm/docs/GlobalISel/RegBankSelect.md
@@ -1,73 +1,66 @@
-.. _regbankselect:
+(regbankselect)=
 
-RegBankSelect
--------------
+# RegBankSelect
 
-This pass constrains the :ref:`gmir-gvregs` operands of generic
-instructions to some :ref:`gmir-regbank`.
+This pass constrains the {ref}`gmir-gvregs` operands of generic
+instructions to some {ref}`gmir-regbank`.
 
 It iteratively maps instructions to a set of per-operand bank assignment.
 The possible mappings are determined by the target-provided
-:ref:`RegisterBankInfo <api-registerbankinfo>`.
-The mapping is then applied, possibly introducing ``COPY`` instructions if
+{ref}`RegisterBankInfo <api-registerbankinfo>`.
+The mapping is then applied, possibly introducing `COPY` instructions if
 necessary.
 
-It traverses the ``MachineFunction`` top down so that all operands are already
+It traverses the `MachineFunction` top down so that all operands are already
 mapped when analyzing an instruction.
 
 This pass could also remap target-specific instructions when beneficial.
 In the future, this could replace the ExeDepsFix pass, as we can directly
 select the best variant for an instruction that's available on multiple banks.
 
-.. _api-registerbankinfo:
+(api-registerbankinfo)=
 
-API: RegisterBankInfo
-^^^^^^^^^^^^^^^^^^^^^
+## API: RegisterBankInfo
 
-The ``RegisterBankInfo`` class describes multiple aspects of register banks.
+The `RegisterBankInfo` class describes multiple aspects of register banks.
 
-* **Banks**: ``addRegBankCoverage`` --- which register bank covers each
+- **Banks**: `addRegBankCoverage` --- which register bank covers each
   register class.
-
-* **Cross-Bank Copies**: ``copyCost`` --- the cost of a ``COPY`` from one bank
+- **Cross-Bank Copies**: `copyCost` --- the cost of a `COPY` from one bank
   to another.
-
-* **Default Mapping**: ``getInstrMapping`` --- the default bank assignments for
+- **Default Mapping**: `getInstrMapping` --- the default bank assignments for
   a given instruction.
-
-* **Alternative Mapping**: ``getInstrAlternativeMapping`` --- the other
+- **Alternative Mapping**: `getInstrAlternativeMapping` --- the other
   possible bank assignments for a given instruction.
 
-``TODO``:
+`TODO`:
 All this information should eventually be static and generated by TableGen,
 mostly using existing information augmented by bank descriptions.
 
-``TODO``:
-``getInstrMapping`` is currently separate from ``getInstrAlternativeMapping``
+`TODO`:
+`getInstrMapping` is currently separate from `getInstrAlternativeMapping`
 because the latter is more expensive: as we move to static mapping info,
 both methods should be free, and we should merge them.
 
-.. _regbankselect-modes:
-
-RegBankSelect Modes
-^^^^^^^^^^^^^^^^^^^
+(regbankselect-modes)=
 
-``RegBankSelect`` currently has two modes:
+## RegBankSelect Modes
 
-* **Fast** --- For each instruction, pick a target-provided "default" bank
-  assignment.  This is the default at -O0.
+`RegBankSelect` currently has two modes:
 
-* **Greedy** --- For each instruction, pick the cheapest of several
+- **Fast** --- For each instruction, pick a target-provided "default" bank
+  assignment. This is the default at -O0.
+- **Greedy** --- For each instruction, pick the cheapest of several
   target-provided bank assignment alternatives.
 
 We intend to eventually introduce an additional optimizing mode:
 
-* **Global** --- Across multiple instructions, pick the cheapest combination of
+- **Global** --- Across multiple instructions, pick the cheapest combination of
   bank assignments.
 
-``NOTE``:
+`NOTE`:
 On AArch64, we are considering using the Greedy mode even at -O0 (or perhaps at
-backend -O1):  because :ref:`gmir-llt` doesn't distinguish floating point from
+backend -O1): because {ref}`gmir-llt` doesn't distinguish floating point from
 integer scalars, the default assignment for loads and stores is the integer
 bank, introducing cross-bank copies on most floating point operations.
 
diff --git a/llvm/docs/GlobalISel/Resources.md b/llvm/docs/GlobalISel/Resources.md
index 6ac35d241aa7e..092482e7cf733 100644
--- a/llvm/docs/GlobalISel/Resources.md
+++ b/llvm/docs/GlobalISel/Resources.md
@@ -1,11 +1,11 @@
-.. _other_resources:
+(other-resources)=
 
-Resources
-=========
+# Resources
+
+- [Global Instruction Selection - A Proposal by Quentin Colombet @LLVMDevMeeting 2015](https://www.youtube.com/watch?v=F6GGbYtae3g)
+- [Global Instruction Selection - Status by Quentin Colombet, Ahmed Bougacha, and Tim Northover @LLVMDevMeeting 2016](https://www.youtube.com/watch?v=6tfb344A7w8)
+- [GlobalISel - LLVM's Latest Instruction Selection Framework by Diana Picus @FOSDEM17](https://www.youtube.com/watch?v=d6dF6E4BPeU)
+- [GlobalISel: Past, Present, and Future by Quentin Colombet and Ahmed Bougacha @LLVMDevMeeting 2017](https://www.llvm.org/devmtg/2017-10/#talk11)
+- [Head First into GlobalISel by Daniel Sanders, Aditya Nandakumar, and Justin Bogner @LLVMDevMeeting 2017](https://www.llvm.org/devmtg/2017-10/#tutorial2)
+- [Generating Optimized Code with GlobalISel by Volkan Keles, Daniel Sanders @LLVMDevMeeting 2019](https://www.llvm.org/devmtg/2019-10/talk-abstracts.html#keynote1)
 
-* `Global Instruction Selection - A Proposal by Quentin Colombet @LLVMDevMeeting 2015 <https://www.youtube.com/watch?v=F6GGbYtae3g>`_
-* `Global Instruction Selection - Status by Quentin Colombet, Ahmed Bougacha, and Tim Northover @LLVMDevMeeting 2016 <https://www.youtube.com/watch?v=6tfb344A7w8>`_
-* `GlobalISel - LLVM's Latest Instruction Selection Framework by Diana Picus @FOSDEM17 <https://www.youtube.com/watch?v=d6dF6E4BPeU>`_
-* `GlobalISel: Past, Present, and Future by Quentin Colombet and Ahmed Bougacha @LLVMDevMeeting 2017 <https://www.llvm.org/devmtg/2017-10/#talk11>`_
-* `Head First into GlobalISel by Daniel Sanders, Aditya Nandakumar, and Justin Bogner @LLVMDevMeeting 2017 <https://www.llvm.org/devmtg/2017-10/#tutorial2>`_
-* `Generating Optimized Code with GlobalISel by Volkan Keles, Daniel Sanders @LLVMDevMeeting 2019 <https://www.llvm.org/devmtg/2019-10/talk-abstracts.html#keynote1>`_
diff --git a/llvm/docs/GlobalISel/index.md b/llvm/docs/GlobalISel/index.md
index 33995779532d1..c960f7fe000d8 100644
--- a/llvm/docs/GlobalISel/index.md
+++ b/llvm/docs/GlobalISel/index.md
@@ -1,29 +1,27 @@
-============================
-Global Instruction Selection
-============================
-
-.. warning::
-   This document is a work in progress.  It reflects the current state of the
-   implementation, as well as open design and implementation issues.
-
-
-.. toctree::
-   :hidden:
-
-   GMIR
-   GenericOpcode
-   MIRPatterns
-   Pipeline
-   Porting
-   Resources
-   IRTranslator
-   Legalizer
-   RegBankSelect
-   InstructionSelect
-   KnownBits
-
-Introduction
-------------
+# Global Instruction Selection
+
+:::{warning}
+This document is a work in progress. It reflects the current state of the
+implementation, as well as open design and implementation issues.
+:::
+
+```{toctree}
+:hidden: true
+
+GMIR
+GenericOpcode
+MIRPatterns
+Pipeline
+Porting
+Resources
+IRTranslator
+Legalizer
+RegBankSelect
+InstructionSelect
+KnownBits
+```
+
+## Introduction
 
 GlobalISel is a framework that provides a set of reusable passes and utilities
 for instruction selection --- translation from LLVM IR to target-specific
@@ -32,65 +30,62 @@ Machine IR (MIR).
 GlobalISel is intended to be a replacement for SelectionDAG and FastISel, to
 solve three major problems:
 
-* **Performance** --- SelectionDAG introduces a dedicated intermediate
+- **Performance** --- SelectionDAG introduces a dedicated intermediate
   representation, which has a compile-time cost.
 
   GlobalISel directly operates on the post-isel representation used by the
   rest of the code generator, MIR.
   It does require extensions to that representation to support arbitrary
-  incoming IR: :ref:`gmir`.
+  incoming IR: {ref}`gmir`.
 
-* **Granularity** --- SelectionDAG and FastISel operate on individual basic
+- **Granularity** --- SelectionDAG and FastISel operate on individual basic
   blocks, losing some global optimization opportunities.
 
   GlobalISel operates on the whole function.
 
-* **Modularity** --- SelectionDAG and FastISel are radically different and share
+- **Modularity** --- SelectionDAG and FastISel are radically different and share
   very little code.
 
   GlobalISel is built in a way that enables code reuse. For instance, both the
-  optimized and fast selectors share the :ref:`pipeline`, and targets can
+  optimized and fast selectors share the {ref}`pipeline`, and targets can
   configure that pipeline to better suit their needs.
 
-Design and Implementation Reference
------------------------------------
+## Design and Implementation Reference
 
 More information on the design and implementation of GlobalISel can be found in
 the following sections.
 
-* :doc:`GMIR`
-* :doc:`GenericOpcode`
-* :doc:`MIRPatterns`
-* :doc:`Pipeline`
-* :doc:`Porting`
-* :doc:`Resources`
+- {doc}`GMIR`
+- {doc}`GenericOpcode`
+- {doc}`MIRPatterns`
+- {doc}`Pipeline`
+- {doc}`Porting`
+- {doc}`Resources`
 
 More information on specific passes can be found in the following sections:
 
-* :doc:`IRTranslator`
-* :doc:`Legalizer`
-* :doc:`RegBankSelect`
-* :doc:`InstructionSelect`
-* :doc:`KnownBits`
+- {doc}`IRTranslator`
+- {doc}`Legalizer`
+- {doc}`RegBankSelect`
+- {doc}`InstructionSelect`
+- {doc}`KnownBits`
 
-.. _progress:
+(progress)=
 
-Progress and Future Work
-------------------------
+## Progress and Future Work
 
-The initial goal is to replace FastISel on AArch64.  The next step will be to
+The initial goal is to replace FastISel on AArch64. The next step will be to
 replace SelectionDAG as the optimized ISel.
 
-``NOTE``:
+`NOTE`:
 While we iterate on GlobalISel, we strive to avoid affecting the performance of
-SelectionDAG, FastISel, or the other MIR passes.  For instance, the types of
-:ref:`gmir-gvregs` are stored in a separate table in ``MachineRegisterInfo``,
-that is destroyed after :ref:`instructionselect`.
+SelectionDAG, FastISel, or the other MIR passes. For instance, the types of
+{ref}`gmir-gvregs` are stored in a separate table in `MachineRegisterInfo`,
+that is destroyed after {ref}`instructionselect`.
 
-.. _progress-fastisel:
+(progress-fastisel)=
 
-FastISel Replacement
-^^^^^^^^^^^^^^^^^^^^
+### FastISel Replacement
 
 For the initial FastISel replacement, we intend to fallback to SelectionDAG on
 selection failures.
@@ -102,11 +97,12 @@ Still, supporting all IR (via a complete legalizer) and avoiding the fallback
 to SelectionDAG in the worst case should enable better amortized performance
 than SelectionDAG+FastISel.
 
-``NOTE``:
+`NOTE`:
 We considered never having a fallback to SelectionDAG, instead deciding early
-whether a given function is supported by GlobalISel or not.  The decision would
-be based on :ref:`milegalizer` queries.
+whether a given function is supported by GlobalISel or not. The decision would
+be based on {ref}`milegalizer` queries.
 We abandoned that for two reasons:
-a) on IR inputs, we'd need to basically simulate the :ref:`irtranslator`;
+a) on IR inputs, we'd need to basically simulate the {ref}`irtranslator`;
 b) to be robust against unforeseen failures and to enable iterative
 improvements.
+
diff --git a/llvm/docs/PDB/CodeViewSymbols.md b/llvm/docs/PDB/CodeViewSymbols.md
index 2758de2497137..265afeeeddda6 100644
--- a/llvm/docs/PDB/CodeViewSymbols.md
+++ b/llvm/docs/PDB/CodeViewSymbols.md
@@ -1,471 +1,399 @@
-=====================================
-CodeView Symbol Records
-=====================================
+# CodeView Symbol Records
 
+(symbols-intro)=
 
-
-.. _symbols_intro:
-
-Introduction
-============
+## Introduction
 
 This document describes the usage and serialization format of the various
-CodeView symbol records that LLVM understands.  Like
-:doc:`CodeView Type Records <CodeViewTypes>`, we describe only the important
+CodeView symbol records that LLVM understands. Like
+{doc}`CodeView Type Records <CodeViewTypes>`, we describe only the important
 types which are generated by modern C++ toolchains.
 
-Record Categories
-=================
+## Record Categories
 
-Symbol records share one major similarity with :doc:`type records <CodeViewTypes>`:
-They start with the same :ref:`record prefix <leaf_types>`, which we will not describe
-again (refer to the previous link for a description).  As a result of this, a sequence
+Symbol records share one major similarity with {doc}`type records <CodeViewTypes>`:
+They start with the same {ref}`record prefix <leaf_types>`, which we will not describe
+again (refer to the previous link for a description). As a result of this, a sequence
 of symbol records can be processed with largely the same code as that which processes
-type records.  There are several important differences between symbol and type records:
+type records. There are several important differences between symbol and type records:
 
-* Symbol records only appear in the :doc:`PublicStream`, :doc:`GlobalStream`, and
-  :doc:`Module Info Streams <ModiStream>`.
-* Type records only appear in the :doc:`TPI & IPI streams <TpiStream>`.
-* While types are referenced from other CodeView records via :ref:`type indices <type_indices>`,
+- Symbol records only appear in the {doc}`PublicStream`, {doc}`GlobalStream`, and
+  {doc}`Module Info Streams <ModiStream>`.
+- Type records only appear in the {doc}`TPI & IPI streams <TpiStream>`.
+- While types are referenced from other CodeView records via {ref}`type indices <type_indices>`,
   symbol records are referenced by the byte offset of the record in the stream that it appears
   in.
-* Types can reference types (via type indices), and symbols can reference both types (via type
+- Types can reference types (via type indices), and symbols can reference both types (via type
   indices) and symbols (via offsets), but types can never reference symbols.
-* There is no notion of :ref:`Leaf Records <leaf_types>` and :ref:`Member Records <member_types>`
-  as there are with types.  Every symbol record describes is own length.
-* Certain special symbol records begin a "scope".  For these records, all following records
-  up until the next ``S_END`` record are "children" of this symbol record.  For example,
+- There is no notion of {ref}`Leaf Records <leaf_types>` and {ref}`Member Records <member_types>`
+  as there are with types. Every symbol record describes is own length.
+- Certain special symbol records begin a "scope". For these records, all following records
+  up until the next `S_END` record are "children" of this symbol record. For example,
   given a symbol record which describes a certain function, all local variables of this
-  function would appear following the function up until the corresponding ``S_END`` record.
+  function would appear following the function up until the corresponding `S_END` record.
 
 Finally, there are three general categories of symbol record, grouped by where they are legal
-to appear in a PDB file.  Public Symbols (which appear only in the
-:doc:`publics stream <PublicStream>`), Global Symbols (which appear only in the
-:doc:`globals stream <GlobalStream>`) and module symbols (which appear in the
-:doc:`module info stream <ModiStream>`).
+to appear in a PDB file. Public Symbols (which appear only in the
+{doc}`publics stream <PublicStream>`), Global Symbols (which appear only in the
+{doc}`globals stream <GlobalStream>`) and module symbols (which appear in the
+{doc}`module info stream <ModiStream>`).
 
+(public-symbols)=
 
-.. _public_symbols:
+### Public Symbols
 
-Public Symbols
---------------
-
-Public symbols are the CodeView equivalent of DWARF ``.debug_pubnames``.  There
+Public symbols are the CodeView equivalent of DWARF `.debug_pubnames`. There
 is one public symbol record for every function or variable in the program that
-has a mangled name.  The :doc:`Publics Stream <PublicStream>`, which contains these
+has a mangled name. The {doc}`Publics Stream <PublicStream>`, which contains these
 records, additionally contains a hash table that allows one to quickly locate a
 record by mangled name.
 
-S_PUB32 (0x110e)
-^^^^^^^^^^^^^^^^
+#### S_PUB32 (0x110e)
 
-There is only type of public symbol, an ``S_PUB32`` which describes a mangled
+There is only type of public symbol, an `S_PUB32` which describes a mangled
 name, a flag indicating what kind of symbol it is (e.g. function, variable), and
-the symbol's address.  The :ref:`dbi_section_map_substream` of the
-:doc:`DBI Stream <DbiStream>` can be consulted to determine what module this address
-corresponds to, and from there that module's :doc:`module debug stream <ModiStream>`
+the symbol's address. The {ref}`dbi_section_map_substream` of the
+{doc}`DBI Stream <DbiStream>` can be consulted to determine what module this address
+corresponds to, and from there that module's {doc}`module debug stream <ModiStream>`
 can be consulted to locate full information for the symbol with the given address.
 
-.. _global_symbols:
+(global-symbols)=
 
-Global Symbols
---------------
+### Global Symbols
 
-While there is one :ref:`public symbol <public_symbols>` for every symbol in the
+While there is one {ref}`public symbol <public_symbols>` for every symbol in the
 program with `external` linkage, there is one global symbol for every symbol in the
-program with linkage (including internal linkage).  As a result, global symbols do
+program with linkage (including internal linkage). As a result, global symbols do
 not describe a mangled name *or* an address, since symbols with internal linkage
-need not have any mangling at all, and also may not have an address.  Thus, all
+need not have any mangling at all, and also may not have an address. Thus, all
 global symbols simply refer directly to the full symbol record via a module/offset
 combination.
 
-Similarly to :ref:`public symbols <public_symbols>`, all global symbols are contained
-in a single :doc:`Globals Stream <GlobalStream>`, which contains a hash table mapping
+Similarly to {ref}`public symbols <public_symbols>`, all global symbols are contained
+in a single {doc}`Globals Stream <GlobalStream>`, which contains a hash table mapping
 fully qualified name to the corresponding record in the globals stream (which as
 mentioned, then contains information allowing one to locate the full record in the
 corresponding module symbol stream).
 
 Note that a consequence and limitation of this design is that program-wide lookup
 by anything other than an exact textually matching fully-qualified name of whatever
-the compiler decided to emit is impractical.  This differs from DWARF, where even
+the compiler decided to emit is impractical. This differs from DWARF, where even
 though we don't necessarily have O(1) lookup by basename within a given scope (including
 O(1) scope, we at least have O(n) access within a given scope).
 
-.. important::
-   Program-wide lookup of names by anything other than an exact textually matching fully
-   qualified name is not possible.
-
+:::{important}
+Program-wide lookup of names by anything other than an exact textually matching fully
+qualified name is not possible.
+:::
 
-S_GDATA32
-^^^^^^^^^^
+#### S_GDATA32
 
-S_GTHREAD32 (0x1113)
-^^^^^^^^^^^^^^^^^^^^
+#### S_GTHREAD32 (0x1113)
 
-S_PROCREF (0x1125)
-^^^^^^^^^^^^^^^^^^
+#### S_PROCREF (0x1125)
 
-S_LPROCREF (0x1127)
-^^^^^^^^^^^^^^^^^^^
+#### S_LPROCREF (0x1127)
 
-S_GMANDATA (0x111d)
-^^^^^^^^^^^^^^^^^^^
+#### S_GMANDATA (0x111d)
 
-.. _module_symbols:
+(module-symbols)=
 
-Module Symbols
---------------
+### Module Symbols
 
-S_END (0x0006)
-^^^^^^^^^^^^^^
+#### S_END (0x0006)
 
-S_FRAMEPROC (0x1012)
-^^^^^^^^^^^^^^^^^^^^
+#### S_FRAMEPROC (0x1012)
 
-S_OBJNAME (0x1101)
-^^^^^^^^^^^^^^^^^^
+#### S_OBJNAME (0x1101)
 
-S_THUNK32 (0x1102)
-^^^^^^^^^^^^^^^^^^
+#### S_THUNK32 (0x1102)
 
-S_BLOCK32 (0x1103)
-^^^^^^^^^^^^^^^^^^
+#### S_BLOCK32 (0x1103)
 
-S_LABEL32 (0x1105)
-^^^^^^^^^^^^^^^^^^
+#### S_LABEL32 (0x1105)
 
-S_REGISTER (0x1106)
-^^^^^^^^^^^^^^^^^^^
+#### S_REGISTER (0x1106)
 
-S_BPREL32 (0x110b)
-^^^^^^^^^^^^^^^^^^
+#### S_BPREL32 (0x110b)
 
-S_LPROC32 (0x110f)
-^^^^^^^^^^^^^^^^^^
+#### S_LPROC32 (0x110f)
 
-S_GPROC32 (0x1110)
-^^^^^^^^^^^^^^^^^^
+#### S_GPROC32 (0x1110)
 
-S_REGREL32 (0x1111)
-^^^^^^^^^^^^^^^^^^^
+#### S_REGREL32 (0x1111)
 
-S_COMPILE2 (0x1116)
-^^^^^^^^^^^^^^^^^^^
+#### S_COMPILE2 (0x1116)
 
-S_UNAMESPACE (0x1124)
-^^^^^^^^^^^^^^^^^^^^^
+#### S_UNAMESPACE (0x1124)
 
-S_TRAMPOLINE (0x112c)
-^^^^^^^^^^^^^^^^^^^^^
+#### S_TRAMPOLINE (0x112c)
 
-S_SECTION (0x1136)
-^^^^^^^^^^^^^^^^^^
+#### S_SECTION (0x1136)
 
-S_COFFGROUP (0x1137)
-^^^^^^^^^^^^^^^^^^^^
+#### S_COFFGROUP (0x1137)
 
-S_EXPORT (0x1138)
-^^^^^^^^^^^^^^^^^
+#### S_EXPORT (0x1138)
 
-S_CALLSITEINFO (0x1139)
-^^^^^^^^^^^^^^^^^^^^^^^
+#### S_CALLSITEINFO (0x1139)
 
-S_FRAMECOOKIE (0x113a)
-^^^^^^^^^^^^^^^^^^^^^^
+#### S_FRAMECOOKIE (0x113a)
 
-S_COMPILE3 (0x113c)
-^^^^^^^^^^^^^^^^^^^
+#### S_COMPILE3 (0x113c)
 
-S_ENVBLOCK (0x113d)
-^^^^^^^^^^^^^^^^^^^
+#### S_ENVBLOCK (0x113d)
 
-.. _s_local:
+(s-local)=
 
-S_LOCAL (0x113e)
-^^^^^^^^^^^^^^^^
+#### S_LOCAL (0x113e)
 
 Defines a local variable.
-This record is followed by a series of ``S_DEFRANGE*`` records that define the
+This record is followed by a series of `S_DEFRANGE*` records that define the
 live range of this variable.
 
-.. code:: cpp
-
-   struct LocalSym {
-     /// The type of this variable (TPI type index).
-     uint32_t Type;
-     /// See enum below.
-     uint16_t Flags;
-     /// Name of the variable. A zero terminated string.
-     char Name[];
-   };
-   enum class LocalSymFlags : uint16_t {
-     None = 0,
-     IsParameter = 1 << 0,
-     IsAddressTaken = 1 << 1,
-     IsCompilerGenerated = 1 << 2,
-     IsAggregate = 1 << 3,
-     IsAggregated = 1 << 4,
-     IsAliased = 1 << 5,
-     IsAlias = 1 << 6,
-     IsReturnValue = 1 << 7,
-     IsOptimizedOut = 1 << 8,
-     IsEnregisteredGlobal = 1 << 9,
-     IsEnregisteredStatic = 1 << 10,
-   };
-
-
-All ``S_DEFRANGE*`` records consist of a header followed by
-``LocalVariableAddrRange`` and a list of ``LocalVariableAddrGap`` (until the
+```cpp
+struct LocalSym {
+  /// The type of this variable (TPI type index).
+  uint32_t Type;
+  /// See enum below.
+  uint16_t Flags;
+  /// Name of the variable. A zero terminated string.
+  char Name[];
+};
+enum class LocalSymFlags : uint16_t {
+  None = 0,
+  IsParameter = 1 << 0,
+  IsAddressTaken = 1 << 1,
+  IsCompilerGenerated = 1 << 2,
+  IsAggregate = 1 << 3,
+  IsAggregated = 1 << 4,
+  IsAliased = 1 << 5,
+  IsAlias = 1 << 6,
+  IsReturnValue = 1 << 7,
+  IsOptimizedOut = 1 << 8,
+  IsEnregisteredGlobal = 1 << 9,
+  IsEnregisteredStatic = 1 << 10,
+};
+```
+
+All `S_DEFRANGE*` records consist of a header followed by
+`LocalVariableAddrRange` and a list of `LocalVariableAddrGap` (until the
 record length is reached) except for the
-`S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE <_defrange_framepointer_rel_full_scope>`_
+[S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE](_defrange_framepointer_rel_full_scope)
 record.
 
-.. code:: cpp
-
-   /// A live range of a variable.
-   struct LocalVariableAddrRange {
-     /// Starting offset in the section
-     uint32_t OffsetStart;
-     /// Index of the section
-     uint16_t ISectStart;
-     /// Size of the range
-     uint16_t Range;
-   };
-   /// A subrange of a `LocalVariableAddrRange` where a variable is _not_ live.
-   struct LocalVariableAddrGap {
-     /// Start of the range, relative to `LocalVariableAddrRange::OffsetStart`
-     uint16_t GapStartOffset;
-     /// Size of the range
-     uint16_t Range;
-   };
+```cpp
+/// A live range of a variable.
+struct LocalVariableAddrRange {
+  /// Starting offset in the section
+  uint32_t OffsetStart;
+  /// Index of the section
+  uint16_t ISectStart;
+  /// Size of the range
+  uint16_t Range;
+};
+/// A subrange of a `LocalVariableAddrRange` where a variable is _not_ live.
+struct LocalVariableAddrGap {
+  /// Start of the range, relative to `LocalVariableAddrRange::OffsetStart`
+  uint16_t GapStartOffset;
+  /// Size of the range
+  uint16_t Range;
+};
+```
 
 The following records only describe the header.
 
-S_DEFRANGE (0x113f)
-^^^^^^^^^^^^^^^^^^^
+#### S_DEFRANGE (0x113f)
 
-.. FIXME: Document the DIA programs. Are these the same as FPO programs?
+% FIXME: Document the DIA programs. Are these the same as FPO programs?
 
 A live range expressed as a DIA program.
 
-.. code:: cpp
+```cpp
+struct DefrangeSymHeader {
+  /// DIA program to evaluate the value of the symbol
+  uint32_t Program;
+};
+```
 
-   struct DefrangeSymHeader {
-     /// DIA program to evaluate the value of the symbol
-     uint32_t Program;
-   };
+#### S_DEFRANGE_SUBFIELD (0x1140)
 
-S_DEFRANGE_SUBFIELD (0x1140)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+A live range of sub field of variable (e.g. `local.i`).
 
-A live range of sub field of variable (e.g. ``local.i``).
+```cpp
+struct DefrangeSubfieldSymHeader {
+  /// DIA program to evaluate the value of the symbol
+  uint32_t Program;
+  /// Offset in parent variable.
+  uint32_t OffsetInParent;
+};
+```
 
-.. code:: cpp
-
-   struct DefrangeSubfieldSymHeader {
-     /// DIA program to evaluate the value of the symbol
-     uint32_t Program;
-     /// Offset in parent variable.
-     uint32_t OffsetInParent;
-   };
-
-S_DEFRANGE_REGISTER (0x1141)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### S_DEFRANGE_REGISTER (0x1141)
 
 A live range of a variable living in a register.
 
-.. code:: cpp
-
-   struct DefrangeRegisterSymHeader {
-     /// Register to hold the value of the symbol
-     uint16_t Register;
-     /// May have no user name on one control flow path
-     uint16_t MayHaveNoName : 1;
-     uint16_t Padding : 15;
-   };
-
-S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+```cpp
+struct DefrangeRegisterSymHeader {
+  /// Register to hold the value of the symbol
+  uint16_t Register;
+  /// May have no user name on one control flow path
+  uint16_t MayHaveNoName : 1;
+  uint16_t Padding : 15;
+};
+```
 
-A live range of frame variable. The register for the frame pointer is specified in ``S_FRAMEPROC``.
+#### S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
 
-.. code:: cpp
+A live range of frame variable. The register for the frame pointer is specified in `S_FRAMEPROC`.
 
-   struct DefrangeFramepointerSymHeader {
-     /// Offset from the frame pointer
-     int32_t Offset;
-   };
+```cpp
+struct DefrangeFramepointerSymHeader {
+  /// Offset from the frame pointer
+  int32_t Offset;
+};
+```
 
-S_DEFRANGE_SUBFIELD_REGISTER (0x1143)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### S_DEFRANGE_SUBFIELD_REGISTER (0x1143)
 
-A live range of sub field of variable (e.g. ``local.i``).
+A live range of sub field of variable (e.g. `local.i`).
 
-.. code:: cpp
+```cpp
+struct DefrangeSubfieldRegisterSymHeader {
+  /// Register to hold the value of the symbol
+  uint16_t Register;
+  /// May have no user name on one of control flow path
+  uint16_t MayHaveNoName : 1;
+  uint16_t Padding1 : 15;
+  /// Offset in parent variable
+  uint32_t OffsetInParent : 12;
+  uint32_t Padding2 : 20;
+};
+```
 
-   struct DefrangeSubfieldRegisterSymHeader {
-     /// Register to hold the value of the symbol
-     uint16_t Register;
-     /// May have no user name on one of control flow path
-     uint16_t MayHaveNoName : 1;
-     uint16_t Padding1 : 15;
-     /// Offset in parent variable
-     uint32_t OffsetInParent : 12;
-     uint32_t Padding2 : 20;
-   };
+(defrange-framepointer-rel-full-scope)=
 
-.. _defrange_framepointer_rel_full_scope:
-
-S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE (0x1144)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#### S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE (0x1144)
 
 A frame variable valid in all function scope.
 
-.. code:: cpp
-
-   struct DefrangeFramepointerRelFullScopeSymHeader {
-     /// Offset from the frame pointer
-     int32_t Offset;
-   };
-
-S_DEFRANGE_REGISTER_REL (0x1145)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-A live range of variable relative to a register (range version of ``S_REGREL32``).
+```cpp
+struct DefrangeFramepointerRelFullScopeSymHeader {
+  /// Offset from the frame pointer
+  int32_t Offset;
+};
+```
 
-.. code:: cpp
+#### S_DEFRANGE_REGISTER_REL (0x1145)
 
-   struct DefrangeRegisterRelSymHeader {
-     /// Register to hold the base pointer of the symbol
-     uint16_t Register;
-     /// Spilled member for s.i
-     uint16_t SpilledUdtMember : 1;
-     uint16_t Padding : 3;
-     /// Offset in parent variable.
-     uint16_t OffsetInParent : 12;
-     /// Offset to register
-     int32_t BasePointerOffset;
-   };
+A live range of variable relative to a register (range version of `S_REGREL32`).
 
-S_DEFRANGE_REGISTER_REL_INDIR (0x1177)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+```cpp
+struct DefrangeRegisterRelSymHeader {
+  /// Register to hold the base pointer of the symbol
+  uint16_t Register;
+  /// Spilled member for s.i
+  uint16_t SpilledUdtMember : 1;
+  uint16_t Padding : 3;
+  /// Offset in parent variable.
+  uint16_t OffsetInParent : 12;
+  /// Offset to register
+  int32_t BasePointerOffset;
+};
+```
 
-A live range of variable indirectly relative to a register (range version of ``S_REGREL32_INDIR``).
+#### S_DEFRANGE_REGISTER_REL_INDIR (0x1177)
 
-.. code:: cpp
+A live range of variable indirectly relative to a register (range version of `S_REGREL32_INDIR`).
 
-   struct DefrangeRegisterRelIndirSymHeader {
-     /// Register to hold the base pointer of the symbol
-     uint16_t Register;
-     /// Spilled member for s.i
-     uint16_t SpilledUdtMember : 1;
-     uint16_t Padding : 3;
-     /// Offset in parent variable.
-     uint16_t OffsetInParent : 12; 
-     /// Offset to register
-     int32_t BasePointerOffset;
-     /// Offset to add after dereferencing `Register + BasePointerOffset`
-     int32_t OffsetInUdt;
-   };
+```cpp
+struct DefrangeRegisterRelIndirSymHeader {
+  /// Register to hold the base pointer of the symbol
+  uint16_t Register;
+  /// Spilled member for s.i
+  uint16_t SpilledUdtMember : 1;
+  uint16_t Padding : 3;
+  /// Offset in parent variable.
+  uint16_t OffsetInParent : 12;
+  /// Offset to register
+  int32_t BasePointerOffset;
+  /// Offset to add after dereferencing `Register + BasePointerOffset`
+  int32_t OffsetInUdt;
+};
+```
 
-S_LPROC32_ID (0x1146)
-^^^^^^^^^^^^^^^^^^^^^
+#### S_LPROC32_ID (0x1146)
 
-S_GPROC32_ID (0x1147)
-^^^^^^^^^^^^^^^^^^^^^
+#### S_GPROC32_ID (0x1147)
 
-S_BUILDINFO (0x114c)
-^^^^^^^^^^^^^^^^^^^^
+#### S_BUILDINFO (0x114c)
 
-S_INLINESITE (0x114d)
-^^^^^^^^^^^^^^^^^^^^^
+#### S_INLINESITE (0x114d)
 
-S_INLINESITE_END (0x114e)
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### S_INLINESITE_END (0x114e)
 
-S_PROC_ID_END (0x114f)
-^^^^^^^^^^^^^^^^^^^^^^
+#### S_PROC_ID_END (0x114f)
 
-S_FILESTATIC (0x1153)
-^^^^^^^^^^^^^^^^^^^^^
+#### S_FILESTATIC (0x1153)
 
-S_LPROC32_DPC (0x1155)
-^^^^^^^^^^^^^^^^^^^^^^
+#### S_LPROC32_DPC (0x1155)
 
-S_LPROC32_DPC_ID (0x1156)
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### S_LPROC32_DPC_ID (0x1156)
 
-S_CALLEES (0x115a)
-^^^^^^^^^^^^^^^^^^
+#### S_CALLEES (0x115a)
 
-S_CALLERS (0x115b)
-^^^^^^^^^^^^^^^^^^
+#### S_CALLERS (0x115b)
 
-S_HEAPALLOCSITE (0x115e)
-^^^^^^^^^^^^^^^^^^^^^^^^
+#### S_HEAPALLOCSITE (0x115e)
 
-S_FASTLINK (0x1167)
-^^^^^^^^^^^^^^^^^^^
+#### S_FASTLINK (0x1167)
 
-S_INLINEES (0x1168)
-^^^^^^^^^^^^^^^^^^^
+#### S_INLINEES (0x1168)
 
-S_REGREL32_INDIR (0x1171)
-^^^^^^^^^^^^^^^^^^^^^^^^^
+#### S_REGREL32_INDIR (0x1171)
 
-This encodes a variable at the location ``*($Register + Offset) + OffsetInUdt``.
+This encodes a variable at the location `*($Register + Offset) + OffsetInUdt`.
 It's equivalent to the following DWARF location expression:
 
-.. code::
-
-   DW_OP_breg{corresponding DWARF register} {Offset}
-   DW_OP_deref
-   DW_OP_plus_uconst {OffsetInUdt}
+```
+DW_OP_breg{corresponding DWARF register} {Offset}
+DW_OP_deref
+DW_OP_plus_uconst {OffsetInUdt}
+```
 
 It's used in C++ 17 structured bindings for example:
 
-.. code:: cpp
-
-   struct Foo { int a, b; };
-
-   void fn() {
-     Foo f = {1, 2};
-     //  ╰─ S_REGREL32{ reg = rsp, offset = 0 }
-     auto &[x, y] = f;
-     //     │  ╰─ S_REGREL32_INDIR{ reg = rsp, offset = 8, offset-in-udt = 4, type = int }
-     //     ╰─ S_REGREL32_INDIR{ reg = rsp, offset = 8, offset-in-udt = 0, type = int }
-   }
+```cpp
+struct Foo { int a, b; };
 
-The ``S_REGREL32_INDIR`` symbol for ``y`` from above looks like this:
+void fn() {
+  Foo f = {1, 2};
+  //  ╰─ S_REGREL32{ reg = rsp, offset = 0 }
+  auto &[x, y] = f;
+  //     │  ╰─ S_REGREL32_INDIR{ reg = rsp, offset = 8, offset-in-udt = 4, type = int }
+  //     ╰─ S_REGREL32_INDIR{ reg = rsp, offset = 8, offset-in-udt = 0, type = int }
+}
+```
 
+The `S_REGREL32_INDIR` symbol for `y` from above looks like this:
 
-============  ============  ============  ========  ========
-Offset        Type          OffsetInUdt   Register  Name
-============  ============  ============  ========  ========
-``08000000``  ``74000000``  ``04000000``  ``4F01``  ``7900``
-8             int           4             RSP       "a"
-============  ============  ============  ========  ========
+| Offset     | Type       | OffsetInUdt | Register | Name   |
+| ---------- | ---------- | ----------- | -------- | ------ |
+| `08000000` | `74000000` | `04000000`  | `4F01`   | `7900` |
+| 8          | int        | 4           | RSP      | "a"    |
 
-.. _module_and_global_symbols:
+(module-and-global-symbols)=
 
-Symbols which can go in either/both of the module info stream & global stream
------------------------------------------------------------------------------
+### Symbols which can go in either/both of the module info stream & global stream
 
-S_CONSTANT (0x1107)
-^^^^^^^^^^^^^^^^^^^
+#### S_CONSTANT (0x1107)
 
-S_UDT (0x1108)
-^^^^^^^^^^^^^^
+#### S_UDT (0x1108)
 
-S_LDATA32 (0x110c)
-^^^^^^^^^^^^^^^^^^
+#### S_LDATA32 (0x110c)
 
-S_LTHREAD32 (0x1112)
-^^^^^^^^^^^^^^^^^^^^
+#### S_LTHREAD32 (0x1112)
 
-S_LMANDATA (0x111c)
-^^^^^^^^^^^^^^^^^^^
+#### S_LMANDATA (0x111c)
 
-S_MANCONSTANT (0x112d)
-^^^^^^^^^^^^^^^^^^^^^^
+#### S_MANCONSTANT (0x112d)
 
diff --git a/llvm/docs/PDB/CodeViewTypes.md b/llvm/docs/PDB/CodeViewTypes.md
index 6614875cb699e..dfa19f4606f25 100644
--- a/llvm/docs/PDB/CodeViewTypes.md
+++ b/llvm/docs/PDB/CodeViewTypes.md
@@ -1,259 +1,211 @@
 =====================================
 CodeView Type Records
-=====================================
+\=====================================
 
+(types-intro)=
 
-
-.. _types_intro:
-
-Introduction
-============
+# Introduction
 
 This document describes the usage and serialization format of the various
-CodeView type records that LLVM understands.  This document does not describe
-every single CodeView type record that is defined.  In some cases, this is
+CodeView type records that LLVM understands. This document does not describe
+every single CodeView type record that is defined. In some cases, this is
 because the records are clearly deprecated and can only appear in very old
-software (e.g. the 16-bit types).  On other cases, it is because the records
-have never been observed in practice.  This could be because they are only
+software (e.g. the 16-bit types). On other cases, it is because the records
+have never been observed in practice. This could be because they are only
 generated for non-C++ code (e.g. Visual Basic, C#), or because they have been
-made obsolete by newer records, or any number of other reasons.  However, the
+made obsolete by newer records, or any number of other reasons. However, the
 records we describe here should cover 99% of type records that one can expect
 to encounter when dealing with modern C++ toolchains.
 
-Record Categories
-=================
+# Record Categories
 
 We can think of a sequence of CodeView type records as an array of variable length
-`leaf records`.  Each such record describes its own length as part of a fixed-size
-header, as well as the kind of record it is.  Leaf records are either padded to 4
+`leaf records`. Each such record describes its own length as part of a fixed-size
+header, as well as the kind of record it is. Leaf records are either padded to 4
 bytes (if this type stream appears in a TPI/IPI stream of a PDB) or not padded at
-all (if this type stream appears in the ``.debug$T`` section of an object file).
+all (if this type stream appears in the `.debug$T` section of an object file).
 Padding is implemented by inserting a decreasing sequence of `<_padding_records>`
-that terminates with ``LF_PAD0``.
+that terminates with `LF_PAD0`.
 
-The final category of record is a ``member record``.  One particular leaf type --
-``LF_FIELDLIST`` -- contains a series of embedded records.  While the outer
-``LF_FIELDLIST`` describes its length (like any other leaf record), the embedded
-records -- called ``member records`` do not.
+The final category of record is a `member record`. One particular leaf type --
+`LF_FIELDLIST` -- contains a series of embedded records. While the outer
+`LF_FIELDLIST` describes its length (like any other leaf record), the embedded
+records -- called `member records` do not.
 
-.. _leaf_types:
+(leaf-types)=
 
-Leaf Records
-------------
+## Leaf Records
 
 All leaf records begin with the following 4-byte prefix:
 
-.. code-block:: c++
-
-  struct RecordHeader {
-    uint16_t RecordLen;  // Record length, not including this 2-byte field.
-    uint16_t RecordKind; // Record kind enum.
-  };
+```c++
+struct RecordHeader {
+  uint16_t RecordLen;  // Record length, not including this 2-byte field.
+  uint16_t RecordKind; // Record kind enum.
+};
+```
 
-LF_POINTER (0x1002)
-^^^^^^^^^^^^^^^^^^^
+### LF_POINTER (0x1002)
 
 **Usage:** Describes a pointer to another type.
 
 **Layout:**
 
-.. code-block:: none
-
-  .--------------------.-- +0
-  |    Referent Type   |
-  .--------------------.-- +4
-  |     Attributes     |
-  .--------------------.-- +8
-  |  Member Ptr Info   |       Only present if |Attributes| indicates this is a member pointer.
-  .--------------------.-- +E
+```none
+.--------------------.-- +0
+|    Referent Type   |
+.--------------------.-- +4
+|     Attributes     |
+.--------------------.-- +8
+|  Member Ptr Info   |       Only present if |Attributes| indicates this is a member pointer.
+.--------------------.-- +E
+```
 
 Attributes is a bitfield with the following layout:
 
-.. code-block:: none
-
-    .-----------------------------------------------------------------------------------------------------.
-    |     Unused                   |  Flags  |       Size       |   Modifiers   |  Mode   |      Kind     |
-    .-----------------------------------------------------------------------------------------------------.
-    |                              |         |                  |               |         |               |
-   0x100                         +0x16     +0x13               +0xD            +0x8      +0x5            +0x0
+```none
+ .-----------------------------------------------------------------------------------------------------.
+ |     Unused                   |  Flags  |       Size       |   Modifiers   |  Mode   |      Kind     |
+ .-----------------------------------------------------------------------------------------------------.
+ |                              |         |                  |               |         |               |
+0x100                         +0x16     +0x13               +0xD            +0x8      +0x5            +0x0
+```
 
 where the various fields are defined by the following enums:
 
-.. code-block:: c++
-
-  enum class PointerKind : uint8_t {
-    Near16 = 0x00,                // 16 bit pointer
-    Far16 = 0x01,                 // 16:16 far pointer
-    Huge16 = 0x02,                // 16:16 huge pointer
-    BasedOnSegment = 0x03,        // based on segment
-    BasedOnValue = 0x04,          // based on value of base
-    BasedOnSegmentValue = 0x05,   // based on segment value of base
-    BasedOnAddress = 0x06,        // based on address of base
-    BasedOnSegmentAddress = 0x07, // based on segment address of base
-    BasedOnType = 0x08,           // based on type
-    BasedOnSelf = 0x09,           // based on self
-    Near32 = 0x0a,                // 32 bit pointer
-    Far32 = 0x0b,                 // 16:32 pointer
-    Near64 = 0x0c                 // 64 bit pointer
-  };
-  enum class PointerMode : uint8_t {
-    Pointer = 0x00,                 // "normal" pointer
-    LValueReference = 0x01,         // "old" reference
-    PointerToDataMember = 0x02,     // pointer to data member
-    PointerToMemberFunction = 0x03, // pointer to member function
-    RValueReference = 0x04          // r-value reference
-  };
-  enum class PointerModifiers : uint8_t {
-    None = 0x00,                    // "normal" pointer
-    Flat32 = 0x01,                  // "flat" pointer
-    Volatile = 0x02,                // pointer is marked volatile
-    Const = 0x04,                   // pointer is marked const
-    Unaligned = 0x08,               // pointer is marked unaligned
-    Restrict = 0x10,                // pointer is marked restrict
-  };
-  enum class PointerFlags : uint8_t {
-    WinRTSmartPointer = 0x01,       // pointer is a WinRT smart pointer
-    LValueRefThisPointer = 0x02,    // pointer is a 'this' pointer of a member function with ref qualifier (e.g. void X::foo() &)
-    RValueRefThisPointer = 0x04     // pointer is a 'this' pointer of a member function with ref qualifier (e.g. void X::foo() &&)
-  };
-
-The ``Size`` field of the Attributes bitmask is a 1-byte value indicating the
-pointer size.  For example, a `void*` would have a size of either 4 or 8 depending
-on the target architecture.  On the other hand, if ``Mode`` indicates that this is
+```c++
+enum class PointerKind : uint8_t {
+  Near16 = 0x00,                // 16 bit pointer
+  Far16 = 0x01,                 // 16:16 far pointer
+  Huge16 = 0x02,                // 16:16 huge pointer
+  BasedOnSegment = 0x03,        // based on segment
+  BasedOnValue = 0x04,          // based on value of base
+  BasedOnSegmentValue = 0x05,   // based on segment value of base
+  BasedOnAddress = 0x06,        // based on address of base
+  BasedOnSegmentAddress = 0x07, // based on segment address of base
+  BasedOnType = 0x08,           // based on type
+  BasedOnSelf = 0x09,           // based on self
+  Near32 = 0x0a,                // 32 bit pointer
+  Far32 = 0x0b,                 // 16:32 pointer
+  Near64 = 0x0c                 // 64 bit pointer
+};
+enum class PointerMode : uint8_t {
+  Pointer = 0x00,                 // "normal" pointer
+  LValueReference = 0x01,         // "old" reference
+  PointerToDataMember = 0x02,     // pointer to data member
+  PointerToMemberFunction = 0x03, // pointer to member function
+  RValueReference = 0x04          // r-value reference
+};
+enum class PointerModifiers : uint8_t {
+  None = 0x00,                    // "normal" pointer
+  Flat32 = 0x01,                  // "flat" pointer
+  Volatile = 0x02,                // pointer is marked volatile
+  Const = 0x04,                   // pointer is marked const
+  Unaligned = 0x08,               // pointer is marked unaligned
+  Restrict = 0x10,                // pointer is marked restrict
+};
+enum class PointerFlags : uint8_t {
+  WinRTSmartPointer = 0x01,       // pointer is a WinRT smart pointer
+  LValueRefThisPointer = 0x02,    // pointer is a 'this' pointer of a member function with ref qualifier (e.g. void X::foo() &)
+  RValueRefThisPointer = 0x04     // pointer is a 'this' pointer of a member function with ref qualifier (e.g. void X::foo() &&)
+};
+```
+
+The `Size` field of the Attributes bitmask is a 1-byte value indicating the
+pointer size. For example, a `void*` would have a size of either 4 or 8 depending
+on the target architecture. On the other hand, if `Mode` indicates that this is
 a pointer to member function or pointer to data member, then the size can be any
 implementation-defined number.
 
-The ``Member Ptr Info`` field of the ``LF_POINTER`` record is only present if the
+The `Member Ptr Info` field of the `LF_POINTER` record is only present if the
 attributes indicate that this is a pointer to member.
 
-Note that "plain" pointers to primitive types are not represented by ``LF_POINTER``
-records, they are indicated by special reserved :ref:`TypeIndex values <type_indices>`.
-
+Note that "plain" pointers to primitive types are not represented by `LF_POINTER`
+records, they are indicated by special reserved {ref}`TypeIndex values <type_indices>`.
 
+### LF_MODIFIER (0x1001)
 
-LF_MODIFIER (0x1001)
-^^^^^^^^^^^^^^^^^^^^
+### LF_PROCEDURE (0x1008)
 
-LF_PROCEDURE (0x1008)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_MFUNCTION (0x1009)
 
-LF_MFUNCTION (0x1009)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_LABEL (0x000e)
 
-LF_LABEL (0x000e)
-^^^^^^^^^^^^^^^^^
+### LF_ARGLIST (0x1201)
 
-LF_ARGLIST (0x1201)
-^^^^^^^^^^^^^^^^^^^
+### LF_FIELDLIST (0x1203)
 
-LF_FIELDLIST (0x1203)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_ARRAY (0x1503)
 
-LF_ARRAY (0x1503)
-^^^^^^^^^^^^^^^^^
+### LF_CLASS (0x1504)
 
-LF_CLASS (0x1504)
-^^^^^^^^^^^^^^^^^
+### LF_STRUCTURE (0x1505)
 
-LF_STRUCTURE (0x1505)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_INTERFACE (0x1519)
 
-LF_INTERFACE (0x1519)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_UNION (0x1506)
 
-LF_UNION (0x1506)
-^^^^^^^^^^^^^^^^^
+### LF_ENUM (0x1507)
 
-LF_ENUM (0x1507)
-^^^^^^^^^^^^^^^^
+### LF_TYPESERVER2 (0x1515)
 
-LF_TYPESERVER2 (0x1515)
-^^^^^^^^^^^^^^^^^^^^^^^
+### LF_VFTABLE (0x151d)
 
-LF_VFTABLE (0x151d)
-^^^^^^^^^^^^^^^^^^^
+### LF_VTSHAPE (0x000a)
 
-LF_VTSHAPE (0x000a)
-^^^^^^^^^^^^^^^^^^^
+### LF_BITFIELD (0x1205)
 
-LF_BITFIELD (0x1205)
-^^^^^^^^^^^^^^^^^^^^
+### LF_FUNC_ID (0x1601)
 
-LF_FUNC_ID (0x1601)
-^^^^^^^^^^^^^^^^^^^
+### LF_MFUNC_ID (0x1602)
 
-LF_MFUNC_ID (0x1602)
-^^^^^^^^^^^^^^^^^^^^
+### LF_BUILDINFO (0x1603)
 
-LF_BUILDINFO (0x1603)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_SUBSTR_LIST (0x1604)
 
-LF_SUBSTR_LIST (0x1604)
-^^^^^^^^^^^^^^^^^^^^^^^
+### LF_STRING_ID (0x1605)
 
-LF_STRING_ID (0x1605)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_UDT_SRC_LINE (0x1606)
 
-LF_UDT_SRC_LINE (0x1606)
-^^^^^^^^^^^^^^^^^^^^^^^^
+### LF_UDT_MOD_SRC_LINE (0x1607)
 
-LF_UDT_MOD_SRC_LINE (0x1607)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+### LF_METHODLIST (0x1206)
 
-LF_METHODLIST (0x1206)
-^^^^^^^^^^^^^^^^^^^^^^
+### LF_PRECOMP (0x1509)
 
-LF_PRECOMP (0x1509)
-^^^^^^^^^^^^^^^^^^^
+### LF_ENDPRECOMP (0x0014)
 
-LF_ENDPRECOMP (0x0014)
-^^^^^^^^^^^^^^^^^^^^^^
+(member-types)=
 
-.. _member_types:
+## Member Records
 
-Member Records
---------------
+### LF_BCLASS (0x1400)
 
-LF_BCLASS (0x1400)
-^^^^^^^^^^^^^^^^^^
+### LF_BINTERFACE (0x151a)
 
-LF_BINTERFACE (0x151a)
-^^^^^^^^^^^^^^^^^^^^^^
+### LF_VBCLASS (0x1401)
 
-LF_VBCLASS (0x1401)
-^^^^^^^^^^^^^^^^^^^
+### LF_IVBCLASS (0x1402)
 
-LF_IVBCLASS (0x1402)
-^^^^^^^^^^^^^^^^^^^^
+### LF_VFUNCTAB (0x1409)
 
-LF_VFUNCTAB (0x1409)
-^^^^^^^^^^^^^^^^^^^^
+### LF_STMEMBER (0x150e)
 
-LF_STMEMBER (0x150e)
-^^^^^^^^^^^^^^^^^^^^
+### LF_METHOD (0x150f)
 
-LF_METHOD (0x150f)
-^^^^^^^^^^^^^^^^^^
+### LF_MEMBER (0x150d)
 
-LF_MEMBER (0x150d)
-^^^^^^^^^^^^^^^^^^
+### LF_NESTTYPE (0x1510)
 
-LF_NESTTYPE (0x1510)
-^^^^^^^^^^^^^^^^^^^^
+### LF_ONEMETHOD (0x1511)
 
-LF_ONEMETHOD (0x1511)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_ENUMERATE (0x1502)
 
-LF_ENUMERATE (0x1502)
-^^^^^^^^^^^^^^^^^^^^^
+### LF_INDEX (0x1404)
 
-LF_INDEX (0x1404)
-^^^^^^^^^^^^^^^^^
+(padding-records)=
 
-.. _padding_records:
+## Padding Records
 
-Padding Records
----------------
+### LF_PADn (0xf0 + n)
 
-LF_PADn (0xf0 + n)
-^^^^^^^^^^^^^^^^^^
diff --git a/llvm/docs/PDB/DbiStream.md b/llvm/docs/PDB/DbiStream.md
index 83a024a854845..d3b4bd000a06c 100644
--- a/llvm/docs/PDB/DbiStream.md
+++ b/llvm/docs/PDB/DbiStream.md
@@ -1,15 +1,11 @@
-=====================================
-The PDB DBI (Debug Info) Stream
-=====================================
+# The PDB DBI (Debug Info) Stream
 
+(dbi-intro)=
 
-.. _dbi_intro:
-
-Introduction
-============
+## Introduction
 
 The PDB DBI Stream (Index 3) is one of the largest and most important streams
-in a PDB file.  It contains information about how the program was compiled,
+in a PDB file. It contains information about how the program was compiled,
 (e.g. compilation flags, etc), the compilands (e.g. object files) that
 were used to link together the program, the source files which were used
 to build the program, as well as references to other streams that contain more
@@ -17,359 +13,330 @@ detailed information about each compiland, such as the CodeView symbol records
 contained within each compiland and the source and line information for
 functions and other symbols within each compiland.
 
+(dbi-header)=
 
-.. _dbi_header:
+## Stream Header
 
-Stream Header
-=============
 At offset 0 of the DBI Stream is a header with the following layout:
 
-
-.. code-block:: c++
-
-  struct DbiStreamHeader {
-    int32_t VersionSignature;
-    uint32_t VersionHeader;
-    uint32_t Age;
-    uint16_t GlobalStreamIndex;
-    uint16_t BuildNumber;
-    uint16_t PublicStreamIndex;
-    uint16_t PdbDllVersion;
-    uint16_t SymRecordStream;
-    uint16_t PdbDllRbld;
-    int32_t ModInfoSize;
-    int32_t SectionContributionSize;
-    int32_t SectionMapSize;
-    int32_t SourceInfoSize;
-    int32_t TypeServerMapSize;
-    uint32_t MFCTypeServerIndex;
-    int32_t OptionalDbgHeaderSize;
-    int32_t ECSubstreamSize;
-    uint16_t Flags;
-    uint16_t Machine;
-    uint32_t Padding;
-  };
-
-- **VersionSignature** - Unknown meaning.  Appears to always be ``-1``.
-
+```c++
+struct DbiStreamHeader {
+  int32_t VersionSignature;
+  uint32_t VersionHeader;
+  uint32_t Age;
+  uint16_t GlobalStreamIndex;
+  uint16_t BuildNumber;
+  uint16_t PublicStreamIndex;
+  uint16_t PdbDllVersion;
+  uint16_t SymRecordStream;
+  uint16_t PdbDllRbld;
+  int32_t ModInfoSize;
+  int32_t SectionContributionSize;
+  int32_t SectionMapSize;
+  int32_t SourceInfoSize;
+  int32_t TypeServerMapSize;
+  uint32_t MFCTypeServerIndex;
+  int32_t OptionalDbgHeaderSize;
+  int32_t ECSubstreamSize;
+  uint16_t Flags;
+  uint16_t Machine;
+  uint32_t Padding;
+};
+```
+
+- **VersionSignature** - Unknown meaning. Appears to always be `-1`.
 - **VersionHeader** - A value from the following enum.
 
-.. code-block:: c++
-
-  enum class DbiStreamVersion : uint32_t {
-    VC41 = 930803,
-    V50 = 19960307,
-    V60 = 19970606,
-    V70 = 19990903,
-    V110 = 20091201
-  };
-
-Similar to the :doc:`PDB Stream <PdbStream>`, this value always appears to be
-``V70``, and it is not clear what the other values are for.
-
-- **Age** - The number of times the PDB has been written.  Equal to the same
-  field from the :ref:`PDB Stream header <pdb_stream_header>`.
-
-- **GlobalStreamIndex** - The index of the :doc:`Global Symbol Stream <GlobalStream>`,
-  which contains CodeView symbol records for all global symbols.  Actual records
+```c++
+enum class DbiStreamVersion : uint32_t {
+  VC41 = 930803,
+  V50 = 19960307,
+  V60 = 19970606,
+  V70 = 19990903,
+  V110 = 20091201
+};
+```
+
+Similar to the {doc}`PDB Stream <PdbStream>`, this value always appears to be
+`V70`, and it is not clear what the other values are for.
+
+- **Age** - The number of times the PDB has been written. Equal to the same
+  field from the {ref}`PDB Stream header <pdb_stream_header>`.
+- **GlobalStreamIndex** - The index of the {doc}`Global Symbol Stream <GlobalStream>`,
+  which contains CodeView symbol records for all global symbols. Actual records
   are stored in the symbol record stream, and are referenced from this stream.
-
 - **BuildNumber** - A bitfield containing values representing the major and minor
   version number of the toolchain (e.g. 12.0 for MSVC 2013) used to build the
   program, with the following layout:
 
-.. code-block:: c++
+```c++
+uint16_t MinorVersion : 8;
+uint16_t MajorVersion : 7;
+uint16_t NewVersionFormat : 1;
+```
 
-  uint16_t MinorVersion : 8;
-  uint16_t MajorVersion : 7;
-  uint16_t NewVersionFormat : 1;
-
-For the purposes of LLVM, we assume ``NewVersionFormat`` to be always ``true``.
-If it is ``false``, the layout above does not apply and the reader should consult
-the `Microsoft Source Code <https://github.com/Microsoft/microsoft-pdb>`__ for
+For the purposes of LLVM, we assume `NewVersionFormat` to be always `true`.
+If it is `false`, the layout above does not apply and the reader should consult
+the [Microsoft Source Code](https://github.com/Microsoft/microsoft-pdb) for
 further guidance.
 
-- **PublicStreamIndex** - The index of the :doc:`Public Symbol Stream <PublicStream>`,
-  which contains CodeView symbol records for all public symbols.  Actual records
+- **PublicStreamIndex** - The index of the {doc}`Public Symbol Stream <PublicStream>`,
+  which contains CodeView symbol records for all public symbols. Actual records
   are stored in the symbol record stream, and are referenced from this stream.
-
-- **PdbDllVersion** - The version number of ``mspdbXXXX.dll`` used to produce this
-  PDB.  Note this obviously does not apply for LLVM as LLVM does not use ``mspdb.dll``.
-
+- **PdbDllVersion** - The version number of `mspdbXXXX.dll` used to produce this
+  PDB. Note this obviously does not apply for LLVM as LLVM does not use `mspdb.dll`.
 - **SymRecordStream** - The stream containing all CodeView symbol records used
-  by the program.  This is used for deduplication, so that many different
+  by the program. This is used for deduplication, so that many different
   compilands can refer to the same symbols without having to include the full record
   content inside of each module stream.
-
 - **PdbDllRbld** - Unknown
-
 - **MFCTypeServerIndex** - The index of the MFC type server in the
-  :ref:`dbi_type_server_map_substream`.
-
+  {ref}`dbi_type_server_map_substream`.
 - **Flags** - A bitfield with the following layout, containing various
   information about how the program was built:
 
-.. code-block:: c++
-
-  uint16_t WasIncrementallyLinked : 1;
-  uint16_t ArePrivateSymbolsStripped : 1;
-  uint16_t HasConflictingTypes : 1;
-  uint16_t Reserved : 13;
-
-The only one of these that is not self-explanatory is ``HasConflictingTypes``.
-Although undocumented, ``link.exe`` contains a hidden flag ``/DEBUG:CTYPES``.
-If it is passed to ``link.exe``, this field will be set.  Otherwise it will
-not be set.  It is unclear what this flag does, although it seems to have
+```c++
+uint16_t WasIncrementallyLinked : 1;
+uint16_t ArePrivateSymbolsStripped : 1;
+uint16_t HasConflictingTypes : 1;
+uint16_t Reserved : 13;
+```
+
+The only one of these that is not self-explanatory is `HasConflictingTypes`.
+Although undocumented, `link.exe` contains a hidden flag `/DEBUG:CTYPES`.
+If it is passed to `link.exe`, this field will be set. Otherwise it will
+not be set. It is unclear what this flag does, although it seems to have
 subtle implications on the algorithm used to look up type records.
 
-- **Machine** - A value from the `CV_CPU_TYPE_e <https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx>`__
-  enumeration.  Common values are ``0x8664`` (x86-64) and ``0x14C`` (x86).
-
-Immediately after the fixed-size DBI Stream header are ``7`` variable-length
-`substreams`.  The following ``7`` fields of the DBI Stream header specify the
-number of bytes of the corresponding substream.  Each substream's contents will
-be described in detail :ref:`below <dbi_substreams>`.  The length of the entire
-DBI Stream should equal ``64`` (the length of the header above) plus the value
-of each of the following ``7`` fields.
-
-- **ModInfoSize** - The length of the :ref:`dbi_mod_info_substream`.
-
-- **SectionContributionSize** - The length of the :ref:`dbi_sec_contr_substream`.
-
-- **SectionMapSize** - The length of the :ref:`dbi_section_map_substream`.
+- **Machine** - A value from the [CV_CPU_TYPE_e](https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx)
+  enumeration. Common values are `0x8664` (x86-64) and `0x14C` (x86).
 
-- **SourceInfoSize** - The length of the :ref:`dbi_file_info_substream`.
+Immediately after the fixed-size DBI Stream header are `7` variable-length
+`substreams`. The following `7` fields of the DBI Stream header specify the
+number of bytes of the corresponding substream. Each substream's contents will
+be described in detail {ref}`below <dbi_substreams>`. The length of the entire
+DBI Stream should equal `64` (the length of the header above) plus the value
+of each of the following `7` fields.
 
-- **TypeServerMapSize** - The length of the :ref:`dbi_type_server_map_substream`.
+- **ModInfoSize** - The length of the {ref}`dbi_mod_info_substream`.
+- **SectionContributionSize** - The length of the {ref}`dbi_sec_contr_substream`.
+- **SectionMapSize** - The length of the {ref}`dbi_section_map_substream`.
+- **SourceInfoSize** - The length of the {ref}`dbi_file_info_substream`.
+- **TypeServerMapSize** - The length of the {ref}`dbi_type_server_map_substream`.
+- **OptionalDbgHeaderSize** - The length of the {ref}`dbi_optional_dbg_stream`.
+- **ECSubstreamSize** - The length of the {ref}`dbi_ec_substream`.
 
-- **OptionalDbgHeaderSize** - The length of the :ref:`dbi_optional_dbg_stream`.
+(dbi-substreams)=
 
-- **ECSubstreamSize** - The length of the :ref:`dbi_ec_substream`.
+## Substreams
 
-.. _dbi_substreams:
+(dbi-mod-info-substream)=
 
-Substreams
-==========
+### Module Info Substream
 
-.. _dbi_mod_info_substream:
-
-Module Info Substream
-^^^^^^^^^^^^^^^^^^^^^
-
-Begins at offset ``0`` immediately after the :ref:`header <dbi_header>`.  The
+Begins at offset `0` immediately after the {ref}`header <dbi_header>`. The
 module info substream is an array of variable-length records, each one
-describing a single module (e.g. object file) linked into the program.  Each
+describing a single module (e.g. object file) linked into the program. Each
 record in the array has the format:
 
-.. code-block:: c++
-
-  struct ModInfo {
-    uint32_t Unused1;
-    struct SectionContribEntry {
-      uint16_t Section;
-      char Padding1[2];
-      int32_t Offset;
-      int32_t Size;
-      uint32_t Characteristics;
-      uint16_t ModuleIndex;
-      char Padding2[2];
-      uint32_t DataCrc;
-      uint32_t RelocCrc;
-    } SectionContr;
-    uint16_t Flags;
-    uint16_t ModuleSymStream;
-    uint32_t SymByteSize;
-    uint32_t C11ByteSize;
-    uint32_t C13ByteSize;
-    uint16_t SourceFileCount;
-    char Padding[2];
-    uint32_t Unused2;
-    uint32_t SourceFileNameIndex;
-    uint32_t PdbFilePathNameIndex;
-    char ModuleName[];
-    char ObjFileName[];
-  };
+```c++
+struct ModInfo {
+  uint32_t Unused1;
+  struct SectionContribEntry {
+    uint16_t Section;
+    char Padding1[2];
+    int32_t Offset;
+    int32_t Size;
+    uint32_t Characteristics;
+    uint16_t ModuleIndex;
+    char Padding2[2];
+    uint32_t DataCrc;
+    uint32_t RelocCrc;
+  } SectionContr;
+  uint16_t Flags;
+  uint16_t ModuleSymStream;
+  uint32_t SymByteSize;
+  uint32_t C11ByteSize;
+  uint32_t C13ByteSize;
+  uint16_t SourceFileCount;
+  char Padding[2];
+  uint32_t Unused2;
+  uint32_t SourceFileNameIndex;
+  uint32_t PdbFilePathNameIndex;
+  char ModuleName[];
+  char ObjFileName[];
+};
+```
 
 - **SectionContr** - Describes the properties of the section in the final binary
   which contain the code and data from this module.
 
-  ``SectionContr.Characteristics`` corresponds to the ``Characteristics`` field
-  of the `IMAGE_SECTION_HEADER <https://msdn.microsoft.com/en-us/library/windows/desktop/ms680341(v=vs.85).aspx>`__
+  `SectionContr.Characteristics` corresponds to the `Characteristics` field
+  of the [IMAGE_SECTION_HEADER](<https://msdn.microsoft.com/en-us/library/windows/desktop/ms680341(v=vs.85).aspx>)
   structure.
 
-
 - **Flags** - A bitfield with the following format:
 
-.. code-block:: c++
-
-  // ``true`` if this ModInfo has been written since reading the PDB.  This is
-  // likely used to support incremental linking, so that the linker can decide
-  // if it needs to commit changes to disk.
-  uint16_t Dirty : 1;
-  // ``true`` if EC information is present for this module. EC is presumed to
-  // stand for "Edit & Continue", which LLVM does not support.  So this flag
-  // will always be false.
-  uint16_t EC : 1;
-  uint16_t Unused : 6;
-  // Type Server Index for this module.  This is assumed to be related to /Zi,
-  // but as LLVM treats /Zi as /Z7, this field will always be invalid for LLVM
-  // generated PDBs.
-  uint16_t TSM : 8;
-
+```c++
+// ``true`` if this ModInfo has been written since reading the PDB.  This is
+// likely used to support incremental linking, so that the linker can decide
+// if it needs to commit changes to disk.
+uint16_t Dirty : 1;
+// ``true`` if EC information is present for this module. EC is presumed to
+// stand for "Edit & Continue", which LLVM does not support.  So this flag
+// will always be false.
+uint16_t EC : 1;
+uint16_t Unused : 6;
+// Type Server Index for this module.  This is assumed to be related to /Zi,
+// but as LLVM treats /Zi as /Z7, this field will always be invalid for LLVM
+// generated PDBs.
+uint16_t TSM : 8;
+```
 
 - **ModuleSymStream** - The index of the stream that contains symbol information
-  for this module.  This includes CodeView symbol information as well as source
-  and line information.  If this field is -1, then no additional debug info will
+  for this module. This includes CodeView symbol information as well as source
+  and line information. If this field is -1, then no additional debug info will
   be present for this module (for example, this is what happens when you strip
   private symbols from a PDB).
-
 - **SymByteSize** - The number of bytes of data from the stream identified by
-  ``ModuleSymStream`` that represent CodeView symbol records.
-
+  `ModuleSymStream` that represent CodeView symbol records.
 - **C11ByteSize** - The number of bytes of data from the stream identified by
-  ``ModuleSymStream`` that represent C11-style CodeView line information.
-
+  `ModuleSymStream` that represent C11-style CodeView line information.
 - **C13ByteSize** - The number of bytes of data from the stream identified by
-  ``ModuleSymStream`` that represent C13-style CodeView line information.  At
-  most one of ``C11ByteSize`` and ``C13ByteSize`` will be non-zero.  Modern PDBs
+  `ModuleSymStream` that represent C13-style CodeView line information. At
+  most one of `C11ByteSize` and `C13ByteSize` will be non-zero. Modern PDBs
   always use C13 instead of C11.
-
 - **SourceFileCount** - The number of source files that contributed to this
   module during compilation.
-
 - **SourceFileNameIndex** - The offset in the names buffer of the primary
-  translation unit used to build this module.  All PDB files observed to date
+  translation unit used to build this module. All PDB files observed to date
   always have this value equal to 0.
-
 - **PdbFilePathNameIndex** - The offset in the names buffer of the PDB file
-  containing this module's symbol information.  This has only been observed
-  to be non-zero for the special ``* Linker *`` module.
-
-- **ModuleName** - The module name.  This is usually either a full path to an
-  object file (either directly passed to ``link.exe`` or from an archive) or
-  a string of the form ``Import:<dll name>``.
-
-- **ObjFileName** - The object file name.  In the case of an module that is
-  linked directly passed to ``link.exe``, this is the same as **ModuleName**.
+  containing this module's symbol information. This has only been observed
+  to be non-zero for the special `* Linker *` module.
+- **ModuleName** - The module name. This is usually either a full path to an
+  object file (either directly passed to `link.exe` or from an archive) or
+  a string of the form `Import:<dll name>`.
+- **ObjFileName** - The object file name. In the case of an module that is
+  linked directly passed to `link.exe`, this is the same as **ModuleName**.
   In the case of a module that comes from an archive, this is usually the full
   path to the archive.
 
-.. _dbi_sec_contr_substream:
+(dbi-sec-contr-substream)=
 
-Section Contribution Substream
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Begins at offset ``0`` immediately after the :ref:`dbi_mod_info_substream` ends,
-and consumes ``Header->SectionContributionSize`` bytes.  This substream begins
-with a single ``uint32_t`` which will be one of the following values:
+### Section Contribution Substream
 
-.. code-block:: c++
+Begins at offset `0` immediately after the {ref}`dbi_mod_info_substream` ends,
+and consumes `Header->SectionContributionSize` bytes. This substream begins
+with a single `uint32_t` which will be one of the following values:
 
-  enum class SectionContrSubstreamVersion : uint32_t {
-    Ver60 = 0xeffe0000 + 19970605,
-    V2 = 0xeffe0000 + 20140516
-  };
+```c++
+enum class SectionContrSubstreamVersion : uint32_t {
+  Ver60 = 0xeffe0000 + 19970605,
+  V2 = 0xeffe0000 + 20140516
+};
+```
 
-``Ver60`` is the only value which has been observed in a PDB so far.  Following
-this is an array of fixed-length structures.  If the version is ``Ver60``,
-it is an array of ``SectionContribEntry`` structures (this is the nested structure
-from the ``ModInfo`` type.  If the version is ``V2``, it is an array of
-``SectionContribEntry2`` structures, defined as follows:
+`Ver60` is the only value which has been observed in a PDB so far. Following
+this is an array of fixed-length structures. If the version is `Ver60`,
+it is an array of `SectionContribEntry` structures (this is the nested structure
+from the `ModInfo` type. If the version is `V2`, it is an array of
+`SectionContribEntry2` structures, defined as follows:
 
-.. code-block:: c++
+```c++
+struct SectionContribEntry2 {
+  SectionContribEntry SC;
+  uint32_t ISectCoff;
+};
+```
 
-  struct SectionContribEntry2 {
-    SectionContribEntry SC;
-    uint32_t ISectCoff;
-  };
-
-The purpose of the second field is not well understood.  The name implies that
+The purpose of the second field is not well understood. The name implies that
 is the index of the COFF section, but this also describes the existing field
-``SectionContribEntry::Section``.
+`SectionContribEntry::Section`.
 
+(dbi-section-map-substream)=
 
-.. _dbi_section_map_substream:
+### Section Map Substream
 
-Section Map Substream
-^^^^^^^^^^^^^^^^^^^^^
-Begins at offset ``0`` immediately after the :ref:`dbi_sec_contr_substream` ends,
-and consumes ``Header->SectionMapSize`` bytes.  This substream begins with an ``4``
-byte header followed by an array of fixed-length records.  The header and records
+Begins at offset `0` immediately after the {ref}`dbi_sec_contr_substream` ends,
+and consumes `Header->SectionMapSize` bytes. This substream begins with an `4`
+byte header followed by an array of fixed-length records. The header and records
 have the following layout:
 
-.. code-block:: c++
-
-  struct SectionMapHeader {
-    uint16_t Count;    // Number of segment descriptors
-    uint16_t LogCount; // Number of logical segment descriptors
-  };
-
-  struct SectionMapEntry {
-    uint16_t Flags;         // See the SectionMapEntryFlags enum below.
-    uint16_t Ovl;           // Logical overlay number
-    uint16_t Group;         // Group index into descriptor array.
-    uint16_t Frame;
-    uint16_t SectionName;   // Byte index of segment / group name in string table, or 0xFFFF.
-    uint16_t ClassName;     // Byte index of class in string table, or 0xFFFF.
-    uint32_t Offset;        // Byte offset of the logical segment within physical segment.  If group is set in flags, this is the offset of the group.
-    uint32_t SectionLength; // Byte count of the segment or group.
-  };
-
-  enum class SectionMapEntryFlags : uint16_t {
-    Read = 1 << 0,              // Segment is readable.
-    Write = 1 << 1,             // Segment is writable.
-    Execute = 1 << 2,           // Segment is executable.
-    AddressIs32Bit = 1 << 3,    // Descriptor describes a 32-bit linear address.
-    IsSelector = 1 << 8,        // Frame represents a selector.
-    IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address.
-    IsGroup = 1 << 10           // If set, descriptor represents a group.
-  };
+```c++
+struct SectionMapHeader {
+  uint16_t Count;    // Number of segment descriptors
+  uint16_t LogCount; // Number of logical segment descriptors
+};
+
+struct SectionMapEntry {
+  uint16_t Flags;         // See the SectionMapEntryFlags enum below.
+  uint16_t Ovl;           // Logical overlay number
+  uint16_t Group;         // Group index into descriptor array.
+  uint16_t Frame;
+  uint16_t SectionName;   // Byte index of segment / group name in string table, or 0xFFFF.
+  uint16_t ClassName;     // Byte index of class in string table, or 0xFFFF.
+  uint32_t Offset;        // Byte offset of the logical segment within physical segment.  If group is set in flags, this is the offset of the group.
+  uint32_t SectionLength; // Byte count of the segment or group.
+};
+
+enum class SectionMapEntryFlags : uint16_t {
+  Read = 1 << 0,              // Segment is readable.
+  Write = 1 << 1,             // Segment is writable.
+  Execute = 1 << 2,           // Segment is executable.
+  AddressIs32Bit = 1 << 3,    // Descriptor describes a 32-bit linear address.
+  IsSelector = 1 << 8,        // Frame represents a selector.
+  IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address.
+  IsGroup = 1 << 10           // If set, descriptor represents a group.
+};
+```
 
 Many of these fields are not well understood, so will not be discussed further.
 
-.. _dbi_file_info_substream:
+(dbi-file-info-substream)=
+
+### File Info Substream
 
-File Info Substream
-^^^^^^^^^^^^^^^^^^^
-Begins at offset ``0`` immediately after the :ref:`dbi_section_map_substream` ends,
-and consumes ``Header->SourceInfoSize`` bytes.  This substream defines the mapping
-from module to the source files that contribute to that module.  Since multiple
+Begins at offset `0` immediately after the {ref}`dbi_section_map_substream` ends,
+and consumes `Header->SourceInfoSize` bytes. This substream defines the mapping
+from module to the source files that contribute to that module. Since multiple
 modules can use the same source file (for example, a header file), this substream
 uses a string table to store each unique file name only once, and then have each
 module use offsets into the string table rather than embedding the string's value
-directly.  The format of this substream is as follows:
+directly. The format of this substream is as follows:
 
-.. code-block:: c++
+```c++
+struct FileInfoSubstream {
+  uint16_t NumModules;
+  uint16_t NumSourceFiles;
 
-  struct FileInfoSubstream {
-    uint16_t NumModules;
-    uint16_t NumSourceFiles;
-
-    uint16_t ModIndices[NumModules];
-    uint16_t ModFileCounts[NumModules];
-    uint32_t FileNameOffsets[NumSourceFiles];
-    char NamesBuffer[][NumSourceFiles];
-  };
+  uint16_t ModIndices[NumModules];
+  uint16_t ModFileCounts[NumModules];
+  uint32_t FileNameOffsets[NumSourceFiles];
+  char NamesBuffer[][NumSourceFiles];
+};
+```
 
 **NumModules** - The number of modules for which source file information is
-contained within this substream.  Should match the corresponding value from the
+contained within this substream. Should match the corresponding value from the
 ref:`dbi_header`.
 
 **NumSourceFiles**: In theory this is supposed to contain the number of source
-files for which this substream contains information.  But that would present a
-problem in that the width of this field being ``16``-bits would prevent one from
-having more than 64K source files in a program.  In early versions of the file
-format, this seems to have been the case.  In order to support more than this, this
+files for which this substream contains information. But that would present a
+problem in that the width of this field being `16`-bits would prevent one from
+having more than 64K source files in a program. In early versions of the file
+format, this seems to have been the case. In order to support more than this, this
 field of the is simply ignored, and computed dynamically by summing up the values of
-the ``ModFileCounts`` array (discussed below).  In short, this value should be
+the `ModFileCounts` array (discussed below). In short, this value should be
 ignored.
 
 **ModIndices** - This array is present, but does not appear to be useful.
 
-**ModFileCountArray** - An array of ``NumModules`` integers, each one containing
+**ModFileCountArray** - An array of `NumModules` integers, each one containing
 the number of source files which contribute to the module at the specified index.
 While each individual module is limited to 64K contributing source files, the
-union of all modules' source files may be greater than 64K.  The real number of
-source files is thus computed by summing this array.  Note that summing this array
+union of all modules' source files may be greater than 64K. The real number of
+source files is thus computed by summing this array. Note that summing this array
 does not give the number of `unique` source files, only the total number of source
 file contributions to modules.
 
@@ -380,84 +347,85 @@ each integer is an offset into **NamesBuffer** pointing to a null terminated str
 **NamesBuffer** - An array of null terminated strings containing the actual source
 file names.
 
-.. _dbi_type_server_map_substream:
+(dbi-type-server-map-substream)=
+
+### Type Server Map Substream
 
-Type Server Map Substream
-^^^^^^^^^^^^^^^^^^^^^^^^^
-Begins at offset ``0`` immediately after the :ref:`dbi_file_info_substream`
-ends, and consumes ``Header->TypeServerMapSize`` bytes.  Neither the purpose
+Begins at offset `0` immediately after the {ref}`dbi_file_info_substream`
+ends, and consumes `Header->TypeServerMapSize` bytes. Neither the purpose
 nor the layout of this substream is understood, although it is assumed to
-related somehow to the usage of ``/Zi`` and ``mspdbsrv.exe``.  This substream
+related somehow to the usage of `/Zi` and `mspdbsrv.exe`. This substream
 will not be discussed further.
 
-.. _dbi_ec_substream:
+(dbi-ec-substream)=
+
+### EC Substream
 
-EC Substream
-^^^^^^^^^^^^
-Begins at offset ``0`` immediately after the
-:ref:`dbi_type_server_map_substream` ends, and consumes
-``Header->ECSubstreamSize`` bytes.  This is presumed to be related to Edit &
-Continue support in MSVC.  LLVM does not support Edit & Continue, so this
+Begins at offset `0` immediately after the
+{ref}`dbi_type_server_map_substream` ends, and consumes
+`Header->ECSubstreamSize` bytes. This is presumed to be related to Edit &
+Continue support in MSVC. LLVM does not support Edit & Continue, so this
 stream will not be discussed further.
 
-.. _dbi_optional_dbg_stream:
+(dbi-optional-dbg-stream)=
 
-Optional Debug Header Stream
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Begins at offset ``0`` immediately after the :ref:`dbi_ec_substream` ends, and
-consumes ``Header->OptionalDbgHeaderSize`` bytes.  This field is an array of
-stream indices (e.g. ``uint16_t``'s), each of which identifies a stream
+### Optional Debug Header Stream
+
+Begins at offset `0` immediately after the {ref}`dbi_ec_substream` ends, and
+consumes `Header->OptionalDbgHeaderSize` bytes. This field is an array of
+stream indices (e.g. `uint16_t`'s), each of which identifies a stream
 index in the larger MSF file which contains some additional debug information.
 Each position of this array has a special meaning, allowing one to determine
-what kind of debug information is at the referenced stream.  ``11`` indices
-are currently understood, although it's possible there may be more.  The
+what kind of debug information is at the referenced stream. `11` indices
+are currently understood, although it's possible there may be more. The
 layout of each stream generally corresponds exactly to a particular type
-of debug data directory from the PE/COFF file.  The format of these fields
-can be found in the `Microsoft PE/COFF Specification <https://www.microsoft.com/en-us/download/details.aspx?id=19509>`__.
+of debug data directory from the PE/COFF file. The format of these fields
+can be found in the [Microsoft PE/COFF Specification](https://www.microsoft.com/en-us/download/details.aspx?id=19509).
 If any of these fields is -1, it means the corresponding type of debug info is
 not present in the PDB.
 
-**FPO Data** - ``DbgStreamArray[0]``.  The data in the referenced stream is an
-array of ``FPO_DATA`` structures.  This contains the relocated contents of
-any ``.debug$F`` section from any of the linker inputs.
+**FPO Data** - `DbgStreamArray[0]`. The data in the referenced stream is an
+array of `FPO_DATA` structures. This contains the relocated contents of
+any `.debug$F` section from any of the linker inputs.
 
-**Exception Data** - ``DbgStreamArray[1]``.  The data in the referenced stream
-is a debug data directory of type ``IMAGE_DEBUG_TYPE_EXCEPTION``.
+**Exception Data** - `DbgStreamArray[1]`. The data in the referenced stream
+is a debug data directory of type `IMAGE_DEBUG_TYPE_EXCEPTION`.
 
-**Fixup Data** - ``DbgStreamArray[2]``.  The data in the referenced stream is a
-debug data directory of type ``IMAGE_DEBUG_TYPE_FIXUP``.
+**Fixup Data** - `DbgStreamArray[2]`. The data in the referenced stream is a
+debug data directory of type `IMAGE_DEBUG_TYPE_FIXUP`.
 
-**Omap To Src Data** - ``DbgStreamArray[3]``.  The data in the referenced stream
-is a debug data directory of type ``IMAGE_DEBUG_TYPE_OMAP_TO_SRC``.  This
+**Omap To Src Data** - `DbgStreamArray[3]`. The data in the referenced stream
+is a debug data directory of type `IMAGE_DEBUG_TYPE_OMAP_TO_SRC`. This
 is used for mapping addresses between instrumented and uninstrumented code.
 
-**Omap From Src Data** - ``DbgStreamArray[4]``.  The data in the referenced stream
-is a debug data directory of type ``IMAGE_DEBUG_TYPE_OMAP_FROM_SRC``.  This
+**Omap From Src Data** - `DbgStreamArray[4]`. The data in the referenced stream
+is a debug data directory of type `IMAGE_DEBUG_TYPE_OMAP_FROM_SRC`. This
 is used for mapping addresses between instrumented and uninstrumented code.
 
-**Section Header Data** - ``DbgStreamArray[5]``.  A dump of all section headers from
+**Section Header Data** - `DbgStreamArray[5]`. A dump of all section headers from
 the original executable.
 
-**Token / RID Map** - ``DbgStreamArray[6]``.  The layout of this stream is not
-understood, but it is assumed to be a mapping from ``CLR Token`` to
-``CLR Record ID``.  Refer to `ECMA 335 <http://www.ecma-international.org/publications/standards/Ecma-335.htm>`__
+**Token / RID Map** - `DbgStreamArray[6]`. The layout of this stream is not
+understood, but it is assumed to be a mapping from `CLR Token` to
+`CLR Record ID`. Refer to [ECMA 335](http://www.ecma-international.org/publications/standards/Ecma-335.htm)
 for more information.
 
-**Xdata** - ``DbgStreamArray[7]``.  A copy of the ``.xdata`` section from the
+**Xdata** - `DbgStreamArray[7]`. A copy of the `.xdata` section from the
 executable.
 
-**Pdata** - ``DbgStreamArray[8]``. This is assumed to be a copy of the ``.pdata``
+**Pdata** - `DbgStreamArray[8]`. This is assumed to be a copy of the `.pdata`
 section from the executable, but that would make it identical to
-``DbgStreamArray[1]``.  The difference between these two indices is not well
+`DbgStreamArray[1]`. The difference between these two indices is not well
 understood.
 
-**New FPO Data** - ``DbgStreamArray[9]``.  The data in the referenced stream is a
-debug data directory of type ``IMAGE_DEBUG_TYPE_FPO``.  Note that this is different
-from ``DbgStreamArray[0]`` in that ``.debug$F`` sections are only emitted by MASM.
+**New FPO Data** - `DbgStreamArray[9]`. The data in the referenced stream is a
+debug data directory of type `IMAGE_DEBUG_TYPE_FPO`. Note that this is different
+from `DbgStreamArray[0]` in that `.debug$F` sections are only emitted by MASM.
 Thus, it is possible for both to appear in the same PDB if both MASM object files
 and cl object files are linked into the same program.
 
-**Original Section Header Data** - ``DbgStreamArray[10]``.  Similar to
-``DbgStreamArray[5]``, but contains the section headers before any binary translation
-has been performed.  This can be used in conjunction with ``DebugStreamArray[3]``
-and ``DbgStreamArray[4]`` to map instrumented and uninstrumented addresses.
+**Original Section Header Data** - `DbgStreamArray[10]`. Similar to
+`DbgStreamArray[5]`, but contains the section headers before any binary translation
+has been performed. This can be used in conjunction with `DebugStreamArray[3]`
+and `DbgStreamArray[4]` to map instrumented and uninstrumented addresses.
+
diff --git a/llvm/docs/PDB/GlobalStream.md b/llvm/docs/PDB/GlobalStream.md
index dcc99ae3a0e23..a0325583b2c97 100644
--- a/llvm/docs/PDB/GlobalStream.md
+++ b/llvm/docs/PDB/GlobalStream.md
@@ -1,3 +1,2 @@
-=====================================
-The PDB Global Symbol Stream
-=====================================
+# The PDB Global Symbol Stream
+
diff --git a/llvm/docs/PDB/HashTable.md b/llvm/docs/PDB/HashTable.md
index da805bc5f9d52..7caa138763d3e 100644
--- a/llvm/docs/PDB/HashTable.md
+++ b/llvm/docs/PDB/HashTable.md
@@ -1,11 +1,8 @@
-The PDB Serialized Hash Table Format
-====================================
+# The PDB Serialized Hash Table Format
 
+(hash-intro)=
 
-.. _hash_intro:
-
-Introduction
-============
+# Introduction
 
 One of the design goals of the PDB format is to provide accelerated access to
 debug information, and for this reason there are several occasions where hash
@@ -13,89 +10,83 @@ tables are serialized and embedded directly to the file, rather than requiring
 a consumer to read a list of values and reconstruct the hash table on the fly.
 
 The serialization format supports hash tables of arbitrarily large size and
-capacity, as well as value types and hash functions.  The only supported key
-value type is a uint32.  The only requirement is that the producer and consumer
-agree on the hash function.  As such, the hash function is not discussed
+capacity, as well as value types and hash functions. The only supported key
+value type is a uint32. The only requirement is that the producer and consumer
+agree on the hash function. As such, the hash function is not discussed
 further in this document. It is assumed that for a particular instance of a PDB
 file hash table, the appropriate hash function is being used.
 
-On-Disk Format
-==============
-
-.. code-block:: none
-
-  .--------------------.-- +0
-  |        Size        |
-  .--------------------.-- +4
-  |      Capacity      |
-  .--------------------.-- +8
-  | Present Bit Vector |
-  .--------------------.-- +N
-  | Deleted Bit Vector |
-  .--------------------.-- +M                  ─╮
-  |        Key         |                        │
-  .--------------------.-- +M+4                 │
-  |       Value        |                        │
-  .--------------------.-- +M+4+sizeof(Value)   │
-           ...                                  ├─ |Capacity| Bucket entries
-  .--------------------.                        │
-  |        Key         |                        │
-  .--------------------.                        │
-  |       Value        |                        │
-  .--------------------.                       ─╯
+# On-Disk Format
+
+```none
+.--------------------.-- +0
+|        Size        |
+.--------------------.-- +4
+|      Capacity      |
+.--------------------.-- +8
+| Present Bit Vector |
+.--------------------.-- +N
+| Deleted Bit Vector |
+.--------------------.-- +M                  ─╮
+|        Key         |                        │
+.--------------------.-- +M+4                 │
+|       Value        |                        │
+.--------------------.-- +M+4+sizeof(Value)   │
+         ...                                  ├─ |Capacity| Bucket entries
+.--------------------.                        │
+|        Key         |                        │
+.--------------------.                        │
+|       Value        |                        │
+.--------------------.                       ─╯
+```
 
 - **Size** - The number of values contained in the hash table.
-
-- **Capacity** - The number of buckets in the hash table.  Producers should
-  maintain a load factor of no greater than ``2/3*Capacity+1``.
-
+- **Capacity** - The number of buckets in the hash table. Producers should
+  maintain a load factor of no greater than `2/3*Capacity+1`.
 - **Present Bit Vector** - A serialized bit vector which contains information
-  about which buckets have valid values.  If the bucket has a value, the
+  about which buckets have valid values. If the bucket has a value, the
   corresponding bit will be set, and if the bucket doesn't have a value (either
   because the bucket is empty or because the value is a tombstone value) the bit
   will be unset.
-
 - **Deleted Bit Vector** - A serialized bit vector which contains information
-  about which buckets have tombstone values.  If the entry in this bucket is
+  about which buckets have tombstone values. If the entry in this bucket is
   deleted, the bit will be set, otherwise it will be unset.
-
-- **Keys and Values** - A list of ``Capacity`` hash buckets, where the first
-  entry is the key (always a uint32), and the second entry is the value.  The
+- **Keys and Values** - A list of `Capacity` hash buckets, where the first
+  entry is the key (always a uint32), and the second entry is the value. The
   state of each bucket (valid, empty, deleted) can be determined by examining
   the present and deleted bit vectors.
 
+(hash-bit-vectors)=
 
-.. _hash_bit_vectors:
-
-Present and Deleted Bit Vectors
-===============================
+# Present and Deleted Bit Vectors
 
 The bit vectors indicating the status of each bucket are serialized as follows:
 
-.. code-block:: none
-
-  .--------------------.-- +0
-  |     Word Count     |
-  .--------------------.-- +4
-  |        Word_0      |        ─╮
-  .--------------------.-- +8    │
-  |        Word_1      |         │
-  .--------------------.-- +12   ├─ |Word Count| values
-           ...                   │
-  .--------------------.         │
-  |       Word_N       |         │
-  .--------------------.        ─╯
+```none
+.--------------------.-- +0
+|     Word Count     |
+.--------------------.-- +4
+|        Word_0      |        ─╮
+.--------------------.-- +8    │
+|        Word_1      |         │
+.--------------------.-- +12   ├─ |Word Count| values
+         ...                   │
+.--------------------.         │
+|       Word_N       |         │
+.--------------------.        ─╯
+```
 
 The words, when viewed as a contiguous block of bytes, represent a bit vector
 with the following layout:
 
-.. code-block:: none
-
-    .------------.         .------------.------------.
-    |   Word_N   |   ...   |   Word_1   |   Word_0   |
-    .------------.         .------------.------------.
-    |            |         |            |            |
-  +N*32      +(N-1)*32    +64          +32          +0
+```none
+  .------------.         .------------.------------.
+  |   Word_N   |   ...   |   Word_1   |   Word_0   |
+  .------------.         .------------.------------.
+  |            |         |            |            |
++N*32      +(N-1)*32    +64          +32          +0
+```
 
 where the k'th bit of this bit vector represents the status of the k'th bucket
 in the hash table.
+
diff --git a/llvm/docs/PDB/ModiStream.md b/llvm/docs/PDB/ModiStream.md
index fe0b1e861268b..22b372274a127 100644
--- a/llvm/docs/PDB/ModiStream.md
+++ b/llvm/docs/PDB/ModiStream.md
@@ -1,78 +1,68 @@
-=====================================
-The Module Information Stream
-=====================================
+# The Module Information Stream
 
+(modi-stream-intro)=
 
-.. _modi_stream_intro:
-
-Introduction
-============
+## Introduction
 
 The Module Info Stream (henceforth referred to as the Modi stream) contains
 information about a single module (object file, import library, etc that
-contributes to the binary this PDB contains debug information about.  There
+contributes to the binary this PDB contains debug information about. There
 is one modi stream for each module, and the mapping between modi stream index
-and module is contained in the :doc:`DBI Stream <DbiStream>`.  The modi stream
+and module is contained in the {doc}`DBI Stream <DbiStream>`. The modi stream
 for a single module contains line information for the compiland, as well as
-all CodeView information for the symbols defined in the compiland.  Finally,
+all CodeView information for the symbols defined in the compiland. Finally,
 there is a "global refs" substream which is not well understood.
 
-.. _modi_stream_layout:
+(modi-stream-layout)=
 
-Stream Layout
-=============
+## Stream Layout
 
 A modi stream is laid out as follows:
 
-
-.. code-block:: c++
-
-  struct ModiStream {
-    uint32_t Signature;
-    uint8_t Symbols[SymbolSize-4];
-    uint8_t C11LineInfo[C11Size];
-    uint8_t C13LineInfo[C13Size];
-
-    uint32_t GlobalRefsSize;
-    uint8_t GlobalRefs[GlobalRefsSize];
-  };
-
-- **Signature** - Unknown.  In practice only the value of ``4`` has been
-  observed.  It is hypothesized that this value corresponds to the set of
-  ``CV_SIGNATURE_xx`` defines in ``cvinfo.h``, with the value of ``4``
+```c++
+struct ModiStream {
+  uint32_t Signature;
+  uint8_t Symbols[SymbolSize-4];
+  uint8_t C11LineInfo[C11Size];
+  uint8_t C13LineInfo[C13Size];
+
+  uint32_t GlobalRefsSize;
+  uint8_t GlobalRefs[GlobalRefsSize];
+};
+```
+
+- **Signature** - Unknown. In practice only the value of `4` has been
+  observed. It is hypothesized that this value corresponds to the set of
+  `CV_SIGNATURE_xx` defines in `cvinfo.h`, with the value of `4`
   meaning that this module has C13 line information (as opposed to C11 line
-  information).  A corollary of this is that we expect to only ever see
+  information). A corollary of this is that we expect to only ever see
   C13 line info, and that we do not understand the format of C11 line info.
-
-- **Symbols** - The :ref:`CodeView Symbol Substream <modi_symbol_substream>`.
-  ``SymbolSize`` is equal to the value of ``SymByteSize`` for the
-  corresponding module's entry in the :ref:`Module Info Substream
-  <dbi_mod_info_substream>` of the :doc:`DBI Stream <DbiStream>`.
-
+- **Symbols** - The {ref}`CodeView Symbol Substream <modi_symbol_substream>`.
+  `SymbolSize` is equal to the value of `SymByteSize` for the
+  corresponding module's entry in the {ref}`Module Info Substream
+  <dbi_mod_info_substream>` of the {doc}`DBI Stream <DbiStream>`.
 - **C11LineInfo** - A block containing CodeView line information in C11
-  format.  ``C11Size`` is equal to the value of ``C11ByteSize`` from the
-  :ref:`Module Info Substream <dbi_mod_info_substream>` of the
-  :doc:`DBI Stream <DbiStream>`.  If this value is ``0``, then C11 line
-  information is not present.  As mentioned previously, the format of
+  format. `C11Size` is equal to the value of `C11ByteSize` from the
+  {ref}`Module Info Substream <dbi_mod_info_substream>` of the
+  {doc}`DBI Stream <DbiStream>`. If this value is `0`, then C11 line
+  information is not present. As mentioned previously, the format of
   C11 line info is not understood and we assume all line in modern PDBs
   to be in C13 format.
-
 - **C13LineInfo** - A block containing CodeView line information in C13
-  format.  ``C13Size`` is equal to the value of ``C13ByteSize`` from the
-  :ref:`Module Info Substream <dbi_mod_info_substream>` of the
-  :doc:`DBI Stream <DbiStream>`.  If this value is ``0``, then C13 line
+  format. `C13Size` is equal to the value of `C13ByteSize` from the
+  {ref}`Module Info Substream <dbi_mod_info_substream>` of the
+  {doc}`DBI Stream <DbiStream>`. If this value is `0`, then C13 line
   information is not present.
-
 - **GlobalRefs** - The meaning of this substream is not understood.
 
-.. _modi_symbol_substream:
+(modi-symbol-substream)=
 
-The CodeView Symbol Substream
-=============================
+## The CodeView Symbol Substream
 
-The CodeView Symbol Substream.  This is an array of variable length
+The CodeView Symbol Substream. This is an array of variable length
 records describing the functions, variables, inlining information,
-and other symbols defined in the compiland.  The entire array consumes
-``SymbolSize-4`` bytes.  The format of a CodeView Symbol Record (and
+and other symbols defined in the compiland. The entire array consumes
+`SymbolSize-4` bytes. The format of a CodeView Symbol Record (and
 thusly, an array of CodeView Symbol Records) is described in
-:doc:`CodeViewSymbols`.
+{doc}`CodeViewSymbols`.
+
diff --git a/llvm/docs/PDB/MsfFile.md b/llvm/docs/PDB/MsfFile.md
index b075075ec3e9b..fa51d2271f529 100644
--- a/llvm/docs/PDB/MsfFile.md
+++ b/llvm/docs/PDB/MsfFile.md
@@ -1,95 +1,89 @@
-=====================================
-The MSF File Format
-=====================================
+# The MSF File Format
 
+(msf-layout)=
 
-.. _msf_layout:
-
-File Layout
-===========
+## File Layout
 
 The MSF file format consists of the following components:
 
-1. :ref:`msf_superblock`
-2. :ref:`msf_freeblockmap` (also know as Free Page Map, or FPM)
+1. {ref}`msf_superblock`
+2. {ref}`msf_freeblockmap` (also know as Free Page Map, or FPM)
 3. Data
 
 Each component is stored as an indexed block, the length of which is specified
-in ``SuperBlock::BlockSize``. The file consists of 1 or more iterations of the
+in `SuperBlock::BlockSize`. The file consists of 1 or more iterations of the
 following pattern (sometimes referred to as an "interval"):
 
 1. 1 block of data
-2. Free Block Map 1 (corresponds to ``SuperBlock::FreeBlockMapBlock`` 1)
-3. Free Block Map 2 (corresponds to ``SuperBlock::FreeBlockMapBlock`` 2)
-4. ``SuperBlock::BlockSize - 3`` blocks of data
+2. Free Block Map 1 (corresponds to `SuperBlock::FreeBlockMapBlock` 1)
+3. Free Block Map 2 (corresponds to `SuperBlock::FreeBlockMapBlock` 2)
+4. `SuperBlock::BlockSize - 3` blocks of data
 
 In the first interval, the first data block is used to store
-:ref:`msf_superblock`.
+{ref}`msf_superblock`.
 
-The following diagram demonstrates the general layout of the file (\| denotes
+The following diagram demonstrates the general layout of the file (| denotes
 the end of an interval, and is for visualization purposes only):
 
-+-------------+-----------------------+------------------+------------------+----------+----+------+------+------+-------------+----+-----+
-| Block Index | 0                     | 1                | 2                | 3 - 4095 | \| | 4096 | 4097 | 4098 | 4099 - 8191 | \| | ... |
-+=============+=======================+==================+==================+==========+====+======+======+======+=============+====+=====+
-| Meaning     | :ref:`msf_superblock` | Free Block Map 1 | Free Block Map 2 | Data     | \| | Data | FPM1 | FPM2 | Data        | \| | ... |
-+-------------+-----------------------+------------------+------------------+----------+----+------+------+------+-------------+----+-----+
+| Block Index | 0                     | 1                | 2                | 3 - 4095 | \|  | 4096 | 4097 | 4098 | 4099 - 8191 | \|  | ... |
+| ----------- | --------------------- | ---------------- | ---------------- | -------- | --- | ---- | ---- | ---- | ----------- | --- | --- |
+| Meaning     | {ref}`msf_superblock` | Free Block Map 1 | Free Block Map 2 | Data     | \|  | Data | FPM1 | FPM2 | Data        | \|  | ... |
 
 The file may end after any block, including immediately after a FPM1.
 
-.. note::
-  LLVM only supports 4096 byte blocks (sometimes referred to as the "BigMsf"
-  variant), so the rest of this document will assume a block size of 4096.
+:::{note}
+LLVM only supports 4096 byte blocks (sometimes referred to as the "BigMsf"
+variant), so the rest of this document will assume a block size of 4096.
+:::
+
+(msf-superblock)=
 
-.. _msf_superblock:
+## The Superblock
 
-The Superblock
-==============
 At file offset 0 in an MSF file is the MSF *SuperBlock*, which is laid out as
 follows:
 
-.. code-block:: c++
-
-  struct SuperBlock {
-    char FileMagic[sizeof(Magic)];
-    ulittle32_t BlockSize;
-    ulittle32_t FreeBlockMapBlock;
-    ulittle32_t NumBlocks;
-    ulittle32_t NumDirectoryBytes;
-    ulittle32_t Unknown;
-    ulittle32_t BlockMapAddr;
-  };
-
-- **FileMagic** - Must be equal to ``"Microsoft C/C++ MSF 7.00\\r\\n"``
-  followed by the bytes ``1A 44 53 00 00 00``.
-- **BlockSize** - The block size of the internal file system.  Valid values are
-  512, 1024, 2048, and 4096 bytes.  Certain aspects of the MSF file layout vary
-  depending on the block sizes.  For the purposes of LLVM, we handle only block
+```c++
+struct SuperBlock {
+  char FileMagic[sizeof(Magic)];
+  ulittle32_t BlockSize;
+  ulittle32_t FreeBlockMapBlock;
+  ulittle32_t NumBlocks;
+  ulittle32_t NumDirectoryBytes;
+  ulittle32_t Unknown;
+  ulittle32_t BlockMapAddr;
+};
+```
+
+- **FileMagic** - Must be equal to `"Microsoft C/C++ MSF 7.00\\r\\n"`
+  followed by the bytes `1A 44 53 00 00 00`.
+- **BlockSize** - The block size of the internal file system. Valid values are
+  512, 1024, 2048, and 4096 bytes. Certain aspects of the MSF file layout vary
+  depending on the block sizes. For the purposes of LLVM, we handle only block
   sizes of 4KiB, and all further discussion assumes a block size of 4KiB.
 - **FreeBlockMapBlock** - The index of a block within the file, at which begins
   a bitfield representing the set of all blocks within the file which are "free"
-  (i.e. the data within that block is not used).  See :ref:`msf_freeblockmap`
+  (i.e. the data within that block is not used). See {ref}`msf_freeblockmap`
   for more information.
-  **Important**: ``FreeBlockMapBlock`` can only be ``1`` or ``2``!
-- **NumBlocks** - The total number of blocks in the file.  ``NumBlocks *
-  BlockSize`` should equal the size of the file on disk.
-- **NumDirectoryBytes** - The size of the stream directory, in bytes.  The
+  **Important**: `FreeBlockMapBlock` can only be `1` or `2`!
+- **NumBlocks** - The total number of blocks in the file. `NumBlocks *
+  BlockSize` should equal the size of the file on disk.
+- **NumDirectoryBytes** - The size of the stream directory, in bytes. The
   stream directory contains information about each stream's size and the set of
-  blocks that it occupies.  It will be described in more detail later.
-- **BlockMapAddr** - The index of a block within the MSF file.  At this block is
-  an array of ``ulittle32_t``'s listing the blocks that the stream directory
-  resides on.  For large MSF files, the stream directory (which describes the
-  block layout of each stream) may not fit entirely on a single block.  As a
+  blocks that it occupies. It will be described in more detail later.
+- **BlockMapAddr** - The index of a block within the MSF file. At this block is
+  an array of `ulittle32_t`'s listing the blocks that the stream directory
+  resides on. For large MSF files, the stream directory (which describes the
+  block layout of each stream) may not fit entirely on a single block. As a
   result, this extra layer of indirection is introduced, whereby this block
   contains the list of blocks that the stream directory occupies, and the stream
-  directory itself can be stitched together accordingly.  The number of
-  ``ulittle32_t``'s in this array is given by ``ceil(NumDirectoryBytes /
-  BlockSize)``.
+  directory itself can be stitched together accordingly. The number of
+  `ulittle32_t`'s in this array is given by `ceil(NumDirectoryBytes /
+  BlockSize)`.
 
-.. _msf_freeblockmap:
+(msf-freeblockmap)=
 
-The Free Block Map
-==================
+## The Free Block Map
 
 The Free Block Map (sometimes referred to as the Free Page Map, or FPM) is a
 series of blocks which contains a bit flag for every block in the file. The
@@ -100,10 +94,10 @@ feature is designed to support incremental and atomic updates of the underlying
 MSF file. While writing to an MSF file, if the active FPM is FPM1, you can
 write your new modified bitfield to FPM2, and vice versa. Only when you commit
 the file to disk do you need to swap the value in the SuperBlock to point to
-the new ``FreeBlockMapBlock``.
+the new `FreeBlockMapBlock`.
 
 The Free Block Maps are stored as a series of single blocks throughout the file
-at intervals of BlockSize. Because each FPM block is of size ``BlockSize``
+at intervals of BlockSize. Because each FPM block is of size `BlockSize`
 bytes, it contains 8 times as many bits as an interval has blocks. This means
 that the first block of each FPM refers to the first 8 intervals of the file
 (the first 32768 blocks), the second block of each FPM refers to the next 8
@@ -111,20 +105,20 @@ blocks, and so on. This results in far more FPM blocks being present than are
 required, but in order to maintain backwards compatibility the format must stay
 this way.
 
-The Stream Directory
-====================
-The Stream Directory is the root of all access to the other streams in an MSF
-file.  Beginning at byte 0 of the stream directory is the following structure:
+## The Stream Directory
 
-.. code-block:: c++
+The Stream Directory is the root of all access to the other streams in an MSF
+file. Beginning at byte 0 of the stream directory is the following structure:
 
-  struct StreamDirectory {
-    ulittle32_t NumStreams;
-    ulittle32_t StreamSizes[NumStreams];
-    ulittle32_t StreamBlocks[NumStreams][];
-  };
+```c++
+struct StreamDirectory {
+  ulittle32_t NumStreams;
+  ulittle32_t StreamSizes[NumStreams];
+  ulittle32_t StreamBlocks[NumStreams][];
+};
+```
 
-And this structure occupies exactly ``SuperBlock->NumDirectoryBytes`` bytes.
+And this structure occupies exactly `SuperBlock->NumDirectoryBytes` bytes.
 Note that each of the last two arrays is of variable length, and in particular
 that the second array is jagged.
 
@@ -139,41 +133,42 @@ Stream 2: ceil(16000 / 4096) = 4 blocks
 
 Stream 3: ceil(9000 / 4096) = 3 blocks
 
-In total, 10 blocks are used.  Let's see what the stream directory might look
+In total, 10 blocks are used. Let's see what the stream directory might look
 like:
 
-.. code-block:: c++
-
-  struct StreamDirectory {
-    ulittle32_t NumStreams = 4;
-    ulittle32_t StreamSizes[] = {1000, 8000, 16000, 9000};
-    ulittle32_t StreamBlocks[][] = {
-      {4},
-      {5, 6},
-      {11, 9, 7, 8},
-      {10, 15, 12}
-    };
+```c++
+struct StreamDirectory {
+  ulittle32_t NumStreams = 4;
+  ulittle32_t StreamSizes[] = {1000, 8000, 16000, 9000};
+  ulittle32_t StreamBlocks[][] = {
+    {4},
+    {5, 6},
+    {11, 9, 7, 8},
+    {10, 15, 12}
   };
+};
+```
 
-In total, this occupies ``15 * 4 = 60`` bytes, so
-``SuperBlock->NumDirectoryBytes`` would equal ``60``, and
-``SuperBlock->BlockMapAddr`` would be an array of one ``ulittle32_t``, since
-``60 <= SuperBlock->BlockSize``.
+In total, this occupies `15 * 4 = 60` bytes, so
+`SuperBlock->NumDirectoryBytes` would equal `60`, and
+`SuperBlock->BlockMapAddr` would be an array of one `ulittle32_t`, since
+`60 <= SuperBlock->BlockSize`.
 
 Note also that the streams are discontiguous, and that part of stream 3 is in the
-middle of part of stream 2.  You cannot assume anything about the layout of the
+middle of part of stream 2. You cannot assume anything about the layout of the
 blocks!
 
-Alignment and Block Boundaries
-==============================
+## Alignment and Block Boundaries
+
 As may be clear by now, it is possible for a single field (whether it be a high
-level record, a long string field, or even a single ``uint16``) to begin and
-end in separate blocks.  For example, if the block size is 4096 bytes, and a
-``uint16`` field begins at the last byte of the current block, then it would
-need to end on the first byte of the next block.  Since blocks are not
+level record, a long string field, or even a single `uint16`) to begin and
+end in separate blocks. For example, if the block size is 4096 bytes, and a
+`uint16` field begins at the last byte of the current block, then it would
+need to end on the first byte of the next block. Since blocks are not
 necessarily contiguously laid out in the file, this means that both the consumer
 and the producer of an MSF file must be prepared to split data apart
-accordingly.  In the aforementioned example, the high byte of the ``uint16``
+accordingly. In the aforementioned example, the high byte of the `uint16`
 would be written to the last byte of block N, and the low byte would be written
 to the first byte of block N+1, which could be tens of thousands of bytes later
 (or even earlier!) in the file, depending on what the stream directory says.
+
diff --git a/llvm/docs/PDB/PdbStream.md b/llvm/docs/PDB/PdbStream.md
index 01b2dd7a26fc1..19380b581e75f 100644
--- a/llvm/docs/PDB/PdbStream.md
+++ b/llvm/docs/PDB/PdbStream.md
@@ -1,137 +1,124 @@
-========================================
-The PDB Info Stream (aka the PDB Stream)
-========================================
+# The PDB Info Stream (aka the PDB Stream)
 
+(pdb-stream-header)=
 
-.. _pdb_stream_header:
+## Stream Header
 
-Stream Header
-=============
 At offset 0 of the PDB Stream is a header with the following layout:
 
-
-.. code-block:: c++
-
-  struct PdbStreamHeader {
-    ulittle32_t Version;
-    ulittle32_t Signature;
-    ulittle32_t Age;
-    Guid UniqueId;
-  };
+```c++
+struct PdbStreamHeader {
+  ulittle32_t Version;
+  ulittle32_t Signature;
+  ulittle32_t Age;
+  Guid UniqueId;
+};
+```
 
 - **Version** - A Value from the following enum:
 
-.. code-block:: c++
-
-  enum class PdbStreamVersion : uint32_t {
-    VC2 = 19941610,
-    VC4 = 19950623,
-    VC41 = 19950814,
-    VC50 = 19960307,
-    VC98 = 19970604,
-    VC70Dep = 19990604,
-    VC70 = 20000404,
-    VC80 = 20030901,
-    VC110 = 20091201,
-    VC140 = 20140508,
-  };
+```c++
+enum class PdbStreamVersion : uint32_t {
+  VC2 = 19941610,
+  VC4 = 19950623,
+  VC41 = 19950814,
+  VC50 = 19960307,
+  VC98 = 19970604,
+  VC70Dep = 19990604,
+  VC70 = 20000404,
+  VC80 = 20030901,
+  VC110 = 20091201,
+  VC140 = 20140508,
+};
+```
 
 While the meaning of this field appears to be obvious, in practice we have
-never observed a value other than ``VC70``, even with modern versions of
-the toolchain, and it is unclear why the other values exist.  It is assumed
+never observed a value other than `VC70`, even with modern versions of
+the toolchain, and it is unclear why the other values exist. It is assumed
 that certain aspects of the PDB stream's layout, and perhaps even that of
-the other streams, will change if the value is something other than ``VC70``.
+the other streams, will change if the value is something other than `VC70`.
 
-- **Signature** - A 32-bit time-stamp generated with a call to ``time()`` at
-  the time the PDB file is written.  Note that due to the inherent uniqueness
+- **Signature** - A 32-bit time-stamp generated with a call to `time()` at
+  the time the PDB file is written. Note that due to the inherent uniqueness
   problems of using a timestamp with 1-second granularity, this field does not
   really serve its intended purpose, and as such is typically ignored in favor
-  of the ``Guid`` field, described below.
-
-- **Age** - The number of times the PDB file has been written.  This can be used
-  along with ``Guid`` to match the PDB to its corresponding executable.
-
+  of the `Guid` field, described below.
+- **Age** - The number of times the PDB file has been written. This can be used
+  along with `Guid` to match the PDB to its corresponding executable.
 - **Guid** - A 128-bit identifier guaranteed to be unique across space and time.
   In general, this can be thought of as the result of calling the Win32 API
-  `UuidCreate <https://msdn.microsoft.com/en-us/library/windows/desktop/aa379205(v=vs.85).aspx>`__,
+  [UuidCreate](<https://msdn.microsoft.com/en-us/library/windows/desktop/aa379205(v=vs.85).aspx>),
   although LLVM cannot rely on that, as it must work on non-Windows platforms.
 
-.. _pdb_named_stream_map:
+(pdb-named-stream-map)=
 
-Named Stream Map
-================
+## Named Stream Map
 
 Following the header is a serialized hash table whose key type is a string, and
-whose value type is an integer.  The existence of a mapping ``X -> Y`` means
-that the stream with the name ``X`` has stream index ``Y`` in the underlying MSF
-file.  Note that not all streams are named (for example, the
-:doc:`TPI Stream <TpiStream>` has a fixed index and as such there is no need to
-look up its index by name).  In practice, there are usually only a small number
-of named streams and these are enumerated in the table of streams in :doc:`index`.
+whose value type is an integer. The existence of a mapping `X -> Y` means
+that the stream with the name `X` has stream index `Y` in the underlying MSF
+file. Note that not all streams are named (for example, the
+{doc}`TPI Stream <TpiStream>` has a fixed index and as such there is no need to
+look up its index by name). In practice, there are usually only a small number
+of named streams and these are enumerated in the table of streams in {doc}`index`.
 A corollary of this is if a stream does have a name (and as such is in the named
 stream map) then consulting the Named Stream Map is likely to be the only way to
-discover the stream's MSF stream index.  Several important streams (such as the
-global string table, which is called ``/names``) can only be located this way, and
+discover the stream's MSF stream index. Several important streams (such as the
+global string table, which is called `/names`) can only be located this way, and
 so it is important to both produce and consume this correctly as tools will not
 function correctly without it.
 
-.. important::
-   Some streams are located by fixed indices (e.g TPI Stream has index 2), but
-   other streams are located by fixed names (e.g. the string table is called
-   ``/names``) and can only be located by consulting the Named Stream Map.
+:::{important}
+Some streams are located by fixed indices (e.g TPI Stream has index 2), but
+other streams are located by fixed names (e.g. the string table is called
+`/names`) and can only be located by consulting the Named Stream Map.
+:::
 
-The on-disk layout of the Named Stream Map consists of 2 components.  The first is
-a buffer of string data prefixed by a 32-bit length.  The second is a serialized
-hash table whose key and value types are both ``uint32_t``.  The key is the offset
+The on-disk layout of the Named Stream Map consists of 2 components. The first is
+a buffer of string data prefixed by a 32-bit length. The second is a serialized
+hash table whose key and value types are both `uint32_t`. The key is the offset
 of a null-terminated string in the string data buffer specifying the name of the
 stream, and the value is the MSF stream index of the stream with said name.
 Note that although the key is an integer, the hash function used to find the right
 bucket hashes the string at the corresponding offset in the string data buffer.
 
-The on-disk layout of the serialized hash table is described at :doc:`HashTable`.
+The on-disk layout of the serialized hash table is described at {doc}`HashTable`.
 
 Note that the entire Named Stream Map is not length-prefixed, so the only way to
 get to the data following it is to de-serialize it in its entirety.
 
+(pdb-stream-features)=
 
-.. _pdb_stream_features:
+## PDB Feature Codes
 
-PDB Feature Codes
-=================
 Following the Named Stream Map, and consuming all remaining bytes of the PDB
 Stream is a list of values from the following enumeration:
 
-.. code-block:: c++
-
-  enum class PdbRaw_FeatureSig : uint32_t {
-    VC110 = 20091201,
-    VC140 = 20140508,
-    NoTypeMerge = 0x4D544F4E,
-    MinimalDebugInfo = 0x494E494D,
-  };
+```c++
+enum class PdbRaw_FeatureSig : uint32_t {
+  VC110 = 20091201,
+  VC140 = 20140508,
+  NoTypeMerge = 0x4D544F4E,
+  MinimalDebugInfo = 0x494E494D,
+};
+```
 
 The meaning of these values is summarized by the following table:
 
-+------------------+-------------------------------------------------+
-| Flag             | Meaning                                         |
-+==================+=================================================+
-| VC110            | - No other features flags are present           |
-|                  | - PDB contains an :doc:`IPI Stream <TpiStream>` |
-+------------------+-------------------------------------------------+
-| VC140            | - Other feature flags may be present            |
-|                  | - PDB contains an :doc:`IPI Stream <TpiStream>` |
-+------------------+-------------------------------------------------+
-| NoTypeMerge      | - Presumably duplicate types can appear in the  |
-|                  |   TPI Stream, although it's unclear why this    |
-|                  |   might happen.                                 |
-+------------------+-------------------------------------------------+
-| MinimalDebugInfo | - Program was linked with /DEBUG:FASTLINK       |
-|                  | - There is no TPI / IPI stream, all type info   |
-|                  |   is contained in the original object files.    |
-+------------------+-------------------------------------------------+
-
-Matching a PDB to its executable
-================================
+| Flag             | Meaning                                                                                                 |
+| ---------------- | ------------------------------------------------------------------------------------------------------- |
+| VC110            | - No other features flags are present
+- PDB contains an 
+  {doc}`IPI Stream <TpiStream>`                                                                                                         |
+| VC140            | - Other feature flags may be present
+- PDB contains an 
+  {doc}`IPI Stream <TpiStream>`                                                                                                         |
+| NoTypeMerge      | - Presumably duplicate types can appear in the TPI Stream, although it's unclear why this might happen. |
+| MinimalDebugInfo | - Program was linked with /DEBUG:FASTLINK
+- There is no TPI / IPI stream, all type info is contained in the original object files.                                                                                                         |
+
+## Matching a PDB to its executable
+
 The linker is responsible for writing both the PDB and the final executable, and
 as a result is the only entity capable of writing the information necessary to
 match the PDB to the executable.
@@ -141,12 +128,13 @@ re-uses the existing guid if it is linking incrementally) and increments the Age
 field.
 
 The executable is a PE/COFF file, and part of a PE/COFF file is the presence of
-number of "directories".  For our purposes here, we are interested in the "debug
-directory".  The exact format of a debug directory is described by the
-`IMAGE_DEBUG_DIRECTORY structure <https://msdn.microsoft.com/en-us/library/windows/desktop/ms680307(v=vs.85).aspx>`__.
+number of "directories". For our purposes here, we are interested in the "debug
+directory". The exact format of a debug directory is described by the
+[IMAGE_DEBUG_DIRECTORY structure](<https://msdn.microsoft.com/en-us/library/windows/desktop/ms680307(v=vs.85).aspx>).
 For this particular case, the linker emits a debug directory of type
-``IMAGE_DEBUG_TYPE_CODEVIEW``.  The format of this record is defined in
-``llvm/DebugInfo/CodeView/CVDebugRecord.h``, but it suffices to say here only
-that it includes the same ``Guid`` and ``Age`` fields.  At runtime, a
+`IMAGE_DEBUG_TYPE_CODEVIEW`. The format of this record is defined in
+`llvm/DebugInfo/CodeView/CVDebugRecord.h`, but it suffices to say here only
+that it includes the same `Guid` and `Age` fields. At runtime, a
 debugger or tool can scan the COFF executable image for the presence of
 a debug directory of the correct type and verify that the Guid and Age match.
+
diff --git a/llvm/docs/PDB/PublicStream.md b/llvm/docs/PDB/PublicStream.md
index 7c860c266eeab..3e5cf19e1ee89 100644
--- a/llvm/docs/PDB/PublicStream.md
+++ b/llvm/docs/PDB/PublicStream.md
@@ -1,3 +1,2 @@
-=====================================
-The PDB Public Symbol Stream
-=====================================
+# The PDB Public Symbol Stream
+
diff --git a/llvm/docs/PDB/TpiStream.md b/llvm/docs/PDB/TpiStream.md
index 8c0202aa8a34d..5e826e1e8ecbd 100644
--- a/llvm/docs/PDB/TpiStream.md
+++ b/llvm/docs/PDB/TpiStream.md
@@ -1,313 +1,277 @@
-=====================================
-The PDB TPI and IPI Streams
-=====================================
+# The PDB TPI and IPI Streams
 
+(tpi-intro)=
 
-.. _tpi_intro:
-
-Introduction
-============
+## Introduction
 
 The PDB TPI Stream (Index 2) and IPI Stream (Index 4) contain information about
-all types used in the program.  It is organized as a :ref:`header <tpi_header>`
-followed by a list of :doc:`CodeView Type Records <CodeViewTypes>`.  Types are
+all types used in the program. It is organized as a {ref}`header <tpi_header>`
+followed by a list of {doc}`CodeView Type Records <CodeViewTypes>`. Types are
 referenced from various streams and records throughout the PDB by their
-:ref:`type index <type_indices>`.  In general, the sequence of type records
-following the :ref:`header <tpi_header>` forms a topologically sorted DAG
+{ref}`type index <type_indices>`. In general, the sequence of type records
+following the {ref}`header <tpi_header>` forms a topologically sorted DAG
 (directed acyclic graph), which means that a type record B can only refer to
-the type A if ``A.TypeIndex < B.TypeIndex``.  While there are rare cases where
+the type A if `A.TypeIndex < B.TypeIndex`. While there are rare cases where
 this property will not hold (particularly when dealing with object files
 compiled with MASM), an implementation should try very hard to make this
 property hold, as it means the entire type graph can be constructed in a single
 pass.
 
-.. important::
-   Type records form a topologically sorted DAG (directed acyclic graph).
+:::{important}
+Type records form a topologically sorted DAG (directed acyclic graph).
+:::
 
-.. _tpi_ipi:
+(tpi-ipi)=
 
-TPI vs IPI Stream
-=================
+## TPI vs IPI Stream
 
 Recent versions of the PDB format (aka all versions covered by this document)
 have 2 streams with identical layout, henceforth referred to as the TPI stream
-and IPI stream.  Subsequent contents of this document describing the on-disk
-format apply equally whether it is for the TPI Stream or the IPI Stream.  The
+and IPI stream. Subsequent contents of this document describing the on-disk
+format apply equally whether it is for the TPI Stream or the IPI Stream. The
 only difference between the two is in *which* CodeView records are allowed to
 appear in each one, summarized by the following table:
 
-+----------------------+---------------------+
-|    TPI Stream        |    IPI Stream       |
-+======================+=====================+
-|  LF_POINTER          | LF_FUNC_ID          |
-+----------------------+---------------------+
-|  LF_MODIFIER         | LF_MFUNC_ID         |
-+----------------------+---------------------+
-|  LF_PROCEDURE        | LF_BUILDINFO        |
-+----------------------+---------------------+
-|  LF_MFUNCTION        | LF_SUBSTR_LIST      |
-+----------------------+---------------------+
-|  LF_LABEL            | LF_STRING_ID        |
-+----------------------+---------------------+
-|  LF_ARGLIST          | LF_UDT_SRC_LINE     |
-+----------------------+---------------------+
-|  LF_FIELDLIST        | LF_UDT_MOD_SRC_LINE |
-+----------------------+---------------------+
-|  LF_ARRAY            |                     |
-+----------------------+---------------------+
-|  LF_CLASS            |                     |
-+----------------------+---------------------+
-|  LF_STRUCTURE        |                     |
-+----------------------+---------------------+
-|  LF_INTERFACE        |                     |
-+----------------------+---------------------+
-|  LF_UNION            |                     |
-+----------------------+---------------------+
-|  LF_ENUM             |                     |
-+----------------------+---------------------+
-|  LF_TYPESERVER2      |                     |
-+----------------------+---------------------+
-|  LF_VFTABLE          |                     |
-+----------------------+---------------------+
-|  LF_VTSHAPE          |                     |
-+----------------------+---------------------+
-|  LF_BITFIELD         |                     |
-+----------------------+---------------------+
-|  LF_METHODLIST       |                     |
-+----------------------+---------------------+
-|  LF_PRECOMP          |                     |
-+----------------------+---------------------+
-|  LF_ENDPRECOMP       |                     |
-+----------------------+---------------------+
+| TPI Stream     | IPI Stream          |
+| -------------- | ------------------- |
+| LF_POINTER     | LF_FUNC_ID          |
+| LF_MODIFIER    | LF_MFUNC_ID         |
+| LF_PROCEDURE   | LF_BUILDINFO        |
+| LF_MFUNCTION   | LF_SUBSTR_LIST      |
+| LF_LABEL       | LF_STRING_ID        |
+| LF_ARGLIST     | LF_UDT_SRC_LINE     |
+| LF_FIELDLIST   | LF_UDT_MOD_SRC_LINE |
+| LF_ARRAY       |                     |
+| LF_CLASS       |                     |
+| LF_STRUCTURE   |                     |
+| LF_INTERFACE   |                     |
+| LF_UNION       |                     |
+| LF_ENUM        |                     |
+| LF_TYPESERVER2 |                     |
+| LF_VFTABLE     |                     |
+| LF_VTSHAPE     |                     |
+| LF_BITFIELD    |                     |
+| LF_METHODLIST  |                     |
+| LF_PRECOMP     |                     |
+| LF_ENDPRECOMP  |                     |
 
 The usage of these records is described in more detail in
-:doc:`CodeView Type Records <CodeViewTypes>`.
+{doc}`CodeView Type Records <CodeViewTypes>`.
 
-.. _type_indices:
+(type-indices)=
 
-Type Indices
-============
+## Type Indices
 
 A type index is a 32-bit integer that uniquely identifies a type inside of an
-object file's ``.debug$T`` section or a PDB file's TPI or IPI stream.  The
+object file's `.debug$T` section or a PDB file's TPI or IPI stream. The
 value of the type index for the first type record from the TPI stream is given
-by the ``TypeIndexBegin`` member of the :ref:`TPI Stream Header <tpi_header>`
+by the `TypeIndexBegin` member of the {ref}`TPI Stream Header <tpi_header>`
 although in practice this value is always equal to 0x1000 (4096).
 
 Any type index with a high bit set is considered to come from the IPI stream,
 although this appears to be more of a hack, and LLVM does not generate type
-indices of this nature.  They can, however, be observed in Microsoft PDBs
-occasionally, so one should be prepared to handle them.  Note that having the
+indices of this nature. They can, however, be observed in Microsoft PDBs
+occasionally, so one should be prepared to handle them. Note that having the
 high bit set is not a necessary condition to determine whether a type index
 comes from the IPI stream, it is only sufficient.
 
-Once the high bit is cleared, any type index >= ``TypeIndexBegin`` is presumed
+Once the high bit is cleared, any type index >= `TypeIndexBegin` is presumed
 to come from the appropriate stream, and any type index less than this is a
 bitmask which can be decomposed as follows:
 
-.. code-block:: none
-
-  .---------------------------.------.----------.
-  |           Unused          | Mode |   Kind   |
-  '---------------------------'------'----------'
-  |+32                        |+12   |+8        |+0
-
+```none
+.---------------------------.------.----------.
+|           Unused          | Mode |   Kind   |
+'---------------------------'------'----------'
+|+32                        |+12   |+8        |+0
+```
 
 - **Kind** - A value from the following enum:
 
-.. code-block:: c++
-
-  enum class SimpleTypeKind : uint32_t {
-    None = 0x0000,          // uncharacterized type (no type)
-    Void = 0x0003,          // void
-    NotTranslated = 0x0007, // type not translated by cvpack
-    HResult = 0x0008,       // OLE/COM HRESULT
-
-    SignedCharacter = 0x0010,   // 8 bit signed
-    UnsignedCharacter = 0x0020, // 8 bit unsigned
-    NarrowCharacter = 0x0070,   // really a char
-    WideCharacter = 0x0071,     // wide char
-    Character16 = 0x007a,       // char16_t
-    Character32 = 0x007b,       // char32_t
-    Character8 = 0x007c,        // char8_t
-
-    SByte = 0x0068,       // 8 bit signed int
-    Byte = 0x0069,        // 8 bit unsigned int
-    Int16Short = 0x0011,  // 16 bit signed
-    UInt16Short = 0x0021, // 16 bit unsigned
-    Int16 = 0x0072,       // 16 bit signed int
-    UInt16 = 0x0073,      // 16 bit unsigned int
-    Int32Long = 0x0012,   // 32 bit signed
-    UInt32Long = 0x0022,  // 32 bit unsigned
-    Int32 = 0x0074,       // 32 bit signed int
-    UInt32 = 0x0075,      // 32 bit unsigned int
-    Int64Quad = 0x0013,   // 64 bit signed
-    UInt64Quad = 0x0023,  // 64 bit unsigned
-    Int64 = 0x0076,       // 64 bit signed int
-    UInt64 = 0x0077,      // 64 bit unsigned int
-    Int128Oct = 0x0014,   // 128 bit signed int
-    UInt128Oct = 0x0024,  // 128 bit unsigned int
-    Int128 = 0x0078,      // 128 bit signed int
-    UInt128 = 0x0079,     // 128 bit unsigned int
-
-    Float16 = 0x0046,                 // 16 bit real
-    Float32 = 0x0040,                 // 32 bit real
-    Float32PartialPrecision = 0x0045, // 32 bit PP real
-    Float48 = 0x0044,                 // 48 bit real
-    Float64 = 0x0041,                 // 64 bit real
-    Float80 = 0x0042,                 // 80 bit real
-    Float128 = 0x0043,                // 128 bit real
-
-    Complex16 = 0x0056,                 // 16 bit complex
-    Complex32 = 0x0050,                 // 32 bit complex
-    Complex32PartialPrecision = 0x0055, // 32 bit PP complex
-    Complex48 = 0x0054,                 // 48 bit complex
-    Complex64 = 0x0051,                 // 64 bit complex
-    Complex80 = 0x0052,                 // 80 bit complex
-    Complex128 = 0x0053,                // 128 bit complex
-
-    Boolean8 = 0x0030,   // 8 bit boolean
-    Boolean16 = 0x0031,  // 16 bit boolean
-    Boolean32 = 0x0032,  // 32 bit boolean
-    Boolean64 = 0x0033,  // 64 bit boolean
-    Boolean128 = 0x0034, // 128 bit boolean
-  };
+```c++
+enum class SimpleTypeKind : uint32_t {
+  None = 0x0000,          // uncharacterized type (no type)
+  Void = 0x0003,          // void
+  NotTranslated = 0x0007, // type not translated by cvpack
+  HResult = 0x0008,       // OLE/COM HRESULT
+
+  SignedCharacter = 0x0010,   // 8 bit signed
+  UnsignedCharacter = 0x0020, // 8 bit unsigned
+  NarrowCharacter = 0x0070,   // really a char
+  WideCharacter = 0x0071,     // wide char
+  Character16 = 0x007a,       // char16_t
+  Character32 = 0x007b,       // char32_t
+  Character8 = 0x007c,        // char8_t
+
+  SByte = 0x0068,       // 8 bit signed int
+  Byte = 0x0069,        // 8 bit unsigned int
+  Int16Short = 0x0011,  // 16 bit signed
+  UInt16Short = 0x0021, // 16 bit unsigned
+  Int16 = 0x0072,       // 16 bit signed int
+  UInt16 = 0x0073,      // 16 bit unsigned int
+  Int32Long = 0x0012,   // 32 bit signed
+  UInt32Long = 0x0022,  // 32 bit unsigned
+  Int32 = 0x0074,       // 32 bit signed int
+  UInt32 = 0x0075,      // 32 bit unsigned int
+  Int64Quad = 0x0013,   // 64 bit signed
+  UInt64Quad = 0x0023,  // 64 bit unsigned
+  Int64 = 0x0076,       // 64 bit signed int
+  UInt64 = 0x0077,      // 64 bit unsigned int
+  Int128Oct = 0x0014,   // 128 bit signed int
+  UInt128Oct = 0x0024,  // 128 bit unsigned int
+  Int128 = 0x0078,      // 128 bit signed int
+  UInt128 = 0x0079,     // 128 bit unsigned int
+
+  Float16 = 0x0046,                 // 16 bit real
+  Float32 = 0x0040,                 // 32 bit real
+  Float32PartialPrecision = 0x0045, // 32 bit PP real
+  Float48 = 0x0044,                 // 48 bit real
+  Float64 = 0x0041,                 // 64 bit real
+  Float80 = 0x0042,                 // 80 bit real
+  Float128 = 0x0043,                // 128 bit real
+
+  Complex16 = 0x0056,                 // 16 bit complex
+  Complex32 = 0x0050,                 // 32 bit complex
+  Complex32PartialPrecision = 0x0055, // 32 bit PP complex
+  Complex48 = 0x0054,                 // 48 bit complex
+  Complex64 = 0x0051,                 // 64 bit complex
+  Complex80 = 0x0052,                 // 80 bit complex
+  Complex128 = 0x0053,                // 128 bit complex
+
+  Boolean8 = 0x0030,   // 8 bit boolean
+  Boolean16 = 0x0031,  // 16 bit boolean
+  Boolean32 = 0x0032,  // 32 bit boolean
+  Boolean64 = 0x0033,  // 64 bit boolean
+  Boolean128 = 0x0034, // 128 bit boolean
+};
+```
 
 - **Mode** - A value from the following enum:
 
-.. code-block:: c++
-
-  enum class SimpleTypeMode : uint32_t {
-    Direct = 0,        // Not a pointer
-    NearPointer = 1,   // Near pointer
-    FarPointer = 2,    // Far pointer
-    HugePointer = 3,   // Huge pointer
-    NearPointer32 = 4, // 32 bit near pointer
-    FarPointer32 = 5,  // 32 bit far pointer
-    NearPointer64 = 6, // 64 bit near pointer
-    NearPointer128 = 7 // 128 bit near pointer
-  };
-
-Note that for pointers, the bitness is represented in the mode.  So a ``void*``
-would have a type index with ``Mode=NearPointer32, Kind=Void`` if built for
-32-bits but a type index with ``Mode=NearPointer64, Kind=Void`` if built for
+```c++
+enum class SimpleTypeMode : uint32_t {
+  Direct = 0,        // Not a pointer
+  NearPointer = 1,   // Near pointer
+  FarPointer = 2,    // Far pointer
+  HugePointer = 3,   // Huge pointer
+  NearPointer32 = 4, // 32 bit near pointer
+  FarPointer32 = 5,  // 32 bit far pointer
+  NearPointer64 = 6, // 64 bit near pointer
+  NearPointer128 = 7 // 128 bit near pointer
+};
+```
+
+Note that for pointers, the bitness is represented in the mode. So a `void*`
+would have a type index with `Mode=NearPointer32, Kind=Void` if built for
+32-bits but a type index with `Mode=NearPointer64, Kind=Void` if built for
 64-bits.
 
-By convention, the type index for ``std::nullptr_t`` is constructed the same
-way as the type index for ``void*``, but using the bitless enumeration value
-``NearPointer``.
+By convention, the type index for `std::nullptr_t` is constructed the same
+way as the type index for `void*`, but using the bitless enumeration value
+`NearPointer`.
 
-.. _tpi_header:
+(tpi-header)=
 
-Stream Header
-=============
-At offset 0 of the TPI Stream is a header with the following layout:
+## Stream Header
 
-.. code-block:: c++
+At offset 0 of the TPI Stream is a header with the following layout:
 
-  struct TpiStreamHeader {
-    uint32_t Version;
-    uint32_t HeaderSize;
-    uint32_t TypeIndexBegin;
-    uint32_t TypeIndexEnd;
-    uint32_t TypeRecordBytes;
+```c++
+struct TpiStreamHeader {
+  uint32_t Version;
+  uint32_t HeaderSize;
+  uint32_t TypeIndexBegin;
+  uint32_t TypeIndexEnd;
+  uint32_t TypeRecordBytes;
 
-    uint16_t HashStreamIndex;
-    uint16_t HashAuxStreamIndex;
-    uint32_t HashKeySize;
-    uint32_t NumHashBuckets;
+  uint16_t HashStreamIndex;
+  uint16_t HashAuxStreamIndex;
+  uint32_t HashKeySize;
+  uint32_t NumHashBuckets;
 
-    int32_t HashValueBufferOffset;
-    uint32_t HashValueBufferLength;
+  int32_t HashValueBufferOffset;
+  uint32_t HashValueBufferLength;
 
-    int32_t IndexOffsetBufferOffset;
-    uint32_t IndexOffsetBufferLength;
+  int32_t IndexOffsetBufferOffset;
+  uint32_t IndexOffsetBufferLength;
 
-    int32_t HashAdjBufferOffset;
-    uint32_t HashAdjBufferLength;
-  };
+  int32_t HashAdjBufferOffset;
+  uint32_t HashAdjBufferLength;
+};
+```
 
 - **Version** - A value from the following enum.
 
-.. code-block:: c++
-
-  enum class TpiStreamVersion : uint32_t {
-    V40 = 19950410,
-    V41 = 19951122,
-    V50 = 19961031,
-    V70 = 19990903,
-    V80 = 20040203,
-  };
-
-Similar to the :doc:`PDB Stream <PdbStream>`, this value always appears to be
-``V80``, and no other values have been observed.  It is assumed that should
+```c++
+enum class TpiStreamVersion : uint32_t {
+  V40 = 19950410,
+  V41 = 19951122,
+  V50 = 19961031,
+  V70 = 19990903,
+  V80 = 20040203,
+};
+```
+
+Similar to the {doc}`PDB Stream <PdbStream>`, this value always appears to be
+`V80`, and no other values have been observed. It is assumed that should
 another value be observed, the layout described by this document may not be
 accurate.
 
-- **HeaderSize** - ``sizeof(TpiStreamHeader)``
-
+- **HeaderSize** - `sizeof(TpiStreamHeader)`
 - **TypeIndexBegin** - The numeric value of the type index representing the
-  first type record in the TPI stream.  This is usually the value 0x1000 as
-  type indices lower than this are reserved (see :ref:`Type Indices
+  first type record in the TPI stream. This is usually the value 0x1000 as
+  type indices lower than this are reserved (see {ref}`Type Indices
   <type_indices>` for
   a discussion of reserved type indices).
-
 - **TypeIndexEnd** - One greater than the numeric value of the type index
-  representing the last type record in the TPI stream.  The total number of
-  type records in the TPI stream can be computed as ``TypeIndexEnd -
-  TypeIndexBegin``.
-
+  representing the last type record in the TPI stream. The total number of
+  type records in the TPI stream can be computed as `TypeIndexEnd -
+  TypeIndexBegin`.
 - **TypeRecordBytes** - The number of bytes of type record data following the
   header.
-
 - **HashStreamIndex** - The index of a stream which contains a list of hashes
-  for every type record.  This value may be -1, indicating that hash
-  information is not present.  In practice a valid stream index is always
+  for every type record. This value may be -1, indicating that hash
+  information is not present. In practice a valid stream index is always
   observed, so any producer implementation should be prepared to emit this
   stream to ensure compatibility with tools which may expect it to be present.
-
 - **HashAuxStreamIndex** - Presumably the index of a stream which contains a
   separate hash table, although this has not been observed in practice and it's
   unclear what it might be used for.
-
 - **HashKeySize** - The size of a hash value (usually 4 bytes).
-
 - **NumHashBuckets** - The number of buckets used to generate the hash values
   in the aforementioned hash streams.
-
 - **HashValueBufferOffset / HashValueBufferLength** - The offset and size within
-  the TPI Hash Stream of the list of hash values.  It should be assumed that
+  the TPI Hash Stream of the list of hash values. It should be assumed that
   there are either 0 hash values, or a number equal to the number of type
-  records in the TPI stream (``TypeIndexEnd - TypeEndBegin``).  Thus, if
-  ``HashBufferLength`` is not equal to ``(TypeIndexEnd - TypeEndBegin) *
-  HashKeySize`` we can consider the PDB malformed.
-
+  records in the TPI stream (`TypeIndexEnd - TypeEndBegin`). Thus, if
+  `HashBufferLength` is not equal to `(TypeIndexEnd - TypeEndBegin) *
+  HashKeySize` we can consider the PDB malformed.
 - **IndexOffsetBufferOffset / IndexOffsetBufferLength** - The offset and size
-  within the TPI Hash Stream of the Type Index Offsets Buffer.  This is a list
-  of pairs of uint32_t's where the first value is a :ref:`Type Index
+  within the TPI Hash Stream of the Type Index Offsets Buffer. This is a list
+  of pairs of uint32_t's where the first value is a {ref}`Type Index
   <type_indices>` and the second value is the offset in the type record data of
-  the type with this index.  This can be used to do a binary search followed by
+  the type with this index. This can be used to do a binary search followed by
   a linear search to get O(log n) lookup by type index.
-
 - **HashAdjBufferOffset / HashAdjBufferLength** - The offset and size within
   the TPI hash stream of a serialized hash table whose keys are the hash values
-  in the hash value buffer and whose values are type indices.  This appears to
+  in the hash value buffer and whose values are type indices. This appears to
   be useful in incremental linking scenarios, so that if a type is modified an
   entry can be created mapping the old hash value to the new type index so that
   a PDB file consumer can always have the most up to date version of the type
   without forcing the incremental linker to garbage collect and update
   references that point to the old version to now point to the new version.
-  The layout of this hash table is described in :doc:`HashTable`.
+  The layout of this hash table is described in {doc}`HashTable`.
 
-.. _tpi_records:
+(tpi-records)=
 
-CodeView Type Record List
-=========================
-Following the header, there are ``TypeRecordBytes`` bytes of data that
-represent a variable length array of :doc:`CodeView type records
-<CodeViewTypes>`.  The number of such records (e.g. the length of the array)
-can be determined by computing the value ``Header.TypeIndexEnd -
-Header.TypeIndexBegin``.
+## CodeView Type Record List
+
+Following the header, there are `TypeRecordBytes` bytes of data that
+represent a variable length array of {doc}`CodeView type records
+<CodeViewTypes>`. The number of such records (e.g. the length of the array)
+can be determined by computing the value `Header.TypeIndexEnd -
+Header.TypeIndexBegin`.
 
 O(log(n)) access is provided by way of the Type Index Offsets array (if
 present) described previously.
+

>From 3e225ee348584b0e45cba4d032f89196d73ac50c Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Tue, 18 Aug 2026 22:11:51 +0000
Subject: [PATCH 2/3] [docs] Finish MyST migration for PDB, DirectX, and
 GlobalISel docs

---
 llvm/docs/DirectX/DXContainer.md      | 127 +++++++++++++++-----------
 llvm/docs/DirectX/DXILArchitecture.md |  38 ++++----
 llvm/docs/GlobalISel/GenericOpcode.md |  25 ++---
 llvm/docs/GlobalISel/Legalizer.md     |  10 +-
 llvm/docs/GlobalISel/Resources.md     |   3 +-
 llvm/docs/PDB/CodeViewSymbols.md      |  19 ++--
 llvm/docs/PDB/CodeViewTypes.md        | 103 ++++++++++-----------
 llvm/docs/PDB/DbiStream.md            |  21 ++---
 llvm/docs/PDB/HashTable.md            |   5 +-
 llvm/docs/PDB/ModiStream.md           |   7 +-
 llvm/docs/PDB/MsfFile.md              |   7 +-
 llvm/docs/PDB/PdbStream.md            |  35 ++++---
 llvm/docs/PDB/TpiStream.md            |  11 +--
 13 files changed, 207 insertions(+), 204 deletions(-)

diff --git a/llvm/docs/DirectX/DXContainer.md b/llvm/docs/DirectX/DXContainer.md
index 00b860b06167f..ea4f1809b3294 100644
--- a/llvm/docs/DirectX/DXContainer.md
+++ b/llvm/docs/DirectX/DXContainer.md
@@ -88,34 +88,34 @@ used by DXC and FXC. Not all compiled shaders contain all parts. In the list
 below parts generated only by DXC are marked with †, and parts generated only by
 FXC are marked with \*.
 
-01. [DXIL]† - Stores the DXIL bytecode.
-02. [HASH]† - Stores the shader MD5 hash.
-03. [ILDB]† - Stores the DXIL bytecode with LLVM Debug Information embedded in the module.
-04. [ILDN]† - Stores shader debug name for external debug information.
-05. [ISG1] - Stores the input signature for Shader Model 5.1+.
+01. {ref}`DXIL <DXIL>`† - Stores the DXIL bytecode.
+02. {ref}`HASH <HASH>`† - Stores the shader MD5 hash.
+03. {ref}`ILDB <ILDB>`† - Stores the DXIL bytecode with LLVM Debug Information embedded in the module.
+04. {ref}`ILDN <ILDN>`† - Stores shader debug name for external debug information.
+05. {ref}`ISG1 <ISG1>` - Stores the input signature for Shader Model 5.1+.
 06. ISGN\* - Stores the input signature for Shader Model 4 and earlier.
-07. [OSG1] - Stores the output signature for Shader Model 5.1+.
+07. {ref}`OSG1 <OSG1>` - Stores the output signature for Shader Model 5.1+.
 08. OSG5\* - Stores the output signature for Shader Model 5.
 09. OSGN\* - Stores the output signature for Shader Model 4 and earlier.
 10. PCSG\* - Stores the patch constant signature for Shader Model 5.1 and earlier.
 11. PDBI† - Stores PDB information.
-12. [PRIV]† - Stores private data, including embedded companion PDB files.
-13. [PSG1] - Stores the patch constant signature for Shader Model 6+.
-14. [PSV0] - Stores Pipeline State Validation data.
+12. {ref}`PRIV <PRIV>`† - Stores private data, including embedded companion PDB files.
+13. {ref}`PSG1 <PSG1>` - Stores the patch constant signature for Shader Model 6+.
+14. {ref}`PSV0 <PSV0>` - Stores Pipeline State Validation data.
 15. RDAT† - Stores Runtime Data.
 16. RDEF\* - Stores resource definitions.
-17. [RTS0] - Stores compiled root signature.
-18. [SFI0] - Stores shader feature flags.
+17. {ref}`RTS0 <RTS0>` - Stores compiled root signature.
+18. {ref}`SFI0 <SFI0>` - Stores shader feature flags.
 19. SHDR\* - Stores compiled DXBC bytecode.
 20. SHEX\* - Stores compiled DXBC bytecode.
 21. DXBC\* - Stores compiled DXBC bytecode.
-22. [SRCI]† - Stores shader source information.
+22. {ref}`SRCI <SRCI>`† - Stores shader source information.
 23. STAT† - Stores shader statistics.
-24. [VERS]† - Stores shader compiler version information.
+24. {ref}`VERS <VERS>`† - Stores shader compiler version information.
 
 ### DXIL Part
 
-(dxil)=
+(DXIL)=
 
 The DXIL part is comprised of three data structures: the `ProgramHeader`, the
 `BitcodeHeader` and the bitcode serialized LLVM 3.7 IR Module.
@@ -129,7 +129,7 @@ start of the bitcode data.
 
 ### HASH Part
 
-(hash)=
+(HASH)=
 
 The HASH part contains a 32-bit unsigned integer with the shader hash flags, and
 a 128-bit MD5 hash digest. The flags field can either have the value `0` to
@@ -139,9 +139,9 @@ including the source code that produced the binary. See {ref}`Compiler Flags
 
 ### ILDB Part
 
-(ildb)=
+(ILDB)=
 
-The ILDB part follows the structure of the [DXIL] part. It stores the
+The ILDB part follows the structure of the {ref}`DXIL <DXIL>` part. It stores the
 unstripped DXIL bitcode module with debug information embedded.
 
 The ILDB part is emitted when the shader is compiled with full debug information
@@ -150,7 +150,7 @@ See {ref}`Compiler Flags <compiler_flags>` for how `/Qembed_debug`,
 `/Qstrip_debug`, `/Fd`, and `/Zs` control whether it appears in the main
 output, the companion PDB, or both.
 
-The stripped [DXIL] part has the `Dwarf Version` and `Debug Info Version`
+The stripped {ref}`DXIL <DXIL>` part has the `Dwarf Version` and `Debug Info Version`
 module flags removed, and `dx.source` metadata nodes are stripped from it.
 Those nodes are preserved in the ILDB module when `/Qsource_in_debug_module`
 is used; otherwise they are replaced with empty placeholder values in the ILDB
@@ -174,7 +174,7 @@ to access it (see {doc}`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
 
 ### ILDN Part
 
-(ildn)=
+(ILDN)=
 
 The ILDN part stores the name of the companion PDB file used for external
 debug information. It is always emitted when the shader is compiled with debug
@@ -196,7 +196,7 @@ of the debug file name in bytes, not including the null terminator.
 
 If no PDB output path is specified, the debug file name defaults to
 `<MD5 hash>.pdb`, where `<MD5 hash>` is the stringified MD5 digest from the
-[HASH] part. See {ref}`Compiler Flags <compiler_flags>` for how `/Fd`, `/Zss`,
+{ref}`HASH <HASH>` part. See {ref}`Compiler Flags <compiler_flags>` for how `/Fd`, `/Zss`,
 and `/Zsb` affect the debug file name and hash computation.
 
 ```{rubric} Reading this part
@@ -207,7 +207,7 @@ it under a `DebugName` mapping.
 
 ### PRIV Part
 
-(priv)=
+(PRIV)=
 
 The PRIV part stores opaque binary data. DXC may emit it when the `/Qpdb_in_private`
 flag is used to embed the companion debug info PDB file in the main DXContainer output.
@@ -234,7 +234,7 @@ llvm-objcopy --dump-section=PRIV=output.priv shader.dxbc
 
 ### SRCI Part
 
-(srci)=
+(SRCI)=
 
 The SRCI part stores shader source information extracted from `dx.source`
 metadata in the LLVM module. It is emitted when source information is available.
@@ -384,7 +384,7 @@ To read SRCI part from a companion PDB file, use {program}`llvm-pdbutil`.
 
 ### VERS Part
 
-(vers)=
+(VERS)=
 
 The VERS part stores compiler version information. It is emitted when the
 shader is compiled with debug information. When a companion PDB file is produced,
@@ -433,11 +433,11 @@ To read VERS part from a companion PDB file, use {program}`llvm-pdbutil`.
 
 ### Program Signature (SG1) Parts
 
-(isg1)=
+(ISG1)=
 
-(osg1)=
+(OSG1)=
 
-(psg1)=
+(PSG1)=
 
 ```c
 struct ProgramSignatureHeader {
@@ -469,7 +469,7 @@ requirements.
 
 ### PSV0 Part
 
-(psv0)=
+(PSV0)=
 
 The Pipeline State Validation data encodes versioned runtime information
 structures. These structures use a scheme where in lieu of encoding a version
@@ -684,7 +684,7 @@ input.
 
 ### Root Signature (RTS0) Part
 
-(rts0)=
+(RTS0)=
 
 The Root Signature data defines the shader's resource interface with Direct3D
 12, specifying what resources the shader needs to access and how they're
@@ -699,13 +699,33 @@ The table below summarizes the data being serialized as well as it's size. The
 details of it part will be discussed in further details on the next sections
 of this document.
 
-| Part Name              | Size In Bytes | Maximum number of Instances |
-| ---------------------- | ------------- | --------------------------- |
-| Root Signature Header  | 24            | 1                           |
-| Root Parameter Headers | 12            | Many                        |
-| Root Parameter         | ```{eval-rst}
-================================ === Root Constants                   12 Root Descriptor Version 1.0      8 Root Descriptor Version 1.1      12 Descriptors Tables Version 1.0   20 Descriptors Tables Version 1.1   24 ================================ === ```               | Many                        |
-| Static Samplers        | 52            | Many                        |
+:::{list-table}
+:header-rows: 1
+
+* - Part Name
+  - Size In Bytes
+  - Maximum number of Instances
+* - Root Signature Header
+  - 24
+  - 1
+* - Root Parameter Headers
+  - 12
+  - Many
+* - Root Parameter
+  - Root Constants: 12
+
+    Root Descriptor Version 1.0: 8
+
+    Root Descriptor Version 1.1: 12
+
+    Descriptors Tables Version 1.0: 20
+
+    Descriptors Tables Version 1.1: 24
+  - Many
+* - Static Samplers
+  - 52
+  - Many
+:::
 
 #### Root Signature Header
 
@@ -853,7 +873,7 @@ struct StaticSamplerDesc {
 
 ### SFI0 Part
 
-(sfi0)=
+(SFI0)=
 
 The SFI0 part encodes a 64-bit unsigned integer bitmask of the feature flags.
 This denotes which optional features the shader requires. The flag values are
@@ -861,12 +881,12 @@ defined in [llvm/include/llvm/BinaryFormat/DXContainerConstants.def](https://git
 
 ## Compiler Flags
 
-(compiler-flags-1)=
+(compiler_flags)=
 
 When compiling HLSL with {program}`dxc`, several flags control whether
 debug information is embedded in the main DXContainer output, written to a
 companion PDB file, or both. Use `/Zi` for full debug output or `/Zs` for
-slim debug output without an [ILDB] part. In {program}`clang-dxc`, most
+slim debug output without an {ref}`ILDB <ILDB>` part. In {program}`clang-dxc`, most
 dxc-style flags are forwarded to {program}`llc` as `-mllvm` options.
 
 ### Debug Output Locations
@@ -874,42 +894,42 @@ dxc-style flags are forwarded to {program}`llc` as `-mllvm` options.
 Debug information is enabled with either `/Zi` (full debug) or `/Zs` (slim
 debug). The two flags are mutually exclusive.
 
-**Full debug with \`\`/Zi\`\`**
+**Full debug with `/Zi`**
 
-When `/Zi` is enabled, the [ILDB] part can appear in the main DXContainer
+When `/Zi` is enabled, the {ref}`ILDB <ILDB>` part can appear in the main DXContainer
 output, in a companion PDB, or both:
 
-- **Embedded in the main DXContainer output.** The [ILDB] part holds the
+- **Embedded in the main DXContainer output.** The {ref}`ILDB <ILDB>` part holds the
   unstripped DXIL module with debug information. It is included when
-  `/Qembed_debug` is used. The main output always contains the stripped [DXIL]
-  part alongside other parts such as [HASH], [ILDN], and [VERS].
+  `/Qembed_debug` is used. The main output always contains the stripped {ref}`DXIL <DXIL>`
+  part alongside other parts such as {ref}`HASH <HASH>`, {ref}`ILDN <ILDN>`, and {ref}`VERS <VERS>`.
 - **Omitted from the main DXContainer output.** When `/Qstrip_debug` is used,
-  the [ILDB] part is not written to the main output. Other debug-related parts
-  such as [ILDN] are still emitted. If `/Fd` is also specified, the [ILDB]
+  the {ref}`ILDB <ILDB>` part is not written to the main output. Other debug-related parts
+  such as {ref}`ILDN <ILDN>` are still emitted. If `/Fd` is also specified, the {ref}`ILDB <ILDB>`
   part is still written to the companion PDB. `/Qstrip_debug` takes precedence
   over the default `/Qembed_debug` behavior when `/Zi` is used without
   `/Fd`. If both `/Qstrip_debug` and `/Qembed_debug` are specified,
-  `/Qstrip_debug` is ignored and the [ILDB] part is embedded.
+  `/Qstrip_debug` is ignored and the {ref}`ILDB <ILDB>` part is embedded.
 - **In a companion PDB file.** A sidecar `.pdb` stores a DXContainer stream
-  with debug-related parts including [ILDB], [SRCI], and [VERS]. This is
+  with debug-related parts including {ref}`ILDB <ILDB>`, {ref}`SRCI <SRCI>`, and {ref}`VERS <VERS>`. This is
   produced when `/Fd` names an output path. Use {program}`llvm-pdbutil` to
   inspect or extract that stream (see
   {doc}`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
 - **Embedded in the private data of the main output.** When
   `/Qpdb_in_private` is used, a copy of the companion PDB file is stored as
-  opaque bytes in [PRIV]. This can be used with or without `/Fd`; without
+  opaque bytes in {ref}`PRIV <PRIV>`. This can be used with or without `/Fd`; without
   `/Fd`, the PDB is not retained as a separate file on disk. After extraction,
   tools treat the bytes as a standalone `.pdb` file.
 
 `/Fd` can be combined with `/Qembed_debug` or `/Qpdb_in_private` to
 write full debug information to more than one location.
 
-**Slim debug with \`\`/Zs\`\`**
+**Slim debug with `/Zs`**
 
-When `/Zs` is enabled, slim debug information is emitted. The [ILDB] part is
-omitted from the main DXContainer output and from any companion PDB or [PRIV]
-embedding, but other debug-related parts such as [HASH], [ILDN], [SRCI], and
-[VERS] are still emitted. A companion PDB from `/Fd` or a [PRIV] embedding
+When `/Zs` is enabled, slim debug information is emitted. The {ref}`ILDB <ILDB>` part is
+omitted from the main DXContainer output and from any companion PDB or {ref}`PRIV <PRIV>`
+embedding, but other debug-related parts such as {ref}`HASH <HASH>`, {ref}`ILDN <ILDN>`, {ref}`SRCI <SRCI>`, and
+{ref}`VERS <VERS>` are still emitted. A companion PDB from `/Fd` or a {ref}`PRIV <PRIV>` embedding
 from `/Qpdb_in_private` therefore contains slim debug data only.
 
 `/Zs` cannot be combined with `/Qembed_debug` or `/Qsource_in_debug_module`.
@@ -1042,4 +1062,3 @@ preconditions are met.
      - No
      - Holds a copy of the companion PDB file.
 ```
-
diff --git a/llvm/docs/DirectX/DXILArchitecture.md b/llvm/docs/DirectX/DXILArchitecture.md
index a89563d1a992d..6a466910e2b7d 100644
--- a/llvm/docs/DirectX/DXILArchitecture.md
+++ b/llvm/docs/DirectX/DXILArchitecture.md
@@ -18,7 +18,7 @@ possible. Similarly, we should introduce DXIL-specific constructs as
 late as possible in the process of lowering to the format.
 
 There are three places to look for DXIL related code in LLVM: The
-`DirectX` backend, for writing DXIL; The `DXILUpgrade` pass, for
+*DirectX* backend, for writing DXIL; The *DXILUpgrade* pass, for
 reading; and in library code that is shared between writing and
 reading. We'll describe these in reverse order.
 
@@ -29,10 +29,10 @@ and writing DXIL in order to avoid code duplication. While we don't
 have a hard and fast rule about where such code should live, there are
 generally three sensible places. Simple definitions of enums and
 values that must stay fixed to match DXIL's ABI can be found in
-`Support/DXILABI.h`, utilities to translate bidirectionally between
-DXIL and modern LLVM constructs live in `lib/Transforms/Utils`, and
+*Support/DXILABI.h*, utilities to translate bidirectionally between
+DXIL and modern LLVM constructs live in *lib/Transforms/Utils*, and
 more analyses that are needed to derive or preserve information are
-implemented as typical `lib/Analysis` passes.
+implemented as typical *lib/Analysis* passes.
 
 ## The DXILUpgrade Pass
 
@@ -41,14 +41,14 @@ compatible with LLVM 3.7 bitcode, and that modern LLVM is capable of
 "upgrading" older bitcode into modern IR. Simply relying on the
 bitcode upgrade process isn't sufficient though, since that leaves a
 number of DXIL specific constructs around. Thus, we have the
-`DXILUpgrade` pass to transform DXIL operations to LLVM operations and
+*DXILUpgrade* pass to transform DXIL operations to LLVM operations and
 smooth over differences in metadata representation. We call this pass
 "upgrade" to reflect that it follows LLVM's standard bitcode upgrade
 process and simply finishes the job for DXIL constructs - while
 "reader" or "lifting" might also be reasonable names, they could be a
 bit misleading.
 
-The `DXILUpgrade` pass itself is fairly lightweight. It mostly relies
+The *DXILUpgrade* pass itself is fairly lightweight. It mostly relies
 on the utilities described in "Common Code" above in order to share
 logic with both the DirectX backend and with Clang's codegen of HLSL
 support as much as possible.
@@ -58,7 +58,7 @@ support as much as possible.
 There are intrinsics that don't map directly to DXIL Ops. In some cases
 an intrinsic needs to be expanded to a set of LLVM IR instructions. In
 other cases an intrinsic needs modifications to the arguments or return
-values of a DXIL Op. The `DXILIntrinsicExpansion` pass handles all
+values of a DXIL Op. The *DXILIntrinsicExpansion* pass handles all
 the cases where our intrinsics don't have a one to one mapping. This
 pass may also be used when the expansion is specific to DXIL to keep
 implementation details out of CodeGen. Finally, there is an expectation
@@ -77,17 +77,17 @@ DXIL represents those constructs, followed by a limited bitcode
 
 Before emitting DXIL, the DirectX backend needs to modify the LLVM IR
 such that external operations, types, and metadata is represented in
-the way that DXIL expects. For example, `DXILOpLowering` translates
-intrinsics into `dx.op` calls. These passes are essentially the
-inverse of the `DXILUpgrade` pass. It's best to do this downgrading
+the way that DXIL expects. For example, *DXILOpLowering* translates
+intrinsics into *dx.op* calls. These passes are essentially the
+inverse of the *DXILUpgrade* pass. It's best to do this downgrading
 process as IR to IR passes when possible, as that means that they can
-be easily tested with `opt` and `FileCheck` without the need for
+be easily tested with *opt* and *FileCheck* without the need for
 external tooling.
 
 The second part of DXIL emission is more or less an LLVM bitcode
 downgrader. We need to emit bitcode that matches the LLVM 3.7
-representation. For this, we have `DXILWriter`, which is an alternate
-version of LLVM's `BitcodeWriter`. At present, this is able to
+representation. For this, we have *DXILWriter*, which is an alternate
+version of LLVM's *BitcodeWriter*. At present, this is able to
 leverage LLVM's current bitcode libraries to do a lot of the work, but
 it's possible that at some point in the future it will need to be
 completely separate as modern LLVM bitcode evolves.
@@ -140,21 +140,21 @@ support are implemented in the ObjectYAML library and tools.
 ## Testing
 
 A lot of DXIL testing can be done with typical IR to IR tests using
-`opt` and `FileCheck`, since a lot of the support is implemented in
+*opt* and *FileCheck*, since a lot of the support is implemented in
 terms of IR level passes as described in the previous sections. You
-can see examples of this in `llvm/test/CodeGen/DirectX` as well as
-`llvm/test/Transforms/DXILUpgrade`, and this type of testing should be
+can see examples of this in *llvm/test/CodeGen/DirectX* as well as
+*llvm/test/Transforms/DXILUpgrade*, and this type of testing should be
 leveraged as much as possible.
 
 However, when it comes to testing the DXIL format itself, IR passes
 are insufficient for testing. For now, the best option we have
 available is using the DXC project's tools in order to round trip.
-These tests are currently found in `test/tools/dxil-dis` and are only
-available if the `LLVM_INCLUDE_DXIL_TESTS` cmake option is set. Note
+These tests are currently found in *test/tools/dxil-dis* and are only
+available if the *LLVM_INCLUDE_DXIL_TESTS* cmake option is set. Note
 that we do not currently have the equivalent testing set up for the
 DXIL reading path.
 
 As soon as we are able, we will also want to round trip using the DXIL
 writing and reading paths in order to ensure self consistency and to
-get test coverage when `dxil-dis` isn't available.
+get test coverage when *dxil-dis* isn't available.
 
diff --git a/llvm/docs/GlobalISel/GenericOpcode.md b/llvm/docs/GlobalISel/GenericOpcode.md
index de6251167fdc4..f95cf2fb9bb74 100644
--- a/llvm/docs/GlobalISel/GenericOpcode.md
+++ b/llvm/docs/GlobalISel/GenericOpcode.md
@@ -1,19 +1,3 @@
----
-substitutions:
-  all_g_atomicrmw: |-
-    G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD,
-    G_ATOMICRMW_SUB, G_ATOMICRMW_AND,
-    G_ATOMICRMW_NAND, G_ATOMICRMW_OR,
-    G_ATOMICRMW_XOR, G_ATOMICRMW_MAX,
-    G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
-    G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD,
-    G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX,
-    G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAXIMUM,
-    G_ATOMICRMW_FMINIMUM, G_ATOMICRMW_UINC_WRAP,
-    G_ATOMICRMW_UDEC_WRAP, G_ATOMICRMW_USUB_COND,
-    G_ATOMICRMW_USUB_SAT
----
-
 (gmir-opcodes)=
 
 # Generic Opcodes
@@ -907,7 +891,13 @@ MachineMemOperand in addition to explicit operands.
 Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
 operands.
 
-### {{ all_g_atomicrmw }}
+<h3 id="all-g-atomicrmw">G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD,
+G_ATOMICRMW_SUB, G_ATOMICRMW_AND, G_ATOMICRMW_NAND, G_ATOMICRMW_OR,
+G_ATOMICRMW_XOR, G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
+G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD, G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX,
+G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAXIMUM, G_ATOMICRMW_FMINIMUM,
+G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP, G_ATOMICRMW_USUB_COND,
+G_ATOMICRMW_USUB_SAT</h3>
 
 Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
 operands.
@@ -1124,4 +1114,3 @@ and other transformations should not look through this. These have no other
 semantics and can be safely eliminated if a target chooses.
 
 Unlisted: G_STACKSAVE, G_STACKRESTORE, G_FSHL, G_FSHR, G_SMULFIX, G_UMULFIX, G_SMULFIXSAT, G_UMULFIXSAT, G_SDIVFIX, G_UDIVFIX, G_SDIVFIXSAT, G_UDIVFIXSAT, G_FPOWI, G_FEXP10, G_FLDEXP, G_FFREXP, G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV, G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE, G_INTRINSIC_FPTRUNC_ROUND, G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT, G_INTRINSIC_ROUNDEVEN, G_READCYCLECOUNTER, G_READSTEADYCOUNTER, G_PREFETCH, G_READ_REGISTER, G_WRITE_REGISTER, G_STRICT_FADD, G_STRICT_FSUB, G_STRICT_FMUL, G_STRICT_FDIV, G_STRICT_FREM, G_STRICT_FMA, G_STRICT_FSQRT, G_STRICT_FLDEXP, G_ASSERT_ALIGN
-
diff --git a/llvm/docs/GlobalISel/Legalizer.md b/llvm/docs/GlobalISel/Legalizer.md
index 3f063eb9a5930..8af2eb9a7b9b2 100644
--- a/llvm/docs/GlobalISel/Legalizer.md
+++ b/llvm/docs/GlobalISel/Legalizer.md
@@ -302,10 +302,11 @@ legal for all type combinations that change the bit pattern in the value.
 
 There are no legality requirements for `G_BUILD_VECTOR`, or `G_BUILD_VECTOR_TRUNC`
 since these can be handled by:
-\* Declaring them legal.
-\* Scalarizing them.
-\* Lowering them to ``` G_TRUNC``+``G_ANYEXT ``` and some legalizable instructions.
-\* Lowering them to target instructions which are legal by definition.
+
+* Declaring them legal.
+* Scalarizing them.
+* Lowering them to `G_TRUNC`+`G_ANYEXT` and some legalizable instructions.
+* Lowering them to target instructions which are legal by definition.
 
 The same reasoning also allows `G_UNMERGE_VALUES` to lack legality requirements
 for vector inputs.
@@ -331,4 +332,3 @@ operations have requirements:
 
 There are many other operations you'd expect to have legality requirements, but
 they can be lowered to target instructions which are legal by definition.
-
diff --git a/llvm/docs/GlobalISel/Resources.md b/llvm/docs/GlobalISel/Resources.md
index 092482e7cf733..cd79aa556d2a1 100644
--- a/llvm/docs/GlobalISel/Resources.md
+++ b/llvm/docs/GlobalISel/Resources.md
@@ -1,4 +1,4 @@
-(other-resources)=
+(other_resources)=
 
 # Resources
 
@@ -8,4 +8,3 @@
 - [GlobalISel: Past, Present, and Future by Quentin Colombet and Ahmed Bougacha @LLVMDevMeeting 2017](https://www.llvm.org/devmtg/2017-10/#talk11)
 - [Head First into GlobalISel by Daniel Sanders, Aditya Nandakumar, and Justin Bogner @LLVMDevMeeting 2017](https://www.llvm.org/devmtg/2017-10/#tutorial2)
 - [Generating Optimized Code with GlobalISel by Volkan Keles, Daniel Sanders @LLVMDevMeeting 2019](https://www.llvm.org/devmtg/2019-10/talk-abstracts.html#keynote1)
-
diff --git a/llvm/docs/PDB/CodeViewSymbols.md b/llvm/docs/PDB/CodeViewSymbols.md
index 265afeeeddda6..6a0315a200c04 100644
--- a/llvm/docs/PDB/CodeViewSymbols.md
+++ b/llvm/docs/PDB/CodeViewSymbols.md
@@ -1,6 +1,6 @@
 # CodeView Symbol Records
 
-(symbols-intro)=
+(symbols_intro)=
 
 ## Introduction
 
@@ -38,7 +38,7 @@ to appear in a PDB file. Public Symbols (which appear only in the
 {doc}`globals stream <GlobalStream>`) and module symbols (which appear in the
 {doc}`module info stream <ModiStream>`).
 
-(public-symbols)=
+(public_symbols)=
 
 ### Public Symbols
 
@@ -57,7 +57,7 @@ the symbol's address. The {ref}`dbi_section_map_substream` of the
 corresponds to, and from there that module's {doc}`module debug stream <ModiStream>`
 can be consulted to locate full information for the symbol with the given address.
 
-(global-symbols)=
+(global_symbols)=
 
 ### Global Symbols
 
@@ -96,7 +96,7 @@ qualified name is not possible.
 
 #### S_GMANDATA (0x111d)
 
-(module-symbols)=
+(module_symbols)=
 
 ### Module Symbols
 
@@ -142,7 +142,7 @@ qualified name is not possible.
 
 #### S_ENVBLOCK (0x113d)
 
-(s-local)=
+(s_local)=
 
 #### S_LOCAL (0x113e)
 
@@ -178,8 +178,8 @@ enum class LocalSymFlags : uint16_t {
 All `S_DEFRANGE*` records consist of a header followed by
 `LocalVariableAddrRange` and a list of `LocalVariableAddrGap` (until the
 record length is reached) except for the
-[S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE](_defrange_framepointer_rel_full_scope)
-record.
+{ref}`S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
+<defrange_framepointer_rel_full_scope>` record.
 
 ```cpp
 /// A live range of a variable.
@@ -270,7 +270,7 @@ struct DefrangeSubfieldRegisterSymHeader {
 };
 ```
 
-(defrange-framepointer-rel-full-scope)=
+(defrange_framepointer_rel_full_scope)=
 
 #### S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE (0x1144)
 
@@ -381,7 +381,7 @@ The `S_REGREL32_INDIR` symbol for `y` from above looks like this:
 | `08000000` | `74000000` | `04000000`  | `4F01`   | `7900` |
 | 8          | int        | 4           | RSP      | "a"    |
 
-(module-and-global-symbols)=
+(module_and_global_symbols)=
 
 ### Symbols which can go in either/both of the module info stream & global stream
 
@@ -396,4 +396,3 @@ The `S_REGREL32_INDIR` symbol for `y` from above looks like this:
 #### S_LMANDATA (0x111c)
 
 #### S_MANCONSTANT (0x112d)
-
diff --git a/llvm/docs/PDB/CodeViewTypes.md b/llvm/docs/PDB/CodeViewTypes.md
index dfa19f4606f25..06a1bae7dd43f 100644
--- a/llvm/docs/PDB/CodeViewTypes.md
+++ b/llvm/docs/PDB/CodeViewTypes.md
@@ -1,10 +1,8 @@
-=====================================
-CodeView Type Records
-\=====================================
+# CodeView Type Records
 
-(types-intro)=
+(types_intro)=
 
-# Introduction
+## Introduction
 
 This document describes the usage and serialization format of the various
 CodeView type records that LLVM understands. This document does not describe
@@ -17,7 +15,7 @@ made obsolete by newer records, or any number of other reasons. However, the
 records we describe here should cover 99% of type records that one can expect
 to encounter when dealing with modern C++ toolchains.
 
-# Record Categories
+## Record Categories
 
 We can think of a sequence of CodeView type records as an array of variable length
 `leaf records`. Each such record describes its own length as part of a fixed-size
@@ -32,9 +30,9 @@ The final category of record is a `member record`. One particular leaf type --
 `LF_FIELDLIST` describes its length (like any other leaf record), the embedded
 records -- called `member records` do not.
 
-(leaf-types)=
+(leaf_types)=
 
-## Leaf Records
+### Leaf Records
 
 All leaf records begin with the following 4-byte prefix:
 
@@ -45,7 +43,7 @@ struct RecordHeader {
 };
 ```
 
-### LF_POINTER (0x1002)
+#### LF_POINTER (0x1002)
 
 **Usage:** Describes a pointer to another type.
 
@@ -123,89 +121,88 @@ attributes indicate that this is a pointer to member.
 Note that "plain" pointers to primitive types are not represented by `LF_POINTER`
 records, they are indicated by special reserved {ref}`TypeIndex values <type_indices>`.
 
-### LF_MODIFIER (0x1001)
+#### LF_MODIFIER (0x1001)
 
-### LF_PROCEDURE (0x1008)
+#### LF_PROCEDURE (0x1008)
 
-### LF_MFUNCTION (0x1009)
+#### LF_MFUNCTION (0x1009)
 
-### LF_LABEL (0x000e)
+#### LF_LABEL (0x000e)
 
-### LF_ARGLIST (0x1201)
+#### LF_ARGLIST (0x1201)
 
-### LF_FIELDLIST (0x1203)
+#### LF_FIELDLIST (0x1203)
 
-### LF_ARRAY (0x1503)
+#### LF_ARRAY (0x1503)
 
-### LF_CLASS (0x1504)
+#### LF_CLASS (0x1504)
 
-### LF_STRUCTURE (0x1505)
+#### LF_STRUCTURE (0x1505)
 
-### LF_INTERFACE (0x1519)
+#### LF_INTERFACE (0x1519)
 
-### LF_UNION (0x1506)
+#### LF_UNION (0x1506)
 
-### LF_ENUM (0x1507)
+#### LF_ENUM (0x1507)
 
-### LF_TYPESERVER2 (0x1515)
+#### LF_TYPESERVER2 (0x1515)
 
-### LF_VFTABLE (0x151d)
+#### LF_VFTABLE (0x151d)
 
-### LF_VTSHAPE (0x000a)
+#### LF_VTSHAPE (0x000a)
 
-### LF_BITFIELD (0x1205)
+#### LF_BITFIELD (0x1205)
 
-### LF_FUNC_ID (0x1601)
+#### LF_FUNC_ID (0x1601)
 
-### LF_MFUNC_ID (0x1602)
+#### LF_MFUNC_ID (0x1602)
 
-### LF_BUILDINFO (0x1603)
+#### LF_BUILDINFO (0x1603)
 
-### LF_SUBSTR_LIST (0x1604)
+#### LF_SUBSTR_LIST (0x1604)
 
-### LF_STRING_ID (0x1605)
+#### LF_STRING_ID (0x1605)
 
-### LF_UDT_SRC_LINE (0x1606)
+#### LF_UDT_SRC_LINE (0x1606)
 
-### LF_UDT_MOD_SRC_LINE (0x1607)
+#### LF_UDT_MOD_SRC_LINE (0x1607)
 
-### LF_METHODLIST (0x1206)
+#### LF_METHODLIST (0x1206)
 
-### LF_PRECOMP (0x1509)
+#### LF_PRECOMP (0x1509)
 
-### LF_ENDPRECOMP (0x0014)
+#### LF_ENDPRECOMP (0x0014)
 
-(member-types)=
+(member_types)=
 
-## Member Records
+### Member Records
 
-### LF_BCLASS (0x1400)
+#### LF_BCLASS (0x1400)
 
-### LF_BINTERFACE (0x151a)
+#### LF_BINTERFACE (0x151a)
 
-### LF_VBCLASS (0x1401)
+#### LF_VBCLASS (0x1401)
 
-### LF_IVBCLASS (0x1402)
+#### LF_IVBCLASS (0x1402)
 
-### LF_VFUNCTAB (0x1409)
+#### LF_VFUNCTAB (0x1409)
 
-### LF_STMEMBER (0x150e)
+#### LF_STMEMBER (0x150e)
 
-### LF_METHOD (0x150f)
+#### LF_METHOD (0x150f)
 
-### LF_MEMBER (0x150d)
+#### LF_MEMBER (0x150d)
 
-### LF_NESTTYPE (0x1510)
+#### LF_NESTTYPE (0x1510)
 
-### LF_ONEMETHOD (0x1511)
+#### LF_ONEMETHOD (0x1511)
 
-### LF_ENUMERATE (0x1502)
+#### LF_ENUMERATE (0x1502)
 
-### LF_INDEX (0x1404)
+#### LF_INDEX (0x1404)
 
-(padding-records)=
+(padding_records)=
 
-## Padding Records
-
-### LF_PADn (0xf0 + n)
+### Padding Records
 
+#### LF_PADn (0xf0 + n)
diff --git a/llvm/docs/PDB/DbiStream.md b/llvm/docs/PDB/DbiStream.md
index d3b4bd000a06c..ec87442b64d2a 100644
--- a/llvm/docs/PDB/DbiStream.md
+++ b/llvm/docs/PDB/DbiStream.md
@@ -1,6 +1,6 @@
 # The PDB DBI (Debug Info) Stream
 
-(dbi-intro)=
+(dbi_intro)=
 
 ## Introduction
 
@@ -13,7 +13,7 @@ detailed information about each compiland, such as the CodeView symbol records
 contained within each compiland and the source and line information for
 functions and other symbols within each compiland.
 
-(dbi-header)=
+(dbi_header)=
 
 ## Stream Header
 
@@ -126,11 +126,11 @@ of each of the following `7` fields.
 - **OptionalDbgHeaderSize** - The length of the {ref}`dbi_optional_dbg_stream`.
 - **ECSubstreamSize** - The length of the {ref}`dbi_ec_substream`.
 
-(dbi-substreams)=
+(dbi_substreams)=
 
 ## Substreams
 
-(dbi-mod-info-substream)=
+(dbi_mod_info_substream)=
 
 ### Module Info Substream
 
@@ -222,7 +222,7 @@ uint16_t TSM : 8;
   In the case of a module that comes from an archive, this is usually the full
   path to the archive.
 
-(dbi-sec-contr-substream)=
+(dbi_sec_contr_substream)=
 
 ### Section Contribution Substream
 
@@ -254,7 +254,7 @@ The purpose of the second field is not well understood. The name implies that
 is the index of the COFF section, but this also describes the existing field
 `SectionContribEntry::Section`.
 
-(dbi-section-map-substream)=
+(dbi_section_map_substream)=
 
 ### Section Map Substream
 
@@ -293,7 +293,7 @@ enum class SectionMapEntryFlags : uint16_t {
 
 Many of these fields are not well understood, so will not be discussed further.
 
-(dbi-file-info-substream)=
+(dbi_file_info_substream)=
 
 ### File Info Substream
 
@@ -347,7 +347,7 @@ each integer is an offset into **NamesBuffer** pointing to a null terminated str
 **NamesBuffer** - An array of null terminated strings containing the actual source
 file names.
 
-(dbi-type-server-map-substream)=
+(dbi_type_server_map_substream)=
 
 ### Type Server Map Substream
 
@@ -357,7 +357,7 @@ nor the layout of this substream is understood, although it is assumed to
 related somehow to the usage of `/Zi` and `mspdbsrv.exe`. This substream
 will not be discussed further.
 
-(dbi-ec-substream)=
+(dbi_ec_substream)=
 
 ### EC Substream
 
@@ -367,7 +367,7 @@ Begins at offset `0` immediately after the
 Continue support in MSVC. LLVM does not support Edit & Continue, so this
 stream will not be discussed further.
 
-(dbi-optional-dbg-stream)=
+(dbi_optional_dbg_stream)=
 
 ### Optional Debug Header Stream
 
@@ -428,4 +428,3 @@ and cl object files are linked into the same program.
 `DbgStreamArray[5]`, but contains the section headers before any binary translation
 has been performed. This can be used in conjunction with `DebugStreamArray[3]`
 and `DbgStreamArray[4]` to map instrumented and uninstrumented addresses.
-
diff --git a/llvm/docs/PDB/HashTable.md b/llvm/docs/PDB/HashTable.md
index 7caa138763d3e..f7b32163ef993 100644
--- a/llvm/docs/PDB/HashTable.md
+++ b/llvm/docs/PDB/HashTable.md
@@ -1,6 +1,6 @@
 # The PDB Serialized Hash Table Format
 
-(hash-intro)=
+(hash_intro)=
 
 # Introduction
 
@@ -56,7 +56,7 @@ file hash table, the appropriate hash function is being used.
   state of each bucket (valid, empty, deleted) can be determined by examining
   the present and deleted bit vectors.
 
-(hash-bit-vectors)=
+(hash_bit_vectors)=
 
 # Present and Deleted Bit Vectors
 
@@ -89,4 +89,3 @@ with the following layout:
 
 where the k'th bit of this bit vector represents the status of the k'th bucket
 in the hash table.
-
diff --git a/llvm/docs/PDB/ModiStream.md b/llvm/docs/PDB/ModiStream.md
index 22b372274a127..e7c9bb78a82ff 100644
--- a/llvm/docs/PDB/ModiStream.md
+++ b/llvm/docs/PDB/ModiStream.md
@@ -1,6 +1,6 @@
 # The Module Information Stream
 
-(modi-stream-intro)=
+(modi_stream_intro)=
 
 ## Introduction
 
@@ -13,7 +13,7 @@ for a single module contains line information for the compiland, as well as
 all CodeView information for the symbols defined in the compiland. Finally,
 there is a "global refs" substream which is not well understood.
 
-(modi-stream-layout)=
+(modi_stream_layout)=
 
 ## Stream Layout
 
@@ -55,7 +55,7 @@ struct ModiStream {
   information is not present.
 - **GlobalRefs** - The meaning of this substream is not understood.
 
-(modi-symbol-substream)=
+(modi_symbol_substream)=
 
 ## The CodeView Symbol Substream
 
@@ -65,4 +65,3 @@ and other symbols defined in the compiland. The entire array consumes
 `SymbolSize-4` bytes. The format of a CodeView Symbol Record (and
 thusly, an array of CodeView Symbol Records) is described in
 {doc}`CodeViewSymbols`.
-
diff --git a/llvm/docs/PDB/MsfFile.md b/llvm/docs/PDB/MsfFile.md
index fa51d2271f529..7fe16d259a287 100644
--- a/llvm/docs/PDB/MsfFile.md
+++ b/llvm/docs/PDB/MsfFile.md
@@ -1,6 +1,6 @@
 # The MSF File Format
 
-(msf-layout)=
+(msf_layout)=
 
 ## File Layout
 
@@ -36,7 +36,7 @@ LLVM only supports 4096 byte blocks (sometimes referred to as the "BigMsf"
 variant), so the rest of this document will assume a block size of 4096.
 :::
 
-(msf-superblock)=
+(msf_superblock)=
 
 ## The Superblock
 
@@ -81,7 +81,7 @@ struct SuperBlock {
   `ulittle32_t`'s in this array is given by `ceil(NumDirectoryBytes /
   BlockSize)`.
 
-(msf-freeblockmap)=
+(msf_freeblockmap)=
 
 ## The Free Block Map
 
@@ -171,4 +171,3 @@ accordingly. In the aforementioned example, the high byte of the `uint16`
 would be written to the last byte of block N, and the low byte would be written
 to the first byte of block N+1, which could be tens of thousands of bytes later
 (or even earlier!) in the file, depending on what the stream directory says.
-
diff --git a/llvm/docs/PDB/PdbStream.md b/llvm/docs/PDB/PdbStream.md
index 19380b581e75f..b3d93e1065695 100644
--- a/llvm/docs/PDB/PdbStream.md
+++ b/llvm/docs/PDB/PdbStream.md
@@ -1,6 +1,6 @@
 # The PDB Info Stream (aka the PDB Stream)
 
-(pdb-stream-header)=
+(pdb_stream_header)=
 
 ## Stream Header
 
@@ -50,7 +50,7 @@ the other streams, will change if the value is something other than `VC70`.
   [UuidCreate](<https://msdn.microsoft.com/en-us/library/windows/desktop/aa379205(v=vs.85).aspx>),
   although LLVM cannot rely on that, as it must work on non-Windows platforms.
 
-(pdb-named-stream-map)=
+(pdb_named_stream_map)=
 
 ## Named Stream Map
 
@@ -87,7 +87,7 @@ The on-disk layout of the serialized hash table is described at {doc}`HashTable`
 Note that the entire Named Stream Map is not length-prefixed, so the only way to
 get to the data following it is to de-serialize it in its entirety.
 
-(pdb-stream-features)=
+(pdb_stream_features)=
 
 ## PDB Feature Codes
 
@@ -105,17 +105,23 @@ enum class PdbRaw_FeatureSig : uint32_t {
 
 The meaning of these values is summarized by the following table:
 
-| Flag             | Meaning                                                                                                 |
-| ---------------- | ------------------------------------------------------------------------------------------------------- |
-| VC110            | - No other features flags are present
-- PDB contains an 
-  {doc}`IPI Stream <TpiStream>`                                                                                                         |
-| VC140            | - Other feature flags may be present
-- PDB contains an 
-  {doc}`IPI Stream <TpiStream>`                                                                                                         |
-| NoTypeMerge      | - Presumably duplicate types can appear in the TPI Stream, although it's unclear why this might happen. |
-| MinimalDebugInfo | - Program was linked with /DEBUG:FASTLINK
-- There is no TPI / IPI stream, all type info is contained in the original object files.                                                                                                         |
+:::{list-table}
+:header-rows: 1
+
+* - Flag
+  - Meaning
+* - VC110
+  - - No other features flags are present
+    - PDB contains an {doc}`IPI Stream <TpiStream>`
+* - VC140
+  - - Other feature flags may be present
+    - PDB contains an {doc}`IPI Stream <TpiStream>`
+* - NoTypeMerge
+  - - Presumably duplicate types can appear in the TPI Stream, although it's unclear why this might happen.
+* - MinimalDebugInfo
+  - - Program was linked with /DEBUG:FASTLINK
+    - There is no TPI / IPI stream, all type info is contained in the original object files.
+:::
 
 ## Matching a PDB to its executable
 
@@ -137,4 +143,3 @@ For this particular case, the linker emits a debug directory of type
 that it includes the same `Guid` and `Age` fields. At runtime, a
 debugger or tool can scan the COFF executable image for the presence of
 a debug directory of the correct type and verify that the Guid and Age match.
-
diff --git a/llvm/docs/PDB/TpiStream.md b/llvm/docs/PDB/TpiStream.md
index 5e826e1e8ecbd..e74f7a2ac1ebc 100644
--- a/llvm/docs/PDB/TpiStream.md
+++ b/llvm/docs/PDB/TpiStream.md
@@ -1,6 +1,6 @@
 # The PDB TPI and IPI Streams
 
-(tpi-intro)=
+(tpi_intro)=
 
 ## Introduction
 
@@ -21,7 +21,7 @@ pass.
 Type records form a topologically sorted DAG (directed acyclic graph).
 :::
 
-(tpi-ipi)=
+(tpi_ipi)=
 
 ## TPI vs IPI Stream
 
@@ -58,7 +58,7 @@ appear in each one, summarized by the following table:
 The usage of these records is described in more detail in
 {doc}`CodeView Type Records <CodeViewTypes>`.
 
-(type-indices)=
+(type_indices)=
 
 ## Type Indices
 
@@ -170,7 +170,7 @@ By convention, the type index for `std::nullptr_t` is constructed the same
 way as the type index for `void*`, but using the bitless enumeration value
 `NearPointer`.
 
-(tpi-header)=
+(tpi_header)=
 
 ## Stream Header
 
@@ -262,7 +262,7 @@ accurate.
   references that point to the old version to now point to the new version.
   The layout of this hash table is described in {doc}`HashTable`.
 
-(tpi-records)=
+(tpi_records)=
 
 ## CodeView Type Record List
 
@@ -274,4 +274,3 @@ Header.TypeIndexBegin`.
 
 O(log(n)) access is provided by way of the Type Index Offsets array (if
 present) described previously.
-

>From 1b1012b63b5bf37c1d624c33f97916b16c15c7c5 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Wed, 19 Aug 2026 18:49:34 +0000
Subject: [PATCH 3/3] [docs] Preserve nested DXContainer table structure

Use a nested Markdown pipe table inside the Root Signature list-table so the Root Parameter size breakdown keeps the original nested table structure from the reST source.

Validation:
- ninja -C build_local docs-llvm-html
- /work/llvm/venv/bin/python /work/llvm/rnk-llvm/validate_rst_md_html_ids.py llvm/docs/DirectX/DXContainer.md (same 43 IDs before/after; only known heading permalink context noise)
- /work/llvm/venv/bin/python /work/llvm/rnk-llvm/check_markdown_html_render.py --before-html-root /tmp/llvm-md-6-before-html --html-root build_local/docs/html --visual-diff-dir /tmp/llvm-md-6-review-followup-visual-diffs llvm/docs/DirectX/DXContainer.md
- scanned touched doc for internal-only markers
---
 llvm/docs/DirectX/DXContainer.md | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/llvm/docs/DirectX/DXContainer.md b/llvm/docs/DirectX/DXContainer.md
index ea4f1809b3294..69837b55ab0aa 100644
--- a/llvm/docs/DirectX/DXContainer.md
+++ b/llvm/docs/DirectX/DXContainer.md
@@ -712,15 +712,13 @@ of this document.
   - 12
   - Many
 * - Root Parameter
-  - Root Constants: 12
-
-    Root Descriptor Version 1.0: 8
-
-    Root Descriptor Version 1.1: 12
-
-    Descriptors Tables Version 1.0: 20
-
-    Descriptors Tables Version 1.1: 24
+  - | Root Parameter Type | Size |
+    | --- | --- |
+    | Root Constants | 12 |
+    | Root Descriptor Version 1.0 | 8 |
+    | Root Descriptor Version 1.1 | 12 |
+    | Descriptors Tables Version 1.0 | 20 |
+    | Descriptors Tables Version 1.1 | 24 |
   - Many
 * - Static Samplers
   - 52



More information about the llvm-branch-commits mailing list