MLIR

Multi-Level IR Compiler Framework

'ptr' Dialect

Pointer dialect

The pointer dialect provides types and operations for representing and interacting with pointer values in MLIR, such as loading and storing values from/to memory addresses.

The dialect’s main type is an opaque pointer (ptr) that can be parameterized by a memory space. This type represents a handle to an object in memory, or target-dependent values like nullptr. Further, the dialect assumes that the minimum addressable unit by a pointer is a byte. However, the dialect does not make assumptions about the size of a byte, which is considered a target-specific property.

Operations 

source

ptr.constant (ptr::ConstantOp) 

Pointer constant operation

Syntax:

operation ::= `ptr.constant` attr-dict $value

The constant operation produces a pointer constant. The attribute must be a typed attribute of pointer type.

Example:

// Create a null pointer
%null = ptr.constant #ptr.null : !ptr.ptr<#ptr.generic_space>

Traits: AlwaysSpeculatableImplTrait, ConstantLike

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes: 

AttributeMLIR TypeDescription
value::mlir::TypedAttr
TypedAttr instance
This interface is used for attributes that have a type. The type of an
attribute is understood to represent the type of the data contained in the
attribute and is often used as the type of a value with this data.

Results: 

ResultDescription
resultpointer type

ptr.from_ptr (ptr::FromPtrOp) 

Casts a !ptr.ptr value to a ptr-like value.

Syntax:

operation ::= `ptr.from_ptr` $ptr (`metadata` $metadata^)? attr-dict `:` type($ptr) `->` type($result)

The from_ptr operation casts a ptr value to a ptr-like object. It’s important to note that:

  • The ptr-like object cannot be a !ptr.ptr.
  • The memory-space of both the ptr and ptr-like object must match.
  • The cast is Pure (no UB and side-effect free).

The optional metadata operand exists to provide any ptr-like metadata that might be required to perform the cast.

Example:

%typed_ptr = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> !my.ptr<f32, #ptr.generic_space>
%memref = ptr.from_ptr %ptr metadata %md : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space>

// Cast the `%ptr` to a memref without utilizing metadata.
%memref = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands: 

OperandDescription
ptrpointer type
metadataPointer metadata type

Results: 

ResultDescription
resultPtrLikeTypeInterface instance

ptr.gather (ptr::GatherOp) 

Gather operation

Syntax:

operation ::= `ptr.gather` $ptrs `,` $mask `,` $passthrough (`alignment` `=` $alignment^)?
              attr-dict `:` type($ptrs) `->` type($result)

The gather operation performs conditional loads from multiple memory locations specified by ptrs based on a mask mask. Elements of the result corresponding to masked-off lanes are taken from the passthrough operand.

The mask operand is a shaped type of i1 elements that must have the same shape as the result type.

Examples:

// Gather values from multiple memory locations
%result = ptr.gather %ptrs, %mask, %passthrough :
  vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xf32>

// Gather with alignment
%result = ptr.gather %ptrs, %mask, %passthrough alignment = 8 :
  vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xf32>

Interfaces: InferTypeOpInterface, MemoryEffectOpInterface

Operands: 

OperandDescription
ptrsA shaped type with value semantics and rank. of pointer type values
maskA shaped type with value semantics and rank. of 1-bit signless integer values
passthroughA shaped type with value semantics and rank. of any type values

Results: 

ResultDescription
resultA shaped type with value semantics and rank. of any type values

ptr.get_metadata (ptr::GetMetadataOp) 

SSA value representing pointer metadata.

Syntax:

operation ::= `ptr.get_metadata` $ptr attr-dict `:` type($ptr)

The get_metadata operation produces an opaque value that encodes the metadata of the ptr-like type.

Example:

%metadata = ptr.get_metadata %memref : memref<?x?xf32>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands: 

OperandDescription
ptrPtrLikeTypeInterface instance

Results: 

ResultDescription
resultPointer metadata type

ptr.load (ptr::LoadOp) 

Syntax:

operation ::= `ptr.load` (`volatile` $volatile_^)? $ptr
              (`atomic` (`syncscope` `(` $syncscope^ `)`)? $ordering^)?
              oilist(
              `nontemporal` $nontemporal |
              `invariant` $invariant |
              `invariant_group` $invariantGroup |
              `alignment` `=` $alignment
              )
              attr-dict `:` qualified(type($ptr)) `->` type($value)

The load operation is used to read from memory. A load may be marked as atomic, volatile, and/or nontemporal.

An atomic load only supports a limited set of value types, and requires an explicit alignment.

Examples:

// A volatile load of a float variable.
%0 = ptr.load volatile %ptr : !ptr.ptr -> f32

// A nontemporal load of a float variable.
%0 = ptr.load %ptr nontemporal : !ptr.ptr -> f32

