[llvm] [IR] Add llvm.structured.gep instruction (PR #167883)
Nathan Gauër via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 18 08:34:20 PST 2025
https://github.com/Keenuts updated https://github.com/llvm/llvm-project/pull/167883
>From 0278030ad59c566722808bea9bb3d22bbc3032b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Thu, 13 Nov 2025 15:34:21 +0100
Subject: [PATCH 1/6] [IR] Add llvm.structured.gep instruction
DO NOT MERGE: we still need to agree on the instruction semantic.
For now, this PR only contains the documentation, and the actual
instruction implementation should be added before this can move
forward.
Link to the RFC: https://discourse.llvm.org/t/rfc-adding-instructions-to-to-carry-gep-type-traversal-information/
...
This commit adds the llvm.structured.gep instruction to LLVM.
---
llvm/docs/LangRef.rst | 173 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 173 insertions(+)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 820cc1cfd02ee..ebc6781edcc66 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -12204,6 +12204,179 @@ makes sense:
%A = call <8 x double> @llvm.masked.gather.v8f64.v8p0f64(
<8 x ptr> align 8 %ptrs, <8 x i1> %mask, <8 x double> %passthru)
+.. _i_structured_gep:
+
+'``llvm.structured.gep``' Instruction
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ <result> = call ptr llvm.structured.gep <basetype> poison, ptr <source>, {, [i32/i64] <index> }*
+
+Overview:
+"""""""""
+
+The '``llvm.structured.gep``' intrinsic computes a new pointer address
+resulting of a logical indexing into the ``<source>`` pointer. The returned
+address depends on the indices and the physical layout of %basetype at
+runtime.
+
+Arguments:
+""""""""""
+
+``<ty> basetype``:
+The type of the element pointed by the pointer source. This type will be
+used along with the provided indices and source operands to compute a new
+pointer representing the result of a logical indexing into a basetype
+pointed by source.
+The actual value passed is ignored, and should usualy be ``poison``.
+
+``ptr <source>``:
+A pointer to a valid memory location assumed to be large enough to hold a
+completely laid out value with the same type as ``basetype``. The physical
+layout of ``basetype`` is target dependent, and is not always known at
+compile time.
+
+``[i32/i64] index, ...``:
+Indices used to traverse into the basetype and determine the target element
+this instruction computes an offset for. Indices can be 32-bit or 64-bit
+unsigned integers. Indices being handled one by one, both sizes can be mixed
+in the same instruction. The precision used to compute the resulting pointer
+is target-dependent.
+
+Semantics:
+""""""""""
+
+The ``llvm.structured.gep`` performs a logical traversal of the type
+``basetype`` using the list of provided indices, computing the pointer
+addressing the targeted element/field assuming ``source`` points to a
+physically laid out ``basetype``.
+
+The first index determines which element/field of ``basetype`` is selected,
+computes the pointer to access this element/field assuming ``source`` points
+to the start of ``basetype``.
+This pointer becomes the new ``source``, the current type the new
+``basetype``, and the next indices is consumed until a scalar type is
+reached or all indices are consumed.
+
+All indices must be consumed, and it is illegal to index into a scalar type.
+Meaning the maximum number of indices depends on the depth of the basetype.
+
+Because this instruction performs a logical addressing, all indices are
+assumed to be inbounds. This means it is not possible to access the next
+element in the logical layout by overflowing:
+
+- If the indexed type is a struct with N fields, the index must be an
+ immediate/constant value in the range ``[0; N[``.
+- If indexing into an array or vector, the index can be a variable, but
+ assumed to be inbounds with regards to the current basetype logical layout.
+- If the traversed type is an array or vector of N elements with ``N > 0``,
+ the index is assumed to belong to ``[0; N[``.
+- If the traversed type is an array of size ``0``, the array size is assumed
+ to be known at runtime, and the instruction assumes the index is always
+ inbound.
+
+If the source pointer is poison, the instruction returns poison.
+The resulting pointer belongs to the same address space as ``source``.
+
+This instruction assumes the pointer ``source`` points to a valid memory
+location large enough to contain the physically laid out version ``basetype``.
+This instruction does not dereference any pointer, but requires the source
+operand to be a valid memory location. Meaning this instruction cannot be
+used as an ``offsetof`` by providing ``ptr 0`` as source.
+If the memory location pointed by source is not large enough, using the
+resulting pointer to access memory yields an undefined behavior.
+
+Example:
+""""""""
+
+**Simple case: logical access of a struct field**
+
+.. code-block:: cpp
+
+ struct A { int a, int b, int c, int d };
+ int val = my_struct->b;
+
+Could be translated to:
+
+.. code-block:: llvm
+
+ %A = type { i32, i32, i32, i32 }
+ %src = call ptr @llvm.structured.gep(%A poison, ptr %my_struct, i32 1)
+ %val = load i32, ptr %src
+
+**A more complex case**
+
+This instruction can also be used on the same pointer with different
+basetypes, as long as codegen knows how those are physically laid out.
+Let’s consider the following code:
+
+.. code-block:: cpp
+
+ struct S {
+ uint3 array[5];
+ float my_float;
+ }
+
+ my_struct->array[2].y = 12;
+ int val = my_struct->array[index].y;
+
+
+The frontend knows this struct has a particular physical layout:
+ - an array of 5 vectors or 3 integers, aligned on 16 bytes.
+ - one float at the end, with no alignment requirement, so packed right
+ after the last ``uint3``, which is a ``<3 x uint>``.
+
+.. code-block:: llvm
+
+ %S = type { [4 x { <3 x i32>, i32 }, <3 x i32>, float }
+ ; `-> explicit padding
+ ; -> 4 byte padding between each array element, except
+ ; between the last vector and the float.
+
+The store is simple:
+
+.. code-block:: llvm
+
+ %dst = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 2, i32 0, i32 1)
+ store i32 12, ptr %dst
+
+But the load depends on a dynamic index. This means accessing logically the
+first 4 elements is different than accessing the last:
+
+.. code-block:: llvm
+
+ %firsts = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 %index, i32 0)
+ %last = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 1)
+
+And because :ref:`i_structured_gep` always assumes indexing inbounds, we
+cannot reach the last element by doing:
+
+.. code-block:: llvm
+
+ ; BAD
+ call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 5, i32 0)
+
+If codegen knew nothing about the physical layout of ``%S``, a condition
+would be required to select between ``%firsts`` and ``%last`` depending on
+the value of ``%index``.
+But in our case, the codegen knows that some logical layouts are equivalent
+to others (even if the physical layout is unknown).
+In this context, it knows that the following type can be used to logically
+address every vector in the array, generating the following code:
+
+.. code-block:: llvm
+
+ %T = type [ 5 x { <3 x i32>, i32 } ]
+ %ptr = call ptr @llvm.structured.gep(%T poison, ptr %my_struct, i32 %index, i32 0, i32 1)
+ store i32 12, ptr %ptr
+
+This is however dependent a context codegen has an insight on. This logical
+layout equivalence is not a generic rule.
+
Conversion Operations
---------------------
>From 6a52e68229dd7552738843e5beb63185d498097c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Fri, 14 Nov 2025 11:19:08 +0100
Subject: [PATCH 2/6] add gep explanation
---
llvm/docs/LangRef.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index ebc6781edcc66..4362d01ec56be 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -12219,7 +12219,7 @@ Syntax:
Overview:
"""""""""
-The '``llvm.structured.gep``' intrinsic computes a new pointer address
+The '``llvm.structured.gep``' intrinsic (structured **G**\ et\ **E**\ lement\ **P**\ tr) computes a new pointer address
resulting of a logical indexing into the ``<source>`` pointer. The returned
address depends on the indices and the physical layout of %basetype at
runtime.
>From 61838a3e25118f340312c342cb8814d801dd06e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Fri, 14 Nov 2025 11:19:19 +0100
Subject: [PATCH 3/6] change wording for physical
---
llvm/docs/LangRef.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 4362d01ec56be..bce771fb8c4b8 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -12221,7 +12221,7 @@ Overview:
The '``llvm.structured.gep``' intrinsic (structured **G**\ et\ **E**\ lement\ **P**\ tr) computes a new pointer address
resulting of a logical indexing into the ``<source>`` pointer. The returned
-address depends on the indices and the physical layout of %basetype at
+address depends on the indices and may depend on the layout of %basetype at
runtime.
Arguments:
>From 974e3bbaa29958119cb98d388e04ef7ec6e5e802 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Fri, 14 Nov 2025 11:22:19 +0100
Subject: [PATCH 4/6] remove usually
---
llvm/docs/LangRef.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index bce771fb8c4b8..9398f1a012ddd 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -12232,7 +12232,7 @@ The type of the element pointed by the pointer source. This type will be
used along with the provided indices and source operands to compute a new
pointer representing the result of a logical indexing into a basetype
pointed by source.
-The actual value passed is ignored, and should usualy be ``poison``.
+The actual value passed is ignored, and should be ``poison``.
``ptr <source>``:
A pointer to a valid memory location assumed to be large enough to hold a
>From fdd056016569d5dbb637fe2b2b3701d383125667 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Fri, 14 Nov 2025 11:24:07 +0100
Subject: [PATCH 5/6] move to intrinsic section
---
llvm/docs/LangRef.rst | 347 +++++++++++++++++++++---------------------
1 file changed, 174 insertions(+), 173 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 9398f1a012ddd..e93211c36389f 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -12204,179 +12204,6 @@ makes sense:
%A = call <8 x double> @llvm.masked.gather.v8f64.v8p0f64(
<8 x ptr> align 8 %ptrs, <8 x i1> %mask, <8 x double> %passthru)
-.. _i_structured_gep:
-
-'``llvm.structured.gep``' Instruction
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Syntax:
-"""""""
-
-::
-
- <result> = call ptr llvm.structured.gep <basetype> poison, ptr <source>, {, [i32/i64] <index> }*
-
-Overview:
-"""""""""
-
-The '``llvm.structured.gep``' intrinsic (structured **G**\ et\ **E**\ lement\ **P**\ tr) computes a new pointer address
-resulting of a logical indexing into the ``<source>`` pointer. The returned
-address depends on the indices and may depend on the layout of %basetype at
-runtime.
-
-Arguments:
-""""""""""
-
-``<ty> basetype``:
-The type of the element pointed by the pointer source. This type will be
-used along with the provided indices and source operands to compute a new
-pointer representing the result of a logical indexing into a basetype
-pointed by source.
-The actual value passed is ignored, and should be ``poison``.
-
-``ptr <source>``:
-A pointer to a valid memory location assumed to be large enough to hold a
-completely laid out value with the same type as ``basetype``. The physical
-layout of ``basetype`` is target dependent, and is not always known at
-compile time.
-
-``[i32/i64] index, ...``:
-Indices used to traverse into the basetype and determine the target element
-this instruction computes an offset for. Indices can be 32-bit or 64-bit
-unsigned integers. Indices being handled one by one, both sizes can be mixed
-in the same instruction. The precision used to compute the resulting pointer
-is target-dependent.
-
-Semantics:
-""""""""""
-
-The ``llvm.structured.gep`` performs a logical traversal of the type
-``basetype`` using the list of provided indices, computing the pointer
-addressing the targeted element/field assuming ``source`` points to a
-physically laid out ``basetype``.
-
-The first index determines which element/field of ``basetype`` is selected,
-computes the pointer to access this element/field assuming ``source`` points
-to the start of ``basetype``.
-This pointer becomes the new ``source``, the current type the new
-``basetype``, and the next indices is consumed until a scalar type is
-reached or all indices are consumed.
-
-All indices must be consumed, and it is illegal to index into a scalar type.
-Meaning the maximum number of indices depends on the depth of the basetype.
-
-Because this instruction performs a logical addressing, all indices are
-assumed to be inbounds. This means it is not possible to access the next
-element in the logical layout by overflowing:
-
-- If the indexed type is a struct with N fields, the index must be an
- immediate/constant value in the range ``[0; N[``.
-- If indexing into an array or vector, the index can be a variable, but
- assumed to be inbounds with regards to the current basetype logical layout.
-- If the traversed type is an array or vector of N elements with ``N > 0``,
- the index is assumed to belong to ``[0; N[``.
-- If the traversed type is an array of size ``0``, the array size is assumed
- to be known at runtime, and the instruction assumes the index is always
- inbound.
-
-If the source pointer is poison, the instruction returns poison.
-The resulting pointer belongs to the same address space as ``source``.
-
-This instruction assumes the pointer ``source`` points to a valid memory
-location large enough to contain the physically laid out version ``basetype``.
-This instruction does not dereference any pointer, but requires the source
-operand to be a valid memory location. Meaning this instruction cannot be
-used as an ``offsetof`` by providing ``ptr 0`` as source.
-If the memory location pointed by source is not large enough, using the
-resulting pointer to access memory yields an undefined behavior.
-
-Example:
-""""""""
-
-**Simple case: logical access of a struct field**
-
-.. code-block:: cpp
-
- struct A { int a, int b, int c, int d };
- int val = my_struct->b;
-
-Could be translated to:
-
-.. code-block:: llvm
-
- %A = type { i32, i32, i32, i32 }
- %src = call ptr @llvm.structured.gep(%A poison, ptr %my_struct, i32 1)
- %val = load i32, ptr %src
-
-**A more complex case**
-
-This instruction can also be used on the same pointer with different
-basetypes, as long as codegen knows how those are physically laid out.
-Let’s consider the following code:
-
-.. code-block:: cpp
-
- struct S {
- uint3 array[5];
- float my_float;
- }
-
- my_struct->array[2].y = 12;
- int val = my_struct->array[index].y;
-
-
-The frontend knows this struct has a particular physical layout:
- - an array of 5 vectors or 3 integers, aligned on 16 bytes.
- - one float at the end, with no alignment requirement, so packed right
- after the last ``uint3``, which is a ``<3 x uint>``.
-
-.. code-block:: llvm
-
- %S = type { [4 x { <3 x i32>, i32 }, <3 x i32>, float }
- ; `-> explicit padding
- ; -> 4 byte padding between each array element, except
- ; between the last vector and the float.
-
-The store is simple:
-
-.. code-block:: llvm
-
- %dst = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 2, i32 0, i32 1)
- store i32 12, ptr %dst
-
-But the load depends on a dynamic index. This means accessing logically the
-first 4 elements is different than accessing the last:
-
-.. code-block:: llvm
-
- %firsts = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 %index, i32 0)
- %last = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 1)
-
-And because :ref:`i_structured_gep` always assumes indexing inbounds, we
-cannot reach the last element by doing:
-
-.. code-block:: llvm
-
- ; BAD
- call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 5, i32 0)
-
-If codegen knew nothing about the physical layout of ``%S``, a condition
-would be required to select between ``%firsts`` and ``%last`` depending on
-the value of ``%index``.
-But in our case, the codegen knows that some logical layouts are equivalent
-to others (even if the physical layout is unknown).
-In this context, it knows that the following type can be used to logically
-address every vector in the array, generating the following code:
-
-.. code-block:: llvm
-
- %T = type [ 5 x { <3 x i32>, i32 } ]
- %ptr = call ptr @llvm.structured.gep(%T poison, ptr %my_struct, i32 %index, i32 0, i32 1)
- store i32 12, ptr %ptr
-
-This is however dependent a context codegen has an insight on. This logical
-layout equivalence is not a generic rule.
-
Conversion Operations
---------------------
@@ -15014,6 +14841,180 @@ Semantics:
See the description for :ref:`llvm.stacksave <int_stacksave>`.
+.. _i_structured_gep:
+
+'``llvm.structured.gep``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ <result> = call ptr llvm.structured.gep <basetype> poison, ptr <source>, {, [i32/i64] <index> }*
+
+Overview:
+"""""""""
+
+The '``llvm.structured.gep``' intrinsic (structured **G**\ et\ **E**\ lement\ **P**\ tr) computes a new pointer address
+resulting of a logical indexing into the ``<source>`` pointer. The returned
+address depends on the indices and may depend on the layout of %basetype at
+runtime.
+
+Arguments:
+""""""""""
+
+``<ty> basetype``:
+The type of the element pointed by the pointer source. This type will be
+used along with the provided indices and source operands to compute a new
+pointer representing the result of a logical indexing into a basetype
+pointed by source.
+The actual value passed is ignored, and should be ``poison``.
+
+``ptr <source>``:
+A pointer to a valid memory location assumed to be large enough to hold a
+completely laid out value with the same type as ``basetype``. The physical
+layout of ``basetype`` is target dependent, and is not always known at
+compile time.
+
+``[i32/i64] index, ...``:
+Indices used to traverse into the basetype and determine the target element
+this instruction computes an offset for. Indices can be 32-bit or 64-bit
+unsigned integers. Indices being handled one by one, both sizes can be mixed
+in the same instruction. The precision used to compute the resulting pointer
+is target-dependent.
+
+Semantics:
+""""""""""
+
+The ``llvm.structured.gep`` performs a logical traversal of the type
+``basetype`` using the list of provided indices, computing the pointer
+addressing the targeted element/field assuming ``source`` points to a
+physically laid out ``basetype``.
+
+The first index determines which element/field of ``basetype`` is selected,
+computes the pointer to access this element/field assuming ``source`` points
+to the start of ``basetype``.
+This pointer becomes the new ``source``, the current type the new
+``basetype``, and the next indices is consumed until a scalar type is
+reached or all indices are consumed.
+
+All indices must be consumed, and it is illegal to index into a scalar type.
+Meaning the maximum number of indices depends on the depth of the basetype.
+
+Because this instruction performs a logical addressing, all indices are
+assumed to be inbounds. This means it is not possible to access the next
+element in the logical layout by overflowing:
+
+- If the indexed type is a struct with N fields, the index must be an
+ immediate/constant value in the range ``[0; N[``.
+- If indexing into an array or vector, the index can be a variable, but
+ assumed to be inbounds with regards to the current basetype logical layout.
+- If the traversed type is an array or vector of N elements with ``N > 0``,
+ the index is assumed to belong to ``[0; N[``.
+- If the traversed type is an array of size ``0``, the array size is assumed
+ to be known at runtime, and the instruction assumes the index is always
+ inbound.
+
+If the source pointer is poison, the instruction returns poison.
+The resulting pointer belongs to the same address space as ``source``.
+
+This instruction assumes the pointer ``source`` points to a valid memory
+location large enough to contain the physically laid out version ``basetype``.
+This instruction does not dereference any pointer, but requires the source
+operand to be a valid memory location. Meaning this instruction cannot be
+used as an ``offsetof`` by providing ``ptr 0`` as source.
+If the memory location pointed by source is not large enough, using the
+resulting pointer to access memory yields an undefined behavior.
+
+Example:
+""""""""
+
+**Simple case: logical access of a struct field**
+
+.. code-block:: cpp
+
+ struct A { int a, int b, int c, int d };
+ int val = my_struct->b;
+
+Could be translated to:
+
+.. code-block:: llvm
+
+ %A = type { i32, i32, i32, i32 }
+ %src = call ptr @llvm.structured.gep(%A poison, ptr %my_struct, i32 1)
+ %val = load i32, ptr %src
+
+**A more complex case**
+
+This instruction can also be used on the same pointer with different
+basetypes, as long as codegen knows how those are physically laid out.
+Let’s consider the following code:
+
+.. code-block:: cpp
+
+ struct S {
+ uint3 array[5];
+ float my_float;
+ }
+
+ my_struct->array[2].y = 12;
+ int val = my_struct->array[index].y;
+
+
+The frontend knows this struct has a particular physical layout:
+ - an array of 5 vectors or 3 integers, aligned on 16 bytes.
+ - one float at the end, with no alignment requirement, so packed right
+ after the last ``uint3``, which is a ``<3 x uint>``.
+
+.. code-block:: llvm
+
+ %S = type { [4 x { <3 x i32>, i32 }, <3 x i32>, float }
+ ; `-> explicit padding
+ ; -> 4 byte padding between each array element, except
+ ; between the last vector and the float.
+
+The store is simple:
+
+.. code-block:: llvm
+
+ %dst = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 2, i32 0, i32 1)
+ store i32 12, ptr %dst
+
+But the load depends on a dynamic index. This means accessing logically the
+first 4 elements is different than accessing the last:
+
+.. code-block:: llvm
+
+ %firsts = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 %index, i32 0)
+ %last = call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 1)
+
+And because :ref:`i_structured_gep` always assumes indexing inbounds, we
+cannot reach the last element by doing:
+
+.. code-block:: llvm
+
+ ; BAD
+ call ptr @llvm.structured.gep(%S poison, ptr %my_struct, i32 0, i32 5, i32 0)
+
+If codegen knew nothing about the physical layout of ``%S``, a condition
+would be required to select between ``%firsts`` and ``%last`` depending on
+the value of ``%index``.
+But in our case, the codegen knows that some logical layouts are equivalent
+to others (even if the physical layout is unknown).
+In this context, it knows that the following type can be used to logically
+address every vector in the array, generating the following code:
+
+.. code-block:: llvm
+
+ %T = type [ 5 x { <3 x i32>, i32 } ]
+ %ptr = call ptr @llvm.structured.gep(%T poison, ptr %my_struct, i32 %index, i32 0, i32 1)
+ store i32 12, ptr %ptr
+
+This is however dependent a context codegen has an insight on. This logical
+layout equivalence is not a generic rule.
+
+
.. _int_get_dynamic_area_offset:
'``llvm.get.dynamic.area.offset``' Intrinsic
>From 401bd1691d4f4a0b8aa20af56ee850340c375efc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Tue, 18 Nov 2025 17:34:00 +0100
Subject: [PATCH 6/6] pr feedback
---
llvm/docs/LangRef.rst | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index e93211c36389f..ca8d013a2430a 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14851,7 +14851,10 @@ Syntax:
::
- <result> = call ptr llvm.structured.gep <basetype> poison, ptr <source>, {, [i32/i64] <index> }*
+ declare <ret_type>
+ @llvm.structured.gep(<basetype> poison,
+ ptr <source>
+ {, [i32/i64] <index> }*)
Overview:
"""""""""
@@ -14872,10 +14875,12 @@ pointed by source.
The actual value passed is ignored, and should be ``poison``.
``ptr <source>``:
-A pointer to a valid memory location assumed to be large enough to hold a
-completely laid out value with the same type as ``basetype``. The physical
-layout of ``basetype`` is target dependent, and is not always known at
-compile time.
+A pointer to a memory location assumed to hold a completely laid out value
+with the same type as ``basetype``. The physical layout of ``basetype`` is
+target dependent, and is not always known at compile time.
+The assumption this instruction makes on the memory location is only relevant
+to this particular call. A frontend could possibly emit multiple structured
+GEP with the same source pointer but a different ``basetype``.
``[i32/i64] index, ...``:
Indices used to traverse into the basetype and determine the target element
@@ -14883,6 +14888,8 @@ this instruction computes an offset for. Indices can be 32-bit or 64-bit
unsigned integers. Indices being handled one by one, both sizes can be mixed
in the same instruction. The precision used to compute the resulting pointer
is target-dependent.
+When used to index into a struct, the value only integer constants are
+allowed.
Semantics:
""""""""""
More information about the llvm-commits
mailing list