// An atomic load of an integer variable.
%0 = ptr.load %ptr atomic monotonic alignment = 8 : !ptr.ptr -> i64

See the following link for more details on the meaning of alignment, volatile_, nontemporal, invariant, invariant_group, ordering, and syncscope: https://llvm.org/docs/LangRef.html#load-instruction

Interfaces: MemoryEffectOpInterface

Attributes: 

AttributeMLIR TypeDescription
syncscope::mlir::StringAttrstring attribute

Operands: 

OperandDescription
ptrpointer type

Results: 

ResultDescription
valueany type

ptr.masked_load (ptr::MaskedLoadOp) 

Masked load operation

Syntax:

operation ::= `ptr.masked_load` $ptr `,` $mask `,` $passthrough (`alignment` `=` $alignment^)?
              attr-dict `:` qualified(type($ptr)) `->` type($result)

The masked_load operation performs a conditional load from memory based on a mask. Elements of the result corresponding to masked-off lanes are taken from the passthrough operand.

The mask operand is a shaped type of i1 elements that must have the same shape as the result type.

Examples:

// Masked load with passthrough on vectors
%result = ptr.masked_load %ptr, %mask, %passthrough :
  !ptr.ptr<#ptr.generic_space> -> vector<4xf32>

// Masked load with passthrough on tensors
%result = ptr.masked_load %ptr, %mask, %passthrough :
  !ptr.ptr<#ptr.generic_space> -> tensor<4xf32>

Interfaces: InferTypeOpInterface, MemoryEffectOpInterface

Operands: 

OperandDescription
ptrpointer type
maskA shaped type with value semantics and rank. of 1-bit signless integer values
passthroughA shaped type with value semantics and rank. of any type values

Results: 

ResultDescription
resultA shaped type with value semantics and rank. of any type values

ptr.masked_store (ptr::MaskedStoreOp) 

Masked store operation

Syntax:

operation ::= `ptr.masked_store` $value `,` $ptr `,` $mask (`alignment` `=` $alignment^)? attr-dict `:`
              type($value) `,` qualified(type($ptr))

The masked_store operation performs a conditional store to memory based on a mask. Only elements corresponding to set bits in the mask are written to memory.

The mask operand is a shaped type of i1 elements that must have the same shape as the value being stored.

Examples:

// Masked store
ptr.masked_store %value, %ptr, %mask :
  vector<4xf32>, !ptr.ptr<#ptr.generic_space>

// Masked store with alignment
ptr.masked_store %value, %ptr, %mask alignment = 8 :
  vector<4xf32>, !ptr.ptr<#ptr.generic_space>

Interfaces: MemoryEffectOpInterface

Operands: 

OperandDescription
valueA shaped type with value semantics and rank. of any type values
ptrpointer type
maskA shaped type with value semantics and rank. of 1-bit signless integer values

ptr.ptr_add (ptr::PtrAddOp) 

Pointer add operation

Syntax:

operation ::= `ptr.ptr_add` ($flags^)? $base `,` $offset attr-dict `:` type($base) `,` type($offset)

The ptr_add operation adds an int-like offset to one or more pointers to produce one or more new pointers.

The operation supports both scalar and shaped types with value semantics:

  • When both base and offset are scalar: produces a single new pointer
  • When base is shaped and offset is scalar: adds the same offset to each pointer in the base
  • When base is scalar and offset is shaped: adds the single pointer to each offset in the shaped value
  • When both are shaped: performs element-wise addition (shapes must be compatible)

Example:

// Scalar base and offset
%x_off  = ptr.ptr_add %x, %off : !ptr.ptr<#ptr.generic_space>, i32
%x_off0 = ptr.ptr_add nusw %x, %off : !ptr.ptr<#ptr.generic_space>, i32

// Shaped base with scalar offset
%ptrs_off = ptr.ptr_add %ptrs, %off : vector<4x!ptr.ptr<#ptr.generic_space>>, i32

// Scalar base with shaped offset
%x_offs = ptr.ptr_add %x, %offs : !ptr.ptr<#ptr.generic_space>, vector<4xi32>

// Both base and offset are shaped
%ptrs_offs = ptr.ptr_add %ptrs, %offs : vector<4x!ptr.ptr<#ptr.generic_space>>, vector<4xi32>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface), ViewLikeOpInterface

Effects: MemoryEffects::Effect{}

Operands: 

OperandDescription
baseA shaped type with value semantics and rank. of pointer type values or pointer type
offsetA shaped type with value semantics and rank. of signless integer or index values or signless integer or index

Results: 

ResultDescription
resultA shaped type with value semantics and rank. of pointer type values or pointer type

ptr.ptr_diff (ptr::PtrDiffOp) 

Pointer difference operation

Syntax:

operation ::= `ptr.ptr_diff` ($flags^)? $lhs `,` $rhs attr-dict `:` type($lhs) `->` type($result)

The ptr_diff operation computes the difference between two pointers, returning an integer or index value representing the number of bytes between them.

The operation supports both scalar and shaped types with value semantics:

  • When both operands are scalar: produces a single difference value
  • When both are shaped: performs element-wise subtraction, shapes must be the same

The operation also supports the following flags:

  • none: No flags are set.
  • nuw: No Unsigned Wrap, if the subtraction causes an unsigned overflow (that is: the result would be negative), the result is a poison value.
  • nsw: No Signed Wrap, if the subtraction causes a signed overflow, the result is a poison value.

NOTE: The pointer difference is calculated using an integer type specified by the data layout. The final result will be sign-extended or truncated to fit the result type as necessary.

Example:

// Scalar pointers
%diff = ptr.ptr_diff %p1, %p2 : !ptr.ptr<#ptr.generic_space> -> i64

// Shaped pointers
%diffs = ptr.ptr_diff nsw %ptrs1, %ptrs2 :
  vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xi64>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultShape

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands: 

OperandDescription
lhsA shaped type with value semantics and rank. of pointer type values or pointer type
rhsA shaped type with value semantics and rank. of pointer type values or pointer type

Results: 

ResultDescription
resultA shaped type with value semantics and rank. of signless integer or index values or signless integer or index

ptr.scatter (ptr::ScatterOp) 

Scatter operation

Syntax:

operation ::= `ptr.scatter` $value `,` $ptrs `,` $mask  (`alignment` `=` $alignment^)?
              attr-dict `:` type($value) `,` type($ptrs)

The scatter operation performs a conditional store of a value value to multiple memory locations specified by ptrs based on a mask mask.

Only elements corresponding to set bits in the mask are written to memory. The mask operand is a shaped type of i1 elements that must have the same shape as the value being stored.

Examples:

// Scatter values to multiple memory locations
ptr.scatter %value, %ptrs, %mask :
  vector<4xf32>, vector<4x!ptr.ptr<#ptr.generic_space>>

// Scatter with alignment
ptr.scatter %value, %ptrs, %mask alignment = 8 :
  vector<4xf32>, vector<4x!ptr.ptr<#ptr.generic_space>>

Interfaces: MemoryEffectOpInterface

Operands: 

OperandDescription
valueA shaped type with value semantics and rank. of any type values
ptrsA shaped type with value semantics and rank. of pointer type values
maskA shaped type with value semantics and rank. of 1-bit signless integer values

ptr.store (ptr::StoreOp) 

Syntax:

operation ::= `ptr.store` (`volatile` $volatile_^)? $value `,` $ptr
              (`atomic` (`syncscope` `(` $syncscope^ `)`)? $ordering^)?
              oilist(
              `nontemporal` $nontemporal |
              `invariant_group` $invariantGroup |
              `alignment` `=` $alignment
              )
              attr-dict `:` type($value) `,` qualified(type($ptr))

The store operation is used to write to memory. A store may be marked as atomic, volatile, and/or nontemporal.

An atomic store only supports a limited set of value types, and requires an explicit alignment.

Examples:

// A volatile store of a float variable.
ptr.store volatile %val, %ptr : f32, !ptr.ptr

// A nontemporal store of a float variable.
ptr.store %val, %ptr nontemporal : f32, !ptr.ptr

// An atomic store of an integer variable.
ptr.store %val, %ptr atomic monotonic alignment = 8: i64, !ptr.ptr

See the following link for more details on the meaning of alignment, volatile_, nontemporal, invariant_group, ordering, and syncscope: https://llvm.org/docs/LangRef.html#store-instruction

Interfaces: MemoryEffectOpInterface

Attributes: 

AttributeMLIR TypeDescription
syncscope::mlir::StringAttrstring attribute

Operands: 

OperandDescription
valueany type
ptrpointer type

ptr.to_ptr (ptr::ToPtrOp) 

Casts a ptr-like value to a !ptr.ptr value.

Syntax:

operation ::= `ptr.to_ptr` $ptr attr-dict `:` type($ptr) `->` type($result)

The to_ptr operation casts a ptr-like object to a !ptr.ptr. It’s important to note that:

  • The ptr-like object cannot be a !ptr.ptr.
  • The memory-space of both the ptr and ptr-like object must match.
  • The cast is side-effect free.

Example:

%ptr0 = ptr.to_ptr %my_ptr : !my.ptr<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space>
%ptr1 = ptr.to_ptr %memref : memref<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands: 

OperandDescription
ptrPtrLikeTypeInterface instance

Results: 

ResultDescription
resultpointer type

ptr.type_offset (ptr::TypeOffsetOp) 

Type offset operation

Syntax:

operation ::= `ptr.type_offset` $elementType attr-dict `:` type($result)

The type_offset operation produces an int or index-typed SSA value equal to a target-specific constant representing the offset of a single element of the given type.

Example:

// Return the offset between two f32 stored in memory
%0 = ptr.type_offset f32 : index
// Return the offset between two memref descriptors stored in memory
%1 = ptr.type_offset memref<12 x f64> : i32

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes: 

AttributeMLIR TypeDescription
elementType::mlir::TypeAttrany type attribute

Results: 

ResultDescription
resultsignless integer or index

Attributes 

AddressAttr 

Address attribute

Syntax:

#ptr.address<
  PtrType,   # type
  ::llvm::APInt   # value
>

The address attribute represents a raw memory address, expressed in bytes.

Example:

  #ptr.address<0x1000> : !ptr.ptr<#ptr.generic_space>

Parameters: 

ParameterC++ typeDescription
typePtrType
value::llvm::APInt

GenericSpaceAttr 

Generic memory space

Syntax: #ptr.generic_space

The generic_space attribute defines a memory space attribute with the following properties:

  • Load and store operations are always valid, regardless of the type.
  • Atomic operations are always valid, regardless of the type.
  • Cast operations to generic_space are always valid.

Example:

  #ptr.generic_space : !ptr.ptr<#ptr.generic_space>

NullAttr 

Null pointer attribute

Syntax:

#ptr.null<
  PtrType   # type
>

The null attribute represents a null pointer.

Example:

  #ptr.null

Parameters: 

ParameterC++ typeDescription
typePtrType

SpecAttr 

Ptr data layout spec

Syntax:

#ptr.spec<
  uint32_t,   # size
  uint32_t,   # abi
  uint32_t,   # preferred
  uint32_t   # index
>

Defines the data layout spec for a pointer type. This attribute has 4 fields:

  • [Required] size: size of the pointer in bits.
  • [Required] abi: ABI-required alignment for the pointer in bits.
  • [Required] preferred: preferred alignment for the pointer in bits.
  • [Optional] index: bitwidth that should be used when performing index computations for the type. Setting the field to kOptionalSpecValue, means the field is optional.

Furthermore, the attribute will verify that all present values are divisible by 8 (number of bits in a byte), and that preferred > abi.

Example:

// Spec for a 64 bit ptr, with a required alignment of 64 bits, but with
// a preferred alignment of 128 bits and an index bitwidth of 64 bits.
#ptr.spec<size = 64, abi = 64, preferred = 128, index = 64>

Parameters: 

ParameterC++ typeDescription
sizeuint32_t
abiuint32_t
preferreduint32_t
indexuint32_t

Types 

PtrMetadataType 

Pointer metadata type

Syntax:

!ptr.ptr_metadata<
  PtrLikeTypeInterface   # type
>

The ptr_metadata type represents an opaque-view of the metadata associated with a ptr-like object type.

Note: It’s a verification error to construct a ptr_metadata type using a ptr-like type with no metadata.

Example:

// The metadata associated with a `memref` type.
!ptr.ptr_metadata<memref<f32>>

Parameters: 

ParameterC++ typeDescription
typePtrLikeTypeInterface

PtrType 

Pointer type

Syntax:

!ptr.ptr<
  MemorySpaceAttrInterface   # memorySpace
>

The ptr type is an opaque pointer type. This type typically represents a handle to an object in memory or target-dependent values like nullptr. Pointers are parameterized by a memory space.

Syntax:

pointer ::= `ptr` (`<` memory-space `>`)?
memory-space ::= attribute-value

Parameters: 

ParameterC++ typeDescription
memorySpaceMemorySpaceAttrInterface

Enums 

AtomicBinOp 

Ptr.atomicrmw binary operations

Cases: 

SymbolValueString
xchg0xchg
add1add
sub2sub
_and3_and
nand4nand
_or5_or
_xor6_xor
max7max
min8min
umax9umax
umin10umin
fadd11fadd
fsub12fsub
fmax13fmax
fmin14fmin
uinc_wrap15uinc_wrap
udec_wrap16udec_wrap

AtomicOrdering 

Atomic ordering for LLVM’s memory model

Cases: 

SymbolValueString
not_atomic0not_atomic
unordered1unordered
monotonic2monotonic
acquire3acquire
release4release
acq_rel5acq_rel
seq_cst6seq_cst

PtrAddFlags 

Pointer add flags

Cases: 

SymbolValueString
none0none
nusw1nusw
nuw2nuw
inbounds3inbounds

PtrDiffFlags 

Pointer difference flags

Cases: 

SymbolValueString
none0none
nuw1nuw
nsw2nsw