CIR Dialect Reference#

A high-level dialect for analyzing and optimizing Clang supported languages

Passes#

-cir-call-conv-lowering#

Lower CIR function signatures and call sites to match target ABI

This pass rewrites cir.func signatures and cir.call sites to match the target ABI’s calling convention requirements (extension attributes, struct coercion, sret/byval indirect passing, struct flattening, etc.).

Requirements on the input IR:

  • All C++-specific CIR types must already be lowered to ABI-relevant shapes. In particular, member pointers and method types must have been rewritten by CXXABILowering so that the pass sees only the final ABI representation of each value.

  • The module must carry a dlti.dl_spec attribute so the classifier can query type sizes and alignments.

Two driver modes select how each function’s classification is computed:

  • target=<name> selects an ABI target. The clang pipeline picks the target from the module triple. Supported targets:

    • "x86_64": System V.

    • "amdgpu": AMDGPU.

    • "test": the MLIR test target in mlir/lib/ABI/Targets/Test/. Other targets will be added as the LLVM ABI library ships them.

  • classification-attr=<name> reads a DictionaryAttr named <name> from each cir.func and parses it via the test-target injection helper. Used by tests to inject arbitrary classifications without depending on a real ABI target.

Exactly one of the two options must be set.

Options#

-target              : Target whose ABI rules drive classification
-classification-attr : Function attribute name carrying a pre-built FunctionClassification DictionaryAttr (alternative to target=, used by tests)
-x86-avx-abi-level   : AVX ABI level for the x86_64 target
-x86-target-attr-avx : Let a function's own target features raise its AVX ABI level above x86-avx-abi-level

-cir-canonicalize#

Performs CIR canonicalization

Perform canonicalizations on CIR and removes some redundant operations.

This pass performs basic cleanup and canonicalization transformations that are not intended to affect CIR-to-source fidelity and high-level code analysis passes. Example transformations performed in this pass include empty scope cleanup, trivial try cleanup, redundant branch cleanup, etc. Those more “heavyweight” transformations and those transformations that could significantly affect CIR-to-source fidelity are performed in the cir-simplify pass.

-cir-cxxabi-lowering#

Lower CIR according to C++ ABI requirements

This pass lowers CIR operations and types that represent high-level C/C++ constructs to a more fundamental form according to the target ABI requirements.

See the description of the TargetLowering pass for the difference between this pass and the TargetLowering pass.

-cir-eh-abi-lowering#

Lower flattened CIR EH operations to target-specific ABI form

This pass lowers the ABI-agnostic exception handling operations produced by CFG flattening into an ABI-specific form. Currently only the Itanium C++ ABI is implemented.

For the Itanium ABI, the pass performs the following transformations:

  • Replaces cir.eh.initiate with cir.eh.inflight_exception

  • Replaces cir.eh.dispatch with cir.eh.typeid + comparison chains

  • Removes cir.begin_cleanup and cir.end_cleanup operations

  • Replaces cir.begin_catch with a call to __cxa_begin_catch

  • Replaces cir.end_catch with a call to __cxa_end_catch

  • Replaces cir.resume with cir.resume.flat

  • Sets the personality function attribute on functions that require EH

If a non-Itanium ABI is specified, the pass emits a diagnostic indicating that the target is not yet implemented.

-cir-flatten-cfg#

Produces flatten CFG

This pass transforms CIR by inlining all the nested regions. Thus, the following conditions are true after the pass applied:

  • there are no nested regions in any function body

  • all the blocks in a function belong to the parent region In other words, this pass removes such CIR operations like IfOp, LoopOp, ScopeOp and etc. and produces a flat CIR.

-cir-goto-solver#

Replaces goto operations with branches

This pass transforms CIR and replaces goto-s with branch operations to the proper blocks.

-cir-hoist-allocas#

Hoist allocas to the entry of the function

This pass hoist all non-dynamic allocas to the entry of the function. This is helpful for later code generation.

-cir-idiom-recognizer#

Raise calls to C/C++ libraries to CIR operations

This pass recognizes idiomatic C++ usage and captures information about C++ standard library containers, library functions calls, and types into CIR operations, attributes and types.

-cir-lib-opt#

Optimize C/C++ library calls

This pass applies transformations on C/C++ standard library idioms, such as library function calls and structs raised to CIR operations using the cir-idiom-recognize pass.

-cir-lowering-prepare#

Lower to more fine-grained CIR operations before lowering to other dialects

This pass does preparation work for lowering to other dialects. For example, it may expand the global variable initialziation in a more ABI-friendly form.

-cir-simplify#

Performs CIR simplification and code optimization

The pass performs semantics-preserving code simplifications and optimizations on CIR while maintaining strict program correctness.

Unlike the cir-canonicalize pass, these transformations may reduce the IR’s structural similarity to the original source code as a trade-off for improved code quality. This can affect debugging fidelity by altering intermediate representations of folded expressions, hoisted operations, and other optimized constructs.

Example transformations include ternary expression folding and code hoisting while preserving program semantics.

-cir-target-lowering#

Lower CIR to a target-specific form

This pass lowers CIR operations from a target-agnostic form to a target-specific form without considering ABI requirements.

CIR has three passes in its lowering pipeline that transform input CIR according to target-specific requirements, scheduled in the pipeline by the following order:

  1. The TargetLowering pass.

  2. The CXXABILowering pass.

  3. The CallConvLowering pass.

The TargetLowering pass acts more like a legalization pass. It ensures every operation in CIR conforms to the target’s constraints. An example would be the handling of synchronization scopes of atomic operations. The x86 family of targets only support a system-wide synchronization scope, thus any atomic operations with a different synchronization scope would be transformed to use the system-wide scope in this pass.

The CXXABILowering pass and the CallConvLowering pass transform the CIR according to the target’s ABI requirements. The former handles all ABI-related lowering except for calling convention handling, which is handled specifically in the latter. Example transformations that the CXXABILowering pass could make include:

  • Replace C/C++ types that have an ABI-defined layout with more fundamental types corresponding to the ABI requirements. For example, the layout of the pointer-to-data-member type in C++ is ABI-defined, thus the CXXABILowering pass would replace all occurrences of this type according to the ABI requirements. With a typical target ABI, it will be replaced by the ptrdiff_t type since this is the type most ABIs use for the layout of the pointer-to-data-member type.

  • Replace CIR operations that have ABI-dependent implementations with more fundamental operations. For example, the dynamic_cast operator in C++ is implemented in an ABI-dependent way, typically by calling into a library function provided by the implementation. The CXXABILowering pass would thus replace all cir.dyn_cast operations with corresponding library function calls.

The CallConvLowering pass is dedicated to handle calling conventions. It rewrites function signatures according to calling convention requirements, and updates function body and call sites accordingly. For example, when passing a large struct by value in C/C++, most ABIs require passing a pointer to a copy of the struct instead. Thus, the CallConvLowering pass would rewrite function signatures that take a value of a large struct type to take a pointer to the struct type instead, and update the function body and the call sites accordingly.

Operations#

cir.abs (::cir::AbsOp)#

Computes the absolute value of a signed integer

Syntax:

operation ::= `cir.abs` $src ( `min_is_poison` $min_is_poison^ )? `:` type($src) attr-dict

cir.abs computes the absolute value of a signed integer or vector of signed integers.

The min_is_poison attribute indicates whether the result value is a poison value if the argument is statically or dynamically the minimum value for the type.

Example:

  %0 = cir.const #cir.int<-42> : s32i
  %1 = cir.abs %0 min_is_poison : s32i
  %2 = cir.abs %3 : !cir.vector<!s32i x 4>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
min_is_poison::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

src

signed integer or vector of signed integer type

Results:#

Result

Description

result

signed integer or vector of signed integer type

cir.acos (::cir::ACosOp)#

Computes the arcus cosine of the specified value

Syntax:

operation ::= `cir.acos` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.acoscomputes the arcus cosine of a given value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.add (::cir::AddOp)#

Integer addition

Syntax:

operation ::= `cir.add` (`nsw` $no_signed_wrap^)?
              (`nuw` $no_unsigned_wrap^)?
              (`sat` $saturated^)?
              $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.add operation performs addition on integer operands. Both operands and the result must have the same integer, vector-of-integer or matrix-of-integer type.

The optional nsw (no signed wrap) and nuw (no unsigned wrap) unit attributes indicate that the result is poison if signed or unsigned overflow occurs, respectively. The optional sat (saturated) attribute clamps the result to the type’s representable range instead of wrapping. The nsw/nuw flags and sat are mutually exclusive.

Example:

%0 = cir.add %a, %b : !s32i
%1 = cir.add nsw %a, %b : !s32i
%2 = cir.add nuw %a, %b : !u32i
%3 = cir.add sat %a, %b : !s32i
%4 = cir.add %va, %vb : !cir.vector<4 x !s32i>
%5 = cir.add %ma, %mb : !cir.matrix<3 x 3 x !s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

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

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

integer or vector/matrix of integer type

rhs

integer or vector/matrix of integer type

Results:#

Result

Description

result

integer or vector/matrix of integer type

cir.add.overflow (::cir::AddOverflowOp)#

Integer addition with overflow checking

Syntax:

operation ::= `cir.add.overflow` $lhs `,` $rhs `:` qualified(type($lhs)) `->` qualified(type($result))
              attr-dict

cir.add.overflow performs addition with overflow checking on integral operands. See CIR_BinOpOverflow for semantics.

Example:

%result, %overflow = cir.add.overflow %a, %b : !u32i -> !u32i
%result, %overflow = cir.add.overflow %a, %b : !cir.int<s, 33> -> !s32i
%result, %overflow = cir.add.overflow %a, %b : !s32i -> !cir.bool

Traits: AlwaysSpeculatableImplTrait, Commutative, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

Integer type with arbitrary precision up to a fixed limit

rhs

Integer type with arbitrary precision up to a fixed limit

Results:#

Result

Description

result

integer or boolean type

overflow

CIR bool type

cir.address_of_return_address (::cir::AddrOfReturnAddrOp)#

The place stores the return address of the current function

Syntax:

operation ::= `cir.address_of_return_address` attr-dict `:` qualified(type($result))

Represents a call to builtin function _AddressOfReturnAddress in CIR. This builtin function returns a pointer to the place in the stack frame where the return address of the current function is stored.

Examples:

%addr = address_of_return_address() : !cir.ptr<!u8i>

Results:#

Result

Description

result

CIR pointer type

cir.alloc.exception (::cir::AllocExceptionOp)#

Allocates an exception according to Itanium ABI

Syntax:

operation ::= `cir.alloc.exception` $size `->` qualified(type($addr)) attr-dict

Implements a slightly higher level __cxa_allocate_exception:

void *__cxa_allocate_exception(size_t thrown_size);

If the operation fails, the program terminates rather than throw.

Example:

// if (b == 0) {
//   ...
//   throw "...";
cir.if %10 {
    %11 = cir.alloc_exception 8 -> !cir.ptr<!void>
    ... // store exception content into %11
    cir.throw %11 : !cir.ptr<!cir.ptr<!u8i>>, ...

Attributes:#

AttributeMLIR TypeDescription
size::mlir::IntegerAttr64-bit signless integer attribute

Results:#

Result

Description

addr

CIR pointer type

cir.alloca (::cir::AllocaOp)#

Defines a scope-local variable

Syntax:

operation ::= `cir.alloca` $name
              `align` `(` $alignment `)`
              oilist( `init`              $init
              | `const`             $constant
              | `cleanup_dest_slot` $cleanup_dest_slot)
              (`size` `(` $dynAllocSize^ `)`)? `:` qualified(type($addr))
              ($annotations^)? attr-dict

The cir.alloca operation defines a scope-local variable.

The presence of the const attribute indicates that the local variable is declared with C/C++ const keyword.

The dynAllocSize specifies the size to dynamically allocate on the stack and ignores the allocation size based on the original type. This is useful when handling VLAs or the alloca builtin and is omitted when declaring regular local variables.

The cleanup_dest_slot attribute indicates that this was a temporary alloca generated by the compiler to handle cleanup exit dispatching.

The result type is a pointer to the input’s type.

Example:

// int count;
%0 = cir.alloca "count" align(4) : !cir.ptr<i32>

// int *ptr;
%1 = cir.alloca "ptr" align(8) : !cir.ptr<!cir.ptr<i32>>
...

Interfaces: PromotableAllocationOpInterface

Attributes:#

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
init::mlir::UnitAttrunit attribute
constant::mlir::UnitAttrunit attribute
cleanup_dest_slot::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
annotations::mlir::ArrayAttrarray of cir.annotation attributes

Operands:#

Operand

Description

dynAllocSize

64-bit unsigned integer

Results:#

Result

Description

addr

CIR pointer type

cir.and (::cir::AndOp)#

Bitwise AND

Syntax:

operation ::= `cir.and` $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.and operation performs a bitwise AND on integer operands. Both operands and the result must have the same integer type.

Example:

%0 = cir.and %a, %b : !s32i
%1 = cir.and %a, %b : !cir.bool

Traits: Commutative, Idempotent, SameOperandsAndResultType

Interfaces: BinaryOpInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

integer, boolean, or vector of bool or integer

rhs

integer, boolean, or vector of bool or integer

Results:#

Result

Description

result

integer, boolean, or vector of bool or integer

cir.array.ctor (::cir::ArrayCtor)#

Initialize array elements with C++ constructors

Syntax:

operation ::= `cir.array.ctor` $addr (`,` $num_elements^)? `:` qualified(type($addr))
              (`,` type($num_elements)^)? $body
              (`partial_dtor` $partial_dtor^)?
              attr-dict

Initialize each array element using the same C++ constructor. This operation has a body region and an optional partial_dtor region. Both regions have a single block whose argument is a pointer to the current array element.

The body region contains the constructor call for one element.

The partial_dtor region, when non-empty, contains the destructor call for one element. During lowering, it is used to build a cleanup that destroys already-constructed elements if a constructor throws. When the element type has a trivial destructor or exceptions are disabled, the partial_dtor region is left empty.

When num_elements is absent, addr must be a pointer to a fixed-size CIR array type and the element count is derived from that array type.

When num_elements is present, addr is a pointer to the first element and num_elements provides the runtime element count (for example new T[n]).

Examples:

// Fixed size without partial destructor:
cir.array.ctor(%0 : !cir.ptr<!cir.array<!rec_S x 42>>) {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_ctor(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Variable size without partial destructor:
cir.array.ctor(%ptr, %n : !cir.ptr<!rec_S>, !u64i) {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_ctor(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Fixed size with partial destructor:
cir.array.ctor(%0 : !cir.ptr<!cir.array<!rec_S x 42>>) {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_ctor(%arg0) : (!cir.ptr<!rec_S>) -> ()
} partial_dtor {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_dtor(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

Traits: SingleBlockImplicitTerminator<cir::YieldOp>, SingleBlock

Operands:#

Operand

Description

addr

pointer type

num_elements

integer type

cir.array.dtor (::cir::ArrayDtor)#

Destroy array elements with C++ destructors

Syntax:

operation ::= `cir.array.dtor` $addr (`,` $num_elements^)? `:` qualified(type($addr))
              (`,` type($num_elements)^)? (`dtor_may_throw` $dtor_may_throw^)? $body
              attr-dict

Destroy each array element using the same C++ destructor. This operation has one region with one block whose argument is a pointer to the current array element.

When num_elements is absent, addr must be a pointer to a fixed-size CIR array type and the element count is derived from that array type.

When num_elements is present, addr is a pointer to the first element and num_elements provides the runtime element count (e.g. from an array cookie for delete[]).

When dtor_may_throw is present, the element destructor call may throw an exception.

Elements are destroyed in reverse order.

Examples:

// Fixed-size (stack array, global):
cir.array.dtor %0 : !cir.ptr<!cir.array<!rec_S x 42>> {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @_ZN1SD1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Dynamic count (delete[] with destructor):
cir.array.dtor %ptr, %n : !cir.ptr<!rec_S>, !u64i {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @_ZN1SD1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Dynamic count (delete[] with throwing destructor):
cir.array.dtor %ptr, %n : !cir.ptr<!rec_S>, !u64i dtor_may_throw {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @_ZN1SD1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

Traits: SingleBlockImplicitTerminator<cir::YieldOp>, SingleBlock

Operands:#

Operand

Description

addr

pointer type

num_elements

integer type

cir.asin (::cir::ASinOp)#

Computes the arcus sine of the specified value

Syntax:

operation ::= `cir.asin` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.asincomputes the arcus sine of a given value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.asm (::cir::InlineAsmOp)#

The cir.asm operation represents C/C++ asm inline.

CIR constraints strings follow the same rules that are established for the C level assembler constraints with several differences caused by clang::AsmStmt processing.

Thus, numbers that appears in the constraint string may also refer to:

  • the output variable index referenced by the input operands.

  • the index of early-clobber operand

Operand attributes are a storage, where each element corresponds to the operand with the same index. The first index relates to the operation result (if any). The operands themselves are stored as VariadicOfVariadic in the following order: output, input and then in/out operands. When several output operands are present, the result type may be represented as an anonymous record type.

Example:

__asm__("foo" : : : );
__asm__("bar $42 %[val]" : [val] "=r" (x), "+&r"(x));
__asm__("baz $42 %[val]" : [val] "=r" (x), "+&r"(x) : "[val]"(y));
!rec_22anon2E022 = !cir.record<struct "anon.0" {!cir.int<s, 32>, !cir.int<s, 32>}>
!rec_22anon2E122 = !cir.record<struct "anon.1" {!cir.int<s, 32>, !cir.int<s, 32>}>
...
%0 = cir.alloca "x" align(4) init : !cir.ptr<!s32i>
%1 = cir.alloca "y" align(4) init : !cir.ptr<!s32i>
...
%2 = cir.load %0 : !cir.ptr<!s32i>, !s32i
%3 = cir.load %1 : !cir.ptr<!s32i>, !s32i

cir.asm(x86_att,
  out = [],
  in = [],
  in_out = [],
  {"foo" "~{dirflag},~{fpsr},~{flags}"}) side_effects

cir.asm(x86_att,
  out = [],
  in = [],
  in_out = [%2 : !s32i],
  {"bar $$42 $0" "=r,=&r,1,~{dirflag},~{fpsr},~{flags}"}) -> !rec_22anon2E022

cir.asm(x86_att,
  out = [],
  in = [%3 : !s32i],
  in_out = [%2 : !s32i],
  {"baz $$42 $0" "=r,=&r,0,1,~{dirflag},~{fpsr},~{flags}"}) -> !rec_22anon2E122

Interfaces: MemoryEffectOpInterface

Attributes:#

AttributeMLIR TypeDescription
asm_string::mlir::StringAttrstring attribute
constraints::mlir::StringAttrstring attribute
side_effects::mlir::UnitAttrunit attribute
asm_flavor::cir::AsmFlavorAttrATT or Intel
operand_attrs::mlir::ArrayAttrarray attribute
operands_segments::mlir::DenseI32ArrayAttri32 dense array attribute

Operands:#

Operand

Description

asm_operands

variadic of any non-token type

Results:#

Result

Description

res

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.assume (::cir::AssumeOp)#

Tell the optimizer that a boolean value is true

Syntax:

operation ::= `cir.assume` $predicate custom<AssumeBundle>($bundle_kind, $bundle_args,
              type($bundle_args))
              `:` type($predicate) attr-dict

The cir.assume operation takes a single boolean predicate as its first argument and does not have any results. The operation tells the optimizer that the predicate is always true.

An optional operand bundle carries additional assumption metadata, mirroring MLIR LLVM dialect’s llvm.assume operand bundles (mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td). The bundle kind is a AssumeBundleKind enum; bundle operands follow the kind keyword in the assembly form. For example, __builtin_assume_dereferenceable(p, n) lowers to cir.assume %true dereferenceable(%p, %n : !cir.ptr<!void>, !u64i) : !cir.bool, which in turn lowers to call void @llvm.assume(i1 true) [ "dereferenceable"(ptr, i64) ].

This operation corresponds to the __assume / __builtin_assume builtins (no bundle), as well as __builtin_assume_aligned (align bundle), __builtin_assume_separate_storage (separate_storage bundle), and __builtin_assume_dereferenceable (dereferenceable bundle).

Attributes:#

AttributeMLIR TypeDescription
bundle_kind::cir::AssumeBundleKindAttrkind of cir.assume operand bundle

Operands:#

Operand

Description

predicate

CIR bool type

bundle_args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.atan (::cir::ATanOp)#

Computes the floating-point arcus tangent value

Syntax:

operation ::= `cir.atan` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.atan computes the arcus tangent of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.atan2 (::cir::ATan2Op)#

Computes the arc tangent of y/x

Syntax:

operation ::= `cir.atan2` $lhs `,` $rhs `:` qualified(type($lhs))
              (`fenv` `` $fenv^)? attr-dict

cir.atan2 computes the arc tangent of the first operand divided by the second operand, using the signs of both to determine the quadrant.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.atomic.clear (::cir::AtomicClearOp)#

Atomic clear

Syntax:

operation ::= `cir.atomic.clear` enum($mem_order) $ptr
              (`align` `(` $alignment^ `)`)?
              (`volatile` $is_volatile^)?
              `:` qualified(type($ptr)) attr-dict

C/C++ atomic clear operation. Implements the builtin function __atomic_clear.

The operation takes as its only operand a pointer to an 8-bit signed integer. The operation atomically sets the integer to zero.

Example:

  cir.atomic.clear seq_cst %ptr : !cir.ptr<!s8i>

Attributes:#

AttributeMLIR TypeDescription
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

ptr

pointer to 8-bit signed integer

cir.atomic.cmpxchg (::cir::AtomicCmpXchgOp)#

Atomic compare and exchange

Syntax:

operation ::= `cir.atomic.cmpxchg` (`weak` $weak^)?
              `success` `(` enum($succ_order) `)` `failure` `(` enum($fail_order) `)`
              `syncscope` `(` enum($sync_scope) `)`
              $ptr `,` $expected `,` $desired
              (`align` `(` $alignment^ `)`)?
              (`volatile` $is_volatile^)?
              `:` functional-type(operands, results) attr-dict

C/C++ atomic compare and exchange operation. Implements builtins like __atomic_compare_exchange_n and __atomic_compare_exchange.

This operation takes three arguments: a pointer ptr and two values expected and desired. This operation compares the value of the object pointed-to by ptr with expected, and if they are equal, it sets the value of the object to desired.

The succ_order attribute gives the memory order of this atomic operation when the exchange takes place. The fail_order attribute gives the memory order of this atomic operation when the exchange does not take place.

The sync_scope attribute specifies the synchronization scope for this atomic operation.

The weak attribute is a boolean flag that indicates whether this is a “weak” compare-and-exchange operation. A weak compare-and-exchange operation allows “spurious failures”, meaning that be treated as if the comparison failed and not exchange values even if *ptr and expected indeed compare equal.

The type of expected and desired must be the same. The pointee type of ptr must be the same as the type of expected and desired.

This operation has two results. The first result old gives the old value of the object pointed-to by ptr, regardless of whether the exchange actually took place. The second result success is a boolean flag indicating whether the exchange actually took place.

Example:

%old, %success = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire)
    syncscope(system) %ptr, %expected, %desired
    : (!cir.ptr<!u64i>, !u64i, !u64i) -> (!u64i, !cir.bool)

Interfaces: InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
succ_order::cir::MemOrderAttrMemory order according to C++11 memory model
fail_order::cir::MemOrderAttrMemory order according to C++11 memory model
sync_scope::cir::SyncScopeKindAttrsync scope kind
alignment::mlir::IntegerAttr64-bit signless integer attribute
weak::mlir::UnitAttrunit attribute
is_volatile::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

ptr

CIR pointer type

expected

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

desired

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

old

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

success

CIR bool type

cir.atomic.fence (::cir::AtomicFenceOp)#

Atomic thread fence

Syntax:

operation ::= `cir.atomic.fence` (`syncscope` `(` enum($syncscope)^ `)`)? enum($ordering) attr-dict

C/C++ Atomic thread fence synchronization primitive. Implements the builtin __atomic_thread_fence which enforces memory ordering constraints across threads within the specified synchronization scope.

This handles all variations including:

  • __atomic_thread_fence

  • __atomic_signal_fence

  • __c11_atomic_thread_fence

  • __c11_atomic_signal_fence

Example:

  cir.atomic.fence syncscope(system) seq_cst
  cir.atomic.fence syncscope(single_thread) seq_cst

Attributes:#

AttributeMLIR TypeDescription
ordering::cir::MemOrderAttrMemory order according to C++11 memory model
syncscope::cir::SyncScopeKindAttrsync scope kind

cir.atomic.fetch (::cir::AtomicFetchOp)#

Atomic fetch-and-update operation

Syntax:

operation ::= `cir.atomic.fetch` enum($binop) enum($mem_order)
              `syncscope` `(` enum($sync_scope) `)`
              (`fetch_first` $fetch_first^)?
              $ptr `,` $val
              (`volatile` $is_volatile^)?
              `:` `(` qualified(type($ptr)) `,` qualified(type($val)) `)`
              `->` type($result) attr-dict

C/C++ atomic fetch-and-update operation. This operation implements the C/C++ builtin functions __atomic_<binop>_fetch, __atomic_fetch_<binop>, and __c11_atomic_fetch_<binop>, where <binop> is one of the following binary opcodes: add, sub, and, xor, or, nand, max, min, uinc_wrap, udec_wrap, maximum, minimum, maximum_num, and minimum_num.

This operation takes 2 arguments: a pointer ptr and a value val. The type of val must match the pointee type of ptr. If the binary operation is add, sub, max, or min, the type of val may either be an integer type or a floating-point type. Otherwise, val must be an integer.

This operation atomically loads the value from ptr, performs the binary operation as indicated by binop on the loaded value and val, and stores the result back to ptr. If the fetch_first flag is present, the result of this operation is the old value loaded from ptr before the binary operation. Otherwise, the result of this operation is the result of the binary operation.

The primary difference between max, maximum, and maximum_num is how they handle floating-point inputs:

  • max on floating-point inputs corresponds to the atomicrmw fmax LLVM instruction.

  • maximum corresponds to the atomicrmw fmaximum LLVM instruction.

  • maximum_num corresponds to the atomicrmw fmaximumnum LLVM instruction.

Similar rules apply to min, minimum, and minimum_num. See the reference for the LLVM instruction atomicrmw for more information.

The operation maximum, minimum, maximum_num, and minimum_num only accept floating-point inputs.

Example:

: (!cir.ptr<!s32i>, !s32i) -> !s32i

Interfaces: InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
binop::cir::AtomicFetchKindAttrBinary opcode for atomic fetch-and-update operations
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
sync_scope::cir::SyncScopeKindAttrsync scope kind
is_volatile::mlir::UnitAttrunit attribute
fetch_first::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

ptr

pointer to integer or floating point type

val

integer or floating point type

Results:#

Result

Description

result

integer or floating point type

cir.atomic.test_and_set (::cir::AtomicTestAndSetOp)#

Atomic test and set

Syntax:

operation ::= `cir.atomic.test_and_set` enum($mem_order) $ptr
              (`align` `(` $alignment^ `)`)?
              (`volatile` $is_volatile^)?
              `:` qualified(type($ptr)) `->` qualified(type($result)) attr-dict

C/C++ atomic test and set operation. Implements the builtin function __atomic_test_and_set.

The operation takes as its only operand a pointer to an 8-bit signed integer. The operation atomically set the integer to an implementation- defined non-zero “set” value. The result of the operation is a boolean value indicating whether the previous value of the integer was the “set” value.

Example:

  %res = cir.atomic.test_and_set seq_cst %ptr : !cir.ptr<!s8i> -> !cir.bool

Interfaces: InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

ptr

pointer to 8-bit signed integer

Results:#

Result

Description

result

CIR bool type

cir.atomic.xchg (::cir::AtomicXchgOp)#

Atomic exchange

Syntax:

operation ::= `cir.atomic.xchg` enum($mem_order)
              `syncscope` `(` enum($sync_scope) `)`
              (`volatile` $is_volatile^)?
              $ptr `,` $val
              `:` functional-type(operands, results) attr-dict

C/C++ atomic exchange operation. This operation implements the C/C++ builtin function __atomic_exchange, __atomic_exchange_n, and __c11_atomic_exchange.

This operation takes two arguments: a pointer ptr and a value val. The operation atomically replaces the value of the object pointed-to by ptr with val, and returns the original value of the object.

Example:

%res = cir.atomic.xchg seq_cst %ptr, %val : !cir.ptr<!u64i> -> !u64i

Interfaces: InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
sync_scope::cir::SyncScopeKindAttrsync scope kind
is_volatile::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

ptr

CIR pointer type

val

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.await (::cir::AwaitOp)#

Wraps C++ co_await implicit logic

Syntax:

operation ::= `cir.await` `(` enum($kind) `,`
              `ready` `:` $ready `,`
              `suspend` `:` $suspend `,`
              `resume` `:` $resume `,`
              `)`
              attr-dict

The under the hood effect of using C++ co_await expr roughly translates to:

// co_await expr;

auto &&x = CommonExpr();
if (!x.await_ready()) {
   ...
   x.await_suspend(...);
   ...
}
x.await_resume();

cir.await represents this logic by using 3 regions:

  • ready: covers veto power from x.await_ready()

  • suspend: wraps actual x.await_suspend() logic

  • resume: handles x.await_resume()

Breaking this up in regions allows individual scrutiny of conditions which might lead to folding some of them out. Lowerings coming out of CIR, e.g. LLVM, should use the suspend region to track more lower level codegen (e.g. intrinsic emission for coro.save/coro.suspend).

There are also 4 flavors of cir.await available:

  • init: compiler generated initial suspend via implicit co_await.

  • user: also known as normal, representing a user written co_await.

  • yield: user written co_yield expressions.

  • final: compiler generated final suspend via implicit co_await.

  cir.scope {
    ... // auto &&x = CommonExpr();
    cir.await(user, ready : {
      ... // x.await_ready()
    }, suspend : {
      ... // x.await_suspend()
    }, resume : {
      ... // x.await_resume()
    })
  }

Note that resulution of the common expression is assumed to happen as part of the enclosing await scope.

Traits: HasAncestor<CoroutineOp>, NoRegionArguments, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
kind::cir::AwaitKindAttrawait kind

cir.base_class_addr (::cir::BaseClassAddrOp)#

Get the base class address for a class/struct

Syntax:

operation ::= `cir.base_class_addr` (`nonnull` $assume_not_null^)?
              $src_addr ` ` `[` $offset `]`
              `:` qualified(type($src_addr)) `->` qualified(type($result))
              attr-dict

The cir.base_class_addr operaration gets the address of a particular non-virtual base class given a derived class pointer. The offset in bytes of the base class must be passed in, since it is easier for the front end to calculate that than the MLIR passes. The operation contains a flag for whether or not the operand may be nullptr. That depends on the context and cannot be known by the operation, and that information affects how the operation is lowered.

The validity of the relationship of derived and base cannot yet be verified. If the target class is not a valid base class for the object, the behavior is undefined.

Example:

struct Base { };
struct Derived : Base { };
Derived d;
Base& b = d;

will generate

%3 = cir.base_class_addr nonnull %1 [0] : !cir.ptr<!rec_Derived> -> !cir.ptr<!rec_Base>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute
assume_not_null::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

src_addr

CIR pointer type

Results:#

Result

Description

result

CIR pointer type

cir.base_data_member (::cir::BaseDataMemberOp)#

Cast a derived class data member pointer to a base class data member pointer

Syntax:

operation ::= `cir.base_data_member` $src `[` $offset `]` `:` qualified(type($src)) `->` qualified(type($result)) attr-dict

The cir.base_data_member operation casts a data member pointer of type T Derived::* to a data member pointer of type T Base::*, where Base is an accessible non-ambiguous non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

Operands:#

Operand

Description

src

CIR type that represents a pointer-to-data-member in C++

Results:#

Result

Description

result

CIR type that represents a pointer-to-data-member in C++

cir.base_method (::cir::BaseMethodOp)#

Cast a derived class pointer-to-member-function to a base class pointer-to-member-function

Syntax:

operation ::= `cir.base_method` $src `[` $offset `]` `:` qualified(type($src))
              `->` qualified(type($result)) attr-dict

The cir.base_method operation casts a pointer-to-member-function of type Ret (Derived::*)(Args) to a pointer-to-member-function of type Ret (Base::*)(Args), where Base is a non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Example:

%1 = cir.base_method %0 [16] : !cir.method<!cir.func<(!s32i)> in !rec_Derived> -> !cir.method<!cir.func<(!s32i)> in !rec_Base>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

Operands:#

Operand

Description

src

CIR type that represents C++ pointer-to-member-function type

Results:#

Result

Description

result

CIR type that represents C++ pointer-to-member-function type

cir.begin_catch (::cir::BeginCatchOp)#

Begin a catch handler

Syntax:

operation ::= `cir.begin_catch` $eh_token `:` type($eh_token) `->` `(` type($catch_token) `,`
              qualified(type($exn_ptr)) `)` attr-dict

cir.begin_catch marks the beginning of a catch handler. It takes a !cir.eh_token representing the inflight exception and returns a !cir.catch_token along with a pointer to the exception object.

The catch token must be passed to the corresponding cir.end_catch operation. The exception pointer points to the caught exception object and can be used to access the exception value.

For catch(...) (catch all), the exception pointer type is !cir.ptr<!void>.

In the high-level CIR representation, this operation appears as the first operation in a catch handler region of a cir.try operation, taking the region’s !cir.eh_token argument. In the flattened CIR representation, it appears in a catch block, taking the block’s !cir.eh_token argument.

Example:

// High-level form (inside cir.try catch handler region):
} catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%eh_token : !cir.eh_token) {
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
  cir.cleanup.scope {
    // Handle exception...
    cir.yield
  } cleanup eh {
    cir.end_catch %catch_token : !cir.catch_token
    cir.yield
  }
  cir.yield
}

// Flattened form (inside a catch block):
^catch_int(%eh_token : !cir.eh_token):
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
  // Handle exception...
  cir.end_catch %catch_token : !cir.catch_token
  cir.br ^continue

Operands:#

Operand

Description

eh_token

CIR exception handling token type

Results:#

Result

Description

catch_token

CIR catch token type

exn_ptr

CIR pointer type

cir.begin_cleanup (::cir::BeginCleanupOp)#

Begin a cleanup block during exception unwinding

Syntax:

operation ::= `cir.begin_cleanup` $eh_token `:` type($eh_token) `->` type($cleanup_token) attr-dict

cir.begin_cleanup marks the beginning of a cleanup handler during exception unwinding. It takes a !cir.eh_token and returns a !cir.cleanup_token that must be passed to the corresponding cir.end_cleanup operation.

The cleanup code between cir.begin_cleanup and cir.end_cleanup will be executed during exception unwinding before control is transferred to the exception dispatcher.

Example:

^cleanup(%eh_token : !cir.eh_token):
  %cleanup_token = cir.begin_cleanup %eh_token : !cir.eh_token
                                               -> !cir.cleanup_token
  cir.call @destructor() : () -> ()
  cir.end_cleanup %cleanup_token : !cir.cleanup_token
  cir.br ^dispatch(%eh_token : !cir.eh_token)

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

eh_token

CIR exception handling token type

Results:#

Result

Description

cleanup_token

CIR cleanup token type

cir.bitreverse (::cir::BitReverseOp)#

Reverse the bit pattern of the operand integer

Syntax:

operation ::= `cir.bitreverse` $input `:` type($result) attr-dict

The cir.bitreverse operation reverses the bits of the operand integer. Its only argument must be of unsigned integer types of width 8, 16, 32, or 64.

Example:

%1 = cir.bitreverse %0: !u32i

Traits: AlwaysSpeculatableImplTrait, Involution, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

unsigned integer type of widths 8/16/32/64

Results:#

Result

Description

result

unsigned integer type of widths 8/16/32/64

cir.block_address (::cir::BlockAddressOp)#

Get the address of a cir.label within a function

Syntax:

operation ::= `cir.block_address` $block_addr_info `:` qualified(type($addr)) attr-dict

The cir.blockaddress operation takes a function name and a label and produces a pointer value that represents the address of that cir.label within the specified function.

This operation models GCC’s “labels as values” extension (&&label), which allows taking the address of a local label and using it as a computed jump target (e.g., with goto *addr;).

Example:

%1 = cir.alloca "ptr" align(8) init : !cir.ptr<!cir.ptr<!void>>
%addr = cir.block_address <@c, "label1"> : !cir.ptr<!cir.void>
cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
cir.br ^bb1
^bb1:
cir.label "label"

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
block_addr_info::cir::BlockAddrInfoAttrBlock address attribute

Results:#

Result

Description

addr

pointer to void type

cir.br (::cir::BrOp)#

Unconditional branch

Syntax:

operation ::= `cir.br` $dest (`(` $destOperands^ `:` type($destOperands) `)`)?
              (`loop_hints` $loop_hints^)? attr-dict

The cir.br branches unconditionally to a block. Used to represent C/C++ goto’s and general block branching.

Note that for source level goto’s crossing scope boundaries, those are usually represented with the “symbolic” cir.goto operation.

When a loop is flattened, the optional loop_hints attribute is placed on the branches that form the loop’s back edge (see cir.brcond).

Example:

  ...
    cir.br ^bb3
  ^bb3:
    cir.return

Traits: AlwaysSpeculatableImplTrait, Terminator

Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
loop_hints::cir::LoopHintAttrOptimizer hints and guarantees attached to a loop

Operands:#

Operand

Description

destOperands

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Successors:#

Successor

Description

dest

any successor

cir.brcond (::cir::BrCondOp)#

Conditional branch

Syntax:

operation ::= `cir.brcond` $cond
              $destTrue (`(` $destOperandsTrue^ `:` type($destOperandsTrue) `)`)?
              `,`
              $destFalse (`(` $destOperandsFalse^ `:` type($destOperandsFalse) `)`)?
              (`loop_hints` $loop_hints^)? attr-dict

The cir.brcond %cond, ^bb0, ^bb1 branches to ‘bb0’ block in case

it branches to ‘bb1’.

The optional loop_hints attribute is attached by CFG flattening to branches that target a loop header (i.e. the loop’s back edge), carrying the #cir.loop_hint of the original loop op.

Example:

  ...
    cir.brcond %a, ^bb3, ^bb4
  ^bb3:
    cir.return
  ^bb4:
    cir.yield

Traits: AlwaysSpeculatableImplTrait, AttrSizedOperandSegments, Terminator

Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
loop_hints::cir::LoopHintAttrOptimizer hints and guarantees attached to a loop

Operands:#

Operand

Description

cond

CIR bool type

destOperandsTrue

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

destOperandsFalse

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Successors:#

Successor

Description

destTrue

any successor

destFalse

any successor

cir.break (::cir::BreakOp)#

C/C++ break statement equivalent

Syntax:

operation ::= `cir.break` attr-dict

The cir.break operation is used to cease the execution of the current loop or switch operation and transfer control to the parent operation. It is only allowed within a breakable operations (loops and switches).

Traits: HasAncestor<WhileOp, DoWhileOp, ForOp, SwitchOp>, Terminator

cir.builtin_int_cast (::cir::BuiltinIntCastOp)#

Cast between a CIR integer and a builtin integer

Syntax:

operation ::= `cir.builtin_int_cast` $src `:` type($src) `->` type($result) attr-dict

Convert between a CIR integer type (!cir.int) and a builtin MLIR integer type (AnyInteger, e.g. i32, si32, ui32) or index, and vice versa.

This allows using operations from e.g. OpenMP or OpenACC dialects that expect the builtin types with CIR operations. Casting can be done in either direction.

Example:

// CIR integer cast to a builtin integer.
%0 = cir.builtin_int_cast %ciri : !cir.int<s, 32> -> i32

// Builtin induction variable / bound cast to CIR type.
%1 = cir.builtin_int_cast %iv : index -> !cir.int<u, 64>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

src

Integer type with arbitrary precision up to a fixed limit or integer or index

Results:#

Result

Description

result

Integer type with arbitrary precision up to a fixed limit or integer or index

cir.byte_swap (::cir::ByteSwapOp)#

Reverse the bytes in the object representation of the operand

Syntax:

operation ::= `cir.byte_swap` $input `:` type($result) attr-dict

The cir.byte_swap operation takes an integer as operand, reverse the bytes in the object representation of the operand integer, and returns the result.

The operand integer must be an unsigned integer whose width is a multiple of 16 bits (e.g. 16, 32, 64, 128, or a wider _BitInt).

Example:

// %0 = 0x12345678
%0 = cir.const #cir.int<305419896> : !u32i

// %1 should be 0x78563412
%1 = cir.byte_swap %0 : !u32i

Traits: AlwaysSpeculatableImplTrait, Involution, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

unsigned integer type with a width that is a multiple of 16 bits

Results:#

Result

Description

result

unsigned integer type with a width that is a multiple of 16 bits

cir.call (::cir::CallOp)#

Call a function

The cir.call operation represents a function call. It could represent either a direct call or an indirect call.

If the operation represents a direct call, the callee should be defined within the same symbol scope as the call. The callee attribute contains a symbol reference to the callee function. All operands of this operation are arguments to the callee function.

If the operation represents an indirect call, the callee attribute is empty. The first operand of this operation must be a pointer to the callee function. The rest operands are arguments to the callee function.

The calling_conv attribute specifies the calling convention used at the call site. It defaults to CallingConv::C, which is omitted when printed. Other calling conventions are printed as cc(<mnemonic>), e.g. cc(spir_function).

Example:

%0 = cir.call @foo()
cir.call @bar() cc(spir_function) : () -> ()

Traits: NoRegionArguments

Interfaces: ArgAndResultAttrsOpInterface, CIRCallOpInterface, CallOpInterface, SymbolUserOpInterface

Attributes:#

AttributeMLIR TypeDescription
callee::mlir::FlatSymbolRefAttrflat symbol reference attribute
nothrow::mlir::UnitAttrunit attribute
nounwind::mlir::UnitAttrunit attribute
willreturn::mlir::UnitAttrunit attribute
inline_kind::cir::InlineKindAttrinline kind
musttail::mlir::UnitAttrunit attribute
memory_effects::cir::MemoryEffectsAttrDescribes the possible memory effects of a function or callee
arg_attrs::mlir::ArrayAttrArray of dictionary attributes
res_attrs::mlir::ArrayAttrArray of dictionary attributes
calling_conv::cir::CallingConvAttrcalling convention

Operands:#

Operand

Description

args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.call_llvm_intrinsic (::cir::LLVMIntrinsicCallOp)#

Call to llvm intrinsic functions that is not defined in CIR

Syntax:

operation ::= `cir.call_llvm_intrinsic` $intrinsic_name $arg_ops `:` functional-type($arg_ops, $result)
              (`fastmath` `` $fastmath_flags^)? attr-dict

cir.call_llvm_intrinsic operation represents a call-like expression which has return type and arguments that maps directly to a llvm intrinsic. It only records intrinsic intrinsic_name.

Attributes:#

AttributeMLIR TypeDescription
intrinsic_name::mlir::StringAttrstring attribute
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

arg_ops

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.case (::cir::CaseOp)#

Case operation

Syntax:

operation ::= `cir.case` `(` enum($kind) `,` $value `)` $caseRegion attr-dict

The cir.case operation represents a case within a C/C++ switch. The cir.case operation must be in a cir.switch operation directly or indirectly.

The cir.case have 4 kinds:

  • equal, <constant>: equality of the second case operand against the condition.

  • anyof, [constant-list]: equals to any of the values in a subsequent following list.

  • range, [lower-bound, upper-bound]: the condition is within the closed interval.

  • default: any other value.

Each case region must be explicitly terminated.

Traits: AutomaticAllocationScope, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
value::mlir::ArrayAttrarray attribute
kind::cir::CaseOpKindAttrcase kind

cir.cast (::cir::CastOp)#

Conversion between values of different types

Syntax:

operation ::= `cir.cast` enum($kind) $src `:` type($src) `->` type($result)
              (`fenv` `` $fenv^)? attr-dict

Apply the usual C/C++ conversion rules between values. This operation models a subset of conversions as defined in Clang’s OperationKinds.def (llvm-project/clang/include/clang/AST/OperationKinds.def).

Note: not all conversions are implemented using cir.cast. For instance, lvalue-to-rvalue conversion is modeled as a cir.load instead. Currently supported kinds:

  • bitcast

  • array_to_ptrdecay

  • `member_ptr_to_bool

  • int_to_ptr

  • ptr_to_int

  • ptr_to_bool

  • integral

  • int_to_bool

  • int_to_float

  • float_to_int

  • float_to_bool

  • bool_to_int

  • floating

  • float_complex

  • int_complex_to_real

  • int_complex_to_bool

  • int_complex

  • int_complex_to_float_complex

  • address_space

CIR also supports some additional conversions that are not part of the classic Clang codegen:

  • bool_to_float

The optional fenv attribute describes constraints on the floating-point handling of the operation. It is only valid for floating-point cast kinds: floating, int_to_float, float_to_int, float_to_bool, bool_to_float, float_to_complex, float_complex_to_real, float_complex_to_bool, float_complex, float_complex_to_int_complex, and int_complex_to_float_complex.

Example:

%4 = cir.cast int_to_bool %3 : i32 -> !cir.bool
...
%x = cir.cast array_to_ptrdecay %0 
   : !cir.ptr<!cir.array<i32 x 10>> -> !cir.ptr<i32>
%y = cir.cast floating %f : !cir.double -> !cir.float fenv<>

Traits: CIR_FenvOpTrait

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, MemoryEffectsOpInterface, PromotableOpInterface

Attributes:#

AttributeMLIR TypeDescription
kind::cir::CastKindAttrcast kind
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.catch_param (::cir::CatchParamOp)#

Represents the catch clause formal parameter

Syntax:

operation ::= `cir.catch_param` (`:` qualified(type($param))^)?
              attr-dict

The cir.catch_param is used to retrieve the exception object inside the handler regions of cir.try.

This operation is used only before the CFG flatterning pass.

Example:

%exception = cir.catch_param : !cir.ptr<!void>

Traits: HasParent<TryOp>

Results:#

Result

Description

param

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.ceil (::cir::CeilOp)#

Computes the ceiling of the specified value

Syntax:

operation ::= `cir.ceil` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.ceil computes the ceiling of a given value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.cleanup.scope (::cir::CleanupScopeOp)#

Represents a scope with associated cleanup code

Syntax:

operation ::= `cir.cleanup.scope` $bodyRegion `cleanup` enum($cleanupKind) $cleanupRegion attr-dict

cir.cleanup.scope contains a body region and a cleanup region. The body region runs first, and the cleanup region may run when the body region is exited.

The cleanup kind attribute specifies which exits from the body region run the cleanup region:

  • normal: Cleanup is executed only on normal exit

  • eh: Cleanup is executed only on exception unwinding

  • all: Cleanup is executed on both normal exit and exception unwinding

Examples:

// Cleanup that runs on both normal and exception paths
cir.cleanup.scope {
  cir.call @mayThrow() : () -> ()
  cir.yield
} cleanup all {
  cir.call @destructor() : () -> ()
  cir.yield
}

// EH-only cleanup (destructor only called on exception)
cir.cleanup.scope {
  cir.call @mayThrow() : () -> ()
  cir.yield
} cleanup eh {
  cir.call @destructor() : () -> ()
  cir.yield
}

Both regions must be terminated. If a region has only one block, the terminator can be left out, and cir.yield will be inserted implicitly.

Traits: AutomaticAllocationScope, NoRegionArguments, RecursiveMemoryEffects, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
cleanupKind::cir::CleanupKindAttrcleanup kind

cir.clear_cache (::cir::ClearCacheOp)#

Clear the processor’s instruction cache if required.

Syntax:

operation ::= `cir.clear_cache` $begin `,` $end `:` qualified(type($begin))
              attr-dict

The cir.clear_cache operation provides a representation for the __builtin__clear_cache builtin and corresponds to the llvm.clear_cache intrinsic in LLVM IR.

This operation ensures visibility of modifications in the specified range to the execution unit of the processor. On targets with non-unified instruction and data cache, the implementation flushes the instruction cache.

On platforms with coherent instruction and data caches (e.g., x86), this intrinsic is a nop. On platforms with non-coherent instruction and data cache (e.g., ARM, MIPS), the operation will be lowered either to appropriate instructions or a system call, if cache flushing requires special privileges.

The default behavior is to emit a call to __clear_cache from the runtime library.

This operation does not empty the instruction pipeline. Modifications of the current function are outside the scope of the operation.

Operands:#

Operand

Description

begin

pointer to void type

end

pointer to void type

cir.clear_padding (::cir::ClearPaddingOp)#

Clear Padding Operation

Syntax:

operation ::= `cir.clear_padding` `(` `align` `(` $alignment `)` $arg `,`
              $padding `)` `:` type($arg) `->` `(` `)` attr-dict

This operation represents a __builtin_clear_padding call, which sets all padding bits in the pointee arg to zero. The arg’s alignment is also stored in this operation so we can properly emit the stores/loads later.

Offsets into the variable are stored as an OffsetPairAttr.

During LLVM-IR lowering, this is converted into getelementptr and store operations.

Example:

cir.clear_padding(align(1) %1,
                  [#cir.offset_pair<0, 2>, #cir.offset_pair<6, 8>])
                  : <rec_Type> -> ()

Attributes:#

AttributeMLIR TypeDescription
alignment::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
padding::mlir::ArrayAttrarray of padding locations

Operands:#

Operand

Description

arg

CIR pointer type

cir.clrsb (::cir::BitClrsbOp)#

Get the number of leading redundant sign bits in the input

Syntax:

operation ::= `cir.clrsb` $input `:` type($result) attr-dict

Compute the number of leading redundant sign bits in the input integer.

The input integer must be a signed integer. The most significant bit of the input integer is the sign bit. The cir.clrsb operation returns the number of consecutive bits following the sign bit that are identical to the sign bit.

The bit width of the input integer must be either 32 or 64.

Examples:

// %0 = 0b1101_1110_1010_1101_1011_1110_1110_1111
%0 = cir.const #cir.int<3735928559> : !s32i
// %1 will be 1 because there is 1 bit following the most significant bit
// that is identical to it.
%1 = cir.clrsb %0 : !s32i

// %2 = 1, 0b0000_0000_0000_0000_0000_0000_0000_0001
%2 = cir.const #cir.int<1> : !s32i
// %3 will be 30 because there are 30 consecutive bits following the sign
// bit that are identical to the sign bit.
%3 = cir.clrsb %2 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

signed integer type of widths 32/64

Results:#

Result

Description

result

signed integer type of widths 32/64

cir.clz (::cir::BitClzOp)#

Get the number of leading 0-bits in the input

Syntax:

operation ::= `cir.clz` $input (`poison_zero` $poison_zero^)?
              `:` type($result) attr-dict

Compute the number of leading 0-bits in the input.

The input integer must be an unsigned integer. The cir.clz operation returns the number of consecutive 0-bits at the most significant bit position in the input.

If the poison_zero attribute is present, this operation will have undefined behavior if the input value is 0.

Example:

// %0 = 0b0000_0000_0000_0000_0000_0000_0000_1000
%0 = cir.const #cir.int<8> : !u32i
// %1 will be 28
%1 = cir.clz %0 poison_zero : !u32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
poison_zero::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

input

unsigned integer type of widths 8/16/32/64/128

Results:#

Result

Description

result

unsigned integer type of widths 8/16/32/64/128

cir.cmp (::cir::CmpOp)#

Compare two values and produce a boolean result

Syntax:

operation ::= `cir.cmp` enum($kind) $lhs `,` $rhs `:` type($lhs)
              (`fenv` `` $fenv^)? attr-dict

The cir.cmp operation compares two operands of the same type and produces a !cir.bool result. It supports integral, boolean, floating-point, and pointer types. Booleans (including enums with a boolean underlying type) are compared as unsigned integers.

The following comparison predicates are available:

  • lt: less than

  • le: less than or equal

  • gt: greater than

  • ge: greater than or equal

  • eq: equal

  • ne: not equal

  • one: ordered and not equal (floating-point only)

  • uno: unordered (floating-point only, true if either operand is NaN)

For floating-point comparisons, the predicate follows C semantics (e.g. NaN comparisons return false for all predicates except ne). The one and uno predicates are floating-point specific: one is ordered not-equal (false for NaN), uno tests if either operand is NaN.

The optional fenv attribute describes constraints on the floating-point handling of the operation. It is only valid for floating-point comparisons.

%0 = cir.cmp gt %1, %2 : !s32i
%1 = cir.cmp eq %a, %b : !cir.ptr<!u8i>
%2 = cir.cmp lt %x, %y : !cir.float fenv<>

Traits: CIR_FenvOpTrait, SameTypeOperands

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
kind::cir::CmpOpKindAttrcompare operation kind
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

comparable type

rhs

comparable type

Results:#

Result

Description

result

CIR bool type

cir.cmp3way (::cir::CmpThreeWayOp)#

Compare two values with C++ three-way comparison semantics

Syntax:

operation ::= `cir.cmp3way` qualified($info) $lhs `,` $rhs `:` qualified(type($lhs))
              `->` qualified(type($result)) attr-dict

The cir.cmp3way operation models the builtin <=> operator in C++20. It takes two operands with the same type and produces a result indicating the ordering between the two input operands.

The result of the operation is a signed integer that indicates the ordering between the two input operands.

There are three kinds of ordering: strong, weak and partial ordering. Comparing different types of values yields different kinds of orderings. The info parameter gives the ordering kind and other necessary information about the comparison.

Example:

!s32i = !cir.int<s, 32>

#cmpinfo_partial_ltn1eq0gt1unn127 =
  #cir.cmp3way_info<partial, lt = -1, eq = 0, gt = 1, unordered = -127>
#cmpinfo_strong_ltn1eq0gt1 =
  #cir.cmp3way_info<strong, lt = -1, eq = 0, gt = 1>

%0 = cir.const #cir.int<0> : !s32i
%1 = cir.const #cir.int<1> : !s32i
%2 = cir.cmp3way #cmpinfo_strong_ltn1eq0gt1 %0, %1 : !s32i -> !s8i

%3 = cir.const #cir.fp<0.0> : !cir.float
%4 = cir.const #cir.fp<1.0> : !cir.float
%5 = cir.cmp3way #cmpinfo_partial_ltn1eq0gt1unn127 %3, %4 : !cir.float -> !s8i

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
info::cir::CmpThreeWayInfoAttrHolds information about a three-way comparison operation

Operands:#

Operand

Description

lhs

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

rhs

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

signed integer type

cir.co_return (::cir::CoReturnOp)#

Coroutine return operation

Syntax:

operation ::= `cir.co_return` attr-dict

The cir.co_return operation models a coroutine return point inside the body region of a cir.coroutine. It may be nested within other operations or regions inside that body.

Traits: AlwaysSpeculatableImplTrait, HasAncestor<CoroutineOp>, ReturnLike, Terminator

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), RegionBranchTerminatorOpInterface

Effects: MemoryEffects::Effect{}

cir.complex.add (::cir::ComplexAddOp)#

Complex addition

Syntax:

operation ::= `cir.complex.add` $lhs `,` $rhs `:` qualified(type($result)) attr-dict

The cir.complex.add operation takes two complex numbers and returns their sum.

Example:

%2 = cir.complex.add %0, %1 : !cir.complex<s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

complex of integer type

rhs

complex of integer type

Results:#

Result

Description

result

complex of integer type

cir.complex.conj (::cir::ComplexConjOp)#

Complex conjugate

Syntax:

operation ::= `cir.complex.conj` $operand `:` qualified(type($operand)) attr-dict

The cir.complex.conj operation takes a complex number and returns its complex conjugate, which is formed by negating the imaginary part.

Example:

%1 = cir.complex.conj %0 : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

operand

CIR complex type

Results:#

Result

Description

result

CIR complex type

cir.complex.create (::cir::ComplexCreateOp)#

Create a complex value from its real and imaginary parts

Syntax:

operation ::= `cir.complex.create` $real `,` $imag
              `:` qualified(type($real)) `->` qualified(type($result)) attr-dict

The cir.complex.create operation takes two operands that represent the real and imaginary part of a complex number, and yields the complex number.

%0 = cir.const #cir.fp<1.000000e+00> : !cir.double
%1 = cir.const #cir.fp<2.000000e+00> : !cir.double
%2 = cir.complex.create %0, %1 : !cir.double -> !cir.complex<!cir.double>

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

real

integer or floating point type

imag

integer or floating point type

Results:#

Result

Description

result

CIR complex type

cir.complex.div (::cir::ComplexDivOp)#

Complex division

Syntax:

operation ::= `cir.complex.div` $lhs `,` $rhs `:` qualified(type($result)) attr-dict

The cir.complex.div operation takes two complex numbers and returns their quotient.

Example:

%2 = cir.complex.div %0, %1 : !cir.complex<s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

complex of integer type

rhs

complex of integer type

Results:#

Result

Description

result

complex of integer type

cir.complex.fadd (::cir::ComplexFAddOp)#

Complex addition

Syntax:

operation ::= `cir.complex.fadd` $lhs `,` $rhs `:` qualified(type($result)) (`fenv` `` $fenv^)? attr-dict

The cir.complex.fadd operation takes two complex numbers and returns their sum.

Example:

%2 = cir.complex.fadd %0, %1 : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

rhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.complex.fdiv (::cir::ComplexFDivOp)#

Complex division

Syntax:

operation ::= `cir.complex.fdiv` $lhs `,` $rhs `range` `(` enum($range) `)` `:` qualified(type($result))
              attr-dict

The cir.complex.div operation takes two complex numbers and returns their quotient.

The range attribute specifies the algorithm to be used when the operation is lowered to the LLVM dialect. For division, ‘improved’ produces Smith’s algorithms for Complex division with no additional handling for NaN values. If ‘promoted’ is used, the values are promoted to a higher precision type, if possible, and the calculation is performed using the algebraic formula, with no additional handling for NaN values. We fall back on Smith’s algorithm when the target doesn’t support a higher precision type. If ‘full’ is used, a runtime-library function is called if one of the intermediate calculations produced a NaN value. and for ‘basic’ algebraic formula with no additional handling for the NaN value will be used. For integers types range attribute will be ignored.

Example:

%2 = cir.complex.fdiv %0, %1 range(basic) : !cir.complex<!cir.float>
%2 = cir.complex.fdiv %0, %1 range(full) : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
range::cir::ComplexRangeKindAttrcomplex multiplication and division implementation

Operands:#

Operand

Description

lhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

rhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.complex.fmul (::cir::ComplexFMulOp)#

Complex multiplication

Syntax:

operation ::= `cir.complex.fmul` $lhs `,` $rhs `range` `(` enum($range) `)` `:` qualified(type($result))
              attr-dict

The cir.complex.mul operation takes two complex numbers and returns their product.

The range attribute specifies the algorithm to be used when the operation is lowered to the LLVM dialect. For multiplication, ‘improved’, ‘promoted’, and ‘basic’ are all handled equivalently, producing the algebraic formula with no special handling for NaN value. If ‘full’ is used, a runtime-library function is called if one of the intermediate calculations produced a NaN value.

Example:

%2 = cir.complex.fmul %0, %1 range(basic) : !cir.complex<!cir.float>
%2 = cir.complex.fmul %0, %1 range(full) : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
range::cir::ComplexRangeKindAttrcomplex multiplication and division implementation

Operands:#

Operand

Description

lhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

rhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.complex.fsub (::cir::ComplexFSubOp)#

Complex subtraction

Syntax:

operation ::= `cir.complex.fsub` $lhs `,` $rhs `:` qualified(type($result)) (`fenv` `` $fenv^)? attr-dict

The cir.complex.fsub operation takes two complex numbers and returns their difference.

Example:

%2 = cir.complex.fsub %0, %1 : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

rhs

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

complex of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.complex.imag (::cir::ComplexImagOp)#

Extract the imaginary part of a complex value

Syntax:

operation ::= `cir.complex.imag` $operand `:` qualified(type($operand)) `->` qualified(type($result))
              attr-dict

cir.complex.imag operation takes an operand of !cir.complex, !cir.int !cir.bool or !cir.float. If the operand is !cir.complex, the imag part of it will be returned, otherwise a zero value will be returned.

Example:

%imag = cir.complex.imag %complex : !cir.complex<!cir.float> -> !cir.float
%imag = cir.complex.imag %scalar : !cir.float -> !cir.float

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

operand

complex, integer, boolean or floating point type

Results:#

Result

Description

result

integer, boolean or floating point type

cir.complex.imag_ptr (::cir::ComplexImagPtrOp)#

Derive a pointer to the imaginary part of a complex value

Syntax:

operation ::= `cir.complex.imag_ptr` $operand `:`
              qualified(type($operand)) `->` qualified(type($result)) attr-dict

cir.complex.imag_ptr operation takes a pointer operand that points to a complex value of type !cir.complex and yields a pointer to the imaginary part of the operand.

Example:

%1 = cir.complex.imag_ptr %0 : !cir.ptr<!cir.complex<!cir.double>>
  -> !cir.ptr<!cir.double>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

operand

pointer to complex type

Results:#

Result

Description

result

pointer to integer or floating point type

cir.complex.mul (::cir::ComplexMulOp)#

Complex multiplication

Syntax:

operation ::= `cir.complex.mul` $lhs `,` $rhs `:` qualified(type($result)) attr-dict

The cir.complex.mul operation takes two complex numbers and returns their product.

Example:

%2 = cir.complex.mul %0, %1 : !cir.complex<s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

complex of integer type

rhs

complex of integer type

Results:#

Result

Description

result

complex of integer type

cir.complex.real (::cir::ComplexRealOp)#

Extract the real part of a complex value

Syntax:

operation ::= `cir.complex.real` $operand `:` qualified(type($operand)) `->` qualified(type($result))
              attr-dict

cir.complex.real operation takes an operand of !cir.complex, cir.int, !cir.bool or !cir.float. If the operand is !cir.complex, the real part of it will be returned, otherwise the value returned unmodified.

Example:

%real = cir.complex.real %complex : !cir.complex<!cir.float> -> !cir.float
%real = cir.complex.real %scalar : !cir.float -> !cir.float

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

operand

complex, integer, boolean or floating point type

Results:#

Result

Description

result

integer, boolean or floating point type

cir.complex.real_ptr (::cir::ComplexRealPtrOp)#

Derive a pointer to the real part of a complex value

Syntax:

operation ::= `cir.complex.real_ptr` $operand `:`
              qualified(type($operand)) `->` qualified(type($result)) attr-dict

cir.complex.real_ptr operation takes a pointer operand that points to a complex value of type !cir.complex and yields a pointer to the real part of the operand.

Example:

%1 = cir.complex.real_ptr %0 : !cir.ptr<!cir.complex<!cir.double>>
  -> !cir.ptr<!cir.double>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

operand

pointer to complex type

Results:#

Result

Description

result

pointer to integer or floating point type

cir.complex.sub (::cir::ComplexSubOp)#

Complex subtraction

Syntax:

operation ::= `cir.complex.sub` $lhs `,` $rhs `:` qualified(type($result)) attr-dict

The cir.complex.sub operation takes two complex numbers and returns their difference.

Example:

%2 = cir.complex.sub %0, %1 : !cir.complex<s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

complex of integer type

rhs

complex of integer type

Results:#

Result

Description

result

complex of integer type

cir.condition (::cir::ConditionOp)#

Loop continuation condition.

Syntax:

operation ::= `cir.condition` `(` $condition `)` attr-dict

The cir.condition terminates conditional regions. It takes a single cir.bool operand and, depending on its value, may branch to different regions:

  • When in the cond region of a loop, it continues the loop if true, or exits it if false.

  • When in the ready region of a cir.await, it branches to the resume region when true, and to the suspend region when false.

Example:

cir.for : cond {
  cir.condition(%val) // Branches to `body` region or exits.
} body {
  cir.yield
} step {
  cir.yield
}

cir.await(user, ready : {
  cir.condition(%arg0) // Branches to `resume` or `suspend` region.
}, suspend : {
  [...]
}, resume : {
  [...]
},)

Traits: Terminator

Interfaces: RegionBranchTerminatorOpInterface

Operands:#

Operand

Description

condition

CIR bool type

cir.const (::cir::ConstantOp)#

Create a CIR constant from a literal attribute

Syntax:

operation ::= `cir.const` $value attr-dict

The cir.const operation turns a literal into an SSA value. The data is attached to the operation as an attribute.

  %0 = cir.const #cir.int<4> : !u32i
  %1 = cir.const #cir.fp<1.500000e+00> : !cir.float
  %2 = cir.const #cir.ptr<null> : !cir.ptr<!void>

Traits: AlwaysSpeculatableImplTrait, ConstantLike

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
value::mlir::TypedAttrTypedAttr instance

Results:#

Result

Description

res

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.construct_catch_param (::cir::ConstructCatchParamOp)#

Construct a catch parameter from the in-flight exception

Syntax:

operation ::= `cir.construct_catch_param` enum($kind) $eh_token `to` $param_addr `using` ($copy_fn^)? `:`
              qualified(type($param_addr)) attr-dict

cir.construct_catch_param abstractly represents the target-specific work that must be performed before cir.begin_catch to bind the in-flight exception object to the local alloca used for the catch parameter.

For example: for non-pointer, non-reference catch parameters whose type has a non-trivial copy constructor, the Itanium C++ ABI requires calling __cxa_get_exception_ptr to obtain the adjusted exception pointer and then invoking the catch parameter’s copy constructor to create a local copy of the object before __cxa_begin_catch is invoked.

This operation takes a !cir.eh_token that represents the in-flight exception and the alloca value for the catch parameter. The optional copy_fn attribute, present for non_trivial_copy, is a flat symbol reference to a cir.func thunk that copies the exception object to a local alloca value. For reference_to_pointer, the operation binds the reference to the exception object itself.

This operation is replaced with a target-specific representation during the EHABI lowering pass. For some targets, such as the Microsoft ABI, this operation is a no-op and is simply erased during lowering.

Example:

cir.construct_catch_param non_trivial_copy %eh_token to %param_addr
  using @__clang_cir_catch_init_T : !cir.ptr<!rec_T>

Interfaces: SymbolUserOpInterface

Attributes:#

AttributeMLIR TypeDescription
kind::cir::InitCatchKindAttrallowed i32 cases: 0, 1, 2, 3, 4, 5, 6, 7
copy_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:#

Operand

Description

eh_token

CIR exception handling token type

param_addr

CIR pointer type

cir.continue (::cir::ContinueOp)#

C/C++ continue statement equivalent

Syntax:

operation ::= `cir.continue` attr-dict

The cir.continue operation is used to end execution of the current iteration of a loop and resume execution beginning at the next iteration. It is only allowed within loop regions.

Traits: HasAncestor<WhileOp, DoWhileOp, ForOp>, Terminator

cir.copy (::cir::CopyOp)#

Copies contents from a CIR pointer to another

Syntax:

operation ::= `cir.copy` $src (`align` `(` $src_alignment^ `)`)?
              `to`
              $dst (`align` `(` $dst_alignment^ `)`)?
              (`volatile` $is_volatile^)?
              (`skip_tail_padding` $skip_tail_padding^)?
              attr-dict `:` custom<CopyTypes>(type($src), type($dst))

Given two CIR pointers, src and dst, cir.copy will copy the memory pointed by src to the memory pointed by dst.

The number of bytes copied is inferred from the pointee type. The pointee type of src and dst must match and both must implement the DataLayoutTypeInterface. The pointers may differ in address space (e.g. when assigning through an address-space-qualified pointer); when the two pointer types differ, both are printed, src first.

The volatile keyword indicates that the operation is volatile.

The skip_tail_padding keyword indicates that only the data bytes should be copied, excluding any tail padding. This is used when copying potentially-overlapping subobjects where the tail padding might be occupied by other objects (e.g. fields marked with [[no_unique_address]]). This is only valid when the pointee type is a record type.

Examples:

  // Copying contents from one record to another:
  cir.copy %0 to %1 : !cir.ptr<!record_ty>

  // Copying without tail padding (for overlapping subobjects):
  cir.copy %0 to %1 skip_tail_padding : !cir.ptr<!record_ty>

Interfaces: PromotableMemOpInterface

Attributes:#

AttributeMLIR TypeDescription
dst_alignment::mlir::IntegerAttr64-bit signless integer attribute
src_alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute
skip_tail_padding::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

dst

CIR pointer type

src

CIR pointer type

cir.copysign (::cir::CopysignOp)#

Copies the sign of a floating-point value

Syntax:

operation ::= `cir.copysign` $lhs `,` $rhs `:` qualified(type($lhs))
              (`fenv` `` $fenv^)? attr-dict

cir.copysign returns a value with the magnitude of the first operand and the sign of the second operand.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.coro.cleanup (::cir::CoroCleanupOp)#

Branches through the enclosing cleanups to the coroutine cleanup

Syntax:

operation ::= `cir.coro.cleanup` attr-dict

Placeholder emitted for the destroy case of a flattened cir.await. Like cir.co_return, it leaves every enclosing cir.cleanup.scope through its cleanup, so the destructors of locals in scope run first. cir.coroutine flattening then rewrites it into a branch to the destroy region, which frees the frame and continues to the exit region. It must not survive flattening.

Traits: Terminator

cir.coro.exit (::cir::CoroExitOp)#

Branches to the enclosing cir.coroutine’s exit region

Syntax:

operation ::= `cir.coro.exit` attr-dict

Placeholder emitted while flattening cir.await. cir.coroutineflattening rewrites it into a cir.br to the exit block. It must not survive flattening.

Traits: Terminator

cir.coro.intrinsic.align (::cir::CoroAlignOp)#

Represents llvm.coro.align

Syntax:

operation ::= `cir.coro.intrinsic.align` `(` operands `)` `:` functional-type(operands, results) attr-dict

Returns the alignment requirement, in bytes, of the coroutine frame.

Results:#

Result

Description

result

fundamental unsigned integer type

cir.coro.intrinsic.alloc (::cir::CoroAllocOp)#

Represents llvm.coro.alloc

Syntax:

operation ::= `cir.coro.intrinsic.alloc` `(` operands `)` `:` functional-type(operands, results) attr-dict

Queries whether the coroutine identified by id needs a dynamically allocated frame. Returns true if the coroutine frame must be allocated, or false otherwise.

Traits: TokenConsumerTrait

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

id

token

Results:#

Result

Description

result

boolean type

cir.coro.intrinsic.begin (::cir::CoroBeginOp)#

Represents llvm.coro.begin

Syntax:

operation ::= `cir.coro.intrinsic.begin` `(` operands `)` `:` functional-type(operands, results) attr-dict

Initializes the coroutine frame using coroframeAddr. id is the token from coro.intrinsic.id, and coroframeAddr points to the memory used for the coroutine frame. Returns the coroutine handle.

Traits: TokenConsumerTrait

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

id

token

coroframeAddr

pointer to void type

Results:#

Result

Description

result

pointer to void type

cir.coro.intrinsic.destroy (::cir::CoroDestroyOp)#

Represents llvm.coro.destroy

Syntax:

operation ::= `cir.coro.intrinsic.destroy` `(` operands `)` `:` functional-type(operands, results) attr-dict

Destroys a suspended coroutine identified by handle. Destroying a coroutine that is not currently suspended is undefined behavior.

Operands:#

Operand

Description

handle

pointer to void type

cir.coro.intrinsic.done (::cir::CoroDoneOp)#

Represents llvm.coro.done

Syntax:

operation ::= `cir.coro.intrinsic.done` `(` operands `)` `:` functional-type(operands, results) attr-dict

Checks whether the coroutine identified by handle is currently suspended at its final suspend point. handle must be a handle to a suspended coroutine.

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

handle

pointer to void type

Results:#

Result

Description

done

CIR bool type

cir.coro.intrinsic.end (::cir::CoroEndOp)#

Represents llvm.coro.end

Syntax:

operation ::= `cir.coro.intrinsic.end` `(` operands `)` `:` functional-type(operands, results) attr-dict

Marks a point at which a coroutine must be suspended or destroyed for the last time, e.g. right before the coroutine returns control to its caller for the final time, or along an exceptional unwind path. handle is the coroutine handle produced by coro.intrinsic.begin, and unwind indicates whether this occurrence of coro.intrinsic.end lies on the unwind path (true) or the normal control-flow path (false).

Traits: TokenConsumerTrait

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

handle

pointer to void type

unwind

boolean type

resultToken

token

Results:#

Result

Description

result

void type

cir.coro.intrinsic.free (::cir::CoroFreeOp)#

Represents llvm.coro.free

Syntax:

operation ::= `cir.coro.intrinsic.free` `(` operands `)` `:` functional-type(operands, results) attr-dict

Given the coroutine identified by id and its frame pointer coroframe (the handle from coro.intrinsic.begin), returns the pointer that must be passed to the deallocation function to free the coroutine frame, or a null pointer if the coroutine frame was not dynamically allocated.

Traits: TokenConsumerTrait

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

id

token

coroframe

pointer to void type

Results:#

Result

Description

result

pointer to void type

cir.coro.intrinsic.id (::cir::CoroIdOp)#

Represents llvm.coro.id

Syntax:

operation ::= `cir.coro.intrinsic.id` `(` operands `)` `:` functional-type(operands, results) attr-dict

Marks the beginning of a coroutine’s lifetime and identifies it to the rest of the coroutine intrinsics. Takes the required alignment of the coroutine frame, a pointer to the coroutine promise (or null if none), the address of the coroutine function itself, and an opaque pointer used by the frontend to convey additional information to the coroutine lowering passes (or null).

The result is a token that must be passed to every other coro.intrinsic.* operation associated with this coroutine (coro.alloc, coro.begin, coro.free, etc.), tying them all to the same coroutine instance.

Traits: TokenProducerTrait

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

align

integer type

promise

pointer to void type

coroaddr

pointer to void type

fnaddrs

pointer to void type

Results:#

Result

Description

result

token

cir.coro.intrinsic.noop (::cir::CoroNoopOp)#

Represents llvm.coro.noop

Syntax:

operation ::= `cir.coro.intrinsic.noop` `(` operands `)` `:` functional-type(operands, results) attr-dict

Returns a coroutine handle to a no-op coroutine.

Interfaces: InferTypeOpInterface

Results:#

Result

Description

result

pointer to void type

cir.coro.intrinsic.promise (::cir::CoroPromiseOp)#

Represents llvm.coro.promise

Syntax:

operation ::= `cir.coro.intrinsic.promise` `(` operands `)` `:` functional-type(operands, results) attr-dict

Given a coroutine handle (if isFromPromise is false) or a pointer to a coroutine promise (if isFromPromise is true), obtains a pointer to the coroutine promise or the coroutine handle, respectively. align is the alignment requirement of the promise, and isFromPromise indicates the direction of the transformation: true recovers the coroutine handle from a promise pointer, false recovers the promise pointer from a coroutine handle. Using this op on a coroutine without a coroutine promise is undefined behavior.

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

coroframe

pointer to void type

align

integer type

isFromPromise

CIR bool type

Results:#

Result

Description

result

pointer to void type

cir.coro.intrinsic.resume (::cir::CoroResumeOp)#

Represents llvm.coro.resume

Syntax:

operation ::= `cir.coro.intrinsic.resume` `(` operands `)` `:` functional-type(operands, results) attr-dict

Resumes a suspended coroutine identified by handle. Resuming a coroutine that is not currently suspended is undefined behavior.

Operands:#

Operand

Description

handle

pointer to void type

cir.coro.intrinsic.save (::cir::CoroSaveOp)#

Represents llvm.coro.save

Syntax:

operation ::= `cir.coro.intrinsic.save` `(` operands `)` `:` functional-type(operands, results) attr-dict

cir.coro.intrinsic.save represents the llvm.coro.save intrinsic.

It marks the point where a coroutine needs to update its state to prepare for resumption, so that it is considered suspended (and thus eligible for resumption).

Traits: TokenProducerTrait

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

coroaddr

pointer to void type

Results:#

Result

Description

result

token

cir.coro.intrinsic.size (::cir::CoroSizeOp)#

Represents llvm.coro.size

Syntax:

operation ::= `cir.coro.intrinsic.size` `(` operands `)` `:` functional-type(operands, results) attr-dict

Returns the size, in bytes, of the coroutine frame.

Results:#

Result

Description

result

fundamental unsigned integer type

cir.coro.intrinsic.suspend (::cir::CoroSuspendOp)#

Represents llvm.coro.suspend

Syntax:

operation ::= `cir.coro.intrinsic.suspend` `(` operands `)` `:` functional-type(operands, results) attr-dict

cir.coro.intrinsic.suspend represents the llvm.coro.suspend intrinsic.

It marks the point where execution of a switched-resume coroutine is suspended and control returns to the caller. The result value indicates how the coroutine should proceed: -1 if suspended, 0 if resumed, or 1 if destroyed.

The id operand is the token produced by a cir.coro.save that marks the point when the coroutine state is prepared for suspension.

The final operand indicates whether this is a final suspend point. If more than one suspend point is marked final, the resume and destroy branches must lead to the same basic blocks.

Traits: TokenConsumerTrait

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

save

token

final

boolean type

Results:#

Result

Description

result

8-bit signed integer

cir.coro.suspend_point (::cir::CoroSuspendPoint)#

Marks the point where a coroutine actually suspends

Syntax:

operation ::= `cir.coro.suspend_point` (`(` $cond^ `)`)? attr-dict

Terminates the suspend region of a cir.await. It has no explicit successors; the destination is determined by CoroutineOp according to how the suspended coroutine is subsequently handled:

  • resume: continues execution through the cir.await’s resume region when the coroutine handle is resumed.

  • exit: transfers directly to the enclosing cir.coroutine’s exit region when the coroutine remains suspended. The coroutine frame remains alive and no cleanups are performed.

  • destroy: transfers through the enclosing cir.cleanup.scopes to the cir.coroutine’s destroy region when the coroutine handle is destroyed.

When the optional cond operand is present, a false value vetoes the suspension and control branches directly to the resume region of the enclosing cir.await. A true value indicates the coroutine actually suspends.

Traits: AlwaysSpeculatableImplTrait, HasParent<AwaitOp>, Terminator

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), RegionBranchTerminatorOpInterface

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

cond

boolean type

cir.coroutine (::cir::CoroutineOp)#

Groups a coroutine’s structured suspend/resume/destroy control flow

Syntax:

operation ::= `cir.coroutine` `initialSuspend` `:` $initialSuspend `,`
              `body` `:` $body `,`
              `finalSuspend` `:` $finalSuspend `,`
              `destroy` `:` $destroy `,`
              `exit` `:` $exit
              attr-dict

cir.coroutine is an op consisting of seven regions: initial_suspend, body, final_suspend, grp (TODO),unwind (TODO), destroy, andexit.

  • initial_suspend: the coroutine ramp/setup region. Its cir.await marked init is the ramp boundary: the coroutine frame and its associated state are established before this point, and crossing the await transfers execution to body.

  • body: the user-written coroutine body, arbitrary CFG, zero or more cir.awaits at any nesting depth, terminated by cir.co_return or a plain cir.yield if control simply falls off the end. This region is a structural boundary separating the coroutine’s setup and teardown logic (initial suspend, final suspend, destroy) from the user-provided statements of the original function body, including co_await and co_return expressions. In particular, cir.co_return operations inside this region mark coroutine exit points and introduce structured control flow that transfers execution to final_suspend.

  • final_suspend: at most one cir.await, marked final. Nothing else. Corresponds to co_await promise.final_suspend(). Suspending at this final suspend point is valid: the coroutine stays suspended until it is destroyed. Resuming past this point is undefined behavior in valid programs, so its resume edge is expected to be dead in practice, but is kept for structural symmetry with the other two suspend regions.

  • gro: TODO.

  • unwind: TODO.

  • destroy: destroys the coroutine frame (coro.free + delete). Reached by an explicit destroy() call on a suspended handle, by normal completion through initial_suspend, final_suspend, or by an exception escaping the coroutine. Falls through to exit except when reached due to an escaping exception, where it continues propagating that exception instead.

  • exit: the shared return-to-caller path. Reached directly from any suspend point that isn’t being destroyed (the coroutine is just pausing), and from destroy when it was entered via ordinary dispatch. Holds coro.end + the actual cir.return.

Traits: AutomaticAllocationScope, NoRegionArguments, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

cir.cos (::cir::CosOp)#

Computes the floating-point cosine value

Syntax:

operation ::= `cir.cos` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.cos computes the cosine of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.cosh (::cir::CoshOp)#

Computes the floating-point hyperbolic cosine value

Syntax:

operation ::= `cir.cosh` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.cosh computes the hyperbolic cosine of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.cpuid (::cir::CpuIdOp)#

Get information about the CPU

Syntax:

operation ::= `cir.cpuid` $cpu_info`,` $function_id`,` $sub_function_id `:`
              qualified(type($cpu_info)) `,`
              type($function_id) `,`
              type($sub_function_id) attr-dict

The cir.cpuid operation retrieves different types of CPU information and stores it in an array of 4 integers.

This operation takes 3 arguments: cpu_info, a pointer to an array of 4 integers; function_id, an integer determining what type of information to be retrieved (for instance, basic information, processor information and features, or cache/TLB information); and sub_function_id, an integer that adds more detail about what information is requested.

As a result, the array of 4 integers is filled with the requested information.

Example:

cir.cpuid %cpui_info, %function_id, %sub_function_id : (!cir.ptr<!s32i>,
    !s32i, !s32i)

Operands:#

Operand

Description

cpu_info

pointer to 32-bit signed integer

function_id

32-bit signed integer

sub_function_id

32-bit signed integer

cir.ctz (::cir::BitCtzOp)#

Get the number of trailing 0-bits in the input

Syntax:

operation ::= `cir.ctz` $input (`poison_zero` $poison_zero^)?
              `:` type($result) attr-dict

Compute the number of trailing 0-bits in the input.

The input integer must be an unsigned integer. The cir.ctz operation counts the number of consecutive 0-bits starting from the least significant bit.

If the poison_zero attribute is present, this operation will have undefined behavior if the input value is 0.

Example:

// %0 = 0b1000
%0 = cir.const #cir.int<8> : !u32i
// %1 will be 3
%1 = cir.ctz %0 poison_zero : !u32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
poison_zero::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

input

unsigned integer type of widths 8/16/32/64/128

Results:#

Result

Description

result

unsigned integer type of widths 8/16/32/64/128

cir.dec (::cir::DecOp)#

Decrement an integer by one

Syntax:

operation ::= `cir.dec` (`nsw` $no_signed_wrap^)?
              $input `:` type($input) attr-dict

The cir.dec operation decrements the operand by one. The operand and result must have the same type.

The optional nsw (no signed wrap) attribute indicates that the result is poison if signed overflow occurs.

Example:

%1 = cir.dec %0 : !s32i
%3 = cir.dec nsw %2 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

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

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

integer or vector of integer type

Results:#

Result

Description

result

integer or vector of integer type

cir.delete_array (::cir::DeleteArrayOp)#

Delete address representing an array

Syntax:

operation ::= `cir.delete_array` $address `:` qualified(type($address))
              `delete_fn` `(` $delete_fn `)`
              (`delete_params` `` $delete_params^)?
              (`element_dtor` `(` $element_dtor^ `)`)?
              (`dtor_may_throw` $dtor_may_throw^)?
              `element_align` `(` $element_align `)`
              attr-dict

cir.delete_array operation deletes an array. For example, delete[] ptr; will be translated to cir.delete_array %ptr.

The delete_fn attribute specifies the operator delete function to call. The optional delete_params attribute describes the parameters needed by the operator delete call. When absent, all parameters have default values.

The element_dtor attribute, when present, specifies the destructor to call on each array element before deallocation.

The dtor_may_throw unit property, when present, indicates that the element destructor may throw exceptions.

The element_align attribute gives the element type’s preferred alignment in bytes, which should be the same value the corresponding new[] uses to size its array cookie.

Attributes:#

AttributeMLIR TypeDescription
delete_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute
delete_params::cir::UsualDeleteParamsAttrParameters describing the usual operator delete signature
element_dtor::mlir::FlatSymbolRefAttrflat symbol reference attribute
element_align::mlir::IntegerAttr64-bit signless integer attribute

Operands:#

Operand

Description

address

CIR pointer type

cir.derived_class_addr (::cir::DerivedClassAddrOp)#

Get the derived class address for a class/struct

Syntax:

operation ::= `cir.derived_class_addr` (`nonnull` $assume_not_null^)?
              $src_addr ` ` `[` $offset `]`
              `:` qualified(type($src_addr)) `->` qualified(type($result))
              attr-dict

The cir.derived_class_addr operaration gets the address of a particular derived class given a non-virtual base class pointer. The offset in bytes of the base class must be passed in, similar to cir.base_class_addr, but going into the other direction. This means lowering to a negative offset.

The operation contains a flag for whether or not the operand may be nullptr. That depends on the context and cannot be known by the operation, and that information affects how the operation is lowered.

The validity of the relationship of derived and base cannot yet be verified. If the target class is not a valid derived class for the object, the behavior is undefined.

Example:

class A {};
class B : public A {};

B *getAsB(A *a) {
  return static_cast<B*>(a);
}

leads to

  %2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>
  %3 = cir.derived_class_addr %2 [0] : !cir.ptr<!rec_A> -> !cir.ptr<!rec_B>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute
assume_not_null::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

src_addr

CIR pointer type

Results:#

Result

Description

result

CIR pointer type

cir.derived_data_member (::cir::DerivedDataMemberOp)#

Cast a base class data member pointer to a derived class data member pointer

Syntax:

operation ::= `cir.derived_data_member` $src `[` $offset `]` `:` qualified(type($src)) `->` qualified(type($result)) attr-dict

The cir.derived_data_member operation casts a data member pointer of type T Base::* to a data member pointer of type T Derived::*, where Base is an accessible non-ambiguous non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

Operands:#

Operand

Description

src

CIR type that represents a pointer-to-data-member in C++

Results:#

Result

Description

result

CIR type that represents a pointer-to-data-member in C++

cir.derived_method (::cir::DerivedMethodOp)#

Cast a base class pointer-to-member-function to a derived class pointer-to-member-function

Syntax:

operation ::= `cir.derived_method` $src `[` $offset `]` `:` qualified(type($src))
              `->` qualified(type($result)) attr-dict

The cir.derived_method operation casts a pointer-to-member-function of type Ret (Base::*)(Args) to a pointer-to-member-function of type Ret (Derived::*)(Args), where Base is a non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Example:

%1 = cir.derived_method %0 [16] : !cir.method<!cir.func<(!s32i)> in !rec_Base> -> !cir.method<!cir.func<(!s32i)> in !rec_Derived>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

Operands:#

Operand

Description

src

CIR type that represents C++ pointer-to-member-function type

Results:#

Result

Description

result

CIR type that represents C++ pointer-to-member-function type

cir.div (::cir::DivOp)#

Integer division

Syntax:

operation ::= `cir.div` $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.div operation performs division on integer operands. Both operands and the result must have the same integer or vector-of-integer or matrix-of-integer type.

Example:

%0 = cir.div %a, %b : !s32i
%1 = cir.div %a, %b : !u32i
%2 = cir.div %va, %vb : !cir.vector<4 x !s32i>
%3 = cir.div %ma, %mb : !cir.matrix<3 x 3 x !s32i>

Traits: SameOperandsAndResultType

Interfaces: BinaryOpInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

integer or vector/matrix of integer type

rhs

integer or vector/matrix of integer type

Results:#

Result

Description

result

integer or vector/matrix of integer type

cir.do (::cir::DoWhileOp)#

C/C++ do-while loop

Syntax:

operation ::= `cir.do` $body `while` $cond (`loop_hints` $loop_hints^)? attr-dict

Represents a C/C++ do-while loop. Identical to cir.while but the condition is evaluated after the body. Because a variable cannot be declared in the condition of a do-while loop, this operation cannot have a cleanup region. A cleanup scope should be created within the body region for any variables within the loop that require cleanup.

Example:

cir.do {
  cir.break
^bb2:
  cir.yield
} while {
  cir.condition(%cond)
}

Traits: NoRegionArguments

Interfaces: LoopLikeOpInterface, LoopOpInterface, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
loop_hints::cir::LoopHintAttrOptimizer hints and guarantees attached to a loop

cir.dyn_cast (::cir::DynamicCastOp)#

Perform dynamic cast on record pointers

Syntax:

operation ::= `cir.dyn_cast` enum($kind) (`relative_layout` $relative_layout^)? $src
              `:` qualified(type($src)) `->` qualified(type($result))
              (qualified($info)^)? attr-dict

The cir.dyn_cast operation models part of the semantics of the dynamic_cast operator in C++. It can be used to perform 3 kinds of casts on record pointers:

  • Down-cast, which casts a base class pointer to a derived class pointer;

  • Side-cast, which casts a class pointer to a sibling class pointer;

  • Cast-to-complete, which casts a class pointer to a void pointer.

The input of the operation must be a record pointer. The result of the operation is either a record pointer or a void pointer.

The parameter kind specifies the semantics of this operation. If its value is ptr, then the operation models dynamic casts on pointers. Otherwise, if its value is ref, the operation models dynamic casts on references. Specifically:

  • When the input pointer is a null pointer value:

    • If kind is ref, the operation will invoke undefined behavior. A sanitizer check will be emitted if sanitizer is on.

    • Otherwise, the operation will return a null pointer value as its result.

  • When the runtime type check fails:

    • If kind is ref, the operation will throw a bad_cast exception.

    • Otherwise, the operation will return a null pointer value as its result.

The info argument gives detailed information about the requested dynamic cast operation. It is an optional #cir.dyn_cast_info attribute that is only present when the operation models a down-cast or a side-cast.

The relative_layout argument specifies whether the Itanium C++ ABI vtable uses relative layout. It is only meaningful when the operation models a cast-to-complete operation.

Examples:

%0 = cir.dyn_cast ptr %p : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
%1 = cir.dyn_cast ptr relative_layout %p : !cir.ptr<!rec_Base>
          -> !cir.ptr<!rec_Derived>
%2 = cir.dyn_cast ref %r : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
          #cir.dyn_cast_info<
            srcRtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>,
            destRtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>,
            runtimeFunc = @__dynamic_cast,
            badCastFunc = @__cxa_bad_cast,
            offsetHint = #cir.int<0> : !s64i
          >

Attributes:#

AttributeMLIR TypeDescription
kind::cir::DynamicCastKindAttrdynamic cast kind
info::cir::DynamicCastInfoAttrABI specific information about a dynamic cast
relative_layout::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

src

pointer to record type

Results:#

Result

Description

result

pointer to any of CIR void type, CIR struct/class type, CIR union type

cir.eh.dispatch (::cir::EhDispatchOp)#

Dispatch to exception handlers based on exception type

Syntax:

operation ::= `cir.eh.dispatch` $eh_token `:` type($eh_token)
              custom<EhDispatchDestinations>($catch_types, $catch_destinations,
              $default_destination, $default_is_catch_all)
              attr-dict

cir.eh.dispatch is a terminator operation that dispatches control flow based on the type of the in-flight exception. It takes an !cir.eh_token as input and branches to an eh handler block based on the exception type.

The operation contains a list of handlers specified as type-block pairs, plus either a catch_all handler or an unwind handler, which continues unwinding if no catch handler matches. Exactly one of catch_all or unwind must be present.

When the type of the in-flight exception matches a type handler, control is transfered to the corresponding block with the eh_token as an argument. The catch_all handler, if present, catches any exception not matched by another type handler. The unwind handler is used when no handler is matched.

A handler may also be a filter, which carries the list of type info symbols permitted by the dynamic exception specification of the enclosing function. A filter handler has the opposite polarity from a catch handler: its destination is taken when the in-flight exception is not one of the listed types. The polarity comes from the Itanium personality routine, which reports a filter failure by selecting the filter clause of the landing pad. A filter handler therefore does not take the place of the default destination, and a dispatch that has one always also has an unwind handler, whose destination is taken when the exception is permitted. A dispatch has at most one filter handler.

Example:

cir.eh.dispatch %eh_token : !cir.eh_token [
  catch (#cir.global_view<@_ZTIi> : !cir.ptr<!u8i>) : ^catch_int,
  catch (#cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>) : ^catch_str,
  catch_all : ^catch_all
]

cir.eh.dispatch %eh_token : !cir.eh_token [
  catch (#cir.global_view<type @_ZTIi> : !cir.ptr<!u8i>) : ^catch_int,
  unwind : ^continue_unwind
]

cir.eh.dispatch %eh_token : !cir.eh_token [
  filter(#cir.global_view<@_ZTIi> : !cir.ptr<!u8i>)
      : ^specification_violated,
  unwind : ^exception_permitted
]

Traits: Terminator

Attributes:#

AttributeMLIR TypeDescription
catch_types::mlir::ArrayAttrarray attribute
default_is_catch_all::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

eh_token

CIR exception handling token type

Successors:#

Successor

Description

default_destination

any successor

catch_destinations

any successor

cir.eh.inflight_exception (::cir::EhInflightOp)#

Materialize the catch clause formal parameter

Syntax:

operation ::= `cir.eh.inflight_exception` (`cleanup` $cleanup^)?
              (`catch_all` $catch_all^)?
              ($catch_type_list^)?
              (`filter` $filter_type_list^)?
              attr-dict

cir.eh.inflight_exception returns two values:

  • exception_ptr: The exception pointer for the inflight exception

  • type_id: the type info index for the exception type This operation is expected to be the first operation in the unwind destination basic blocks of a cir.try_call operation.

The cleanup attribute indicates that clean up code must be run before the values produced by this operation are used to dispatch the exception. This cleanup code must be executed even if the exception is not caught. This helps CIR to pass down more accurate information for LLVM lowering to landingpads.

The catch_all attribute indicates that a catch-all handler exists for the exception being dispatched. When lowered to LLVM IR, this results in a catch ptr null clause on the landing pad. When catch_all is present alongside typed catches, the landing pad will contain both the typed catch clauses and a trailing catch ptr null.

The filter_type_list attribute lists the type info symbols permitted by the dynamic exception specification of the enclosing function. It lowers to the filter clause of the LLVM IR landingpad instruction. An empty list is distinct from an absent one: it represents throw() and lowers to a zero-length filter clause, which the personality routine treats as permitting nothing. Since the exception specification encloses the whole function body, the filter clause always comes after any catch clauses, and it terminates the clause list in the same way that catch_all does.

Example:

%exception_ptr, %type_id = cir.eh.inflight_exception
%exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc]
%exception_ptr, %type_id = cir.eh.inflight_exception cleanup
%exception_ptr, %type_id = cir.eh.inflight_exception catch_all [@_ZTIi]
%exception_ptr, %type_id = cir.eh.inflight_exception filter [@_ZTIi]
%exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi] filter []

Interfaces: InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
cleanup::mlir::UnitAttrunit attribute
catch_all::mlir::UnitAttrunit attribute
catch_type_list::mlir::ArrayAttrflat symbol ref array attribute
filter_type_list::mlir::ArrayAttrflat symbol ref array attribute

Results:#

Result

Description

exception_ptr

pointer to void type

type_id

32-bit unsigned integer

cir.eh.initiate (::cir::EhInitiateOp)#

Initiate exception handling in flattened CIR

Syntax:

operation ::= `cir.eh.initiate` (`cleanup` $cleanup^)? `:` type($eh_token) attr-dict

cir.eh.initiate is the first operation in the unwind destination of a cir.try_call operation after CFG flattening. It returns an opaque !cir.eh_token that represents the in-flight exception.

The cleanup attribute indicates that cleanup code must be executed before the exception is dispatched to any handlers. When present, the operation will be followed by cleanup code before branching to a cir.eh.dispatch operation.

The returned token is passed to cir.begin_cleanup, cir.begin_catch, or cir.eh.dispatch operations.

Example:

^unwind:
  %eh_token = cir.eh.initiate : !cir.eh_token
  cir.br ^dispatch(%eh_token : !cir.eh_token)

^unwind_with_cleanup:
  %eh_token = cir.eh.initiate cleanup : !cir.eh_token
  cir.br ^cleanup(%eh_token : !cir.eh_token)

Interfaces: InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
cleanup::mlir::UnitAttrunit attribute

Results:#

Result

Description

eh_token

CIR exception handling token type

cir.eh.longjmp (::cir::EhLongjmpOp)#

CIR longjmp operation

Syntax:

operation ::= `cir.eh.longjmp` $env `:` qualified(type($env)) attr-dict

Restore the environment (e.g., stack pointer, instruction pointer, signal mask, and other registers) at the time of setjmp() call, by using the information saved in env by setjmp().

Examples:

  cir.eh.longjmp %arg0 : !cir.ptr<!cir.void>

Operands:#

Operand

Description

env

CIR pointer type

cir.eh.setjmp (::cir::EhSetjmpOp)#

CIR setjmp operation

Syntax:

operation ::= `cir.eh.setjmp` $env `:` functional-type($env, results) attr-dict

Saves call-site information (e.g., stack pointer, instruction pointer, signal mask, and other registers) in memory at env for use by longjmp(). In this case, setjmp() returns 0. Following a successful longjmp(), execution proceeds from cir.eh.setjmp with the operation yielding a non-zero value.

Examples:

  %0 = cir.eh.setjmp %arg0 : (!cir.ptr<!cir.void>) -> !s32i

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

env

CIR pointer type

Results:#

Result

Description

res

32-bit signed integer

cir.eh.terminate (::cir::EhTerminateOp)#

Terminate due to an exception that must not escape

Syntax:

operation ::= `cir.eh.terminate` $eh_token `:` type($eh_token) attr-dict

cir.eh.terminate terminates program execution when an exception reaches a point from which the C++ standard does not allow it to propagate, and requires std::terminate() to be called instead. That happens when an exception is thrown while executing cleanup code during unwinding, and when an exception tries to escape a function that cannot throw.

This operation takes an !cir.eh_token and acts as a terminator. In high-level CIR it appears as the only operation in the catch-all handler region of the cir.try that wraps the body of a function that cannot throw, where the token comes from the handler region’s block argument. The handler is a catch-all because such a function terminates on any escaping exception, and it has no cir.begin_catch because the runtime helper this operation lowers to performs the catch. After CFG flattening the token comes from a cir.eh.initiate operation; flattening also produces this operation for throwing calls found in EH cleanup regions.

During EH ABI lowering, this is replaced with target-specific termination code. For the Itanium ABI, the cir.eh.initiate is lowered to cir.eh.inflight_exception (producing an exception pointer), and the cir.eh.terminate becomes a call to __clang_call_terminate with that pointer, followed by an unreachable operation.

Example:

cir.try {
  ...
} catch all (%eh_token : !cir.eh_token) {
  cir.eh.terminate %eh_token : !cir.eh_token
}

And after CFG flattening:

^terminate_unwind:
  %eh_token = cir.eh.initiate : !cir.eh_token
  cir.eh.terminate %eh_token : !cir.eh_token

Traits: Terminator

Operands:#

Operand

Description

eh_token

CIR exception handling token type

cir.eh.typeid (::cir::EhTypeIdOp)#

Compute exception type id from its global type symbol

Syntax:

operation ::= `cir.eh.typeid` $type_sym attr-dict

Returns the exception type id for a given global symbol representing a type.

Example:

%type_id = cir.eh.typeid @_ZTIi

Traits: AlwaysSpeculatableImplTrait

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

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
type_sym::mlir::FlatSymbolRefAttrflat symbol reference attribute

Results:#

Result

Description

type_id

32-bit unsigned integer

cir.eh.unexpected (::cir::EhUnexpectedOp)#

Handle an exception that violates an exception specification

Syntax:

operation ::= `cir.eh.unexpected` $eh_token `:` type($eh_token) attr-dict

cir.eh.unexpected signals that the in-flight exception violated the dynamic exception specification of the enclosing function, and that std::unexpected() must be called. The C++ standard requires this when an exception that the specification does not permit tries to escape the function.

This operation takes a !cir.eh_token and acts as a terminator. In high-level CIR it is the only operation in the unexpected handler region of a cir.try operation, where the token comes from the handler region’s block argument. After CFG flattening the token comes from a cir.eh.initiate operation.

Like cir.eh.terminate, this operation is ABI-agnostic. During EH ABI lowering it is replaced with target-specific code. For the Itanium ABI it becomes a call to __cxa_call_unexpected with the exception pointer, followed by an unreachable operation.

Example:

^unexpected:
  %eh_token = cir.eh.initiate : !cir.eh_token
  cir.eh.unexpected %eh_token : !cir.eh_token

Traits: Terminator

Operands:#

Operand

Description

eh_token

CIR exception handling token type

cir.end_catch (::cir::EndCatchOp)#

End a catch handler

Syntax:

operation ::= `cir.end_catch` $catch_token `:` type($catch_token) attr-dict

cir.end_catch marks the end of a catch handler. It takes the !cir.catch_token returned by the corresponding cir.begin_catch operation.

In the high-level CIR representation, this operation appears inside the cleanup region of the cir.cleanup.scope that follows cir.begin_catch in a catch handler region. In the flattened CIR representation, it appears at the end of a path that exits the catch handler.

Example:

// High-level form (inside cir.try catch handler region):
} catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%eh_token : !cir.eh_token) {
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
  cir.cleanup.scope {
    // Handle exception...
    cir.yield
  } cleanup eh {
    cir.end_catch %catch_token : !cir.catch_token
    cir.yield
  }
}

// Flattened form:
^catch_int(%eh_token : !cir.eh_token):
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
  // Handle exception...
  cir.end_catch %catch_token : !cir.catch_token
  cir.br ^continue

Operands:#

Operand

Description

catch_token

CIR catch token type

cir.end_cleanup (::cir::EndCleanupOp)#

End a cleanup block during exception unwinding

Syntax:

operation ::= `cir.end_cleanup` $cleanup_token `:` type($cleanup_token) attr-dict

cir.end_cleanup marks the end of a cleanup block during exception unwinding. It takes the !cir.cleanup_token returned by the corresponding cir.begin_cleanup operation.

After the cleanup is complete, control typically transfers to either a catch dispatch block or continues unwinding via cir.resume.

Example:

^cleanup(%eh_token : !cir.eh_token):
  %cleanup_token = cir.begin_cleanup %eh_token : !cir.eh_token
                                               -> !cir.cleanup_token
  cir.call @destructor() : () -> ()
  cir.end_cleanup %cleanup_token : !cir.cleanup_token
  cir.br ^dispatch(%eh_token : !cir.eh_token)

Operands:#

Operand

Description

cleanup_token

CIR cleanup token type

cir.exp (::cir::ExpOp)#

Computes the floating-point base-e exponential value

Syntax:

operation ::= `cir.exp` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.exp computes the exponential of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.exp10 (::cir::Exp10Op)#

Computes the floating-point base-10 exponential value

Syntax:

operation ::= `cir.exp10` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.exp10 computes the base-10 exponential of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.exp2 (::cir::Exp2Op)#

Computes the floating-point base-2 exponential value

Syntax:

operation ::= `cir.exp2` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.exp2 computes the base-2 exponential of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.expect (::cir::ExpectOp)#

Tell the optimizer that two values are likely to be equal.

Syntax:

operation ::= `cir.expect` `(` $val`,` $expected (`,` $prob^)? `)` `:` type($val) attr-dict

The cir.expect operation may take 2 or 3 arguments.

When the argument prob is missing, this operation effectively models the __builtin_expect builtin function. It tells the optimizer that val and expected are likely to be equal.

When the argument prob is present, this operation effectively models the __builtin_expect_with_probability builtin function. It tells the optimizer that val and expected are equal to each other with a certain probability.

val and expected must be integers and their types must match.

The result of this operation is always equal to val.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
prob::mlir::FloatAttr64-bit float attribute

Operands:#

Operand

Description

val

fundamental integer type

expected

fundamental integer type

Results:#

Result

Description

result

fundamental integer type

cir.extract_member (::cir::ExtractMemberOp)#

Extract the value of a member of a record value

Syntax:

operation ::= `cir.extract_member` $record `[` $index `]` attr-dict
              `:` qualified(type($record)) `->` qualified(type($result))

The cir.extract_member operation extracts the value of a particular member from the input record. Unlike cir.get_member which derives pointers, this operation operates on values. It takes a value of record type and extracts the value of the specified record member from the input record value.

Currently cir.extract_member does not work on unions.

Example:

// Suppose we have a record with multiple members.
!s32i = !cir.int<s, 32>
!s8i = !cir.int<s, 32>
!record_ty = !cir.record<"struct.Bar" {!s32i, !s8i}>

// And suppose we have a value of the record type.
%0 = cir.const #cir.const_record<{#cir.int<1> : !s32i,
                              #cir.int<2> : !s8i}> : !record_ty

// Extract the value of the second member of the record.
%1 = cir.extract_member %0[1] : !record_ty -> !s8i

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
index::mlir::IntegerAttr64-bit signless integer attribute

Operands:#

Operand

Description

record

CIR record type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.fabs (::cir::FAbsOp)#

Computes the floating-point absolute value

Syntax:

operation ::= `cir.fabs` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.fabs computes the absolute value of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fadd (::cir::FAddOp)#

Floating-point addition

Syntax:

operation ::= `cir.fadd` $lhs `,` $rhs `:` type($lhs) (`fenv` `` $fenv^)? prop-dict attr-dict

The cir.fadd operation performs floating-point addition on its operands. Both operands and the result must have the same floating-point scalar, vector-of-float or matrix-of-float type.

Example:

%0 = cir.fadd %a, %b : !cir.float
%1 = cir.fadd %a, %b : !cir.double
%2 = cir.fadd %va, %vb : !cir.vector<4 x !cir.float>
%3 = cir.fadd %ma, %mb : !cir.matrix<3 x 3 x !cir.float>

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: BinaryOpInterface, CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

lhs

floating point or vector/matrix of floating point type

rhs

floating point or vector/matrix of floating point type

Results:#

Result

Description

result

floating point or vector/matrix of floating point type

cir.fdiv (::cir::FDivOp)#

Floating-point division

Syntax:

operation ::= `cir.fdiv` $lhs `,` $rhs `:` type($lhs) (`fenv` `` $fenv^)? prop-dict attr-dict

The cir.fdiv operation performs floating-point division on its operands. Both operands and the result must have the same floating-point scalar or ector-of-float or matrix-of-float type.

Example:

%0 = cir.fdiv %a, %b : !cir.float
%1 = cir.fdiv %a, %b : !cir.double
%2 = cir.fdiv %va, %vb : !cir.vector<4 x !cir.float>
%3 = cir.fdiv %ma, %mb : !cir.matrix<3 x 3 x !cir.float>

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: BinaryOpInterface, CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

lhs

floating point or vector/matrix of floating point type

rhs

floating point or vector/matrix of floating point type

Results:#

Result

Description

result

floating point or vector/matrix of floating point type

cir.ffs (::cir::BitFfsOp)#

Get the position of the least significant 1-bit in input

Syntax:

operation ::= `cir.ffs` $input `:` type($result) attr-dict

Compute the 1-based position of the least significant 1-bit of the input.

The input integer must be a signed integer. The cir.ffs operation returns one plus the index of the least significant 1-bit of the input signed integer. If the input integer is 0, cir.ffs yields 0.

Example:

!s32i = !cir.int<s, 32>

// %0 = 0x0010_1000
%0 = cir.const #cir.int<40> : !s32i
// #1 will be 4 since the 4th least significant bit is 1.
%1 = cir.ffs %0 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

signed integer type of widths 32/64

Results:#

Result

Description

result

signed integer type of widths 32/64

cir.floor (::cir::FloorOp)#

Computes the floating-point floor value

Syntax:

operation ::= `cir.floor` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.floor computes the floor of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Example:

// $x : !cir.double
%y = cir.floor %x : !cir.double

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fma (::cir::FMAOp)#

Fused Multiply-Add operation

Syntax:

operation ::= `cir.fma` $a `,` $b `,` $c `:` type($a) (`fenv` `` $fenv^)? attr-dict

Computes the fused multiply-add of three floating-point values or vector.

The inputs must be either: • floating-point scalar types, or • vectors whose element type is floating-point.

The result type must match the input type exactly.

Examples: // scalar

// vector

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

a

floating point or vector of floating point type

b

floating point or vector of floating point type

c

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fmaximum (::cir::FMaximumOp)#

Returns the larger of two floating-point values (IEEE 754-2019)

Syntax:

operation ::= `cir.fmaximum` $lhs `,` $rhs `:` qualified(type($lhs))
              (`fenv` `` $fenv^)? attr-dict

cir.fmaximum returns the larger of its two operands according to IEEE 754-2019 semantics. If either operand is NaN, NaN is returned.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fmaxnum (::cir::FMaxNumOp)#

Returns the larger of two floating-point values

Syntax:

operation ::= `cir.fmaxnum` $lhs `,` $rhs `:` qualified(type($lhs))
              (`fenv` `` $fenv^)? attr-dict

cir.fmaxnum returns the larger of its two operands. If one operand is NaN, the other operand is returned.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fminimum (::cir::FMinimumOp)#

Returns the smaller of two floating-point values (IEEE 754-2019)

Syntax:

operation ::= `cir.fminimum` $lhs `,` $rhs `:` qualified(type($lhs))
              (`fenv` `` $fenv^)? attr-dict

cir.fminimum returns the smaller of its two operands according to IEEE 754-2019 semantics. If either operand is NaN, NaN is returned.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fminnum (::cir::FMinNumOp)#

Returns the smaller of two floating-point values

Syntax:

operation ::= `cir.fminnum` $lhs `,` $rhs `:` qualified(type($lhs))
              (`fenv` `` $fenv^)? attr-dict

cir.fminnum returns the smaller of its two operands. If one operand is NaN, the other operand is returned.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fmod (::cir::FModOp)#

Computes the floating-point remainder

Syntax:

operation ::= `cir.fmod` $lhs `,` $rhs `:` qualified(type($lhs))
              (`fenv` `` $fenv^)? attr-dict

cir.fmod computes the floating-point remainder of dividing the first operand by the second operand.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fmul (::cir::FMulOp)#

Floating-point multiplication

Syntax:

operation ::= `cir.fmul` $lhs `,` $rhs `:` type($lhs) (`fenv` `` $fenv^)? prop-dict attr-dict

The cir.fmul operation performs floating-point multiplication on its operands. Both operands and the result must have the same floating-point scalar or vector-of-float type.

Example:

%0 = cir.fmul %a, %b : !cir.float
%1 = cir.fmul %a, %b : !cir.double
%2 = cir.fmul %va, %vb : !cir.vector<4 x !cir.float>

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: BinaryOpInterface, CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

lhs

floating point or vector/matrix of floating point type

rhs

floating point or vector/matrix of floating point type

Results:#

Result

Description

result

floating point or vector/matrix of floating point type

cir.fmuladd (::cir::FMulAddOp)#

Contractable fused multiply-add operation

Syntax:

operation ::= `cir.fmuladd` $a `,` $b `,` $c `:` type($a) (`fenv` `` $fenv^)? attr-dict

Computes (a * b) + c, allowing the multiply and add to be fused (or not) into a single rounding step at the target’s discretion. It lowers to the llvm.fmuladd intrinsic (or its constrained variant when an fenv attribute is present).

Unlike cir.fma, which maps to llvm.fma and guarantees a single rounding, cir.fmuladd expresses the FP-contraction relaxation used for a * b + c under -ffp-contract=on / fast, where the backend is free to emit either a fused or an unfused sequence.

The inputs must be either: • floating-point scalar types, or • vectors whose element type is floating-point.

The result type must match the input type exactly.

Examples: // scalar

// vector

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

a

floating point or vector of floating point type

b

floating point or vector of floating point type

c

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.fneg (::cir::FNegOp)#

Floating-point negation

Syntax:

operation ::= `cir.fneg` $input `:` type($input) attr-dict

The cir.fneg operation negates the operand. The operand and result must have the same type.

Example:

%1 = cir.fneg %0 : !cir.float
%3 = cir.fneg %2 : !cir.double
%5 = cir.fneg %4 : !cir.vector<4 x !cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

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

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.for (::cir::ForOp)#

C/C++ for loop counterpart

Syntax:

operation ::= `cir.for` `:` `cond` $cond
              `body` $body
              `step` $step
              (`cleanup` enum($cleanupKind) $cleanup^)?
              (`loop_hints` $loop_hints^)?
              attr-dict

Represents a C/C++ for loop. It consists of three or four regions:

  • cond: single block region with the loop’s condition. Should be terminated with a cir.condition operation.

  • body: contains the loop body and an arbitrary number of blocks.

  • step: single block region with the loop’s step.

  • cleanup: optional region that runs on every per-iteration exit edge (condition-false exit, end-of-iteration after the step, break/continue, and EH unwinding when the cleanup kind includes EH). This is used to destroy a condition variable whose lifetime is a single iteration. When present, it carries a cleanup kind matching cir.cleanup.scope (normal or all).

Example:

cir.for : cond {
  cir.condition(%val)
} body {
  cir.break
^bb2:
  cir.yield
} step {
  cir.yield
}

cir.for : cond {
  cir.condition(%val)
} body {
  cir.yield
} step {
  cir.yield
} cleanup all {
  cir.yield
}

Traits: NoRegionArguments

Interfaces: LoopLikeOpInterface, LoopOpInterface, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
cleanupKind::cir::CleanupKindAttrcleanup kind
loop_hints::cir::LoopHintAttrOptimizer hints and guarantees attached to a loop

cir.frame_address (::cir::FrameAddrOp)#

The frame address of the current function, or of one of its callers

Syntax:

operation ::= `cir.frame_address` `(` $level `)` attr-dict `:` qualified(type($result))

Represents a call to builtin function __builtin_frame_address in CIR. This builtin function returns the frame address of the current function, or of one of its callers. The frame is the area on the stack that holds local variables and saved registers. The frame address is normally the address of the first word pushed on to the stack by the function. However, the exact definition depends upon the processor and the calling convention. If the processor has a dedicated frame pointer register, and the function has a frame, then __builtin_frame_address returns the value of the frame pointer register.

The level argument is number of frames to scan up the call stack. For instance, value of 0 yields the frame address of the current function, value of 1 yields the frame address of the caller of the current function, and so forth.

Examples:

%p = frame_address(%level) : !cir.ptr<!u8i>

Operands:#

Operand

Description

level

32-bit unsigned integer

Results:#

Result

Description

result

CIR pointer type

cir.freeze (::cir::FreezeOp)#

Stop propagation of undef and poison values

Syntax:

operation ::= `cir.freeze` $input `:` type($input) attr-dict

The cir.freeze operation takes a single operand and returns a value of the same type. If the operand is a poison or undef value, cir.freeze returns an arbitrary, but fixed, value of the operand type. Otherwise it returns the operand unchanged.

Example:

%1 = cir.freeze %0 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.frem (::cir::FRemOp)#

Floating-point remainder

Syntax:

operation ::= `cir.frem` $lhs `,` $rhs `:` type($lhs) (`fenv` `` $fenv^)? prop-dict attr-dict

The cir.frem operation computes the floating-point remainder of its operands. Both operands and the result must have the same floating-point scalar or vector-of-float type.

Example:

%0 = cir.frem %a, %b : !cir.float
%1 = cir.frem %a, %b : !cir.double
%2 = cir.frem %va, %vb : !cir.vector<4 x !cir.float>

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: BinaryOpInterface, CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.frexp (::cir::FrexpOp)#

Decomposes a floating-point value into significand and exponent

Syntax:

operation ::= `cir.frexp` $src `:` type($src) `->` type($result) `,` type($exp) attr-dict

cir.frexp splits a floating-point value into a normalized significand (in the range [0.5, 1.0)) and an integral power-of-two exponent, such that src = significand * 2^exp. Returns both as separate results.

Lowers to llvm.frexp.

Example:

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

src

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

exp

integer type

cir.fshl (::cir::FshlOp)#

Funnel shift left

Syntax:

operation ::= `cir.fshl` $a `,` $b `,` $c `:` type($a) attr-dict

The cir.fshl operation concatenates a and b (with a in the high half), shifts the concatenation left by c bit positions, and returns the high half of the result. The shift amount is treated modulo the bitwidth of the operands.

All operands and the result must have the same integer type or vector-of-integer type.

Example:

%r = cir.fshl %a, %b, %c : !u32i
%v = cir.fshl %va, %vb, %vc : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

a

integer or vector of integer type

b

integer or vector of integer type

c

integer or vector of integer type

Results:#

Result

Description

result

integer or vector of integer type

cir.fshr (::cir::FshrOp)#

Funnel shift right

Syntax:

operation ::= `cir.fshr` $a `,` $b `,` $c `:` type($a) attr-dict

The cir.fshr operation concatenates a and b (with a in the high half), shifts the concatenation right by c bit positions, and returns the low half of the result. The shift amount is treated modulo the bitwidth of the operands.

All operands and the result must have the same integer type or vector-of-integer type.

Example:

%r = cir.fshr %a, %b, %c : !u32i
%v = cir.fshr %va, %vb, %vc : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

a

integer or vector of integer type

b

integer or vector of integer type

c

integer or vector of integer type

Results:#

Result

Description

result

integer or vector of integer type

cir.fsub (::cir::FSubOp)#

Floating-point subtraction

Syntax:

operation ::= `cir.fsub` $lhs `,` $rhs `:` type($lhs) (`fenv` `` $fenv^)? prop-dict attr-dict

The cir.fsub operation performs floating-point subtraction on its operands. Both operands and the result must have the same floating-point scalar vector-of-float or matrix-of-float type.

Example:

%0 = cir.fsub %a, %b : !cir.float
%1 = cir.fsub %a, %b : !cir.double
%2 = cir.fsub %va, %vb : !cir.vector<4 x !cir.float>
%3 = cir.fsub %ma, %mb : !cir.matrix<3 x 3 x !cir.float>

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: BinaryOpInterface, CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

lhs

floating point or vector/matrix of floating point type

rhs

floating point or vector/matrix of floating point type

Results:#

Result

Description

result

floating point or vector/matrix of floating point type

cir.func (::cir::FuncOp)#

Declare or define a function

The cir.func operation defines a function, similar to the mlir::FuncOp built-in.

The function linkage information is specified by linkage, as defined by GlobalLinkageKind attribute.

The calling_conv attribute specifies the calling convention of the function. By default calling convention is CallingConv::C. When printed, C calling convention is omitted. Other calling conventions are printed as cc(<mnemonic>), e.g. cc(amdgpu_kernel).

A compiler builtin function must be marked as builtin for further processing when lowering from CIR.

The coroutine keyword is used to mark a coroutine function, which requires at least one cir.await instruction to be used in its body.

The lambda translates to a C++ operator() that implements a lambda, this allow callsites to make certain assumptions about the real function nature when writing analysis.

The no_proto keyword is used to identify functions that were declared without a prototype and, consequently, may contain calls with invalid arguments and undefined behavior.

The global_ctor keyword indicates whether a function should execute before main() function, as specified by __attribute__((constructor)). An execution priority can also be specified global_ctor(<priority>). Similarly, for global destructors both global_dtor and global_dtor(<priority>) are available.

The no_inline attribute marks a function that should not be inlined. The always_inline attribute marks a function that should always be inlined. The inline_hint attribute suggests that the function should be inlined.

The personality attribute specifies the personality function to use for exception handling. This is a symbol reference to the personality function (e.g., @__gxx_personality_v0 for C++ exceptions).

The ‘comdat’ attribute marks the function as belonging to a COMDAT group. This attribute includes an optional ‘group’ name, which if not provided, results in the function’s symbol name being used.

Example:

// External function definitions.
cir.func @abort()

// A function with internal linkage.
cir.func internal @count(%x: i64) -> (i64)
  return %x : i64

// Linkage information
cir.func linkonce_odr @some_method(...)

// Calling convention information
cir.func @func1(...) cc(amdgpu_kernel)

// Inline information
cir.func no_inline @some_method(...)

// Builtin function
cir.func builtin @__builtin_coro_end(!cir.ptr<i8>, !cir.bool) -> !cir.bool
// Coroutine
cir.func coroutine @_Z10silly_taskv() -> !CoroTask {
  ...
  cir.await(...)
  ...
}

Traits: AutomaticAllocationScope, IsolatedFromAbove, SymbolName, SymbolVisibility

Interfaces: ArgAndResultAttrsOpInterface, CIRGlobalValueInterface, CallableOpInterface, FunctionOpInterface, Symbol

Attributes:#

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
function_type::mlir::TypeAttrtype attribute of CIR function type
builtin::mlir::UnitAttrunit attribute
coroutine::mlir::UnitAttrunit attribute
flattened_coroutine::mlir::UnitAttrunit attribute
inline_kind::cir::InlineKindAttrinline kind
lambda::mlir::UnitAttrunit attribute
no_proto::mlir::UnitAttrunit attribute
dso_local::mlir::UnitAttrunit attribute
linkage::cir::GlobalLinkageKindAttrlinkage kind
calling_conv::cir::CallingConvAttrcalling convention
sym_visibility::mlir::StringAttrstring attribute
comdat::mlir::StringAttrstring attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute
preferred_alignment::mlir::IntegerAttr64-bit signless integer attribute
arg_attrs::mlir::ArrayAttrArray of dictionary attributes
res_attrs::mlir::ArrayAttrArray of dictionary attributes
aliasee::mlir::FlatSymbolRefAttrflat symbol reference attribute
memory_effects::cir::MemoryEffectsAttrDescribes the possible memory effects of a function or callee
personality::mlir::FlatSymbolRefAttrflat symbol reference attribute
global_ctor_priority::mlir::IntegerAttr32-bit signless integer attribute whose minimum value is 101 whose maximum value is 65535
global_dtor_priority::mlir::IntegerAttr32-bit signless integer attribute whose minimum value is 101 whose maximum value is 65535
func_info::mlir::Attributefunction information attribute
annotations::mlir::ArrayAttrarray of cir.annotation attributes
uwtable::cir::UnwindTableKindAttrEncodes the unwind table kind for a function.
frame_pointer::cir::FramePointerKindAttrEncodes the frame pointer kind for a function or a module.

cir.get_bitfield (::cir::GetBitfieldOp)#

Get the information for a bitfield member

Syntax:

operation ::= `cir.get_bitfield` (`align` `(` $alignment^ `)`)?
              ` ` `(`$bitfield_info `,` $addr
              (` ` `{` `is_volatile` $is_volatile^ `}`)? attr-dict `:`
              qualified(type($addr)) `)` `->` type($result)

The cir.get_bitfield operation provides a load-like access to a bit field of a record.

It expects a name if a bit field, a pointer to a storage in the base record, a type of the storage, a name of the bitfield, a size the bit field, an offset of the bit field and a sign.

A unit attribute volatile can be used to indicate a volatile load of the bitfield.

  cir.get_bitfield(#bfi, %0 {is_volatile} : !cir.ptr<!u64i>) -> !s32i

Example: Suppose we have a struct with multiple bitfields stored in different members. The cir.get_bitfield operation gets the value of the bitfield.

typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
} S;

int load_bitfield(S& s) {
  return s.e;
}
// 'e' is in the storage with the index 1
!cir.struct<"S" packed {!u64i, !u16i,
                        pad !cir.array<!u8i x 2>}>
#bfi_e = #cir.bitfield_info<name = "e", storage_type = !u16i, size = 15,
                            offset = 0, is_signed = true>

%2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
%3 = cir.get_member %2[1] {name = "e"} : !cir.ptr<!record_type>
                                                         -> !cir.ptr<!u16i>
%4 = cir.get_bitfield align(4) (#bfi_e, %3 : !cir.ptr<!u16i>) -> !s32i

Attributes:#

AttributeMLIR TypeDescription
bitfield_info::cir::BitfieldInfoAttrRepresents info for a bit-field member
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

addr

CIR pointer type

Results:#

Result

Description

result

integer or boolean type

cir.get_element (::cir::GetElementOp)#

Get the address of an array element

Syntax:

operation ::= `cir.get_element` $base`[` $index `:` type($index) `]` attr-dict
              `:` qualified(type($base)) `->` qualified(type($result))

The cir.get_element operation gets the address of a particular element from the base array.

It expects a pointer to the base array and the index of the element. The result pointer preserves the address space of the base pointer.

Example:

// Suppose we have a array.
!s32i = !cir.int<s, 32>
!arr_ty = !cir.array<!s32i x 4>

// Get the address of the element at index 1.
%elem_1 = cir.get_element %0[1 : !s32i] : !cir.ptr<!array_ty> -> !cir.ptr<!s32i>

// Get the address of the element at index %i.
%i = ...
%elem_i = cir.get_element %0[%i : !s32i] : !cir.ptr<!array_ty> -> !cir.ptr<!s32i>

// With address space (e.g., GPU private memory):
%elem_gpu = cir.get_element %gpu_arr[%i : !s32i] :
  !cir.ptr<!cir.array<!s32i x 10>, target_address_space(5)> ->
  !cir.ptr<!s32i, target_address_space(5)>

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

base

pointer to array type

index

fundamental integer type

Results:#

Result

Description

result

CIR pointer type

cir.get_global (::cir::GetGlobalOp)#

Get the address of a global variable

Syntax:

operation ::= `cir.get_global` (`thread_local` $tls^)?
              (`static_local` $static_local^)?
              $name `:` qualified(type($addr)) attr-dict

The cir.get_global operation retrieves the address pointing to a named global variable. If the global variable is marked constant, writing to the resulting address (such as through a cir.store operation) is undefined. The resulting type must always be a !cir.ptr<...> type with the same address space as the global variable.

Addresses of thread local globals can only be retrieved if this operation is marked thread_local, which indicates the address isn’t constant.

The static_local attribute indicates that this global is a function-local static variable that requires guarded initialization (e.g., C++ static local variables with non-constant initializers).

Example:

%x = cir.get_global @gv : !cir.ptr<i32>
...
%y = cir.get_global thread_local @tls_gv : !cir.ptr<i32>
...
%w = cir.get_global static_local @func_static : !cir.ptr<i32>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
name::mlir::FlatSymbolRefAttrflat symbol reference attribute
tls::mlir::UnitAttrunit attribute
static_local::mlir::UnitAttrunit attribute

Results:#

Result

Description

addr

CIR pointer type

cir.get_member (::cir::GetMemberOp)#

Get the address of a member of a record

Syntax:

operation ::= `cir.get_member` $addr `[` $index_attr `]` `{` `name` `=` $name `}` attr-dict
              `:` qualified(type($addr)) `->` qualified(type($result))

The cir.get_member operation gets the address of a particular named member from the input record.

It expects a pointer to the base record as well as the name of the member and its field index.

Example:

// Suppose we have a record with multiple members.
!s32i = !cir.int<s, 32>
!s8i = !cir.int<s, 8>
!ty_B = !cir.record<"struct.B" {!s32i, !s8i}>

// Get the address of the member at index 1.
%1 = cir.get_member %0[1] {name = "i"} : (!cir.ptr<!ty_B>) -> !cir.ptr<!s8i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
index_attr::mlir::IntegerAttrindex attribute

Operands:#

Operand

Description

addr

CIR pointer type

Results:#

Result

Description

result

CIR pointer type

cir.get_method (::cir::GetMethodOp)#

Resolve a method to a function pointer as callee

Syntax:

operation ::= `cir.get_method` $method `,` $object
              `:` `(` qualified(type($method)) `,` qualified(type($object)) `)`
              `->` `(` qualified(type($callee)) `,` qualified(type($adjusted_this)) `)`
              attr-dict

The cir.get_method operation takes a pointer to method (!cir.method) and a pointer to a class object (!cir.ptr<!cir.record>>) as input, and yields a function pointer that points to the actual function corresponding to the input method. The operation also applies any necessary adjustments to the input object pointer for calling the method and yields the adjusted pointer.

This operation is generated when calling a method through a pointer-to- member-function in C++:

// Foo *object;
// int arg;
// void (Foo::*method)(int);

(object->*method)(arg);

The code above will generate CIR similar to:

%callee, %this = cir.get_method %method, %object
cir.call %callee(%this, %arg)

The method type must match the callee type. That is:

  • The return type of the method must match the return type of the callee.

  • The first parameter of the callee must have type !cir.ptr<!cir.void>.

  • Types of other parameters of the callee must match the method’s parameters after the implicit this pointer.

Operands:#

Operand

Description

method

CIR type that represents C++ pointer-to-member-function type

object

pointer to record type

Results:#

Result

Description

callee

pointer to function type

adjusted_this

pointer to void type

cir.get_runtime_member (::cir::GetRuntimeMemberOp)#

Get the address of a member of a record

Syntax:

operation ::= `cir.get_runtime_member` $addr `[` $member `:` qualified(type($member)) `]` attr-dict
              `:` qualified(type($addr)) `->` qualified(type($result))

The cir.get_runtime_member operation gets the address of a member from the input record. The target member is given by a value of type !cir.data_member (i.e. a pointer-to-data-member value).

This operation differs from cir.get_member in when the target member can be determined. For the cir.get_member operation, the target member is specified as a constant index so the member it returns access to is known when the operation is constructed. For the cir.get_runtime_member operation, the target member is given through a pointer-to-data-member value which is unknown until the program being compiled is executed. In other words, cir.get_member represents a normal member access through the . operator in C/C++:

struct Foo { int x; };
Foo f;
(void)f.x;  // cir.get_member

And cir.get_runtime_member represents a member access through the .* or the ->* operator in C++:

struct Foo { int x; }
Foo f;
Foo *p;
int Foo::*member;

(void)f.*member;   // cir.get_runtime_member
(void)p->*member;  // cir.get_runtime_member

This operation expects a pointer to the base record as well as the pointer to the target member.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

addr

pointer to record type

member

CIR type that represents a pointer-to-data-member in C++

Results:#

Result

Description

result

CIR pointer type

cir.global (::cir::GlobalOp)#

Declare or define a global variable

Syntax:

operation ::= `cir.global` ($sym_visibility^)?
              ($global_visibility^)?
              (`constant` $constant^)?
              enum($linkage)
              custom<ComdatName>($comdat)
              (`tls_model` `=` enum($tls_model)^)?
              (`tls_refs` `=` $tls_refs^)?
              (`dso_local` $dso_local^)?
              (`dynamic_init_guard` `` $dynamic_init_guard^)?
              (` ` custom<GlobalMemorySpace>($addr_space)^ )?
              $sym_name
              (`alias` `(` $aliasee^ `)`)?
              custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value,
              $ctorRegion, $dtorRegion)
              ($annotations^)?
              (`align` `(` $alignment^ `)`)?
              (`ast` `(` $ast^ `)`)?
              (`dynamic_init_info` `` $dynamic_init_info^)?
              (`section` `(` $section^ `)`)?
              (`strictfp` $strictfp^)?
              (`init_priority` `(` $init_priority^ `)`)?
              attr-dict

The cir.global operation declares or defines a named global variable.

The backing memory for the variable is allocated statically and is described by the type of the variable.

The linkage tracks C/C++ linkage types, currently very similar to LLVM’s. Symbol visibility in sym_visibility is defined in terms of MLIR’s visibility and verified to be in accordance to linkage.

The dynamic_init_guard attribute indicates that this global requires guarded dynamic initialization via the Itanium __cxa_guard_* protocol (e.g., C++ static local variables with non-constant initializers, or namespace-scope variables with vague linkage such as weak/linkonce_odr inline variables). It contains the mangled name of the guard variable.

The strictfp attribute indicates that the dynamic initialization emitted into the ctorRegion/dtorRegion runs under a constrained floating-point environment. LoweringPrepare forwards it to the strictfp attribute of the generated __cxx_global_var_init function.

The init_priority attribute records the priority specified by a C++ init_priority attribute on the source variable declaration. LoweringPrepare uses it to place the dynamic initializer emitted from ctorRegion into a priority-specific _GLOBAL__I_<priority> function instead of the default _GLOBAL__sub_I_* function.

Traits: NoRegionArguments, SymbolName, SymbolVisibility

Interfaces: CIRGlobalValueInterface, RegionBranchOpInterface, Symbol

Attributes:#

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
sym_visibility::mlir::StringAttrstring attribute
sym_type::mlir::TypeAttrany type attribute
linkage::cir::GlobalLinkageKindAttrlinkage kind
addr_space::mlir::ptr::MemorySpaceAttrInterfaceMemorySpaceAttrInterface instance
tls_model::cir::TLSModelAttrTLS model
tls_refs::cir::ThreadLocalGlobalWrapperInitAttrWrapper and Init function names for thread local variables
initial_value::mlir::Attributeany attribute
comdat::mlir::StringAttrstring attribute
dynamic_init_guard::cir::DynamicInitGuardAttrGuard variable name for guarded dynamic initialization
alignment::mlir::IntegerAttr64-bit signless integer attribute
ast::cir::ASTVarDeclInterfaceASTVarDeclInterface instance
dynamic_init_info::cir::DynamicInitInfoAttrVariable facts needed by guarded dynamic initialization lowering
section::mlir::StringAttrstring attribute
annotations::mlir::ArrayAttrarray of cir.annotation attributes
aliasee::mlir::FlatSymbolRefAttrflat symbol reference attribute
strictfp::mlir::UnitAttrunit attribute
init_priority::mlir::IntegerAttr32-bit signless integer attribute

cir.goto (::cir::GotoOp)#

Syntax:

operation ::= `cir.goto` $label attr-dict

Transfers control to the specified label. This requires a corresponding cir.label to exist and is used by to represent source level gotos that jump across region boundaries. Alternatively, cir.br is used to construct goto’s that don’t violate such boundaries.

cir.goto is completely symbolic (i.e. it “jumps” on a label that isn’t yet materialized) and should be taken into account by passes and analysis when deciding if it’s safe to make some assumptions about a given region or basic block.

Example:

  int test(int x) {
    if (x)
      goto label;
    {
      x = 10;
  label:
      return x;
    }
  }
  cir.scope {  // REGION #1
    %2 = cir.load %0 : !cir.ptr<!s32i>, !s32i
    %3 = cir.cast int_to_bool %2 : !s32i -> !cir.bool
    cir.if %3 {
      cir.goto "label"
    }
    }
    cir.scope {  // REGION #2
      %2 = cir.const #cir.int<10> : !s32i
      cir.store %2, %0 : !s32i, !cir.ptr<!s32i>
      cir.br ^bb1
    ^bb1:  // pred: ^bb0
      cir.label "label"
      %3 = cir.load %0 : !cir.ptr<!s32i>, !s32i
      cir.store %3, %1 : !s32i, !cir.ptr<!s32i>
      %4 = cir.load %1 : !cir.ptr<!s32i>, !s32i
      cir.return %4 : !s32i
    }
    cir.unreachable

Traits: Terminator

Attributes:#

AttributeMLIR TypeDescription
label::mlir::StringAttrstring attribute

cir.if (::cir::IfOp)#

The if-then-else operation

The cir.if operation represents an if-then-else construct for conditionally executing two regions of code. The operand is a cir.bool type.

Examples:

cir.if %cond  {
  ...
} else {
  ...
}

cir.if %cond  {
  ...
}

cir.if %cond  {
  ...
  cir.br ^a
^a:
  cir.yield
}

cir.if defines no values and the ‘else’ can be omitted. The if/else regions must be terminated. If the region has only one block, the terminator can be left out, and cir.yield terminator will be inserted implictly. Otherwise, the region must be explicitly terminated.

Traits: AutomaticAllocationScope, NoRegionArguments, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

Operands:#

Operand

Description

condition

CIR bool type

cir.inc (::cir::IncOp)#

Increment an integer by one

Syntax:

operation ::= `cir.inc` (`nsw` $no_signed_wrap^)?
              $input `:` type($input) attr-dict

The cir.inc operation increments the operand by one. The operand and result must have the same type.

The optional nsw (no signed wrap) attribute indicates that the result is poison if signed overflow occurs.

Example:

%1 = cir.inc %0 : !s32i
%3 = cir.inc nsw %2 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

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

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

integer or vector of integer type

Results:#

Result

Description

result

integer or vector of integer type

cir.indirect_br (::cir::IndirectBrOp)#

Indirect branch

Syntax:

operation ::= `cir.indirect_br` $addr ( `poison` $poison^ )? `:` qualified(type($addr)) `,`
              custom<IndirectBrOpSucessors>(ref(type($addr)),
              $successors,
              $succ_operands,
              type($succ_operands))
              attr-dict

The cir.indirectbr operation represents an indirect branch to one of several possible successor blocks. The target block is computed from the value of the given address operand.

This operation is typically generated when handling constructs like the GCC extension &&label combined with an indirect goto *ptr;.

The poison attribute is used to mark an indirectbr that was created but is known to be invalid, for instance when a label address was taken but no indirect branch was ever emitted.

Example:

  %0 = cir.block_address <@A, "A"> : !cir.ptr<!void>
  cir.indirectbr %0 poison : <!void>, [
  ^bb1
  ]

Traits: AlwaysSpeculatableImplTrait, SameVariadicOperandSize, Terminator

Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
poison::mlir::UnitAttrunit attribute
operand_segments::mlir::DenseI32ArrayAttri32 dense array attribute

Operands:#

Operand

Description

addr

pointer to void type

succ_operands

variadic of any non-token type

Successors:#

Successor

Description

successors

any successor

cir.indirect_goto (::cir::IndirectGotoOp)#

Symbolic indirect goto

Syntax:

operation ::= `cir.indirect_goto` $addr `:` qualified(type($addr)) attr-dict

Transfers control to the block whose address is held in $addr, the void-pointer value of a goto *expr; (the GNU computed-goto extension). Like cir.goto, it is symbolic: it references no successor block, so it is valid inside any region even before FlattenCFG merges nested scopes. GotoSolver runs after FlattenCFG and rewrites each cir.indirect_goto into a cir.br to a shared block holding a cir.indirect_br over every address-taken label.

Example:

  %0 = cir.load %p : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
  cir.indirect_goto %0 : !cir.ptr<!void>

Traits: Terminator

Operands:#

Operand

Description

addr

pointer to void type

cir.init_catch_param (::cir::InitCatchParamOp)#

Initialize a catch parameter from the exception pointer

Syntax:

operation ::= `cir.init_catch_param` enum($kind) $exn_ptr `to` $param_addr `:`
              qualified(type($exn_ptr)) `,` qualified(type($param_addr)) attr-dict

cir.init_catch_param represents copying or otherwise materializing the caught exception object into the local catch parameter variable. It takes the exception pointer returned by cir.begin_catch and the address of the alloca created for the catch parameter, and has no result.

This operation is target-independent. It is replaced during EHABI lowering with the appropriate target/ABI-specific sequence (for example, the Itanium C++ ABI may emit a load and store for scalar/pointer catch types, an aggregate copy for record types, or a call to a copy constructor when one is required).

A catch parameter that is a reference to a pointer uses the reference_to_record_pointer kind when the pointer’s source-level pointee type is a record (class, struct, or union), and reference_to_pointer otherwise. A reference to any other type uses reference.

A reference_to_pointer or non_trivial_copy operation requires its catch handler to start with a cir.construct_catch_param of the same kind on the same parameter. When the handler starts with a cir.construct_catch_param on the parameter of the operation, the two must have the same kind.

Example:

%catch_token, %exn_ptr = cir.begin_catch %eh_token
  : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
%param_addr = cir.alloca "e" align(4) init : !cir.ptr<!s32i>
cir.init_catch_param %exn_ptr to %param_addr
  : !cir.ptr<!void>, !cir.ptr<!s32i>

Attributes:#

AttributeMLIR TypeDescription
kind::cir::InitCatchKindAttrallowed i32 cases: 0, 1, 2, 3, 4, 5, 6, 7

Operands:#

Operand

Description

exn_ptr

CIR pointer type

param_addr

CIR pointer type

cir.insert_member (::cir::InsertMemberOp)#

Overwrite the value of a member of a record value

Syntax:

operation ::= `cir.insert_member` $record `[` $index `]` `,` $value attr-dict
              `:` qualified(type($record)) `,` qualified(type($value))

The cir.insert_member operation overwrites the value of a particular member in the input record, and returns the modified record. The result of this operation is equal to the input record, except for the member specified by index_attr whose value is equal to the given value.

This operation is named after the LLVM instruction insertvalue.

Currently cir.insert_member does not work on unions.

Example:

// Suppose we have a record with multiple members.
!s32i = !cir.int<s, 32>
!s8i = !cir.int<s, 32>
!record_ty = !cir.record<"struct.Bar" {!s32i, !s8i}>

// And suppose we have a value of the record type.
%0 = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : !s8i}> : !record_ty
// %0 is {1, 2}

// Overwrite the second member of the record value.
%1 = cir.const #cir.int<3> : !s8i
%2 = cir.insert_member %0[1], %1 : !record_ty, !s8i
// %2 is {1, 3}

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
index::mlir::IntegerAttr64-bit signless integer attribute

Operands:#

Operand

Description

record

CIR record type

value

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR record type

cir.is_constant (::cir::IsConstantOp)#

Test for manifest compile-time constant

Syntax:

operation ::= `cir.is_constant` $val `:` qualified(type($val)) `->` qualified(type($result)) attr-dict

Returns true if the argument is known to be a manifest compile-time constant otherwise returns false. If the argument is a constant expression which refers to a global (the address of which is a constant, but not manifest during the compile), then the intrinsic evaluates to false.

This is used to represent __builtin_constant_p in cases where the argument isn’t known to be constant during initial translation of the source code but might be proven to be constant after later optimizations.

Example:

%1 = cir.is_constant %2 : !s32i -> !cir.bool

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

val

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR bool type

cir.is_fp_class (::cir::IsFPClassOp)#

Corresponding to the __builtin_fpclassify builtin function in clang

Syntax:

operation ::= `cir.is_fp_class` $src `,` enum($flags) `:` functional-type($src, $result) attr-dict

The cir.is_fp_class operation takes a floating-point value as its first argument and a bitfield of flags as its second argument. The operation returns a boolean value indicating whether the floating-point value satisfies the given flags.

The flags must be a compile time constant and the values are:

Bit #

floating-point class

0

Signaling NaN

1

Quiet NaN

2

Negative infinity

3

Negative normal

4

Negative subnormal

5

Negative zero

6

Positive zero

7

Positive subnormal

8

Positive normal

9

Positive infinity

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
flags::cir::FPClassTestAttrfloating-point class test flags

Operands:#

Operand

Description

src

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

CIR bool type

cir.label (::cir::LabelOp)#

Syntax:

operation ::= `cir.label` $label attr-dict

An identifier which may be referred by cir.goto operation

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable

Attributes:#

AttributeMLIR TypeDescription
label::mlir::StringAttrstring attribute

cir.launder (::cir::LaunderOp)#

Launder operation

Syntax:

operation ::= `cir.launder` $arg `:` qualified(type($result)) attr-dict

This operation represents a call to ‘launder’ in C++, which acts as an optimization boundary that breaks type invariance.

Example:

  %0 = cir.alloca "" align(8) : !cir.ptr<!cir.ptr<!rec_S>>
  %1 = cir.load align(8) %1 : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
  %2 = cir.launder(%1) : !cir.ptr<!rec_S>

Traits: SameOperandsAndResultType

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

arg

CIR pointer type

Results:#

Result

Description

result

CIR pointer type

cir.libc.memchr (::cir::MemChrOp)#

Libc’s memchr

Syntax:

operation ::= `cir.libc.memchr` `(` $src `,` $pattern `,` $len `)` attr-dict
              `:` qualified(type($src)) `,` qualified(type($pattern)) `,`
              qualified(type($len))

Search for pattern in data range from src to src + len. len provides a bound to the search in src. result is a pointer to found pattern or a null pointer.

pattern has the width of the target int and len has the width of the target size_t. The module records these widths as cir.int_type_width and cir.size_type_width, each a signless i32 holding a fundamental integer width, and the verifier checks the operands against them. src must be a void pointer in the default address space and result has the same type as src.

Examples:

%p = cir.libc.memchr(%src, %pattern, %len) : !cir.ptr<!void>, !s32i, !u64i

Interfaces: InferTypeOpInterface

Operands:#

Operand

Description

src

pointer to void type

pattern

fundamental signed integer type

len

fundamental unsigned integer type

Results:#

Result

Description

result

pointer to void type

cir.libc.memcpy (::cir::MemCpyOp)#

Equivalent to libc’s memcpy

Syntax:

operation ::= `cir.libc.memcpy` $len `bytes` `from` $src (`align` `(` $src_alignment^ `)`)?
              `to` $dst (`align` `(` $dst_alignment^ `)`)? attr-dict
              `:` type($len) `,` qualified(type($src)) `->` qualified(type($dst))

Given two CIR pointers, src and dst, cir.libc.memcpy will copy len bytes from the memory pointed by src to the memory pointed by dst.

While cir.copy is meant to be used for implicit copies in the code where the length of the copy is known, cir.memcpy copies only from and to void pointers, requiring the copy length to be passed as an argument.

As is the case for memcpy in the C standard library, this operation exhibits undefined behavior (UB) if any of the following conditions hold:

  • src and/or dst are null pointers; or

  • the memory regions referenced by src and dst overlap.

Examples:

  // Copying 2 bytes from one array to a record:
  %2 = cir.const #cir.int<2> : !u32i
  cir.libc.memcpy %2 bytes from %arr to %record : !cir.ptr<!arr> -> !cir.ptr<!record>

Attributes:#

AttributeMLIR TypeDescription
dst_alignment::mlir::IntegerAttr64-bit signless integer attribute
src_alignment::mlir::IntegerAttr64-bit signless integer attribute

Operands:#

Operand

Description

dst

pointer to void type

src

pointer to void type

len

fundamental unsigned integer type

cir.libc.memmove (::cir::MemMoveOp)#

Equivalent to libc’s memmove

Syntax:

operation ::= `cir.libc.memmove` $len `bytes` `from` $src (`align` `(` $src_alignment^ `)`)?
              `to` $dst (`align` `(` $dst_alignment^ `)`)? attr-dict
              `:` qualified(type($dst)) `,` type($len)

Given two CIR pointers, src and dst, cir.libc.memmove will copy len bytes from the memory pointed by src to the memory pointed by dst.

similiar to cir.libc.memcpy but accounts for overlapping memory.

Examples:

  // Copying 2 bytes from one array to a record:
  %2 = cir.const #cir.int<2> : !u32i
  cir.libc.memmove %2 bytes from %arr to %record : !cir.ptr<!void>, !u64i

Attributes:#

AttributeMLIR TypeDescription
dst_alignment::mlir::IntegerAttr64-bit signless integer attribute
src_alignment::mlir::IntegerAttr64-bit signless integer attribute

Operands:#

Operand

Description

dst

pointer to void type

src

pointer to void type

len

fundamental unsigned integer type

cir.libc.memset (::cir::MemSetOp)#

Equivalent to libc’s memset

Syntax:

operation ::= `cir.libc.memset` $len `bytes` `at` $dst (`align` `(` $alignment^ `)`)? `to` $val attr-dict
              `:` qualified(type($dst)) `,` type($val) `,` type($len)

Given the CIR pointer, dst, cir.libc.memset will set the first len bytes of the memory pointed by dst to the specified val.

Examples:

  // Set 2 bytes in a record to 0:
  %len = cir.const #cir.int<2> : !u32i
  %zero = cir.const #cir.int<0> : !u8i
  cir.libc.memset %len bytes at %record to %zero : !cir.ptr<!void>,
                                                   !s32i, !u64i

Attributes:#

AttributeMLIR TypeDescription
alignment::mlir::IntegerAttr64-bit signless integer attribute

Operands:#

Operand

Description

dst

pointer to void type

val

8-bit unsigned integer

len

fundamental unsigned integer type

cir.lifetime.end (::cir::LifetimeEndOp)#

Marks the end of the lifetime of a variable produced by a cir.alloca operation

Syntax:

operation ::= `cir.lifetime.end` $ptr attr-dict `:` qualified(type($ptr))

The cir.lifetime.end operation marks the end of the lifetime of the storage pointed to by $ptr. After this operation the underlying storage is considered dead, and the optimizer is free to reuse the storage for other purposes, until a subsequent cir.lifetime.start on the same pointer revives it.

The cir.scope is the operation that models the block scope of the C/C++ source. Once ClangIR is no longer structured, cir.scope can no longer express the lifetime of a local variable. This happens, for example, after FlattenCFG, where cir.scope regions are dissolved into plain basic blocks, or after HoistAllocas, where an alloca is moved to the function entry so that its position no longer reflects the scope it was declared in. In that form, these lifetime markers are what delimit the beginning and end of a variable’s lifetime.

The verifier requires $ptr to be produced by a cir.alloca. cir.lifetime.end should be preceded by a matching cir.lifetime.start on the same pointer on every control-flow path that reaches it.

This operation corresponds to the LLVM intrinsic llvm.lifetime.end.

Example:

cir.lifetime.end %ptr : !cir.ptr<!s32i>

Operands:#

Operand

Description

ptr

CIR pointer type

cir.lifetime.start (::cir::LifetimeStartOp)#

Marks the start of the lifetime of a variable produced by a cir.alloca operation

Syntax:

operation ::= `cir.lifetime.start` $ptr attr-dict `:` qualified(type($ptr))

The cir.lifetime.start operation marks the beginning of the lifetime of the storage pointed to by $ptr. Between this operation and a matching cir.lifetime.end on the same pointer, the underlying storage is considered live; outside that range it is considered dead, and the optimizer is free to reuse the storage for other purposes.

The cir.scope is the operation that models the block scope of the C/C++ source. Once ClangIR is no longer structured, cir.scope can no longer express the lifetime of a local variable. This happens, for example, after FlattenCFG, where cir.scope regions are dissolved into plain basic blocks, or after HoistAllocas, where an alloca is moved to the function entry so that its position no longer reflects the scope it was declared in. In that form, these lifetime markers are what delimit the beginning and end of a variable’s lifetime.

The verifier requires $ptr to be produced by a cir.alloca. For the lifetime to be meaningful, a matching cir.lifetime.end on the same pointer should follow on every control-flow path. This is different from LLVM, where an llvm.lifetime.start may appear without a matching llvm.lifetime.end – there the storage is also implicitly marked dead when the function returns (see the LLVM LangRef).

This operation corresponds to the LLVM intrinsic llvm.lifetime.start.

Example:

cir.lifetime.start %ptr : !cir.ptr<!s32i>

Operands:#

Operand

Description

ptr

CIR pointer type

cir.llrint (::cir::LlrintOp)#

Rounds floating-point to long long integer using current rounding mode

Syntax:

operation ::= `cir.llrint` $src `:` type($src) `->` type($result)
              (`fenv` `` $fenv^)? attr-dict

cir.llrint rounds a floating-point value to the nearest integer value using the current rounding mode and returns the result as a long long.

Traits: CIR_FenvOpTrait

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

Integer type with arbitrary precision up to a fixed limit

cir.llround (::cir::LlroundOp)#

Rounds floating-point to long long integer

Syntax:

operation ::= `cir.llround` $src `:` type($src) `->` type($result)
              (`fenv` `` $fenv^)? attr-dict

cir.llround rounds a floating-point value to the nearest integer value, rounding halfway cases away from zero, and returns the result as a long long.

Traits: CIR_FenvOpTrait

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

Integer type with arbitrary precision up to a fixed limit

cir.load (::cir::LoadOp)#

Load value from memory adddress

Syntax:

operation ::= `cir.load` (`deref` $isDeref^)?
              (`volatile` $is_volatile^)?
              (`nontemporal` $is_nontemporal^)?
              (`invariant` $invariant^)?
              (`align` `(` $alignment^ `)`)?
              (`syncscope` `(` enum($sync_scope)^ `)`)?
              (`atomic` `(` enum($mem_order)^ `)`)?
              $addr `:` qualified(type($addr)) `,` type($result) attr-dict

cir.load reads a value (lvalue to rvalue conversion) given an address backed up by a cir.ptr type. A unit attribute deref can be used to mark the resulting value as used by another operation to dereference a pointer. A unit attribute volatile can be used to indicate a volatile loading. Load can be marked atomic by using atomic(<mem_order>).

alignment can be used to specify an alignment that’s different from the default, which is computed from result’s type ABI data layout.

A unit attribute invariant can be used to indicate that the loaded memory never changes, mapping to LLVM IR’s !invariant.load metadata.

Example:


// Read from local variable, address in %0.
%1 = cir.load %0 : !cir.ptr<i32>, i32

// Load address from memory at address %0. %3 is used by at least one
// operation that dereferences a pointer.
%3 = cir.load deref %0 : !cir.ptr<!cir.ptr<i32>>

// Perform a volatile load from address in %0.
%4 = cir.load volatile %0 : !cir.ptr<i32>, i32

// Perform an invariant load from address in %0.
%5 = cir.load invariant %0 : !cir.ptr<i32>, i32

// Others
%x = cir.load align(16) atomic(seq_cst) %0 : !cir.ptr<i32>, i32

Interfaces: InferTypeOpInterface, PromotableMemOpInterface

Attributes:#

AttributeMLIR TypeDescription
isDeref::mlir::UnitAttrunit attribute
is_volatile::mlir::UnitAttrunit attribute
is_nontemporal::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute
sync_scope::cir::SyncScopeKindAttrsync scope kind
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
invariant::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

addr

CIR pointer type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.local_init (::cir::LocalInitOp)#

Initialize a static or thread local object

Syntax:

operation ::= `cir.local_init` (`thread_local` $tls^) : (`static_local`)?
              $globalName attr-dict
              (`ctor` $ctorRegion^)?
              (`dtor` $dtorRegion^)?

The ‘cir.local_init’ operation has no result, but is responsible for containing the regions to initialize and destroy the static local variable. This will be handled during lowering-prepare to include the guard variables correctly for the variable.

This operation may also represent a static local thread local variable, which would be indicated by the ‘tls’ flag.

Example:

// Note: despite this always being static_local, we print it anyway to be
// visually consistent with get_global, and as a 'counter' to 'tls'.
cir.local_init static_local @GlobalName ctor {
  %4 = cir.get_global static_local @GlobalName : !cir.ptr<!rec_CtorDtor>
  %5 = cir.call @_Z5get_iv() : () -> !s32i
  cir.call @_ZN8CtorDtorC1Ei(%4, %5) : !cir.ptr<!rec_CtorDtor>
  cir.yield
}, dtor {
  %4 = cir.get_global static_local @_ZZ3foovE8localCD2 :
                                              !cir.ptr<!rec_CtorDtor>
  cir.call @_ZN8CtorDtorD1Ev(%4) : (!cir.ptr<!rec_CtorDtor>) -> ()
  cir.yield
}

Traits: `HasAncestor<FuncOp>`, `NoRegionArguments`

Interfaces: `SymbolUserOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>globalName</code></td><td>::mlir::FlatSymbolRefAttr</td><td>flat symbol reference attribute</td></tr>
</table>



### `cir.log` (::cir::LogOp)

_Computes the floating-point natural logarithm_

Syntax:

operation ::= cir.log $src : type($src) (fenv `` $fenv^)? attr-dict


`cir.log` computes the natural logarithm of a floating-point operand and
returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.log10` (::cir::Log10Op)

_Computes the floating-point base-10 logarithm_

Syntax:

operation ::= cir.log10 $src : type($src) (fenv `` $fenv^)? attr-dict


`cir.log10` computes the base-10 logarithm of a floating-point operand and
returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.log2` (::cir::Log2Op)

_Computes the floating-point base-2 logarithm_

Syntax:

operation ::= cir.log2 $src : type($src) (fenv `` $fenv^)? attr-dict


`cir.log2` computes the base-2 logarithm of a floating-point operand and
returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.lrint` (::cir::LrintOp)

_Rounds floating-point to long integer using current rounding mode_

Syntax:

operation ::= cir.lrint $src : type($src) -> type($result) (fenv `` $fenv^)? attr-dict


`cir.lrint` rounds a floating-point value to the nearest integer value
using the current rounding mode and returns the result as a `long`.

Traits: `CIR_FenvOpTrait`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | Integer type with arbitrary precision up to a fixed limit |



### `cir.lround` (::cir::LroundOp)

_Rounds floating-point to long integer_

Syntax:

operation ::= cir.lround $src : type($src) -> type($result) (fenv `` $fenv^)? attr-dict


`cir.lround` rounds a floating-point value to the nearest integer value,
rounding halfway cases away from zero, and returns the result as a `long`.

Traits: `CIR_FenvOpTrait`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | Integer type with arbitrary precision up to a fixed limit |



### `cir.matrix.column_major_load` (::cir::MatrixColumnMajorLoadOp)

_Matrix column major load_

Syntax:

operation ::= cir.matrix.column_major_load $value : type($value) , $stride : type($stride) (volatile $is_volatile^)? , qualified(type($result)) attr-dict


The `cir.matrix.column_major_load` operation provides a representation for
the `__builtin_matrix_column_major_load` builtin and corresponds to the
`llvm.matrix.column.major.load` intrinsic in LLVM IR.

This operation performs a load of any matrix type with a stride to compute
the start address of the different columns.

The `stride` argument is the column stride which much be greater than or equal 
to `row`, giving the following 2x3 matrix `[[1, 2, 3], [4, 5, 6]]` with a 
stride of 2, the result matrix will be `[[1, 3, 5], [2, 4, 6]]`.

!cir.matrix<2 x 3 x !cir.float>

!cir.matrix<5 x 5 x !cir.double>

volatile, !cir.matrix<5 x 5 x !cir.double>


Interfaces: `PromotableMemOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>is_volatile</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `value` | CIR pointer type |
| `stride` | Integer type with arbitrary precision up to a fixed limit |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR matrix type |



### `cir.matrix.column_major_store` (::cir::MatrixColumnMajorStoreOp)

_Matrix column major store_

Syntax:

operation ::= cir.matrix.column_major_store $matrix : type($matrix) , $value : type($value) , $stride : type($stride) (volatile $is_volatile^)? attr-dict


The `cir.matrix.column_major_store` operation provides a representation for
the `__builtin_matrix_column_major_store` builtin and corresponds to the
`llvm.matrix.column.major.store` intrinsic in LLVM IR.

This operation performs a store of data from matrix type with a stride to
compute the start address of the different columns.

The `stride` argument is the column stride which much be greater than or equal 
to `row`, giving the following 2x3 matrix `[[1, 2, 3], [4, 5, 6]]` with a 
stride of 2, the stored data will be `[1, 3, 5, 2, 4, 6]`.

cir.matrix.column_major_store %matrix : <3 x 3 x !cir.float>,


Interfaces: `PromotableMemOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>is_volatile</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `matrix` | CIR matrix type |
| `value` | CIR pointer type |
| `stride` | Integer type with arbitrary precision up to a fixed limit |



### `cir.matrix.extract` (::cir::MatrixExtractOp)

_Extract one element from a matrix object_

Syntax:

operation ::= cir.matrix.extract $matrix [ $rowIdx : type($rowIdx) ] [ $columnIdx : type($columnIdx) ] attr-dict : qualified(type($matrix))


The `cir.matrix.extract` operation extracts the element at the given row 
and column indices from a matrix object.

: !cir.matrix<3 x 3 x !cir.float>


Traits: `AlwaysSpeculatableImplTrait`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `matrix` | CIR matrix type |
| `rowIdx` | fundamental integer type |
| `columnIdx` | fundamental integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | any cir boolean, integer, floating point type |



### `cir.matrix.extract_row` (::cir::MatrixExtractRowOp)

_Extract a row from a matrix object_

Syntax:

operation ::= cir.matrix.extract_row $matrix [ $rowIdx : type($rowIdx) ] attr-dict : qualified(type($matrix))


The `cir.matrix.extract_row` operation extracts a row from from a matrix
object using a row index.

: !cir.matrix<3 x 3 x !cir.float>


Traits: `AlwaysSpeculatableImplTrait`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `matrix` | CIR matrix type |
| `rowIdx` | fundamental integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | vector type |



### `cir.matrix.insert` (::cir::MatrixInsertOp)

_Insert one element into a matrix object_

Syntax:

operation ::= cir.matrix.insert $value , $matrix [ $rowIdx : type($rowIdx) ] [ $columnIdx : type($columnIdx) ] attr-dict : qualified(type($matrix))


The `cir.matrix.insert` operation returns a copy of a matrix object with
the element at the given row and column indices replaced by `value`.

: !cir.matrix<3 x 3 x !cir.float>


Traits: `AlwaysSpeculatableImplTrait`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `value` | any cir boolean, integer, floating point type |
| `matrix` | CIR matrix type |
| `rowIdx` | fundamental integer type |
| `columnIdx` | fundamental integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR matrix type |



### `cir.matrix.multiply` (::cir::MatrixMultiplyOp)

_Matrix multiplication_

Syntax:

operation ::= cir.matrix.multiply $lhs , $rhs attr-dict : ( qualified(type($lhs)) , qualified(type($rhs)) ) -> qualified(type($result))


The `cir.matrix.multiply` operation multiplies two matrices and
corresponds to the `llvm.matrix.multiply` intrinsic in LLVM IR.

The left-hand operand must have dimensions `M x K`, the right-hand operand
`K x N`, and the result `M x N`. All three must share an element type.

: (!cir.matrix<2 x 3 x !cir.float>, !cir.matrix<3 x 4 x !cir.float>)
-> !cir.matrix<2 x 4 x !cir.float>

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | CIR matrix type |
| `rhs` | CIR matrix type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR matrix type |



### `cir.matrix.transpose` (::cir::MatrixTransposeOp)

_Matrix transpose_

Syntax:

operation ::= cir.matrix.transpose $value : type($value) , qualified(type($result)) attr-dict


The `cir.matrix.transpose` operation provides a representation for the
`__builtin_matrix_transpose` builtin and corresponds to the
`llvm.matrix.transpose` intrinsic in LLVM IR.

This operation performs transposition to switch the row and column
indices of the matrix and returns the transposed matrix,

!cir.matrix<2 x 3 x !cir.float>

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `value` | CIR matrix type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR matrix type |



### `cir.max` (::cir::MaxOp)

_Integer maximum_

Syntax:

operation ::= cir.max $lhs , $rhs : type($lhs) attr-dict


The `cir.max` operation computes the maximum of two integer operands.
Both operands and the result must have the same integer type or vector of
integer type.

Example:


Traits: `Commutative`, `Idempotent`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector of integer type |
| `rhs` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.min` (::cir::MinOp)

_Integer minimum_

Syntax:

operation ::= cir.min $lhs , $rhs : type($lhs) attr-dict


The `cir.min` operation computes the minimum of two integer operands.
Both operands and the result must have the same integer type or vector of
integer type.

Example:


Traits: `Commutative`, `Idempotent`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector of integer type |
| `rhs` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.minus` (::cir::MinusOp)

_Integer unary minus (negation)_

Syntax:

operation ::= cir.minus (nsw $no_signed_wrap^)? $input : type($input) attr-dict


The `cir.minus` operation negates the operand. The operand and result
must have the same type.

The optional `nsw` (no signed wrap) attribute indicates that the result
is poison if signed overflow occurs (e.g. negating the minimum signed
integer).

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`, `UnaryOpInterface`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | integer or vector of bool or integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of bool or integer type |



### `cir.modf` (::cir::ModfOp)

_Decomposes a floating-point value into fractional and integral parts_

Syntax:

operation ::= cir.modf $src : type($src) -> type($fractional) , type($integral) attr-dict


`cir.modf` splits a floating-point value into its fractional and integral
parts.  Both parts have the same sign as the input.

Lowers to `llvm.modf`.

Example:
  %frac, %intpart = cir.modf %x : !cir.float -> !cir.float, !cir.float

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `fractional` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |
| `integral` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |



### `cir.mul` (::cir::MulOp)

_Integer multiplication_

Syntax:

operation ::= cir.mul (nsw $no_signed_wrap^)? (nuw $no_unsigned_wrap^)? $lhs , $rhs : type($lhs) attr-dict


The `cir.mul` operation performs multiplication on integer operands. Both
operands and the result must have the same integer or vector-of-integer
or matrix-of-integer type.

The optional `nsw` (no signed wrap) and `nuw` (no unsigned wrap) unit
attributes indicate that the result is poison if signed or unsigned
overflow occurs, respectively.

Example:


Traits: `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector/matrix of integer type |
| `rhs` | integer or vector/matrix of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector/matrix of integer type |



### `cir.mul.overflow` (::cir::MulOverflowOp)

_Integer multiplication with overflow checking_

Syntax:

operation ::= cir.mul.overflow $lhs , $rhs : qualified(type($lhs)) -> qualified(type($result)) attr-dict


`cir.mul.overflow` performs multiplication with overflow checking on
integral operands. See `CIR_BinOpOverflow` for semantics.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `Commutative`, `SameTypeOperands`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | Integer type with arbitrary precision up to a fixed limit |
| `rhs` | Integer type with arbitrary precision up to a fixed limit |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or boolean type |
| `overflow` | CIR bool type |



### `cir.nearbyint` (::cir::NearbyintOp)

_Rounds floating-point value to nearest integer_

Syntax:

operation ::= cir.nearbyint $src : type($src) (fenv `` $fenv^)? attr-dict


`cir.nearbyint` rounds a floating-point operand to the nearest integer value
and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.not` (::cir::NotOp)

_Bitwise NOT / logical NOT_

Syntax:

operation ::= cir.not $input : type($input) attr-dict


The `cir.not` operation performs a bitwise NOT on integer types or a
logical NOT on boolean types. The operand and result must have the same
type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `Involution`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`, `UnaryOpInterface`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | integer, boolean, or vector of bool or integer |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer, boolean, or vector of bool or integer |



### `cir.objsize` (::cir::ObjSizeOp)

_Implements the llvm.objsize builtin_

Syntax:

operation ::= cir.objsize (min $min^) : (max)? (nullunknown $nullunknown^)? (dynamic $dynamic^)? $ptr : qualified(type($ptr)) -> qualified(type($result)) attr-dict


The `cir.objsize` operation is designed to provide information to the
optimizer to determine whether a) an operation (like memcpy) will
overflow a buffer that corresponds to an object, or b) that a runtime
check for overflow isn’t necessary. An object in this context means an
allocation of a specific class, structure, array, or other object.

When the `min` attribute is present, the operation returns the minimum
guaranteed accessible size. When absent (max mode), it returns the maximum
possible object size. Corresponds to `llvm.objectsize`'s `min` argument.

The `dynamic` attribute determines if the value should be evaluated at
runtime. Corresponds to `llvm.objectsize`'s `dynamic` argument.

The `nullunknown` attribute controls how null pointers are handled. When
present, null pointers are treated as having unknown size. When absent,
null pointers are treated as having 0 size (in min mode) or -1 size
(in max mode). Corresponds to `llvm.objectsize`'s `nullunknown` argument.

Example:


Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>min</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>nullunknown</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>dynamic</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `ptr` | CIR pointer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | fundamental integer type |



### `cir.offload.printf` (::cir::OffloadPrintfOp)

_Device-side printf_

Syntax:

operation ::= cir.offload.printf ( $format (, $args^)? ) attr-dict : functional-type(operands, results)


Represents a call to `printf` in device code. The target is responsible for
the appropriate lowering.

`format` is the format string and `args` are the remaining arguments,
after the language's default argument promotions. `result` is the value
`printf` returns on the target, which follows the target's conventions
rather than C's.

Like the GPU dialect's `gpu.printf`, the op represents a device printf
independently of the target, and each target expands it when lowering.
Unlike `gpu.printf`, it must represent any call to C `printf`, so:

- `format` is a value rather than an attribute, as the format string need
  not be a constant.
- `args` may also be pointers, such as strings printed with `%s`,
  pointers to data members, and vectors.
- The op returns the result of `printf`.
- The op has no memory effect annotations, as printing may read memory
  through `format` and `args`.

Example:


Interfaces: `InferTypeOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `format` | pointer to 8-bit character type |
| `args` | variadic of integer type or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or pointer type or data member type or vector type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | 32-bit signed integer |



### `cir.or` (::cir::OrOp)

_Bitwise OR_

Syntax:

operation ::= cir.or $lhs , $rhs : type($lhs) attr-dict


The `cir.or` operation performs a bitwise OR on integer operands.
Both operands and the result must have the same integer type.

Example:


Traits: `Commutative`, `Idempotent`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer, boolean, or vector of bool or integer |
| `rhs` | integer, boolean, or vector of bool or integer |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer, boolean, or vector of bool or integer |



### `cir.parity` (::cir::BitParityOp)

_Get the parity of input_

Syntax:

operation ::= cir.parity $input : type($result) attr-dict


Compute the parity of the input. The parity of an integer is the number of
1-bits in it modulo 2.

The input must be an unsigned integer.

Example:

// %0 = 0x0110_1000

// %1 will be 1 since there are three 1-bits in %0


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | unsigned integer type of widths 32/64 |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | unsigned integer type of widths 32/64 |



### `cir.popcount` (::cir::BitPopcountOp)

_Get the number of 1-bits in input_

Syntax:

operation ::= cir.popcount $input : type($result) attr-dict


Compute the number of 1-bits in the input.

The input must be an unsigned integer.

Example:

// %0 = 0x0110_1000

// %1 will be 3 since there are 3 1-bits in %0


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | unsigned integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | unsigned integer type |



### `cir.pow` (::cir::PowOp)

_Computes the power of a floating-point value_

Syntax:

operation ::= cir.pow $lhs , $rhs : qualified(type($lhs)) (fenv `` $fenv^)? attr-dict


`cir.pow` computes the first operand raised to the power of the second
operand.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.prefetch` (::cir::PrefetchOp)

_Prefetch operation_

Syntax:

operation ::= cir.prefetch (write $isWrite^) : (read)? locality ( $locality ) $addr : qualified(type($addr)) attr-dict


The `cir.prefetch` operation is a hint to the code generator to insert a
prefetch instruction if supported; otherwise, it is a noop. Prefetches
have no effect on the behavior of the program but can change its
performance characteristics.

cir.prefetch(%0 : !cir.ptr<!void>) locality(1) write


$locality is a temporal locality specifier ranging from (0) - no locality,
to (3) - extremely local, keep in cache. If $locality is not present, the
default value is 3.

$isWrite specifies whether the prefetch is for a 'read' or 'write'. If
$isWrite is not specified, it means that prefetch is prepared for 'read'.

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>locality</code></td><td>::mlir::IntegerAttr</td><td>32-bit signless integer attribute whose minimum value is 0 whose maximum value is 3</td></tr>
<tr><td><code>isWrite</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `addr` | pointer to void type |



### `cir.ptr_diff` (::cir::PtrDiffOp)

_Pointer subtraction arithmetic_

Syntax:

operation ::= cir.ptr_diff $lhs , $rhs : qualified(type($lhs)) -> qualified(type($result)) attr-dict


The cir.ptr_diff operation computes the difference between two pointers that
have the same element type.

The result reflects the ABI-defined size of the pointed-to type. For example,
subtracting two !cir.ptr<!u64i> values may yield 1, representing an 8-byte
difference. In contrast, for pointers to void or function types, a result of
8 corresponds to an 8-byte difference.

For pointers to types whose size are not aligned with the target data
layout, the size is generally rounded to the next power of 2 bits. For
example, subtracting two !cir.ptr<!s24i> values for the _BitInt(24) type may
yield 1, representing a 4-byte difference (as opposed to a 3-byte
difference).

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameTypeOperands`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | CIR pointer type |
| `rhs` | CIR pointer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | fundamental integer type |



### `cir.ptr_mask` (::cir::PtrMaskOp)

_Clear bits of a pointer_

Syntax:

operation ::= cir.ptr_mask $ptr, $mask : functional-type(operands, results) attr-dict


The `cir.ptr_mask` operation clears the bits of `ptr` that are not set in
`mask`.  The result stays a pointer, whereas masking it as an integer
would lose provenance.

`mask` must be exactly the target's pointer index width.


Traits: `AlwaysSpeculatableImplTrait`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `ptr` | CIR pointer type |
| `mask` | fundamental integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR pointer type |



### `cir.ptr_stride` (::cir::PtrStrideOp)

_Pointer access with stride_

Syntax:

operation ::= cir.ptr_stride $base, $stride : functional-type(operands, results) attr-dict


The `cir.ptr_stride` operation computes a new pointer from a base pointer
and an integer stride, similar to a single-index `getelementptr` in LLVM IR.
It moves the pointer by `stride * sizeof(element_type)` bytes.


Traits: `AlwaysSpeculatableImplTrait`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `base` | CIR pointer type |
| `stride` | fundamental integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR pointer type |



### `cir.register_exit_dtor` (::cir::RegisterExitDtorOp)

_Register the destruction of a global at program or thread exit_

Syntax:

operation ::= cir.register_exit_dtor $object $body attr-dict


The `cir.register_exit_dtor` operation registers its body to run when the
storage duration of the global `object` ends: at program exit, or at
thread exit when `object` is thread local.  The registration happens when
the operation executes, so objects registered later are destroyed earlier.

It must be nested in the ctor region of a `cir.global` or
`cir.local_init`, but not inside another `cir.register_exit_dtor`,
typically right after the construction of a temporary whose lifetime that
variable extends.  `object` must have no ctor or dtor region of its own.
The body destroys `object`, which it reaches through `cir.get_global`.

Example:

cir.global external @r = #cir.zero : !rec_Refs ctor {

cir.call @_ZN3TmpC1Ei(%0, %1) : (!cir.ptr<!rec_Tmp>, !s32i) -> () cir.register_exit_dtor @ZGR1r { %2 = cir.get_global @ZGR1r : !cir.ptr<!rec_Tmp> cir.call @_ZN3TmpD1Ev(%2) : (!cir.ptr<!rec_Tmp>) -> () } … }


Traits: `IsolatedFromAbove`, `NoRegionArguments`, `SingleBlockImplicitTerminator<cir::YieldOp>`, `SingleBlock`

Interfaces: `SymbolUserOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>object</code></td><td>::mlir::FlatSymbolRefAttr</td><td>flat symbol reference attribute</td></tr>
</table>



### `cir.rem` (::cir::RemOp)

_Integer remainder_

Syntax:

operation ::= cir.rem $lhs , $rhs : type($lhs) attr-dict


The `cir.rem` operation computes the remainder of division on integer
operands. Both operands and the result must have the same integer or
vector-of-integer type.

Example:


Traits: `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector of integer type |
| `rhs` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.resume` (::cir::ResumeOp)

_Resumes execution after not catching exceptions_

Syntax:

operation ::= cir.resume $eh_token : type($eh_token) attr-dict


The `cir.resume` operation handles an uncaught exception scenario.

Before CFG flattening, this operation is used as the terminator of a
`CatchUnwind` region of `cir.try`, where it receives an `!cir.eh_token`
argument representing the in-flight exception.

During CFG flattening, this operation may temporarily appear inside any
structured CIR operation (scope, loop, switch, etc.) when an inner cleanup
scope is flattened before the enclosing structured op. When the enclosing
op is subsequently flattened, the resume will end up in a `cir.try`
operation or at function level.

After CFG flattening, this operation appears at the function level (inside
`cir.func`) to indicate that the exception should be re-thrown to the
caller after cleanup code has been executed.

Examples:

// Before CFG flattening (in try unwind region) cir.try { cir.yield } unwind (%eh_token : !cir.eh_token) { cir.resume %eh_token : !cir.eh_token }

// After CFG flattening (at function level, after cleanup) ^eh_cleanup(%eh_token : !cir.eh_token):

cir.call @destructor() : () -> () cir.end_cleanup %ct : !cir.cleanup_token cir.resume %eh_token : !cir.eh_token


Traits: `Terminator`

Interfaces: `RegionBranchTerminatorOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `eh_token` | CIR exception handling token type |



### `cir.resume.flat` (::cir::ResumeFlatOp)

_A flattened version of `cir.resume`_

Syntax:

operation ::= cir.resume.flat $exception_ptr , $type_id attr-dict


The `cir.resume.flat` operation is a region-less and simplified
version of the `cir.resume`.

Its representation is closer to LLVM IR dialect
than the C/C++ language feature.

This operation is used only after the CFG flatterning pass.

Examples:

cir.resume.flat %exception_ptr, %type_id


Traits: `ReturnLike`, `Terminator`

Interfaces: `RegionBranchTerminatorOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `exception_ptr` | pointer to void type |
| `type_id` | 32-bit unsigned integer |



### `cir.return` (::cir::ReturnOp)

_Return from function_

Syntax:

operation ::= cir.return ($input^ : type($input))? attr-dict


The "return" operation represents a return operation within a function.
The operation takes an optional operand and produces no results.
The operand type must match the signature of the function that contains
the operation.

func @foo() -> i32 { … cir.return %0 : i32 }


Traits: `HasParent<FuncOp, ScopeOp, IfOp, SwitchOp, CaseOp, CleanupScopeOp, CoroutineOp, DoWhileOp, WhileOp, ForOp, TryOp>`, `Terminator`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |



### `cir.return_address` (::cir::ReturnAddrOp)

_The return address of the current function, or of one of its callers_

Syntax:

operation ::= cir.return_address ( $level ) attr-dict


Represents a call to builtin function ` __builtin_return_address` in CIR.
This builtin function returns the return address of the current function,
or of one of its callers.

The `level` argument is number of frames to scan up the call stack.
For instance, value of 0 yields the return address of the current function,
value of 1 yields the return address of the caller of the current function,
and so forth.

Examples:


Interfaces: `InferTypeOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `level` | 32-bit unsigned integer |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | pointer to void type |



### `cir.rint` (::cir::RintOp)

_Rounds floating-point value to nearest integer_

Syntax:

operation ::= cir.rint $src : type($src) (fenv `` $fenv^)? attr-dict


`cir.rint` rounds a floating-point operand to the nearest integer value
and returns a result of the same type.

This operation does not set `errno`. Unlike `cir.nearbyint`, this operation
may raise the `FE_INEXACT` exception if the input value is not an exact
integer, but this is not guaranteed to happen.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.rotate` (::cir::RotateOp)

_Rotate the bits in the operand integer_

Syntax:

operation ::= cir.rotate (left $rotateLeft^) : (right)? $input , $amount : type($result) attr-dict


The `cir.rotate` rotates the bits in `input` by the given amount `amount`.
The rotate direction is specified by the `left` and `right` keyword.

`input` must be an unsigned integer and its width must be either 8, 16, 32,
or 64. The types of `input`, `amount`, and the result must all match.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

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

Effects: `MemoryEffects::Effect{}`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>rotateLeft</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | unsigned integer type of widths 8/16/32/64 |
| `amount` | Integer type with arbitrary precision up to a fixed limit |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | Integer type with arbitrary precision up to a fixed limit |



### `cir.round` (::cir::RoundOp)

_Rounds floating-point value to nearest integer_

Syntax:

operation ::= cir.round $src : type($src) (fenv `` $fenv^)? attr-dict


`cir.round` rounds a floating-point operand to the nearest integer value
and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.roundeven` (::cir::RoundEvenOp)

_Rounds floating-point value to nearest integer, ties to even_

Syntax:

operation ::= cir.roundeven $src : type($src) (fenv `` $fenv^)? attr-dict


`cir.roundeven` rounds a floating-point operand to the nearest integer
value, with ties rounding to even (banker's rounding).

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `CIR_FenvOpTrait`, `SameOperandsAndResultType`

Interfaces: `CIR_FPEnvConstrainedOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `MemoryEffectsOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>fenv</code></td><td>::cir::FenvAttr</td><td>Describes floating-point environment constraints</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.scope` (::cir::ScopeOp)

_Represents a C/C++ scope_

Syntax:

operation ::= cir.scope custom($scopeRegion) (: type($results)^)? attr-dict


`cir.scope` contains one region and defines a strict "scope" for all new
values produced within its blocks.

The region can contain an arbitrary number of blocks but usually defaults
to one and can optionally return a value (useful for representing values
coming out of C++ full-expressions) via `cir.yield`:


… cir.yield %value }


The blocks can be terminated by `cir.yield`, `cir.return` or `cir.throw`.
If `cir.scope` yields no value, the `cir.yield` can be left out, and
will be inserted implicitly.

Traits: `AutomaticAllocationScope`, `NoRegionArguments`, `RecursiveMemoryEffects`, `RecursivelySpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `RegionBranchOpInterface`

#### Results:

| Result | Description |
| :----: | ----------- |
| `results` | CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |



### `cir.select` (::cir::SelectOp)

_Yield one of two values based on a boolean value_

Syntax:

operation ::= cir.select if $condition then $true_value else $false_value : ( qualified(type($condition)) , qualified(type($true_value)) , qualified(type($false_value)) ) -> qualified(type($result)) attr-dict


The `cir.select` operation takes three operands. The first operand
`condition` is either a boolean value of type `!cir.bool` or a boolean
vector of type `!cir.bool`.  The second and the third operand can be of
any CIR types, but their types must be the same. If the first operand 
is `true`, the operation yields its second operand. Otherwise, the
operation yields its third operand.

In the case where the first operand is a boolean vector, then the second 
and third operand needs to also be of some vectors of the same type to
each other and that the number of elements of all three operands needs to 
be the same as well.

Example:


Traits: `AlwaysSpeculatableImplTrait`

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

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `condition` | CIR bool type or vector of CIR bool type |
| `true_value` | CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |
| `false_value` | CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |



### `cir.set_bitfield` (::cir::SetBitfieldOp)

_Set the value of a bitfield member_

Syntax:

operation ::= cir.set_bitfield (align ( $alignment^ ))? ($bitfield_info, $addr:qualified(type($addr)), $src:type($src) ) ({ is_volatile $is_volatile^ })? attr-dict -> type($result)


The `cir.set_bitfield` operation provides a store-like access to
a bit field of a record.

A bitfield info attribute must be provided to describe the location of
the bitfield within the memory referenced by the $addr argument.
The $src argument is inserted at the appropriate place in the memory and
the value that was stored. Returns the value being stored.

A unit attribute `volatile` can be used to indicate a volatile store of the
bitfield.
cir.set_bitfield(#bfi, %0 : !cir.ptr<!u32i>, %1 : !s32i) {is_volatile}
                                                               -> !s32i

Example.
Suppose we have a struct with multiple bitfields stored in
different storages. The `cir.set_bitfield` operation sets the value
of the bitfield.
```C++
typedef struct {
int a : 4;
int b : 27;
int c : 17;
int d : 2;
int e : 15;
} S;

void store_bitfield(S& s) {
s.e = 3;
}
// 'e' is in the storage with the index 1
!record_type = !cir.struct<"S" packed {!u64i, !u16i,
                                       pad !cir.array<!u8i x 2>}>
#bfi_e = #cir.bitfield_info<name = "e", storage_type = !u16i, size = 15,
                            offset = 0, is_signed = true>

%1 = cir.const #cir.int<3> : !s32i
%2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
%3 = cir.get_member %2[1] {name = "e"} : !cir.ptr<!record_type>
                                                         -> !cir.ptr<!u16i>
%4 = cir.set_bitfield align(4) (#bfi_e, %3 : !cir.ptr<!u16i>, %1 : !s32i)
                                                                   -> !s32i

Attributes:#

AttributeMLIR TypeDescription
bitfield_info::cir::BitfieldInfoAttrRepresents info for a bit-field member
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

addr

CIR pointer type

src

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

integer or boolean type

cir.shift (::cir::ShiftOp)#

Shift

Syntax:

operation ::= `cir.shift` `(`
              (`left` $isShiftleft^) : (```right`)?
              `,` $value `:` type($value)
              `,` $amount `:` type($amount)
              `)` `->` type($result) attr-dict

The cir.shift operation performs a bitwise shift, either to the left or to the right, based on the first operand. The second operand specifies the value to be shifted, and the third operand determines the number of positions by which the shift is applied, They must be either all vector of integer type, or all integer type. If they are vectors, each vector element of the shift target is shifted by the corresponding shift amount in the shift amount vector.

%res = cir.shift(left, %lhs : !u64i, %amount : !s32i) -> !u64i
%new_vec = cir.shift(left, %lhs : !cir.vector<2 x !s32i>, %rhs :
    !cir.vector<2 x !s32i>) -> !cir.vector<2 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
isShiftleft::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

value

integer or vector of integer type

amount

integer or vector of integer type

Results:#

Result

Description

result

integer or vector of integer type

cir.signbit (::cir::SignBitOp)#

Checks the sign of a floating-point number

Syntax:

operation ::= `cir.signbit` $input attr-dict `:` type($input) `->` qualified(type($res))

It returns whether the sign bit (i.e. the highest bit) of the input operand is set.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

res

CIR bool type

cir.sin (::cir::SinOp)#

Computes the floating-point sine

Syntax:

operation ::= `cir.sin` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.sin computes the sine of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.sinh (::cir::SinhOp)#

Computes the floating-point hyperbolic sine

Syntax:

operation ::= `cir.sinh` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.sinh computes the hyperbolic sine of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.sqrt (::cir::SqrtOp)#

Floating-point square root operation

Syntax:

operation ::= `cir.sqrt` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

Computes the square root of a floating-point value or vector.

The input must be either: • a floating-point scalar type, or • a vector whose element type is floating-point.

The result type must match the input type exactly.

Examples: // scalar

// vector

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.stackrestore (::cir::StackRestoreOp)#

Restores the state of the function stack

Syntax:

operation ::= `cir.stackrestore` $ptr attr-dict `:` qualified(type($ptr))

Restore the state of the function stack to the state it was in when the corresponding cir.stacksave executed. This is used during the lowering of variable length array allocas.

This operation corresponds to LLVM intrinsic stackrestore.

%0 = cir.alloca "saved_stack" align(8) : !cir.ptr<!cir.ptr<!u8i>>
%1 = cir.stacksave : <!u8i>
cir.store %1, %0 : !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>
%2 = cir.load %0 : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
cir.stackrestore %2 : !cir.ptr<!u8i>

Operands:#

Operand

Description

ptr

CIR pointer type

cir.stacksave (::cir::StackSaveOp)#

Remembers the current state of the function stack

Syntax:

operation ::= `cir.stacksave` attr-dict `:` qualified(type($result))

Saves current state of the function stack. Returns a pointer to an opaque object that later can be passed into cir.stackrestore. This is used during the lowering of variable length array allocas.

This operation corresponds to LLVM intrinsic stacksave.

%0 = cir.stacksave : <!u8i>

Results:#

Result

Description

result

CIR pointer type

cir.std.find (::cir::StdFindOp)#

Std::find()

Syntax:

operation ::= `cir.std.find` `(` $first `:` qualified(type($first)) `,`
              $last `:` qualified(type($last)) `,`
              $pattern `:` qualified(type($pattern)) `,`
              $original_fn `)` `->` qualified(type($result)) attr-dict

Interfaces: CIR_StdOpInterface, InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
original_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:#

Operand

Description

first

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

last

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

pattern

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.std.strlen (::cir::StrLenOp)#

C standard library strlen()

Syntax:

operation ::= `cir.std.strlen` `(` $string `:` qualified(type($string)) `,` $original_fn `)`
              `->` qualified(type($result)) attr-dict

Interfaces: CIR_StdOpInterface

Attributes:#

AttributeMLIR TypeDescription
original_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:#

Operand

Description

string

pointer to 8-bit character type

Results:#

Result

Description

result

fundamental unsigned integer type

cir.store (::cir::StoreOp)#

Store value to memory address

Syntax:

operation ::= `cir.store` (`volatile` $is_volatile^)?
              (`nontemporal` $is_nontemporal^)?
              (`align` `(` $alignment^ `)`)?
              (`syncscope` `(` enum($sync_scope)^ `)`)?
              (`atomic` `(` enum($mem_order)^ `)`)?
              $value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr))

cir.store stores a value (first operand) to the memory address specified in the second operand. A unit attribute volatile can be used to indicate a volatile store. Store’s can be marked atomic by using atomic(<mem_order>).

alignment can be used to specify an alignment that’s different from the default, which is computed from result’s type ABI data layout.

Example:

// Store a function argument to local storage, address in %0.
cir.store %arg0, %0 : i32, !cir.ptr<i32>

// Perform a volatile store into memory location at the address in %0.
cir.store volatile %arg0, %0 : i32, !cir.ptr<i32>

// Others
cir.store align(16) atomic(seq_cst) %x, %addr : i32, !cir.ptr<i32>

Interfaces: PromotableMemOpInterface

Attributes:#

AttributeMLIR TypeDescription
is_volatile::mlir::UnitAttrunit attribute
is_nontemporal::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute
sync_scope::cir::SyncScopeKindAttrsync scope kind
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model

Operands:#

Operand

Description

value

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

addr

CIR pointer type

cir.sub (::cir::SubOp)#

Integer subtraction

Syntax:

operation ::= `cir.sub` (`nsw` $no_signed_wrap^)?
              (`nuw` $no_unsigned_wrap^)?
              (`sat` $saturated^)?
              $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.sub operation performs subtraction on integer operands. Both operands and the result must have the same integer, vector-of-integer or matrix-of-integer type.

The optional nsw (no signed wrap) and nuw (no unsigned wrap) unit attributes indicate that the result is poison if signed or unsigned overflow occurs, respectively. The optional sat (saturated) attribute clamps the result to the type’s representable range. The nsw/nuw flags and sat are mutually exclusive.

Example:

%0 = cir.sub %a, %b : !s32i
%1 = cir.sub nsw %a, %b : !s32i
%2 = cir.sub sat %a, %b : !s32i
%3 = cir.sub %va, %vb : !cir.vector<4 x !s32i>
%4 = cir.sub %ma, %mb : !cir.matrix<3 x 3 x !s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

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

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

integer or vector/matrix of integer type

rhs

integer or vector/matrix of integer type

Results:#

Result

Description

result

integer or vector/matrix of integer type

cir.sub.overflow (::cir::SubOverflowOp)#

Integer subtraction with overflow checking

Syntax:

operation ::= `cir.sub.overflow` $lhs `,` $rhs `:` qualified(type($lhs)) `->` qualified(type($result))
              attr-dict

cir.sub.overflow performs subtraction with overflow checking on integral operands. See CIR_BinOpOverflow for semantics.

Example:

%result, %overflow = cir.sub.overflow %a, %b : !u32i -> !u32i

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

Integer type with arbitrary precision up to a fixed limit

rhs

Integer type with arbitrary precision up to a fixed limit

Results:#

Result

Description

result

integer or boolean type

overflow

CIR bool type

cir.switch (::cir::SwitchOp)#

Switch operation

Syntax:

operation ::= `cir.switch` `(` $condition `:` qualified(type($condition)) `)`
              (`all_enum_cases_covered` $all_enum_cases_covered^)?
              $body
              attr-dict

The cir.switch operation represents C/C++ switch functionality for conditionally executing multiple regions of code. The operand to an switch is an integral condition value.

Besides taking an integer condition and CIR regions, it also accepts an all_enum_cases_covered attribute indicating whether all enum cases are handled by the operation. Note that the presence of a default CaseOp does not imply all_enum_cases_covered. The original AST switch must explicitly list every enum case.

The set of cir.case operations and their enclosing cir.switch represent the semantics of a C/C++ switch statement. Users can use collectCases(llvm::SmallVector<CaseOp> &cases) to collect the cir.case operation in the cir.switch operation easily.

The cir.case operations don’t have to be in the region of cir.switch directly. However, when all the cir.case operations live in the region of cir.switch directly and there are no other operations except the ending cir.yield operation in the region of cir.switch directly, we say the cir.switch operation is in a simple form. Users can use bool isSimpleForm(llvm::SmallVector<CaseOp> &cases) member function to detect if the cir.switch operation is in a simple form. The simple form makes it easier for analyses to handle the cir.switch operation and makes the boundary to give up clear.

To make the simple form as common as possible, CIR code generation attaches operations corresponding to the statements that lives between top level cases into the closest cir.case operation.

For example,

switch(int cond) {
  case 4:
    a++;
    b++;
  case 5:
    c++;

  ...
}

The statement b++ is not a sub-statement of the case statement case 4. But to make the generated cir.switch a simple form, we will attach the statement b++ into the closest cir.case operation. So that the generated code will be like:

cir.switch(int cond) {
  cir.case(equal, 4) {
    a++;
    b++;
    cir.yield
  }
  cir.case(equal, 5) {
    c++;
    cir.yield
  }
  ...
}

For the same reason, we will hoist the case statement as the substatement of another case statement so that they will be in the same level. For example,

switch(int cond) {
  case 4:
  default;
  case 5:
    a++;
  ...
}

will be generated as

cir.switch(int cond) {
  cir.case(equal, 4) {
    cir.yield
  }
  cir.case(default) {
    cir.yield
  }
  cir.case(equal, 5) {
    a++;
    cir.yield
  }
  ...
}

The cir.switch is not be considered “simple” if any of the following is true:

  • There are case statements of the switch statement that are scope other than the top level compound statement scope. Note that a case statement itself doesn’t form a scope.

  • The sub-statement of the switch statement is not a compound statement.

  • There is any code before the first case statement. For example,

switch(int cond) {
  l:
    b++;

  case 4:
    a++;
    break;

  case 5:
    goto l;
  ...
}

the generated CIR for this non-simple switch would be:

cir.switch(int cond) {
  cir.label "l"
  b++;
  cir.case(4) {
    a++;
    cir.break
  }
  cir.case(5) {
    goto "l"
  }
  cir.yield
}

Traits: AutomaticAllocationScope, NoRegionArguments, RecursiveMemoryEffects, RecursivelySpeculatableImplTrait, SameVariadicOperandSize

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
all_enum_cases_covered::mlir::UnitAttrunit attribute

Operands:#

Operand

Description

condition

Integer type with arbitrary precision up to a fixed limit

cir.switch.flat (::cir::SwitchFlatOp)#

A flattened version of cir.switch

Syntax:

operation ::= `cir.switch.flat` $condition `:` type($condition) `,`
              $defaultDestination (`(` $defaultOperands^ `:` type($defaultOperands) `)`)?
              custom<SwitchFlatOpCases>(ref(type($condition)), $caseValues,
              $caseDestinations, $caseOperands,
              type($caseOperands))
              attr-dict

The cir.switch.flat operation is a region-less and simplified version of the cir.switch. Its representation is closer to LLVM IR dialect than the C/C++ language feature.

Traits: AttrSizedOperandSegments, Terminator

Interfaces: BranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
caseValues::mlir::ArrayAttrarray attribute
case_operand_segments::mlir::DenseI32ArrayAttri32 dense array attribute

Operands:#

Operand

Description

condition

Integer type with arbitrary precision up to a fixed limit

defaultOperands

variadic of any non-token type

caseOperands

variadic of any non-token type

Successors:#

Successor

Description

defaultDestination

any successor

caseDestinations

any successor

cir.tan (::cir::TanOp)#

Computes the floating-point tangent

Syntax:

operation ::= `cir.tan` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.tan computes the tangent of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.tanh (::cir::TanhOp)#

Computes the floating-point hyperbolic tangent

Syntax:

operation ::= `cir.tanh` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.tanh computes the hyperbolic tangent of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.ternary (::cir::TernaryOp)#

The cond ? a : b C/C++ ternary operation

Syntax:

operation ::= `cir.ternary` `(` $cond `,`
              `true` $trueRegion `,`
              `false` $falseRegion
              `)` `:` functional-type(operands, results) attr-dict

The cir.ternary operation represents C/C++ ternary, much like a select operation. The first argument is a cir.bool condition to evaluate, followed by two regions to execute (true or false). This is different from cir.if since each region is one block sized and the cir.yield closing the block scope should have one argument.

cir.ternary also represents the GNU binary conditional operator ?: which reuses the parent operation for both the condition and the true branch to evaluate it only once.

Example:

// cond = a && b;

%x = cir.ternary (%cond, true_region {
  ...
  cir.yield %a : i32
}, false_region {
  ...
  cir.yield %b : i32
}) -> i32

Traits: AutomaticAllocationScope, NoRegionArguments, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

Operands:#

Operand

Description

cond

CIR bool type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.throw (::cir::ThrowOp)#

(Re)Throws an exception

Syntax:

operation ::= `cir.throw` ($exception_ptr^ `:` type($exception_ptr))?
              (`,` $type_info^)?
              (`,` $dtor^)?
              attr-dict

This operation is equivalent to either __cxa_throw or __cxa_rethrow, depending on the arguments.

The absense of arguments for cir.throw means it rethrows.

For the no-rethrow version, it must have at least two operands, the RTTI information, a pointer to the exception object (likely allocated via cir.alloc_exception) and finally an optional dtor, which might run as part of this operation.

Example:

// re-throw;
cir.throw

// if (b == 0)
//   throw "Division by zero condition!";

// Type info for char const*
cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i>
cir.if %cond {
  %exception_addr = cir.alloc_exception 8 -> !cir.ptr<!void>
  ...
  // Store string addr for "Division by zero condition!"
  cir.store %string_addr, %exception_addr : !cir.ptr<!s8i>,
    !cir.ptr<!cir.ptr<!s8i>>
  cir.throw %exception_addr : !cir.ptr<!cir.ptr<!u8i>>,
    @_ZTIPKc

Attributes:#

AttributeMLIR TypeDescription
type_info::mlir::FlatSymbolRefAttrflat symbol reference attribute
dtor::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:#

Operand

Description

exception_ptr

CIR pointer type

cir.token.none (::cir::TokenNoneOp)#

Produces an empty token value.

Syntax:

operation ::= `cir.token.none` attr-dict

Produces a none token value, mirroring LLVM IR’s none token literal. Lowers to llvm::ConstantTokenNone.

Traits: AlwaysSpeculatableImplTrait, TokenProducerTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Results:#

Result

Description

result

token

cir.trap (::cir::TrapOp)#

Exit the program abnormally

Syntax:

operation ::= `cir.trap` attr-dict

The cir.trap operation causes the program to exit abnormally. The implementations may implement this operation with different mechanisms. For example, an implementation may implement this operation by calling abort, while another implementation may implement this operation by executing an illegal instruction.

Traits: Terminator

cir.trunc (::cir::TruncOp)#

Truncates floating-point value to integer

Syntax:

operation ::= `cir.trunc` $src `:` type($src) (`fenv` `` $fenv^)? attr-dict

cir.trunc truncates a floating-point operand to an integer value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: CIR_FenvOpTrait, SameOperandsAndResultType

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, InferTypeOpInterface, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

src

floating point or vector of floating point type

Results:#

Result

Description

result

floating point or vector of floating point type

cir.try (::cir::TryOp)#

C++ try block

Syntax:

operation ::= `cir.try` (`cleanup` $cleanup^)?
              $try_region
              custom<TryHandlerRegions>($handler_regions, $handler_types)
              attr-dict

Holds the lexical scope of try {}. Note that resources used on catch clauses are usually allocated in the same parent as cir.try.

cleanup: indicates that there are cleanups that must be performed when exiting the try region via exception, even if the exception is not caught.

Each catch handler region and unwind region receives a !cir.eh_token argument representing the inflight exception. The first operation in a catch handler region must be a cir.begin_catch operation. This must be followed by a cir.cleanup.scope operation, with the cir.end_catch operation in its cleanup region. The catch handling code will be emitted into the body of the cleanup scope. This ensures that all paths out of the catch handler will execute the end_catch operation.

A cir.try operation may instead have a filter handler paired with an unexpected handler, which together implement the dynamic exception specification of the enclosing function. The filter handler lists the permitted type info symbols and holds the path taken when the in-flight exception is permitted, which is a cir.resume that continues unwinding to the caller. The unexpected handler holds the path taken when the specification is violated, which is a cir.eh.unexpected. An empty permitted type list represents throw(), which permits nothing, so the filter handler region holds a cir.unreachable instead. Like unwind, and unlike a catch handler, neither region begins with cir.begin_catch.

The two handlers must appear together, with the filter first, and must be the only handlers on the operation. The try operation created for an exception specification wraps the entire function body, and each try statement written in the source becomes a separate cir.try operation nested inside it.

Example:

cir.try {
  cir.call exception @function() : () -> ()
  cir.yield
} catch [type #cir.global_view<@_ZTIPf> : !cir.ptr<!u8i>] (%eh_token : !cir.eh_token) {
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.float>)
  cir.cleanup.scope {
    ...
    cir.yield
  } cleanup eh {
    cir.end_catch %catch_token : !cir.catch_token
    cir.yield
  }
  cir.yield
} unwind (%eh_token : !cir.eh_token) {
  cir.resume %eh_token : !cir.eh_token
}

Example of a void f() throw(int) exception specification:

cir.try {
  cir.call exception @function() : () -> ()
  cir.yield
} filter [#cir.global_view<@_ZTIi> : !cir.ptr<!u8i>]
    (%eh_token : !cir.eh_token) {
  cir.resume %eh_token : !cir.eh_token
} unexpected (%eh_token.1 : !cir.eh_token) {
  cir.eh.unexpected %eh_token.1 : !cir.eh_token
}

Traits: AutomaticAllocationScope, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
cleanup::mlir::UnitAttrunit attribute
handler_types::mlir::ArrayAttrcatch all, unwind, eh filter, eh unexpected or global view array attribute

cir.try_call (::cir::TryCallOp)#

Try_call operation

Similar to cir.call but requires two destination blocks, one which is used if the call returns without throwing an exception (the “normal” destination) and another which is used if an exception is thrown (the “unwind” destination).

This operation is used only after the CFG flatterning pass.

Example:

// Before CFG flattening
cir.try {
  %call = cir.call @division(%a, %b) : () -> !s32i
  cir.yield
} catch all {
  cir.yield
}

// After CFG flattening
%call = cir.try_call @division(%a, %b) ^normalDest, ^unwindDest
  : (f32, f32) -> f32
^normalDest:
  cir.br ^afterTryBlock
^unwindDest:
  %exception_ptr, %type_id = cir.eh.inflight_exception
  cir.br ^catchHandlerBlock(%exception_ptr : !cir.ptr<!void>)
^catchHandlerBlock:
  ...

Traits: Terminator

Interfaces: ArgAndResultAttrsOpInterface, CIRCallOpInterface, CallOpInterface, SymbolUserOpInterface

Attributes:#

AttributeMLIR TypeDescription
callee::mlir::FlatSymbolRefAttrflat symbol reference attribute
nothrow::mlir::UnitAttrunit attribute
nounwind::mlir::UnitAttrunit attribute
willreturn::mlir::UnitAttrunit attribute
inline_kind::cir::InlineKindAttrinline kind
musttail::mlir::UnitAttrunit attribute
memory_effects::cir::MemoryEffectsAttrDescribes the possible memory effects of a function or callee
arg_attrs::mlir::ArrayAttrArray of dictionary attributes
res_attrs::mlir::ArrayAttrArray of dictionary attributes
calling_conv::cir::CallingConvAttrcalling convention

Operands:#

Operand

Description

args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Successors:#

Successor

Description

normalDest

any successor

unwindDest

any successor

cir.try_throw (::cir::TryThrowOp)#

Throw an exception with an unwind destination

Syntax:

operation ::= `cir.try_throw` ($exception_ptr^ `:` type($exception_ptr))?
              (`,` $type_info^)?
              (`,` $dtor^)?
              $normalDest `,` $unwindDest
              attr-dict

Similar to cir.throw but acts as a terminator with two destination blocks: a normalDest that should contain a cir.unreachable operation (since a throw never returns) and an unwindDest that receives control when the throw needs to unwind through an enclosing cleanup or catch handler. This is the EH counterpart of cir.throw, analogous to how cir.try_call is the EH counterpart of cir.call.

Like cir.throw, the absence of operands means rethrow. With operands, it carries the same exception pointer, type info, and optional destructor as cir.throw.

This operation is produced by the FlattenCFG pass for cir.throw operations that appear inside a cleanup scope or try region. It is later lowered by the EHABI lowering pass to a cir.try_call of __cxa_throw (or __cxa_rethrow).

Example:

cir.try_throw %exception_addr : !cir.ptr<!s32i>, @_ZTIi
    ^normalDest, ^unwindDest
^normalDest:
  cir.unreachable
^unwindDest:
  ...

Traits: Terminator

Attributes:#

AttributeMLIR TypeDescription
type_info::mlir::FlatSymbolRefAttrflat symbol reference attribute
dtor::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:#

Operand

Description

exception_ptr

CIR pointer type

Successors:#

Successor

Description

normalDest

any successor

unwindDest

any successor

cir.unreachable (::cir::UnreachableOp)#

Invoke immediate undefined behavior

Syntax:

operation ::= `cir.unreachable` attr-dict

If the program control flow reaches a cir.unreachable operation, the program exhibits undefined behavior immediately. This operation is useful in cases where the unreachability of a program point needs to be explicitly marked.

Traits: Terminator

cir.va_arg (::cir::VAArgOp)#

Fetches next variadic element as a given type

Syntax:

operation ::= `cir.va_arg` $arg_list attr-dict `:` functional-type(operands, $result)

The cir.va_arg operation models the C/C++ va_arg macro by reading the next argument from an active variable argument list and producing it as a value of a specified result type.

The operand must be a pointer to the target’s va_list representation. The operation advances the va_list state as a side effect and returns the fetched value as the result, whose type is chosen by the user of the operation.

A cir.va_arg must only be used on a va_list that has been initialized with cir.va.start and not yet finalized by cir.va.end. The semantics (including alignment and promotion rules) follow the platform ABI; the frontend is responsible for providing a va_list pointer that matches the target representation.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
        : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
        -> !cir.ptr<!rec___va_list_tag>
cir.va.start %p : !cir.ptr<!rec___va_list_tag>

// Fetch an `int` from the vararg list.
%v = cir.va_arg %p : (!cir.ptr<!rec___va_list_tag>) -> !s32i

cir.va.end %p : !cir.ptr<!rec___va_list_tag>

Operands:#

Operand

Description

arg_list

CIR pointer type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.va_copy (::cir::VACopyOp)#

Copied a variable argument list

Syntax:

operation ::= `cir.va_copy` $src_list `to` $dst_list attr-dict `:` type(operands)

The cir.copy operation models the C/C++ va_copy macro. The variable argument list passed as the $src_list is copied to an unitialized va_list in the destination operand. The next argument that can be extracted from the copied list is the same as the next argument in the source list. The copied list must be destroyed with va_end.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
      : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
      -> !cir.ptr<!rec___va_list_tag>
cir.va_copy %p to %dst
      : (!cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>)

Operands:#

Operand

Description

dst_list

CIR pointer type

src_list

CIR pointer type

cir.va_end (::cir::VAEndOp)#

Ends a variable argument list

Syntax:

operation ::= `cir.va_end` $arg_list attr-dict `:` type(operands)

The cir.va_end operation models the C/C++ va_end macro by finalizing and cleaning up a variable argument list previously initialized with cir.va_start.

The operand must be a pointer to the target’s va_list representation. This operation has no results and produces its effect by mutating the storage referenced by the pointer operand.

cir.va_end must only be called after a matching cir.va_start on the same va_list along all control-flow paths. After cir.va_end, the va_list is invalid and must not be accessed unless reinitialized.

Lowering typically maps this to the LLVM intrinsic llvm.va_end, passing the appropriately decayed pointer to the underlying va_list storage.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
      : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
      -> !cir.ptr<!rec___va_list_tag>
cir.va_end %p : !cir.ptr<!rec___va_list_tag>

Operands:#

Operand

Description

arg_list

CIR pointer type

cir.va_start (::cir::VAStartOp)#

Starts a variable argument list

Syntax:

operation ::= `cir.va_start` $arg_list attr-dict `:` type(operands)

The cir.va_start operation models the C/C++ va_start macro by initializing a variable argument list at the given va_list storage location.

The operand must be a pointer to the target’s va_list representation. This operation has no results and produces its effect by mutating the storage referenced by the pointer operand.

Each cir.va_start must be paired with a corresponding cir.va_end on the same logical va_list object along all control-flow paths. After cir.va_end, the va_list must not be accessed unless reinitialized with another cir.va_start.

Lowering maps this to the LLVM intrinsic llvm.va_start, passing the appropriately decayed pointer to the underlying va_list storage.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
      : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>)
      -> !cir.ptr<!rec___va_list_tag>
cir.va_start %p : !cir.ptr<!rec___va_list_tag>

Operands:#

Operand

Description

arg_list

CIR pointer type

cir.vec.cmp (::cir::VecCmpOp)#

Compare two vectors

Syntax:

operation ::= `cir.vec.cmp` `(` enum($kind) `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
              qualified(type($result)) (`fenv` `` $fenv^)? attr-dict

The cir.vec.cmp operation does an element-wise comparison of two vectors of the same type. The result is a vector of the same size as the operands whose element type is the signed integral type that is the same size as the element type of the operands. The values in the result are 0 or -1.

The optional fenv attribute describes constraints on the floating-point handling of the operation. It is only valid for floating-point vector comparisons.

%eq = cir.vec.cmp(eq, %vec_a, %vec_b) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>
%lt = cir.vec.cmp(lt, %vec_a, %vec_b) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>
%gt = cir.vec.cmp(gt, %va, %vb) : !cir.vector<4 x !cir.float>, !cir.vector<4 x !s32i> fenv<>

Traits: CIR_FenvOpTrait, SameTypeOperands

Interfaces: CIR_FPEnvConstrainedOpInterface, ConditionallySpeculatable, MemoryEffectsOpInterface

Attributes:#

AttributeMLIR TypeDescription
kind::cir::CmpOpKindAttrcompare operation kind
fenv::cir::FenvAttrDescribes floating-point environment constraints

Operands:#

Operand

Description

lhs

CIR vector type

rhs

CIR vector type

Results:#

Result

Description

result

CIR vector type

cir.vec.create (::cir::VecCreateOp)#

Create a vector value

Syntax:

operation ::= `cir.vec.create` `(` ($elements^ `:` type($elements))? `)` `:` qualified(type($result))
              attr-dict

The cir.vec.create operation creates a vector value with the given element values. The number of element arguments must match the number of elements in the vector type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

elements

variadic of any cir boolean, integer, floating point

Results:#

Result

Description

result

CIR vector type

cir.vec.extract (::cir::VecExtractOp)#

Extract one element from a vector object

Syntax:

operation ::= `cir.vec.extract` $vec `[` $index `:` type($index) `]` attr-dict `:` qualified(type($vec))

The cir.vec.extract operation extracts the element at the given index from a vector object.

%tmp = cir.load %vec : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
%idx = cir.const #cir.int<1> : !s32i
%element = cir.vec.extract %tmp[%idx : !s32i] : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

vec

CIR vector type

index

fundamental integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.insert (::cir::VecInsertOp)#

Insert one element into a vector object

Syntax:

operation ::= `cir.vec.insert` $value `,` $vec `[` $index `:` type($index) `]` attr-dict `:`
              qualified(type($vec))

The cir.vec.insert operation produces a new vector by replacing the element of the input vector at index with value.

%value = cir.const #cir.int<5> : !s32i
%index = cir.const #cir.int<2> : !s32i
%vec_tmp = cir.load %0 : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
%new_vec = cir.vec.insert %value, %vec_tmp[%index : !s32i] : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

vec

CIR vector type

value

any cir boolean, integer, floating point

index

fundamental integer type

Results:#

Result

Description

result

CIR vector type

cir.vec.masked_load (::cir::VecMaskedLoadOp)#

Masked vector load from memory

Syntax:

operation ::= `cir.vec.masked_load` (`align` `(` $alignment^ `)`)?
              $addr `,` $mask `,` $pass_thru
              `:` qualified(type($addr)) `,` type($mask) `,` type($pass_thru)
              `->` type($result)
              attr-dict

cir.masked_load conditionally loads elements from memory based on a mask. Elements for which the mask is false are taken from pass_thru.

This operation corresponds to LLVM’s masked load op (llvm.intr.maskedload) and lower directly to it.

alignment can be provided to override the default alignment derived from the pointee/element type data layout.

Example:

%v = cir.masked_load align(16) %ptr, %mask, %passthru
     : !cir.ptr<i32>, <4xi1>, <4xi32> -> <4xi32>

Interfaces: InferTypeOpInterface

Attributes:#

AttributeMLIR TypeDescription
alignment::mlir::IntegerAttr64-bit signless integer attribute whose value is positive and whose value is a power of two > 0

Operands:#

Operand

Description

addr

CIR pointer type

mask

CIR vector type

pass_thru

CIR vector type

Results:#

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

cir.vec.reduce.add (::cir::VecReduceAddOp)#

Reduce a vector using add

Syntax:

operation ::= `cir.vec.reduce.add` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of any of boolean type, integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.and (::cir::VecReduceAndOp)#

Reduce a vector using and

Syntax:

operation ::= `cir.vec.reduce.and` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of any of boolean type, integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.fadd (::cir::VecReduceFAddOp)#

Reduce a floating-point vector using fadd

Syntax:

operation ::= `cir.vec.reduce.fadd` `(` $accumulator `,` $input `)` `:` functional-type(operands, results)
              prop-dict attr-dict

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

accumulator

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

input

vector of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.vec.reduce.fmax (::cir::VecReduceFMaxOp)#

Reduce a floating-point vector using fmax

Syntax:

operation ::= `cir.vec.reduce.fmax` `(` $input `)` `:` functional-type(operands, results)
              prop-dict attr-dict

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

input

vector of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.vec.reduce.fmin (::cir::VecReduceFMinOp)#

Reduce a floating-point vector using fmin

Syntax:

operation ::= `cir.vec.reduce.fmin` `(` $input `)` `:` functional-type(operands, results)
              prop-dict attr-dict

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

input

vector of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.vec.reduce.fmul (::cir::VecReduceFMulOp)#

Reduce a floating-point vector using fmul

Syntax:

operation ::= `cir.vec.reduce.fmul` `(` $accumulator `,` $input `)` `:` functional-type(operands, results)
              prop-dict attr-dict

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
fastmath_flags::cir::FastMathFlagsAttrfast-math flags

Operands:#

Operand

Description

accumulator

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

input

vector of single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

Results:#

Result

Description

result

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

cir.vec.reduce.mul (::cir::VecReduceMulOp)#

Reduce a vector using mul

Syntax:

operation ::= `cir.vec.reduce.mul` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of any of boolean type, integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.or (::cir::VecReduceOrOp)#

Reduce a vector using or

Syntax:

operation ::= `cir.vec.reduce.or` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of any of boolean type, integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.smax (::cir::VecReduceSMaxOp)#

Reduce a vector using smax

Syntax:

operation ::= `cir.vec.reduce.smax` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of signed integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.smin (::cir::VecReduceSMinOp)#

Reduce a vector using smin

Syntax:

operation ::= `cir.vec.reduce.smin` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of signed integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.umax (::cir::VecReduceUMaxOp)#

Reduce a vector using umax

Syntax:

operation ::= `cir.vec.reduce.umax` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of any of unsigned integer type, boolean type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.umin (::cir::VecReduceUMinOp)#

Reduce a vector using umin

Syntax:

operation ::= `cir.vec.reduce.umin` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of any of unsigned integer type, boolean type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.reduce.xor (::cir::VecReduceXorOp)#

Reduce a vector using xor

Syntax:

operation ::= `cir.vec.reduce.xor` `(` $input `)` `:` functional-type(operands, results) attr-dict

Reduces the elements of a vector to a scalar of the vector element type.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

input

vector of any of boolean type, integer type

Results:#

Result

Description

result

any cir boolean, integer, floating point

cir.vec.shuffle (::cir::VecShuffleOp)#

Combine two vectors using indices passed as constant integers

Syntax:

operation ::= `cir.vec.shuffle` `(` $vec1 `,` $vec2 `:` qualified(type($vec1)) `)` $indices `:`
              qualified(type($result)) attr-dict

The cir.vec.shuffle operation implements the documented form of Clang’s __builtin_shufflevector, where the indices of the shuffled result are integer constants.

The two input vectors, which must have the same type, are concatenated. Each of the integer constant arguments is interpreted as an index into that concatenated vector, with a value of -1 meaning that the result value doesn’t matter. The result vector, which must have the same element type as the input vectors and the same number of elements as the list of integer constant indices, is constructed by taking the elements at the given indices from the concatenated vector. The size of the result vector does not have to match the size of the individual input vectors or of the concatenated vector.

%new_vec = cir.vec.shuffle(%vec_1, %vec_2 : !cir.vector<2 x !s32i>)
    [#cir.int<3> : !s64i, #cir.int<1> : !s64i] : !cir.vector<2 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
indices::mlir::ArrayAttrinteger array attribute

Operands:#

Operand

Description

vec1

CIR vector type

vec2

CIR vector type

Results:#

Result

Description

result

CIR vector type

cir.vec.shuffle.dynamic (::cir::VecShuffleDynamicOp)#

Shuffle a vector using indices in another vector

Syntax:

operation ::= `cir.vec.shuffle.dynamic` $vec `:` qualified(type($vec)) `,` $indices `:` qualified(type($indices))
              attr-dict

The cir.vec.shuffle.dynamic operation implements the undocumented form of Clang’s __builtin_shufflevector, where the indices of the shuffled result can be runtime values.

There are two input vectors, which must have the same number of elements. The second input vector must have an integral element type. The elements of the second vector are interpreted as indices into the first vector. The result vector is constructed by taking the elements from the first input vector from the indices indicated by the elements of the second vector.

%new_vec = cir.vec.shuffle.dynamic %vec : !cir.vector<4 x !s32i>, %indices
    : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

vec

CIR vector type

indices

vector of integer type

Results:#

Result

Description

result

CIR vector type

cir.vec.splat (::cir::VecSplatOp)#

Convert a scalar into a vector or matrix

Syntax:

operation ::= `cir.vec.splat` $value `:` type($value) `,` qualified(type($result)) attr-dict

The cir.vec.splat operation creates a vector or matrix value from a scalar value. All elements of the result have the same value, that of the given scalar.

It’s a separate operation from cir.vec.create because more efficient LLVM IR can be generated for it, and because some optimization and analysis passes can benefit from knowing that all elements of the vector have the same value.

%value = cir.const #cir.int<3> : !s32i
%value_vec = cir.vec.splat %value : !s32i, !cir.vector<4 x !s32i>
%value_mat = cir.vec.splat %value : !s32i, !cir.matrix<2 x 2 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

value

any cir boolean, integer, floating point

Results:#

Result

Description

result

vector or matrix type

cir.vec.ternary (::cir::VecTernaryOp)#

The cond ? a : b ternary operator for vector types

Syntax:

operation ::= `cir.vec.ternary` `(` $cond `,` $lhs`,` $rhs `)` `:` qualified(type($cond)) `,`
              qualified(type($lhs)) attr-dict

The cir.vec.ternary operation represents the C/C++ ternary operator, ?:, for vector types, which does a select on individual elements of the vectors. Unlike a regular ?: operator, there is no short circuiting. All three arguments are always evaluated. Because there is no short circuiting, there are no regions in this operation, unlike cir.ternary.

The first argument is a vector of integral type. The second and third arguments are vectors of the same type and have the same number of elements as the first argument.

The result is a vector of the same type as the second and third arguments. Each element of the result is (bool)a[n] ? b[n] : c[n].

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

cond

vector of any of boolean type, integer type

lhs

CIR vector type

rhs

CIR vector type

Results:#

Result

Description

result

CIR vector type

cir.vtable.address_point (::cir::VTableAddrPointOp)#

Get the vtable (global variable) address point

Syntax:

operation ::= `cir.vtable.address_point` `(`
              $name `,` `address_point` `=` $address_point
              `)`
              `:` qualified(type($addr)) attr-dict

The vtable.address_point operation retrieves the “effective” address (address point) of a C++ virtual table. An object internal __vptr gets initializated on top of the value returned by this operation.

address_point.index (vtable index) provides the appropriate vtable within the vtable group (as specified by Itanium ABI), and address_point.offset (address point index) the actual address point within that vtable.

The return type is always !cir.vptr.

Example:

cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.vtable.address_point(@_ZTV1B,
          address_point = <index = 0, offset = 2>) : !cir.vptr

Traits: AlwaysSpeculatableImplTrait

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

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
name::mlir::FlatSymbolRefAttrflat symbol reference attribute
address_point::cir::AddressPointAttrAddress point attribute

Results:#

Result

Description

addr

CIR type that is used for the vptr member of C++ objects

cir.vtable.get_type_info (::cir::VTableGetTypeInfoOp)#

Get the address of the type_info from the vtable

Syntax:

operation ::= `cir.vtable.get_type_info` $vptr attr-dict `:` qualified(type($vptr)) `->` qualified(type($result))

The vtable.get_type_info operation retreives the address of the dynamic type_info/rtti object from an object’s vtable. This is an ABI independent abstraction of this operation.

The vptr operand must be a !cir.vptr value, which would have been returned by a previous call to cir.vtable.get_vptr.

The return type is a loadable pointer to a type_info struct.

Example:

%5 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_A> -> !cir.ptr<!cir.vptr>
%6 = cir.load align(8) %5 : !cir.ptr<!cir.vptr>, !cir.vptr
%7 = cir.vtable.get_type_info %6 : !cir.vptr -> !cir.ptr<!cir.ptr<!rec_std3A3Atype_info>>
%8 = cir.load align(8) %7 : !cir.ptr<!cir.ptr<!rec_std3A3Atype_info>>, !cir.ptr<!rec_std3A3Atype_info>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

vptr

CIR type that is used for the vptr member of C++ objects

Results:#

Result

Description

result

CIR pointer type

cir.vtable.get_virtual_fn_addr (::cir::VTableGetVirtualFnAddrOp)#

Get a the address of a virtual function pointer

Syntax:

operation ::= `cir.vtable.get_virtual_fn_addr` $vptr `[` $index `]` attr-dict
              `:` qualified(type($vptr)) `->` qualified(type($result))

The vtable.get_virtual_fn_addr operation retrieves the address of a virtual function pointer from an object’s vtable (__vptr). This is an abstraction to perform the basic pointer arithmetic to get the address of the virtual function pointer, which can then be loaded and called.

The vptr operand must be a !cir.ptr<!cir.vptr> value, which would have been returned by a previous call to cir.vtable.get_vptr. The index operand is an index of the virtual function in the vtable.

The return type is a pointer-to-pointer to the function type.

Example:

%2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_C>>, !cir.ptr<!rec_C>
%3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_C> -> !cir.ptr<!cir.vptr>
%4 = cir.load %3 : !cir.ptr<!cir.vptr>, !cir.vptr
%5 = cir.vtable.get_virtual_fn_addr %4[2] : !cir.vptr
              -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>>
%6 = cir.load align(8) %5 : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_C>)
                                                             -> !s32i>>>,
                            !cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>
%7 = cir.call %6(%2) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>,
                        !cir.ptr<!rec_C>) -> !s32i

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
index::mlir::IntegerAttr64-bit signless integer attribute

Operands:#

Operand

Description

vptr

CIR type that is used for the vptr member of C++ objects

Results:#

Result

Description

result

CIR pointer type

cir.vtable.get_vptr (::cir::VTableGetVPtrOp)#

Get a the address of the vtable pointer for an object

Syntax:

operation ::= `cir.vtable.get_vptr` $src `:` qualified(type($src)) `->` qualified(type($result)) attr-dict

The vtable.get_vptr operation retrieves the address of the vptr for a C++ object. This operation requires that the object pointer points to the start of a complete object. (TODO: Describe how we get that). The vptr will always be at offset zero in the object, but this operation is more explicit about what is being retrieved than a direct bitcast.

The return type is always !cir.ptr<!cir.vptr>.

Example:

%2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_C>>, !cir.ptr<!rec_C>
%3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_C> -> !cir.ptr<!cir.vptr>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

src

CIR pointer type

Results:#

Result

Description

result

pointer to vptr type

cir.vtt.address_point (::cir::VTTAddrPointOp)#

Get the VTT address point

Syntax:

operation ::= `cir.vtt.address_point` ($name^)?
              ($sym_addr^ `:` type($sym_addr))?
              `,`
              `offset` `=` $offset
              `->` qualified(type($addr)) attr-dict

The vtt.address_point operation retrieves an element from the virtual table table (VTT), which is the address point of a C++ vtable. In virtual inheritance, a set of internal __vptr members for an object are initialized by this operation, which assigns an element from the VTT. The initialization order is as follows:

The complete object constructors and destructors find the VTT, via the mangled name of the VTT global variable. They pass the address of the subobject’s sub-VTT entry in the VTT as a second parameter when calling the base object constructors and destructors. The base object constructors and destructors use the address passed to initialize the primary virtual pointer and virtual pointers that point to the classes which either have virtual bases or override virtual functions with a virtual step.

The first parameter is either the mangled name of VTT global variable or the address of the subobject’s sub-VTT entry in the VTT. The second parameter offset provides a virtual step to adjust to the actual address point of the vtable.

The return type is always a !cir.ptr<!cir.ptr<void>>.

Example:

cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.base_class_addr(%1 : !cir.ptr<!rec_D> nonnull) [0]
         -> !cir.ptr<!rec_B>
%4 = cir.vtt.address_point @_ZTT1D, offset = 1
         -> !cir.ptr<!cir.ptr<!void>>
cir.call @_ZN1BC2Ev(%3, %4)

Or:

%7 = cir.vtt.address_point %3 : !cir.ptr<!cir.ptr<!void>>, offset = 1
         -> !cir.ptr<!cir.ptr<!void>>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface

Effects: MemoryEffects::Effect{}

Attributes:#

AttributeMLIR TypeDescription
name::mlir::FlatSymbolRefAttrflat symbol reference attribute
offset::mlir::IntegerAttr32-bit signless integer attribute

Operands:#

Operand

Description

sym_addr

CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Results:#

Result

Description

addr

CIR pointer type

cir.while (::cir::WhileOp)#

C/C++ while loop

Syntax:

operation ::= `cir.while` $cond `do` $body (`cleanup` enum($cleanupKind) $cleanup^)?
              (`loop_hints` $loop_hints^)? attr-dict

Represents a C/C++ while loop. It consists of two or three regions:

  • cond: single block region with the loop’s condition. Should be terminated with a cir.condition operation.

  • body: contains the loop body and an arbitrary number of blocks.

  • cleanup: optional region that runs on every per-iteration exit edge (condition-false exit, end-of-iteration, break/continue, and EH unwinding when the cleanup kind includes EH). This is used to destroy a condition variable whose lifetime is a single iteration. When present, it carries a cleanup kind matching cir.cleanup.scope (normal or all). Note that a DoWhileOp cannot contain a cleanup region.

Example:

cir.while {
  cir.condition(%cond)
} do {
  cir.yield
}

cir.while {
  cir.condition(%cond)
} do {
  cir.yield
} cleanup all {
  cir.yield
}

Traits: NoRegionArguments

Interfaces: LoopLikeOpInterface, LoopOpInterface, RegionBranchOpInterface

Attributes:#

AttributeMLIR TypeDescription
cleanupKind::cir::CleanupKindAttrcleanup kind
loop_hints::cir::LoopHintAttrOptimizer hints and guarantees attached to a loop

cir.xor (::cir::XorOp)#

Bitwise XOR

Syntax:

operation ::= `cir.xor` $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.xor operation performs a bitwise XOR on integer operands. Both operands and the result must have the same integer type.

Example:

%0 = cir.xor %a, %b : !s32i
%1 = cir.xor %a, %b : !cir.bool

Traits: Commutative, SameOperandsAndResultType

Interfaces: BinaryOpInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

lhs

integer, boolean, or vector of bool or integer

rhs

integer, boolean, or vector of bool or integer

Results:#

Result

Description

result

integer, boolean, or vector of bool or integer

cir.yield (::cir::YieldOp)#

Represents the default branching behaviour of a region

Syntax:

operation ::= `cir.yield` ($args^ `:` type($args))? attr-dict

The cir.yield operation terminates regions on different CIR operations, and it is used to represent the default branching behaviour of a region. Said branching behaviour is determinted by the parent operation. For example, a yield in a switch-case region implies a fallthrough, while a yield in a cir.if region implies a branch to the exit block, and so on.

In some cases, it might yield an SSA value and the semantics of how the values are yielded is defined by the parent operation. For example, a cir.ternary operation yields a value from one of its regions.

As a general rule, cir.yield must be explicitly used whenever a region has more than one block and no terminator, or within cir.switch regions not cir.return terminated.

Examples:

cir.if %4 {
  ...
  cir.yield
}

cir.switch (%5) [
  case (equal, 3) {
    ...
    cir.yield
  }, ...
]

cir.scope {
  ...
  cir.yield
}

%x = cir.scope {
  ...
  cir.yield %val
}

%y = cir.ternary {
  ...
  cir.yield %val : i32
} : i32

Traits: HasParent<ArrayCtor, ArrayDtor, AwaitOp, CaseOp, CleanupScopeOp, CoroutineOp, DoWhileOp, ForOp, GlobalOp, IfOp, LocalInitOp, RegisterExitDtorOp, ScopeOp, SwitchOp, TernaryOp, TryOp, WhileOp>, ReturnLike, Terminator

Interfaces: NoMemoryEffect (MemoryEffectOpInterface), RegionBranchTerminatorOpInterface

Effects: MemoryEffects::Effect{}

Operands:#

Operand

Description

args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or CIR matrix type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR bit-field access unit member type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CUDA device surface reference type or CUDA device texture reference type or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

Attributes#

ASTVarDeclAttr#

Wraps a ‘const clang::VarDecl *’ AST node.

Operations optionally refer to this node, they could be available depending on the CIR lowering stage. Whether it’s attached to the appropriate CIR operation is delegated to the operation verifier.

Note: the AST pointer can be null when CIR is parsed from text, since there is no serialization support for AST nodes yet.

Parameters:#

Parameter

C++ type

Description

ast

const clang::VarDecl *

AddressPointAttr#

Address point attribute

Syntax:

#cir.address_point<
  int32_t,   # index
  int32_t   # offset
>

Attribute specifying the address point within a C++ virtual table (vtable).

The index (vtable index) parameter identifies which vtable to use within a vtable group, while the offset (address point index) specifies the offset within that vtable where the address begins.

Example:

cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.vtable.address_point(@_ZTV1B,
                              address_point = <index = 0, offset = 2>)
                             : !cir.vptr

Parameters:#

Parameter

C++ type

Description

index

int32_t

offset

int32_t

AnnotationAttr#

Annotation attribute for global variables and functions

Syntax:

#cir.annotation<
  ::mlir::StringAttr,   # name
  mlir::ArrayAttr   # args
>

Represents a C/C++ __attribute__((annotate(...))) in CIR.

Example C code:

int *a __attribute__((annotate("testptr", "21", 12)));

In CIR, the attribute for above annotation looks like:

[#cir.annotation<"testptr", ["21", 12 : i32]>]

Parameters:#

Parameter

C++ type

Description

name

::mlir::StringAttr

args

mlir::ArrayAttr

AsmFlavorAttr#

ATT or Intel

Syntax:

#cir.asm_flavor<
  `x86_att` | `x86_intel`   # value
>

Enum cases:

  • x86_att (x86_att)

  • x86_intel (x86_intel)

Parameters:#

Parameter

C++ type

Description

value

::cir::AsmFlavor

an enum of type AsmFlavor

AssumeBundleKindAttr#

Kind of cir.assume operand bundle

Syntax:

#cir.assume_bundle<
  `None` | `align` | `separate_storage` | `dereferenceable`   # value
>

Enum cases:

  • None (None)

  • align (Align)

  • separate_storage (SeparateStorage)

  • dereferenceable (Dereferenceable)

Parameters:#

Parameter

C++ type

Description

value

::cir::AssumeBundleKind

an enum of type AssumeBundleKind

AtomicFetchKindAttr#

Binary opcode for atomic fetch-and-update operations

Syntax:

#cir.atomic_fetch<
  `add` | `sub` | `and` | `xor` | `or` | `nand` | `max` | `min` | `uinc_wrap` | `udec_wrap` | `maximum` | `minimum` | `maximum_num` | `minimum_num`   # value
>

Enum cases:

  • add (Add)

  • sub (Sub)

  • and (And)

  • xor (Xor)

  • or (Or)

  • nand (Nand)

  • max (Max)

  • min (Min)

  • uinc_wrap (UIncWrap)

  • udec_wrap (UDecWrap)

  • maximum (Maximum)

  • minimum (Minimum)

  • maximum_num (MaximumNum)

  • minimum_num (MinimumNum)

Parameters:#

Parameter

C++ type

Description

value

::cir::AtomicFetchKind

an enum of type AtomicFetchKind

AwaitKindAttr#

Await kind

Syntax:

#cir.await<
  `init` | `user` | `yield` | `final`   # value
>

Enum cases:

  • init (Init)

  • user (User)

  • yield (Yield)

  • final (Final)

Parameters:#

Parameter

C++ type

Description

value

::cir::AwaitKind

an enum of type AwaitKind

BitFieldDeclAttr#

How the source declared one bit-field

Syntax:

#cir.bitfield_decl<
  ::mlir::Type,   # declared_type
  uint64_t,   # width
  bool   # is_unnamed
>

Records a single bit-field as its declaration wrote it: the declared type, the number of bits the field holds, and whether the declaration named it.

A run of bit-fields shares one access unit whose width the compiler picks, so none of this can be recovered from the unit. The fields in a run need not even agree on a declared type: struct { int a : 2; long long b : 30; } packs an int and a long long into a single 32-bit unit. This attribute is therefore per field, and !cir.bitfield carries one of them for every bit-field in the unit.

A width of zero is a zero-width bit-field, int : 0, which holds no bits and exists only to end the run before it.

unnamed marks a bit-field the source cannot read, int : 3. It still occupies bits of the unit, and the x86-64 classifier reads it, but it is not a field any expression names. Every zero-width bit-field is unnamed.

Example:

  #cir.bitfield_decl<!s32i, 4>
  #cir.bitfield_decl<!s64i, 30>
  #cir.bitfield_decl<!s32i, 3, unnamed>
  #cir.bitfield_decl<!u32i, 0, unnamed>

Parameters:#

Parameter

C++ type

Description

declared_type

::mlir::Type

integer or boolean type

width

uint64_t

is_unnamed

bool

unnamed bit-field flag

BitfieldInfoAttr#

Represents info for a bit-field member

Syntax:

#cir.bitfield_info<
  mlir::StringAttr,   # name
  mlir::Type,   # storage_type
  uint64_t,   # size
  uint64_t,   # offset
  bool   # is_signed
>

Holds the following information about bitfields: name, storage type, size and position in the storage, and signedness. Example: Given the following struct with bitfields: c++     typedef struct {       int a : 4;       int b : 27;       int c : 17;       int d : 2;       int e : 15;     } S;    

The CIR representation of the struct S might look like:

  !rec_S = !cir.struct<"S" packed {!u64i, !u16i,
                                   pad !cir.array<!u8i x 2>}>

And the bitfield info attribute for member a would be:

  #bfi_a = #cir.bitfield_info<name = "a", storage_type = !u64i,
                              size = 4, offset = 0, is_signed = true>

This metadata describes that field a is stored in a 64-bit integer, is 4 bits wide, starts at offset 0, and is signed.

Parameters:#

Parameter

C++ type

Description

name

mlir::StringAttr

storage_type

mlir::Type

size

uint64_t

offset

uint64_t

is_signed

bool

BlockAddrDiffAttr#

Difference between two block addresses

Syntax:

#cir.block_addr_diff<
  cir::IntType,   # type
  mlir::FlatSymbolRefAttr,   # func
  mlir::StringAttr,   # lhs_label
  mlir::StringAttr   # rhs_label
>

This attribute represents the constant difference between the addresses of two basic blocks within the same function. It is produced for GCC’s “labels as values” extension when the difference of two label addresses appears in a constant context, e.g. &&lhs - &&rhs.

Both labels belong to the function referenced by func. The value is the address of lhs_label minus the address of rhs_label, truncated to the attribute’s integer type.

Example:

cir.global "private" internal @b.ar =
    #cir.block_addr_diff<@b, "l2", "l1"> : !s32i

Parameters:#

Parameter

C++ type

Description

type

cir::IntType

func

mlir::FlatSymbolRefAttr

lhs_label

mlir::StringAttr

rhs_label

mlir::StringAttr

BlockAddrInfoAttr#

Block address attribute

Syntax:

#cir.block_addr_info<
  cir::PointerType,   # type
  mlir::FlatSymbolRefAttr,   # func
  mlir::StringAttr   # label
>

This attribute is used to represent the address of a basic block within a function. It combines the symbol reference to a function with the name of a label inside that function.

Parameters:#

Parameter

C++ type

Description

type

cir::PointerType

func

mlir::FlatSymbolRefAttr

label

mlir::StringAttr

BoolAttr#

Represent true/false for !cir.bool types

Syntax:

#cir.bool<
  cir::BoolType,   # type
  bool   # value
>

The BoolAttr represents a ‘true’ or ‘false’ value.

Parameters:#

Parameter

C++ type

Description

type

cir::BoolType

value

bool

CUDAExternallyInitializedAttr#

The marked variable is externally initialized.

Syntax: #cir.cu.externally_initialized

CUDA device and constant variables, along with surface and textures, might be initialized by host, hence “externally initialized”. Therefore they must be emitted even if they are not referenced.

The attribute corresponds to the attribute on LLVM with the same name.

CUDAKernelNameAttr#

Device-side function name for this stub.

Syntax:

#cir.cu.kernel_name<
  mlir::StringAttr   # kernel_name
>

This attribute is attached to function definitions and records the mangled name of the kernel function used on the device.

In CUDA, global functions (kernels) are processed differently for host and device. On host, Clang generates device stubs; on device, they are treated as normal functions. As they probably have different mangled names, we must record the corresponding device-side name for a stub. Preserving the device-side kernel name is crucial for performing its respective function runtime registration on the host.

Parameters:#

Parameter

C++ type

Description

kernel_name

mlir::StringAttr

CUDAVarRegistrationInfoAttr#

Device variable registration flags.

Parameters:#

Parameter

C++ type

Description

device_side_name

std::string

kind

CUDADeviceVarKind

isExtern

bool

isConstant

bool

isManaged

bool

CXXAssignAttr#

Marks a function as a CXX assignment operator

Syntax:

#cir.cxx_assign<
  mlir::Type,   # type
  `copy` | `move`,   # assign_kind
  bool   # is_trivial
>

This attribute identifies a C++ assignment operator and classifies its kind:

  • copy: a copy assignment

  • move: a move assignment

Parameters:#

Parameter

C++ type

Description

type

mlir::Type

assign_kind

::cir::AssignKind

an enum of type AssignKind

is_trivial

bool

CXXCtorAttr#

Marks a function as a C++ constructor

Syntax:

#cir.cxx_ctor<
  mlir::Type,   # type
  `custom` | `default` | `copy` | `move`,   # ctor_kind
  bool   # is_trivial
>

This attribute identifies a C++ constructor and classifies its kind:

  • custom: a user-defined constructor

  • default: a default constructor

  • copy: a copy constructor

  • move: a move constructor

Example:

#cir.cxx_ctor<!rec_a, copy>
#cir.cxx_ctor<!rec_b, default, trivial>

Parameters:#

Parameter

C++ type

Description

type

mlir::Type

ctor_kind

::cir::CtorKind

an enum of type CtorKind

is_trivial

bool

CXXDtorAttr#

Marks a function as a CXX destructor

Syntax:

#cir.cxx_dtor<
  mlir::Type,   # type
  bool   # is_trivial
>

This attribute identifies a C++ destructor.

Parameters:#

Parameter

C++ type

Description

type

mlir::Type

is_trivial

bool

CXXModuleInitAttr#

Initializer function of an imported C++20 named module

Syntax:

#cir.cxx_module_init<
  mlir::StringAttr,   # name
  mlir::LocationAttr   # loc
>

The Itanium-mangled name of the initializer function of a C++20 named module the translation unit imports, with the location of the import declaration. CIRGen lists one per module whose initializer the unit’s global init function must call, in call order, in the cir.cxx_module_imported_inits module attribute; LoweringPrepare declares each function at that location and calls it before the unit’s own initializers.

Example:

cir.cxx_module_imported_inits = [#cir.cxx_module_init<"_ZGIW1a", loc("use.cpp":1:1)>]

Parameters:#

Parameter

C++ type

Description

name

mlir::StringAttr

loc

mlir::LocationAttr

CallingConvAttr#

Calling convention

Syntax:

#cir.calling_conv<
  `c` | `ptx_kernel` | `spir_function` | `spir_kernel` | `amdgpu_kernel`   # value
>

Enum cases:

  • c (C)

  • ptx_kernel (PTXKernel)

  • spir_function (SpirFunction)

  • spir_kernel (SpirKernel)

  • amdgpu_kernel (AMDGPUKernel)

Parameters:#

Parameter

C++ type

Description

value

::cir::CallingConv

an enum of type CallingConv

CaseOpKindAttr#

Case kind

Syntax:

#cir.case<
  `default` | `equal` | `anyof` | `range`   # value
>

Enum cases:

  • default (Default)

  • equal (Equal)

  • anyof (Anyof)

  • range (Range)

Parameters:#

Parameter

C++ type

Description

value

::cir::CaseOpKind

an enum of type CaseOpKind

CastKindAttr#

Cast kind

Syntax:

#cir.cast<
  `bitcast` | `array_to_ptrdecay` | `member_ptr_to_bool` | `int_to_ptr` | `ptr_to_int` | `ptr_to_bool` | `integral` | `int_to_bool` | `int_to_float` | `float_to_int` | `float_to_bool` | `bool_to_int` | `floating` | `float_to_complex` | `float_complex_to_real` | `float_complex_to_bool` | `float_complex` | `float_complex_to_int_complex` | `int_to_complex` | `int_complex_to_real` | `int_complex_to_bool` | `int_complex` | `int_complex_to_float_complex` | `address_space` | `bool_to_float`   # value
>

Enum cases:

  • bitcast (bitcast)

  • array_to_ptrdecay (array_to_ptrdecay)

  • member_ptr_to_bool (member_ptr_to_bool)

  • int_to_ptr (int_to_ptr)

  • ptr_to_int (ptr_to_int)

  • ptr_to_bool (ptr_to_bool)

  • integral (integral)

  • int_to_bool (int_to_bool)

  • int_to_float (int_to_float)

  • float_to_int (float_to_int)

  • float_to_bool (float_to_bool)

  • bool_to_int (bool_to_int)

  • floating (floating)

  • float_to_complex (float_to_complex)

  • float_complex_to_real (float_complex_to_real)

  • float_complex_to_bool (float_complex_to_bool)

  • float_complex (float_complex)

  • float_complex_to_int_complex (float_complex_to_int_complex)

  • int_to_complex (int_to_complex)

  • int_complex_to_real (int_complex_to_real)

  • int_complex_to_bool (int_complex_to_bool)

  • int_complex (int_complex)

  • int_complex_to_float_complex (int_complex_to_float_complex)

  • address_space (address_space)

  • bool_to_float (bool_to_float)

Parameters:#

Parameter

C++ type

Description

value

::cir::CastKind

an enum of type CastKind

CatchAllAttr#

Syntax: #cir.all

CleanupKindAttr#

Cleanup kind

Syntax:

#cir.cleanup<
  `normal` | `eh` | `all`   # value
>

Enum cases:

  • normal (Normal)

  • eh (EH)

  • all (All)

Parameters:#

Parameter

C++ type

Description

value

::cir::CleanupKind

an enum of type CleanupKind

CmpOpKindAttr#

Compare operation kind

Syntax:

#cir.cmp<
  `lt` | `le` | `gt` | `ge` | `eq` | `ne` | `one` | `uno`   # value
>

Enum cases:

  • lt (lt)

  • le (le)

  • gt (gt)

  • ge (ge)

  • eq (eq)

  • ne (ne)

  • one (one)

  • uno (uno)

Parameters:#

Parameter

C++ type

Description

value

::cir::CmpOpKind

an enum of type CmpOpKind

CmpThreeWayInfoAttr#

Holds information about a three-way comparison operation

Syntax:

#cir.cmp3way_info<
  `strong` | `weak` | `partial`,   # ordering
  int64_t,   # lt
  int64_t,   # eq
  int64_t,   # gt
  std::optional<int64_t>   # unordered
>

The #cmpinfo attribute contains information about a three-way comparison operation cir.cmp3way.

The ordering parameter gives the ordering kind of the three-way comparison operation: strong ordering, weak ordering, or partial ordering. Strong and weak orderings are both total orderings (i.e. every two elements are comparable), while partial orderings can have incomparable elements.

Given the two input operands of the three-way comparison operation lhs and rhs, the lt, eq, gt, and unordered parameters gives the result value that should be produced by the three-way comparison operation when the ordering between lhs and rhs is lhs < rhs, lhs == rhs, lhs > rhs, or neither, respectively.

Example:

!s32i = !cir.int<s, 32>

#cmpinfo_partial_ltn1eq0gt1unn127 = #cir.cmp3way_info<partial, lt = -1, eq = 0, gt = 1, unordered = -127>
#cmpinfo_strong_ltn1eq0gt1 = #cir.cmp3way_info<strong, lt = -1, eq = 0, gt = 1>

%0 = cir.const #cir.int<0> : !s32i
%1 = cir.const #cir.int<1> : !s32i
%2 = cir.cmp3way(%0 : !s32i, %1, #cmpinfo_strong_ltn1eq0gt1) : !s8i

%3 = cir.const #cir.fp<0.0> : !cir.float
%4 = cir.const #cir.fp<1.0> : !cir.float
%5 = cir.cmp3way(%3 : !cir.float, %4, #cmpinfo_partial_ltn1eq0gt1unn127) : !s8

Parameters:#

Parameter

C++ type

Description

ordering

::cir::CmpOrdering

an enum of type CmpOrdering

lt

int64_t

eq

int64_t

gt

int64_t

unordered

std::optional<int64_t>

ComplexRangeKindAttr#

Complex multiplication and division implementation

Syntax:

#cir.complex_range<
  `full` | `improved` | `promoted` | `basic`   # value
>

Enum cases:

  • full (Full)

  • improved (Improved)

  • promoted (Promoted)

  • basic (Basic)

Parameters:#

Parameter

C++ type

Description

value

::cir::ComplexRangeKind

an enum of type ComplexRangeKind

ConstArrayAttr#

A constant array from ArrayAttr or StringRefAttr

An CIR array attribute is an array of literals of the specified attr types.

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

elts

mlir::Attribute

trailingZerosNum

int

ConstComplexAttr#

An attribute that contains a constant complex value

Syntax:

#cir.const_complex<
  cir::ComplexType,   # type
  ::mlir::TypedAttr,   # real
  ::mlir::TypedAttr   # imag
>

The #cir.const_complex attribute contains a constant value of complex number type. The real parameter gives the real part of the complex number and the imag parameter gives the imaginary part of the complex number.

The real and imag parameters must both reference the same type and must be either IntAttr or FPAttr.

%ci = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i>
    : !cir.complex<!s32i>
%cf = #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float,
    #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>

Parameters:#

Parameter

C++ type

Description

type

cir::ComplexType

real

::mlir::TypedAttr

integer or floating point type

imag

::mlir::TypedAttr

integer or floating point type

ConstPtrAttr#

Holds a constant pointer value

Syntax:

#cir.ptr<
  ::cir::PointerType,   # type
  mlir::IntegerAttr   # value
>

A pointer attribute is a literal attribute that represents an integral value of a pointer type.

Parameters:#

Parameter

C++ type

Description

type

::cir::PointerType

value

mlir::IntegerAttr

ConstRecordAttr#

Represents a constant record

Syntax:

#cir.const_record<
  ::mlir::Type,   # type
  mlir::ArrayAttr   # members
>

Effectively supports “struct-like” constants. It’s must be built from an mlir::ArrayAttr instance where each element is a typed attribute (mlir::TypedAttribute).

These must be initialized with a set of types that exactly match the type of the attribute, with one exception: flexible array members. If the last member of a struct type or a member of a union type is a zero-length array, the ConstRecordAttr may initialize it with a larger array of the same element type. This is necessary to support global and static storage duration variables that use the flexible array member functionality.

Example:

cir.global external @rgb2 = #cir.const_record<{0 : i8,
                                               5 : i64, #cir.null : !cir.ptr<i8>
                                              }> : !cir.record<"", i8, i64, !cir.ptr<i8>>

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

members

mlir::ArrayAttr

ConstVectorAttr#

A constant vector from ArrayAttr

Syntax:

#cir.const_vector<
  ::mlir::Type,   # type
  mlir::ArrayAttr   # elts
>

A CIR vector attribute is an array of literals of the specified attribute types.

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

elts

mlir::ArrayAttr

DataMemberAttr#

Holds a constant data member pointer value

Syntax:

#cir.data_member<
  cir::DataMemberType,   # type
  mlir::DenseI32ArrayAttr   # member_path
>

A data member attribute is a literal attribute that represents a constant pointer-to-data-member value.

The member_path parameter is a GEP-like sequence of field indices navigating from classTy down to the pointed-to member. An absent member_path represents a null pointer-to-data-member.

Examples:

// int Point::*p = &Point::z  (z is field 2)
#cir.data_member<[2]> : !cir.data_member<!s32i in !rec_Point>

// int Derived::*p = &Derived::x  (Base subobject at [0], x at [0])
#cir.data_member<[0, 0]> : !cir.data_member<!s32i in !rec_Derived>

// null
#cir.data_member<null> : !cir.data_member<!s32i in !rec_Point>

Parameters:#

Parameter

C++ type

Description

type

cir::DataMemberType

member_path

mlir::DenseI32ArrayAttr

DataMemberOffsetAttr#

Constant pointer-to-data-member given by a byte offset

Syntax:

#cir.data_member_offset<
  cir::DataMemberType,   # type
  uint64_t   # offset
>

Like #cir.data_member, this is a literal attribute representing a constant (non-null) pointer-to-data-member value. It is used for members that are not laid out in the CIR record and therefore have no field-index path – in particular [[no_unique_address]] empty fields. The concrete byte offset of the member within the class is stored directly.

Example:

// Empty S::*p = &S::e  (e is a no_unique_address empty field at byte 1)
#cir.data_member_offset<1> : !cir.data_member<!rec_Empty in !rec_S>

Parameters:#

Parameter

C++ type

Description

type

cir::DataMemberType

offset

uint64_t

DynamicCastInfoAttr#

ABI specific information about a dynamic cast

Syntax:

#cir.dyn_cast_info<
  ::cir::GlobalViewAttr,   # src_rtti
  ::cir::GlobalViewAttr,   # dest_rtti
  mlir::FlatSymbolRefAttr,   # runtime_func
  mlir::FlatSymbolRefAttr,   # bad_cast_func
  ::cir::IntAttr   # offset_hint
>

Provide ABI specific information about a dynamic cast operation.

The src_rtti and the dest_rtti parameters give the RTTI of the source record type and the destination record type, respectively.

The runtime_func parameter gives the __dynamic_cast function which is provided by the runtime. The bad_cast_func parameter gives the __cxa_bad_cast function which is also provided by the runtime.

The offset_hint parameter gives the hint value that should be passed to the __dynamic_cast runtime function.

Parameters:#

Parameter

C++ type

Description

src_rtti

::cir::GlobalViewAttr

Provides constant access to a global address

dest_rtti

::cir::GlobalViewAttr

Provides constant access to a global address

runtime_func

mlir::FlatSymbolRefAttr

bad_cast_func

mlir::FlatSymbolRefAttr

offset_hint

::cir::IntAttr

An attribute containing an integer value

DynamicCastKindAttr#

Dynamic cast kind

Syntax:

#cir.dynamic_cast<
  `ptr` | `ref`   # value
>

Enum cases:

  • ptr (Ptr)

  • ref (Ref)

Parameters:#

Parameter

C++ type

Description

value

::cir::DynamicCastKind

an enum of type DynamicCastKind

DynamicInitGuardAttr#

Guard variable name for guarded dynamic initialization

Syntax:

#cir.dynamic_init_guard<
  mlir::StringAttr   # name
>

Contains the mangled guard variable name for guarded dynamic initialization. This covers both function-local static variables and namespace-scope variables with vague linkage (e.g. weak/linkonce_odr inline variables), which both use the Itanium __cxa_guard_* protocol. See DynamicInitInfoAttr for the facts that distinguish the two.

Example:

cir.global internal dynamic_init_guard<"_ZGVZ3foovE1x"> @_ZZ3foovE1x = ...

Parameters:#

Parameter

C++ type

Description

name

mlir::StringAttr

DynamicInitInfoAttr#

Variable facts needed by guarded dynamic initialization lowering

Syntax:

#cir.dynamic_init_info<
  bool,   # local
  `none` | `static` | `dynamic`,   # tls
  bool,   # is_inline
  `undeclared` | `implicit_instantiation` | `explicit_specialization` | `explicit_instantiation_declaration` | `explicit_instantiation_definition`   # tsk
>

Holds the subset of a guarded-dynamic-initialization variable’s declaration facts that post-CIRGen lowering needs, as plain data (no clang::VarDecl pointer). Always accompanies a DynamicInitGuardAttr, and applies equally to function-local statics and to namespace-scope variables with vague linkage (e.g. weak/linkonce_odr inline variables).

  • local: whether the variable is a block-scope (local) declaration. Mirrors clang::VarDecl::isLocalVarDecl(). The namespace-scope inline variables that also reach guarded initialization are not local.

  • tls: the thread-local storage kind (none, static, or dynamic).

  • is_inline: whether the variable is inline. Mirrors clang::VarDecl::isInline().

  • tsk: the template-specialization kind (undeclared, implicit_instantiation, explicit_specialization, explicit_instantiation_declaration, or explicit_instantiation_definition).

Example:

cir.global ... @x = ...
  dynamic_init_info<local = true, tls = none, is_inline = false,
                    tsk = undeclared>

Because it stores plain data rather than a clang::VarDecl pointer, it round-trips through textual CIR and stays valid once the AST is gone. This is what lets LoweringPrepare consume these facts without a live clang::ASTContext; the $ast ASTVarDeclAttr remains a separate, live-AST handle for consumers that need arbitrary AST properties.

Parameters:#

Parameter

C++ type

Description

local

bool

tls

::cir::TLSKind

an enum of type TLSKind

is_inline

bool

tsk

::cir::TemplateSpecializationKind

an enum of type TemplateSpecializationKind

EhFilterAttr#

Dynamic exception specification filter handler

Syntax:

#cir.eh_filter<
  mlir::ArrayAttr   # permitted_types
>

Identifies the handler of a cir.try operation that is reached when the in-flight exception is permitted by the dynamic exception specification of the enclosing function. The attribute carries the list of type info symbols naming the permitted types. An empty list represents throw(), which permits nothing.

Parameters:#

Parameter

C++ type

Description

permitted_types

mlir::ArrayAttr

EhUnexpectedAttr#

Dynamic exception specification unexpected exception handler

Syntax: #cir.eh_unexpected

Identifies the handler of a cir.try operation that is reached when the in-flight exception is not permitted by the dynamic exception specification of the enclosing function.

FPAttr#

An attribute containing a floating-point value

Syntax:

#cir.fp<
  ::cir::FPTypeInterface,   # type
  ::llvm::APFloat   # value
>

An fp attribute is a literal attribute that represents a floating-point value of the specified floating-point type. Supporting only CIR FP types.

Parameters:#

Parameter

C++ type

Description

type

::cir::FPTypeInterface

value

::llvm::APFloat

FPClassTestAttr#

Floating-point class test flags

Syntax:

#cir.fp_class<
  `fcNone` | `fcSNan` | `fcQNan` | `fcNegInf` | `fcNegNormal` | `fcNegSubnormal` | `fcNegZero` | `fcPosZero` | `fcPosSubnormal` | `fcPosNormal` | `fcPosInf` | `fcNan` | `fcInf` | `fcNormal` | `fcSubnormal` | `fcZero` | `fcPosFinite` | `fcNegFinite` | `fcFinite` | `fcPositive` | `fcNegative` | `fcAllFlags`   # value
>

Enum cases:

  • fcNone (None)

  • fcSNan (SignalingNaN)

  • fcQNan (QuietNaN)

  • fcNegInf (NegativeInfinity)

  • fcNegNormal (NegativeNormal)

  • fcNegSubnormal (NegativeSubnormal)

  • fcNegZero (NegativeZero)

  • fcPosZero (PositiveZero)

  • fcPosSubnormal (PositiveSubnormal)

  • fcPosNormal (PositiveNormal)

  • fcPosInf (PositiveInfinity)

  • fcNan (Nan)

  • fcInf (Infinity)

  • fcNormal (Normal)

  • fcSubnormal (Subnormal)

  • fcZero (Zero)

  • fcPosFinite (PositiveFinite)

  • fcNegFinite (NegativeFinite)

  • fcFinite (Finite)

  • fcPositive (Positive)

  • fcNegative (Negative)

  • fcAllFlags (All)

Parameters:#

Parameter

C++ type

Description

value

::cir::FPClassTest

an enum of type FPClassTest

FastMathFlagsAttr#

Fast-math flags

Syntax:

#cir.fastmath<
  `none` | `nnan` | `ninf` | `nsz` | `arcp` | `contract` | `afn` | `reassoc` | `fast`   # value
>

Describes fast-math flags for CIR operations. This attribute is shared by operations with floating-point semantics and is not specific to LLVM intrinsic calls.

Parameters:#

Parameter

C++ type

Description

value

::cir::FastMathFlags

an enum of type FastMathFlags

FenvAttr#

Describes floating-point environment constraints

Syntax:

#cir.fenv<
  std::optional<cir::FPDynamicRoundingMode>,   # dynamic_rounding_mode
  std::optional<cir::FPExceptionMode>,   # except_mode
  mlir::BoolAttr   # strict_except
>

The #cir.fenv attribute describes constraints on the floating-point handling of a floating-point operation. It is attached to floating-point operations to capture rounding and exception behavior. All of its parameters are optional.

  • dynamic_rounding_mode: the known dynamic rounding mode at the point the instruction is executed. Otherwise the behavior is undefined.

  • except_mode: the known exception mode at the point the instruction is executed. Otherwise the behavior is undefined.

  • strict_except: if false, any case that would produce an FP exception produces it non-deterministically instead (i.e. it may or may not occur). This means the FP status is written non-deterministically, and, if exceptions are unmasked, the instruction traps non-deterministically.

An absent dynamic_rounding_mode defaults to unknown, an absent except_mode defaults to masked, and an absent strict_except defaults to false.

Example:

#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown,
          strict_except = true>

Parameters:#

Parameter

C++ type

Description

dynamic_rounding_mode

std::optional<cir::FPDynamicRoundingMode>

except_mode

std::optional<cir::FPExceptionMode>

strict_except

mlir::BoolAttr

FramePointerKindAttr#

Encodes the frame pointer kind for a function or a module.

Syntax:

#cir.frame_pointer<
  `none` | `non_leaf` | `all` | `reserved` | `non_leaf_no_reserve`   # value
>

Mirrors the frame-pointer function attribute and module flag of LLVM IR (https://llvm.org/docs/LangRef.html#function-attributes), which tell the code generator whether a function should keep its frame pointer. The code generator may keep a frame pointer even when the kind says it can be eliminated.

  • none: the frame pointer can be eliminated, and its register can be used for other purposes.

  • reserved: the frame pointer register must either be updated to point to a valid frame record for the current function, or not be modified.

  • non_leaf: the frame pointer should be kept if the function calls other functions.

  • non_leaf_no_reserve: like non_leaf, but a leaf function may use the frame pointer register for other purposes.

  • all: the frame pointer should be kept.

On a function, the attribute applies to that function. On the module, it becomes the frame-pointer module flag, which LLVM applies to the functions it creates after CIR is lowered, such as sanitizer constructors. Without the attribute, the kind is none.

Example:

module attributes {cir.frame_pointer = #cir.frame_pointer<all>} {
  cir.func private @f() attributes {frame_pointer = #cir.frame_pointer<all>}
}

Parameters:#

Parameter

C++ type

Description

value

::cir::FramePointerKind

an enum of type FramePointerKind

FuncIdentityAttr#

Identifies a function as a known standard library entity

Syntax:

#cir.func_identity<
  `std::find`   # kind
>

Names the standard library entity a function represents, so that transformations can recognize calls to well known library functions without decoding mangled symbol names.

The tag names the whole entity. For std::find that is the free function named find in the std namespace, so a member function, a static member, or an operator can never carry the tag. Inline namespaces, such as the versioning namespace of libc++, count as part of std. The tag never encodes signatures, and a function that matches no known entity carries no attribute.

Example:

#cir.func_identity<"std::find">

Parameters:#

Parameter

C++ type

Description

kind

::cir::KnownFuncKind

an enum of type KnownFuncKind

GlobalCtorAttr#

Marks a function as a global constructor

Syntax:

#cir.global_ctor<
  mlir::StringAttr,   # name
  int,   # priority
  mlir::FlatSymbolRefAttr   # associated
>

Marks the function as a global constructor in the module’s constructor list. It will be executed before main() is called.

Parameters:#

Parameter

C++ type

Description

name

mlir::StringAttr

priority

int

associated

mlir::FlatSymbolRefAttr

GlobalDtorAttr#

Marks a function as a global destructor

Syntax:

#cir.global_dtor<
  mlir::StringAttr,   # name
  int,   # priority
  mlir::FlatSymbolRefAttr   # associated
>

Marks a function as a global destructor in the module dtors list. The function will be executed before the module unloading.

Parameters:#

Parameter

C++ type

Description

name

mlir::StringAttr

priority

int

associated

mlir::FlatSymbolRefAttr

GlobalLinkageKindAttr#

Linkage kind

Syntax:

#cir.linkage<
  `external` | `available_externally` | `linkonce` | `linkonce_odr` | `weak` | `weak_odr` | `appending` | `internal` | `cir_private` | `extern_weak` | `common`   # value
>

Enum cases:

  • external (ExternalLinkage)

  • available_externally (AvailableExternallyLinkage)

  • linkonce (LinkOnceAnyLinkage)

  • linkonce_odr (LinkOnceODRLinkage)

  • weak (WeakAnyLinkage)

  • weak_odr (WeakODRLinkage)

  • appending (AppendingLinkage)

  • internal (InternalLinkage)

  • cir_private (PrivateLinkage)

  • extern_weak (ExternalWeakLinkage)

  • common (CommonLinkage)

Parameters:#

Parameter

C++ type

Description

value

::cir::GlobalLinkageKind

an enum of type GlobalLinkageKind

GlobalOffsetAttr#

Provides constant access to a byte offset from a global

Syntax:

#cir.global_offset<
  ::mlir::Type,   # type
  mlir::FlatSymbolRefAttr,   # symbol
  int64_t   # offset
>

Get the constant address that is offset bytes away from the address of global symbol. Like #cir.global_view, it provides a way to access globals from other globals and always produces a pointer, and the type of the referenced symbol may differ from the type of the attribute.

Whereas #cir.global_view navigates the type of the symbol using subelement indices, this attribute describes a flat displacement in bytes. It is used for the addresses that cannot be described by subelement indices, namely addresses outside of the referenced object, such as the one-past-the-end address of a record, and addresses that do not fall on a subelement boundary. This mirrors the byte offset that classic codegen applies to every constant lvalue.

Example:

struct S { int x; };
S s;
S *p = &s + 1;

produces

cir.global external @p = #cir.global_offset<@s, 4> : !cir.ptr<!rec_S>

which lowers to

@p = global ptr getelementptr (i8, ptr @s, i64 4)

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

symbol

mlir::FlatSymbolRefAttr

offset

int64_t

GlobalViewAttr#

Provides constant access to a global address

Syntax:

#cir.global_view<
  ::mlir::Type,   # type
  mlir::FlatSymbolRefAttr,   # symbol
  mlir::ArrayAttr,   # indices
  bool   # address_point
>

Get constant address of global symbol and optionally apply offsets to access existing subelements. It provides a way to access globals from other global and always produces a pointer.

The type of the input symbol can be different from #cir.global_view output type, since a given view of the global might require a static cast for initializing other globals.

A list of indices can be optionally passed and each element subsequently indexes underlying types. For symbol types like !cir.array and !cir.record, it leads to the constant address of sub-elements, while for !cir.ptr, an offset is applied. The first index is relative to the original symbol type, not the produced one.

The result type of this attribute may be an integer type. In such a case, the pointer to the referenced global is casted to an integer and this attribute represents the casted result.

Example:

  cir.global external @s = @".str2": !cir.ptr<i8>
  cir.global external @x = #cir.global_view<@s> : !cir.ptr<i8>
  cir.global external @s_addr = #cir.global_view<@s> : !s64i

  cir.global external @rgb = #cir.const_array<[0 : i8, -23 : i8, 33 : i8]
                                               : !cir.array<i8 x 3>>
  cir.global external @elt_ptr = #cir.global_view<@rgb, [1]> : !cir.ptr<i8>

Note, that unlike LLVM IR’s gep instruction, CIR doesn’t add the leading zero index when it’s known to be constant zero, e.g. for pointers, i.e. we use indexes exactly to access sub elements or for the offset. The leading zero index is added later in the lowering.

Example:

struct A {
  int a;
};

struct B:  virtual A {
  int b;
};

address_point marks a vtable address point: symbol is a vtable and indices are the vtable within the group and the address point within it. As in classic codegen, it lowers to an inbounds GEP whose inrange spans that one vtable.

VTT for B in CIR:

cir.global linkonce_odr @_ZTT1B = #cir.const_array<[
          #cir.global_view<@_ZTV1B, [0 : i32, 3 : i32], address_point>
               : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 1>

VTT for B in LLVM IR:

@_ZTT1B = linkonce_odr global [1 x ptr] [ptr getelementptr inbounds
          inrange(-24, 0) (i8, ptr @_ZTV1B, i64 24)], align 8

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

symbol

mlir::FlatSymbolRefAttr

indices

mlir::ArrayAttr

address_point

bool

InitCatchKindAttr#

Allowed i32 cases: 0, 1, 2, 3, 4, 5, 6, 7

Syntax:

#cir.init_catch<
  `reference` | `pointer` | `scalar` | `objc` | `trivial_copy` | `non_trivial_copy` | `reference_to_pointer` | `reference_to_record_pointer`   # value
>

Enum cases:

  • reference (Reference)

  • pointer (Pointer)

  • scalar (Scalar)

  • objc (Objc)

  • trivial_copy (TrivialCopy)

  • non_trivial_copy (NonTrivialCopy)

  • reference_to_pointer (ReferenceToPointer)

  • reference_to_record_pointer (ReferenceToRecordPointer)

Parameters:#

Parameter

C++ type

Description

value

::cir::InitCatchKind

an enum of type InitCatchKind

InlineKindAttr#

Inline kind

Syntax:

#cir.inline<
  `no_inline` | `always_inline` | `inline_hint`   # value
>

Inline Kind attributes. no_inline and always_inline spellings correspond to the attributes of the same name, and inline_hint is the inline keyword in the language.

Parameters:#

Parameter

C++ type

Description

value

::cir::InlineKind

an enum of type InlineKind

IntAttr#

An attribute containing an integer value

Syntax:

#cir.int<
  cir::IntTypeInterface,   # type
  ::llvm::APInt   # value
>

An integer attribute is a literal attribute that represents an integral value of the specified integer type.

Parameters:#

Parameter

C++ type

Description

type

cir::IntTypeInterface

value

::llvm::APInt

LangAddressSpaceAttr#

Represents a language address space

Syntax:

#cir.lang_address_space<
  `default` | `offload_private` | `offload_local` | `offload_global` | `offload_constant` | `offload_generic` | `offload_global_device` | `offload_global_host`   # value
>

Encodes the semantic address spaces defined by the front-end language (e.g. __shared__, __constant__, __local__). Values are stored using the cir::LangAddressSpace enum, keeping the representation compact and preserving the qualifier until it is mapped onto target/LLVM address-space numbers.

Example:

!cir.ptr<!s32i, lang_address_space(offload_local)>
cir.global constant external lang_address_space(offload_constant)

Parameters:#

Parameter

C++ type

Description

value

::cir::LangAddressSpace

an enum of type LangAddressSpace

LoopHintAttr#

Optimizer hints and guarantees attached to a loop

Syntax:

#cir.loop_hint<
  mlir::UnitAttr,   # must_progress
  mlir::UnitAttr,   # vectorize_enable
  uint32_t,   # vectorize_width
  mlir::BoolAttr,   # vectorize_scalable
  mlir::BoolAttr,   # vectorize_predicate
  uint32_t,   # interleave_count
  std::optional<cir::LoopUnrollMode>,   # unroll
  uint32_t,   # unroll_count
  std::optional<cir::LoopUnrollMode>,   # unroll_and_jam
  uint32_t,   # unroll_and_jam_count
  mlir::BoolAttr,   # distribute
  mlir::UnitAttr,   # pipeline_disabled
  uint32_t,   # pipeline_initiation_interval
  mlir::UnitAttr,   # licm_disabled
  mlir::UnitAttr,   # parallel
  uint32_t   # code_align
>

The #cir.loop_hint attribute carries per-loop information for the optimizer: the forward-progress guarantee and the hints from #pragma clang loop, #pragma unroll, [[clang::code_align]] and their OpenCL and HLSL spellings. It is attached to the loop operations (cir.for, cir.while, cir.do).

  • must_progress: the loop must eventually terminate or have an observable side effect (the forward-progress guarantee of C++11 and later, and C11 loops with a non-constant condition).

  • vectorize_enable: force vectorization on.

  • vectorize_width: the vectorization factor. A width of 1 disables vectorization.

  • vectorize_scalable: whether the vectorization factor is scalable, or explicitly fixed.

  • vectorize_predicate: enable or disable predicated vectorization.

  • interleave_count: the interleave count. A count of 1 disables interleaving.

  • unroll: The unrolling mode: enable, disable, or full.

  • unroll_count: the unroll factor.

  • unroll_and_jam: the unroll-and-jam mode: enable, disable, or full.

  • distribute: enable or disable loop distribution.

  • pipeline_disabled: disable software pipelining.

  • pipeline_initiation_interval: the pipelining initiation interval.

  • licm_disabled: disable loop-invariant code motion.

  • parallel: the loop’s iterations are independent, so its memory accesses are parallel accesses.

  • code_align: the alignment of the loop, in bytes.

Example:

#cir.loop_hint<>
#cir.loop_hint< must_progress>
#cir.loop_hint< must_progress vectorize_enable interleave_count = 2
                unroll_count = 4>

Parameters:#

Parameter

C++ type

Description

must_progress

mlir::UnitAttr

vectorize_enable

mlir::UnitAttr

vectorize_width

uint32_t

vectorize_scalable

mlir::BoolAttr

vectorize_predicate

mlir::BoolAttr

interleave_count

uint32_t

unroll

std::optional<cir::LoopUnrollMode>

unroll_count

uint32_t

unroll_and_jam

std::optional<cir::LoopUnrollMode>

unroll_and_jam_count

uint32_t

distribute

mlir::BoolAttr

pipeline_disabled

mlir::UnitAttr

pipeline_initiation_interval

uint32_t

licm_disabled

mlir::UnitAttr

parallel

mlir::UnitAttr

code_align

uint32_t

LoweringLangOptionsAttr#

LangOptions facts that post-CIRGen lowering consumes

Syntax:

#cir.lowering_lang_options<
  bool,   # exceptions
  bool,   # threadsafe_statics
  bool,   # cuda
  bool,   # cuda_is_device
  bool,   # hip
  bool,   # hlsl
  bool,   # gpu_rdc
  bool,   # openmp
  bool,   # openmp_is_target_device
  int32_t   # clang_abi_compat
>

Serializes the subset of clang::LangOptions that post-CIRGen lowering reads, as plain data, so a reloaded .cir module lowers the same way it was compiled without a live clang::LangOptions. Only LangOpts flags with no triple/module representation live here; target-derived facts (size_t width, CXXABI, fp formats, etc.) are rebuilt from cir.triple instead.

Each bool field mirrors the like-named LangOptions member: exceptions, threadsafe_statics, cuda, cuda_is_device, hip, hlsl, gpu_rdc, openmp (LangOpts.OpenMP != 0; only its on/off state matters), and openmp_is_target_device. clang_abi_compat is an i32 mirroring LangOptions::ClangABI; it is an i32 rather than a CIR enum because ClangABI gains an enumerator every Clang release (see clang/Basic/ABIVersions.def), and the ordinal round-trips fine within a single toolchain.

Example:

module attributes {cir.lowering_lang_options = #cir.lowering_lang_options<
  exceptions = false, threadsafe_statics = true, cuda = false,
  cuda_is_device = false, hip = false, gpu_rdc = false, openmp = false,
  openmp_is_target_device = false, clang_abi_compat = 17>} { }

Parameters:#

Parameter

C++ type

Description

exceptions

bool

threadsafe_statics

bool

cuda

bool

cuda_is_device

bool

hip

bool

hlsl

bool

gpu_rdc

bool

openmp

bool

openmp_is_target_device

bool

clang_abi_compat

int32_t

MaxWorkGroupSizeAttr#

Maximum kernel work-group size

Syntax:

#cir.max_work_group_size<
  uint32_t,   # x
  uint32_t,   # y
  uint32_t   # z
>

Stores the maximum work-group size of a kernel, emitted to LLVM IR as max_work_group_size function metadata.

Parameters:#

Parameter

C++ type

Description

x

uint32_t

y

uint32_t

z

uint32_t

MemOrderAttr#

Memory order according to C++11 memory model

Syntax:

#cir.mem_order<
  `relaxed` | `consume` | `acquire` | `release` | `acq_rel` | `seq_cst`   # value
>

Enum cases:

  • relaxed (Relaxed)

  • consume (Consume)

  • acquire (Acquire)

  • release (Release)

  • acq_rel (AcquireRelease)

  • seq_cst (SequentiallyConsistent)

Parameters:#

Parameter

C++ type

Description

value

::cir::MemOrder

an enum of type MemOrder

MemoryEffectsAttr#

Describes the possible memory effects of a function or callee

Syntax:

#cir.memory_effects<
  ModRefInfo,   # other
  ModRefInfo,   # arg_mem
  ModRefInfo,   # inaccessible_mem
  ModRefInfo,   # errno_mem
  ModRefInfo,   # target_mem0
  ModRefInfo   # target_mem1
>

Specifies the possible memory effects of a function or callee. Memory is divided into classes, each carrying its own access, so that a promise about one class need not be a promise about all of them:

  • other: the access for every location not named by one of the other parameters, including locations with no class of their own such as globals and captured pointers.

  • arg_mem: accesses based on the function’s pointer arguments.

  • inaccessible_mem: accesses to memory the current module cannot reach, often used to model the control dependencies of intrinsics.

  • errno_mem: accesses to the errno variable.

  • target_mem0, target_mem1: target-specific state.

The classes and their meanings match the LLVM dialect’s #llvm.memory_effects, which lowering converts this attribute to.

An absent attribute means the effects are unknown, which is the conservative default and what a function with no memory annotation gets. Lowering leaves such a function with no memory attribute at all.

Example:

#cir.memory_effects<other = read, arg_mem = readwrite,
                    inaccessible_mem = none, errno_mem = none,
                    target_mem0 = none, target_mem1 = none>

The attribute has no keyword syntax, so on an operation it is written in the attribute dictionary:

cir.func private @f() attributes {memory_effects = #cir.memory_effects<...>}
%0 = cir.call @f() {memory_effects = #cir.memory_effects<...>} : () -> !s32i

Parameters:#

Parameter

C++ type

Description

other

ModRefInfo

arg_mem

ModRefInfo

inaccessible_mem

ModRefInfo

errno_mem

ModRefInfo

target_mem0

ModRefInfo

target_mem1

ModRefInfo

MethodAttr#

Holds a constant pointer-to-member-function value

A method attribute is a literal attribute that represents a constant pointer-to-member-function value.

If the member function is a non-virtual function, the symbol parameter gives the global symbol for the non-virtual member function.

If the member function is a virtual function, the vtable_offset parameter gives the offset of the vtable entry corresponding to the virtual member function.

symbol and vtable_offset cannot be present at the same time. If both of symbol and vtable_offset are not present, the attribute represents a null pointer constant.

Examples:

// Non-virtual method
%0 = cir.const #cir.method<@_ZN1S2m1Ei> :
         !cir.method<!cir.func<(!s32i)> in !rec_S>

// Virtual method
%1 = cir.const #cir.method<vtable_offset = 8> :
         !cir.method<!cir.func<(!s32i)> in !rec_S>

// Null method pointer
%0 = cir.const #cir.method<null> :
         !cir.method<!cir.func<(!s32i)> in !rec_S>

Parameters:#

Parameter

C++ type

Description

type

cir::MethodType

symbol

std::optional<mlir::FlatSymbolRefAttr>

vtable_offset

std::optional<uint64_t>

OffloadKindAttr#

Offload kind of a module in an offload container

Syntax:

#cir.offload<
  `host` | `device`   # value
>

Marks a module nested inside an offload container - identified by the cir.offload.container unit attribute - as either the host module (carrying cir.offload.kind = #cir.offload<host>) or one of the device modules (carrying cir.offload.kind = #cir.offload<device>) of the offload container. This creates a tiered module layout, where a singular offload container contains a single host module and one or more device modules, granting the offload merge/split pipeline passes the cross-boundary view.

Example:

module attributes {cir.offload.container} {
  module @host attributes {cir.offload.kind = #cir.offload<host>} {}
  module @device1 attributes {cir.offload.kind = #cir.offload<device>} {}
  module @device2 attributes {cir.offload.kind = #cir.offload<device>} {}
}

Note: In order to simplify offload passes, the offload container module requires that the first module inside it is the host module and the rest of the modules are device modules.

The nested modules are plain builtin.module ops rather than a dedicated container op, so that the existing module infrastructure applies to them unchanged; the layout above is enforced by the CIR dialect attribute verifier, following the gpu.container_module precedent.

The attribute names cir.offload.container and cir.offload.kind are defined by the getOffloadContainerAttrName and getOffloadKindAttrName methods in the CIRDialect class.

Parameters:#

Parameter

C++ type

Description

value

::cir::OffloadKind

an enum of type OffloadKind

OffsetPairAttr#

Offset Pair attribute

Syntax:

#cir.offset_pair<
  uint64_t,   # start
  uint64_t   # end
>

An attribute that specifies a pair of positive integral values that represent a bit-offset range in an existing structure. The range represented by this is [start, end).

Example:

cir.clear_padding(align(1) %1,
                  [#cir.offset_pair<0, 2>, #cir.offset_pair<6, 8>])
                  : <rec_Type> -> ()

Parameters:#

Parameter

C++ type

Description

start

uint64_t

end

uint64_t

OpenCLKernelArgMetadataAttr#

OpenCL kernel argument metadata

Syntax:

#cir.cl.kernel_arg_metadata<
  ::mlir::ArrayAttr,   # addr_space
  ::mlir::ArrayAttr,   # access_qual
  ::mlir::ArrayAttr,   # type
  ::mlir::ArrayAttr,   # base_type
  ::mlir::ArrayAttr,   # type_qual
  ::mlir::ArrayAttr   # name
>

Stores the OpenCL kernel argument metadata emitted to LLVM IR as kernel_arg_* metadata.

All parameters are arrays containing the argument information in source order. The name field is optional and is emitted only when requested by -cl-kernel-arg-info.

Parameters:#

Parameter

C++ type

Description

addr_space

::mlir::ArrayAttr

language address space array attribute

access_qual

::mlir::ArrayAttr

string array attribute

type

::mlir::ArrayAttr

string array attribute

base_type

::mlir::ArrayAttr

string array attribute

type_qual

::mlir::ArrayAttr

string array attribute

name

::mlir::ArrayAttr

string array attribute or null

OpenCLVersionAttr#

OpenCL version

Syntax:

#cir.cl.version<
  int32_t,   # majorVersion
  int32_t   # minorVersion
>

Represents an OpenCL language version preserved as module metadata.

The cir.cl.cxx.version module attribute requires a companion cir.cl.version attribute specifying the compatible OpenCL version.

Example:

// Module compiled from OpenCL C 1.2.
module attributes {cir.cl.version = #cir.cl.version<1, 2>} {}
// Module compiled from C++ for OpenCL 2021.
module attributes {
  cir.cl.cxx.version = #cir.cl.version<2021, 0>,
  cir.cl.version = #cir.cl.version<3, 0>
} {}

Parameters:#

Parameter

C++ type

Description

majorVersion

int32_t

minorVersion

int32_t

OptInfoAttr#

A module-level attribute that holds the optimization information

Syntax:

#cir.opt_info<
  unsigned,   # level
  unsigned   # size
>

The #cir.opt_info attribute holds optimization related information. For now this attribute is a module-level attribute that gets attached to the module operation during CIRGen.

The level parameter gives the optimization level. It must be an integer between 0 and 3, inclusive. It corresponds to the OptimizationLevel field within the clang::CodeGenOptions structure.

The size parameter gives the code size optimization level. It must be an integer between 0 and 2, inclusive. It corresponds to the OptimizeSize field within the clang::CodeGenOptions structure.

The level and size parameters correspond to the optimization level command line options passed to clang driver. The table below lists the current correspondance relationship:

Flag

level

size

-O0 or nothing

0

0

-O1

1

0

-O2

2

0

-O3

3

0

-Os

2

1

-Oz

2

2

Examples:

#cir.opt_info<level = 2, size = 0>  // -O2

Parameters:#

Parameter

C++ type

Description

level

unsigned

size

unsigned

PoisonAttr#

Represent a typed poison constant

Syntax:

#cir.poison<
  ::mlir::Type   # type
>

The PoisonAttr represents a typed poison constant, corresponding to LLVM’s notion of poison.

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

PtrSpecAttr#

!cir.ptr data layout spec

Syntax:

#cir.ptr_spec<
  uint32_t,   # size
  uint32_t,   # abi
  uint32_t,   # preferred
  uint32_t   # index
>

Pointer data layout for !cir.ptr: size, abi and preferred are required bitwidths; index is the optional bitwidth for index computations, defaulting to size. All present values must be divisible by 8, with preferred >= abi.

This is the CIR-native analogue of the ptr dialect’s #ptr.spec; a native attribute keeps CIR’s data-layout queries free of any ptr-dialect dependency.

Used as the value of the !cir.ptr<!cir.void>-keyed data-layout entry:

#dlti.dl_spec<!cir.ptr<!cir.void> =
    #cir.ptr_spec<size = 64, abi = 64, preferred = 64>>

Parameters:#

Parameter

C++ type

Description

size

uint32_t

abi

uint32_t

preferred

uint32_t

index

uint32_t

RecordLayoutAttr#

ABI layout metadata for a record type

Syntax:

#cir.record_layout<
  `can_pass_in_regs` | `cannot_pass_in_regs` | `can_never_pass_in_regs`,   # arg_passing_kind
  bool,   # has_trivial_dtor
  uint64_t   # record_align
>

Holds AST-derived ABI metadata for a named record type. These properties are translation-unit / target properties, not intrinsic to the type, so they live on the module rather than on RecordType.

Fields:

  • arg_passing_kind: whether the record can be passed in registers per the C++ ABI (mirrors RecordDecl::getArgPassingRestrictions()).

  • has_trivial_destructor: from CXXRecordDecl::hasTrivialDestructor().

  • record_align_in_bytes: from ASTRecordLayout::getAlignment(). Needed because CIR’s DataLayout cannot account for __attribute__((aligned(N))).

Example:

module attributes {
  cir.record_layouts = {
    "Trivial" = #cir.record_layout<
      arg_passing_kind = can_pass_in_regs,
      has_trivial_dtor = true,
      record_align = 4>,
    "NonTrivialDtor" = #cir.record_layout<
      arg_passing_kind = cannot_pass_in_regs,
      has_trivial_dtor = false,
      record_align = 4>
  }
}

Parameters:#

Parameter

C++ type

Description

arg_passing_kind

::cir::ArgPassingKind

an enum of type ArgPassingKind

has_trivial_dtor

bool

record_align

uint64_t

SourceLanguageAttr#

Module source language

Syntax:

#cir.lang<
  `c` | `cxx` | `opencl_c` | `opencl_cxx`   # value
>

Represents the source language used to generate the module.

Example:

// Module compiled from C.
module attributes {cir.lang = cir.lang<c>} {}
// Module compiled from C++.
module attributes {cir.lang = cir.lang<cxx>} {}
// Module compiled from OpenCL C.
module attributes {cir.lang = cir.lang<opencl_c>} {}
// Module compiled from C++ for OpenCL.
module attributes {cir.lang = cir.lang<opencl_cxx>} {}

Module source language attribute name is cir.lang is defined by getSourceLanguageAttrName method in CIRDialect class.

Parameters:#

Parameter

C++ type

Description

value

::cir::SourceLanguage

an enum of type SourceLanguage

SyncScopeKindAttr#

Sync scope kind

Syntax:

#cir.sync_scope<
  `single_thread` | `system` | `device` | `workgroup` | `wavefront` | `cluster` | `hip_single_thread` | `hip_system` | `hip_agent` | `hip_workgroup` | `hip_wavefront` | `hip_cluster` | `opencl_work_group` | `opencl_device` | `opencl_all_svm_devices` | `opencl_sub_group`   # value
>

Enum cases:

  • single_thread (SingleThread)

  • system (System)

  • device (Device)

  • workgroup (Workgroup)

  • wavefront (Wavefront)

  • cluster (Cluster)

  • hip_single_thread (HIPSingleThread)

  • hip_system (HIPSystem)

  • hip_agent (HIPAgent)

  • hip_workgroup (HIPWorkgroup)

  • hip_wavefront (HIPWavefront)

  • hip_cluster (HIPCluster)

  • opencl_work_group (OpenCLWorkGroup)

  • opencl_device (OpenCLDevice)

  • opencl_all_svm_devices (OpenCLAllSVMDevices)

  • opencl_sub_group (OpenCLSubGroup)

Parameters:#

Parameter

C++ type

Description

value

::cir::SyncScopeKind

an enum of type SyncScopeKind

TLSModelAttr#

TLS model

Syntax:

#cir.tls_model<
  `tls_dyn` | `tls_local_dyn` | `tls_init_exec` | `tls_local_exec`   # value
>

The TLS mode for the global, which comes from either the tls_model attribute, or -ftls-model flag.

Parameters:#

Parameter

C++ type

Description

value

::cir::TLSModel

an enum of type TLSModel

TargetAddressSpaceAttr#

Represents a target-specific numeric address space

Syntax:

#cir.target_address_space<
  unsigned   # value
>

The TargetAddressSpaceAttr represents a target-specific numeric address space, corresponding to the LLVM IR addrspace qualifier and the clang address_space attribute.

A value of zero represents the default address space. The semantics of non-zero address spaces are target-specific.

Example:

// Target-specific numeric address spaces
!cir.ptr<!s32i, addrspace(target<1>)>
!cir.ptr<!s32i, addrspace(target<10>)>

Parameters:#

Parameter

C++ type

Description

value

unsigned

ThreadLocalGlobalWrapperInitAttr#

Wrapper and Init function names for thread local variables

Syntax:

#cir.tls_wrapper_init<
  mlir::StringAttr,   # wrapper_name
  mlir::StringAttr,   # init_name
  mlir::StringAttr   # guard_name
>

Contains the mangled name of the wrapper function, init function, and guard variable for a namespace/global scope thread local variable. The guard variable is optional, as it is only required for unordered thread local variables, as ordered thread local variables share a guard.

Unordered global thread local variables (such as variable template instantiations) are individually initialized when first used on a thread. Ordered global thread local variables are ALL initialized together when any that require initialization are referenced.

This is accomplished by rewriting all calls to these variables as calls to the wrapper. If the variable requires initialization, the wrapper calls the init function, then returns the global variable reference.

Throughout CIR though, these are just represented as normal get_global calls to globals with ctor/dtor regions (if necessary). The lowering-prepare pass manages the generation of the wrapper,x initialization, and call rewrites.

Example:

cir.global tls_dyn dyn_tls_refs = <"_ZTW7tls_var", "_ZTH7tls_var"> @_ZZZ7tls_var = ...
...
cir.get_global thread_local @ZZZ7tls_var : !cir.ptr<!s32i>

Parameters:#

Parameter

C++ type

Description

wrapper_name

mlir::StringAttr

init_name

mlir::StringAttr

guard_name

mlir::StringAttr

TypeInfoAttr#

Represents a typeinfo used for RTTI

Syntax:

#cir.typeinfo<
  ::mlir::Type,   # type
  ::mlir::ArrayAttr   # data
>

The typeinfo data for a given class is stored into an ArrayAttr. The layout is determined by the C++ ABI used (clang only implements itanium on CIRGen).

The verifier enforces that the output type is always a !cir.record, and that the ArrayAttr element types match the equivalent member type for the resulting record, i.e, a GlobalViewAttr for symbol reference or an IntAttr for flags.

Example:

cir.global "private" external @_ZTVN10__cxxabiv120__si_class_type_infoE
  : !cir.ptr<i32>

!rec_anon_struct = !cir.record<struct  {!cir.ptr<!u8i>, !cir.ptr<!u8i>,
  !cir.ptr<!u8i>}>

cir.global constant external @type_info = #cir.typeinfo<{
  #cir.global_view<@_ZTVN10__cxxabiv120__si_class_type_infoE, [2 : i32]>
  : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1B> : !cir.ptr<!u8i>,
  #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> : !rec_anon_struct

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

data

::mlir::ArrayAttr

integer or global view array attribute

UndefAttr#

Represent an undef constant

Syntax:

#cir.undef<
  ::mlir::Type   # type
>

The UndefAttr represents an undef constant, corresponding to LLVM’s notion of undef.

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

UnwindAttr#

Syntax: #cir.unwind

UnwindTableKindAttr#

Encodes the unwind table kind for a function.

Syntax:

#cir.uwtable<
  `none` | `sync` | `async`   # value
>

This mirrors the UWTableKindEnum in The LLVM dialect, and is passed through to the llvm dialect. According to the LLVM documentation: The ‘uwtable’ attribute is about the ABI or the user mandating an / entry in the unwind table.

Parameters:#

Parameter

C++ type

Description

value

::cir::UnwindTableKind

an enum of type UnwindTableKind

UsualDeleteParamsAttr#

Parameters describing the usual operator delete signature

Syntax:

#cir.usual_delete_params<
  bool,   # size
  std::optional<uint64_t>,   # alignment
  bool,   # type_aware_delete
  bool   # destroying_delete
>

Captures the properties of the usual deallocation function associated with an operator delete. These mirror the fields of clang::UsualDeleteParams.

Parameters:#

Parameter

C++ type

Description

size

bool

alignment

std::optional<uint64_t>

type_aware_delete

bool

destroying_delete

bool

VTableAttr#

Represents a C++ vtable

Syntax:

#cir.vtable<
  ::mlir::Type,   # type
  mlir::ArrayAttr   # data
>

Wraps a #cir.const_record containing one or more vtable arrays.

In most cases, the anonymous record type wrapped by this attribute will contain a single array corresponding to the vtable for one class. However, in the case of multiple inheritence, the anonymous structure may contain multiple arrays, each of which is a vtable.

Example 1 (single vtable):

cir.global linkonce_odr @_ZTV6Mother =
  #cir.vtable<{
    #cir.const_array<[
      #cir.ptr<null> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZTI6Mother> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Mother9MotherFooEv> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
    ]> : !cir.array<!cir.ptr<!u8i> x 4>
  }> : !rec_anon_struct1

Example 2 (multiple vtables):

cir.global linkonce_odr @_ZTV5Child =
  #cir.vtable<{
    #cir.const_array<[
      #cir.ptr<null> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN5Child9MotherFooEv> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
    ]> : !cir.array<!cir.ptr<!u8i> x 4>,
    #cir.const_array<[
      #cir.ptr<-8 : i64> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Father9FatherFooEv> : !cir.ptr<!u8i>
    ]> : !cir.array<!cir.ptr<!u8i> x 3>
  }> : !rec_anon_struct2

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

data

mlir::ArrayAttr

ZeroAttr#

Attribute to represent zero initialization

Syntax:

#cir.zero<
  ::mlir::Type   # type
>

The ZeroAttr is used to indicate zero initialization on structs.

Parameters:#

Parameter

C++ type

Description

type

::mlir::Type

Types#

ArrayType#

CIR array type

Syntax:

!cir.array<
  ::mlir::Type,   # elementType
  uint64_t   # size
>

!cir.array represents C/C++ constant arrays.

Parameters:#

Parameter

C++ type

Description

elementType

::mlir::Type

any type except void

size

uint64_t

BF16Type#

CIR bfloat16 16-bit float type

Syntax: !cir.bf16

A 16-bit floating-point type in the bfloat16 format, which is the same as IEEE binary32 except that the lower 16 bits of the mantissa are missing. It represents the type std::bfloat16_t in C++, also spelled __bf16 in some implementations.

BitFieldType#

CIR bit-field access unit member type

Syntax:

!cir.bitfield<
  mlir::Type,   # storage_type
  ::llvm::ArrayRef<cir::BitFieldDeclAttr>   # fields
>

A run of bit-fields shares one access unit. A record has one member per access unit, and that member has this type. The storage_type is the unit the record stores, and fields says which bit-fields the source packed into it, in declaration order.

The unit answers where the bits live, and fields answers how the fields were declared in the user’s source code. The storage type can be narrower than the declared type of a bit-field within it, and the fields in it need not agree on a declared type.

A zero-width bit-field belongs to no unit. It is spelled as a member with no storage_type and a single zero-width field, which occupies no bytes of the record and becomes no field of the lowered LLVM struct. Every other member of this type owns the bytes of its unit.

Examples:

    // struct S { int a : 4; int b : 27; };
    !rec_S = !cir.struct<"S"
        {bitfield !cir.bitfield<!u32i, [#cir.bitfield_decl<!s32i, 4>,
                                        #cir.bitfield_decl<!s32i, 27>]>}>

    // struct M { int a : 2; long long b : 30; };
    !rec_M = !cir.struct<"M"
        {bitfield !cir.bitfield<!u32i, [#cir.bitfield_decl<!s32i, 2>,
                                        #cir.bitfield_decl<!s64i, 30>]>,
         pad !cir.array<!u8i x 4>}>

    // struct Tail { int x; unsigned : 0; };
    !rec_Tail = !cir.struct<"Tail"
        {data !s32i,
         empty !cir.bitfield<[#cir.bitfield_decl<!u32i, 0, unnamed>]>}>

Parameters:#

Parameter

C++ type

Description

storage_type

mlir::Type

fields

::llvm::ArrayRef<cir::BitFieldDeclAttr>

BoolType#

CIR bool type

Syntax: !cir.bool

!cir.bool represents C++ bool type.

CUDADeviceSurfaceType#

CUDA device surface reference type

Syntax: !cir.cuda_surface

!cir.cuda_surface represents a CUDA built-in surface reference in CIR. The type preserves surface semantics at the CIR level and lowers to the NVPTX device-side handle representation (i64) during lowering to LLVM IR.

CUDADeviceTextureType#

CUDA device texture reference type

Syntax: !cir.cuda_texture

!cir.cuda_texture represents a CUDA built-in texture reference in CIR. The type preserves texture semantics at the CIR level and is lowered to the target device representation during lowering to LLVM IR.

CatchTokenType#

CIR catch token type

Syntax: !cir.catch_token

!cir.catch_token is an opaque type used to track catch handling state in flattened CIR. It is returned by cir.begin_catch and consumed by cir.end_catch.

This token ensures that catch handlers are properly paired and allows the ABI lowering pass to generate appropriate exception catching code.

CleanupTokenType#

CIR cleanup token type

Syntax: !cir.cleanup_token

!cir.cleanup_token is an opaque type used to track cleanup handling state in flattened CIR. It is returned by cir.begin_cleanup and consumed by cir.end_cleanup.

This token ensures that cleanup regions are properly paired and allows the ABI lowering pass to generate appropriate cleanup handling code.

ComplexType#

CIR complex type

Syntax:

!cir.complex<
  ::mlir::Type   # elementType
>

CIR type that represents a C complex number. cir.complex models the C type T _Complex.

cir.complex type is not directly mapped to std::complex.

The type models complex values, per C99 6.2.5p11. It supports the C99 complex float types as well as the GCC integer complex extensions.

The parameter elementType gives the type of the real and imaginary part of the complex number. elementType must be either a CIR integer type or a CIR floating-point type.

!cir.complex<!s32i>
!cir.complex<!cir.float>

Parameters:#

Parameter

C++ type

Description

elementType

::mlir::Type

integer or floating point type

DataMemberType#

CIR type that represents a pointer-to-data-member in C++

Syntax:

!cir.data_member<
  mlir::Type,   # member_ty
  cir::RecordType   # class_ty
>

cir.data_member models a pointer-to-data-member in C++. Values of this type are essentially offsets of the pointed-to member within one of its containing record.

Parameters:#

Parameter

C++ type

Description

member_ty

mlir::Type

class_ty

cir::RecordType

DoubleType#

CIR double-precision 64-bit float type

Syntax: !cir.double

A 64-bit floating-point type whose format is IEEE-754 binary64. It represents the types double', '_Float64, std::float64_t, and _Float32x in C and C++. This is the underlying type for long double on some platforms, including Windows.

EhTokenType#

CIR exception handling token type

Syntax: !cir.eh_token

!cir.eh_token is an opaque type used to track exception handling state in flattened CIR. It is returned by cir.eh.initiate and passed to cir.eh.dispatch, cir.begin_cleanup, and cir.begin_catch operations.

This token represents an in-flight exception and is used during ABI-lowering to generate the appropriate exception handling code.

FP16Type#

CIR half-precision 16-bit float type

Syntax: !cir.f16

A 16-bit floating-point type whose format is IEEE-754 binary16. It represents the types ‘_Float16andstd::float16_t` in C and C++.

FP80Type#

CIR x87 80-bit float type

Syntax: !cir.f80

An 80-bit floating-point type in the x87 extended precision format. The size and alignment of the type are both 128 bits, even though only 80 of those bits are used. This is the underlying type for long double on Linux x86 platforms, and it is available as an extension in some implementations.

FP128Type#

CIR quad-precision 128-bit float type

Syntax: !cir.f128

A 128-bit floating-point type whose format is IEEE-754 binary128. It represents the types _Float128 and std::float128_t in C and C++, and the extension __float128 in some implementations. This is the underlying type for long double on some platforms including Linux Arm.

FuncType#

CIR function type

Syntax:

!cir.func<
  ::llvm::ArrayRef<mlir::Type>,   # inputs
  mlir::Type,   # optionalReturnType
  bool   # varArg
>

The !cir.func is a function type. It consists of an optional return type, a list of parameter types and can optionally be variadic.

Example:

!cir.func<()>
!cir.func<() -> bool>
!cir.func<(!s8i, !s8i)>
!cir.func<(!s8i, !s8i) -> !s32i>
!cir.func<(!s32i, ...) -> !s32i>

Parameters:#

Parameter

C++ type

Description

inputs

::llvm::ArrayRef<mlir::Type>

optionalReturnType

mlir::Type

varArg

bool

IntType#

Integer type with arbitrary precision up to a fixed limit

CIR type that represents integer types with arbitrary precision, including standard integral types such as int and long, extended integral types such as __int128, and arbitrary width types such as _BitInt(n).

Those integer types that are directly available in C/C++ standard are called fundamental integer types. Said types are: signed char, short, int, long, long long, and their unsigned variations.

Examples: !cir.int<s, 32>, !cir.int<u, 64>, !cir.int<s, 128, bitint>

Parameters:#

Parameter

C++ type

Description

width

unsigned

is_signed

bool

is_bit_int

bool

LongDoubleType#

CIR float type for long double

Syntax:

!cir.long_double<
  ::mlir::Type   # underlying
>

A floating-point type that represents the long double type in C and C++.

The underlying floating-point format of a long double value depends on the target platform and the implementation. The underlying parameter specifies the CIR floating-point type that corresponds to this format. Underlying types of IEEE 64-bit, IEEE 128-bit, x87 80-bit, and IBM’s double-double format are all in use.

Parameters:#

Parameter

C++ type

Description

underlying

::mlir::Type

expects !cir.double, !cir.fp80 or !cir.fp128

MatrixType#

CIR matrix type

Syntax:

!cir.matrix<
  ::mlir::Type,   # element_type
  uint64_t,   # num_rows
  uint64_t   # num_columns
>

The !cir.matrix type represents a fixed-size 2-dimensional matrix. It takes three parameters: the element type, the number of rows, and columns.

Syntax:

matrix-type ::= !cir.matrix<row x colum x element-type>
size ::= (decimal-literal | `[` decimal-literal `]`)
element-type ::= float-type | integer-type | bool-type

The element-type must be a scalar CIR type. Zero-sized matrices are not allowed. The row and column count must be a positive integer.

Examples:

!cir.matrix<3 x 3 x !cir.int<u, 8>>
!cir.matrix<2 x 4 x !cir.float>

Parameters:#

Parameter

C++ type

Description

element_type

::mlir::Type

any cir boolean, integer, floating point type

num_rows

uint64_t

num_columns

uint64_t

MethodType#

CIR type that represents C++ pointer-to-member-function type

Syntax:

!cir.method<
  cir::FuncType,   # member_func_ty
  cir::RecordType   # class_ty
>

cir.method models the pointer-to-member-function type in C++. The layout of this type is ABI-dependent.

Parameters:#

Parameter

C++ type

Description

member_func_ty

cir::FuncType

class_ty

cir::RecordType

PointerType#

CIR pointer type

Syntax:

!cir.ptr<
  mlir::Type,   # pointee
  mlir::ptr::MemorySpaceAttrInterface   # addrSpace
>

The !cir.ptr type is a typed pointer type. It is used to represent pointers to objects in C/C++. The type of the pointed-to object is given by the pointee parameter. The addrSpace parameter is an optional address space attribute that specifies the address space of the pointer. If not specified, the pointer is assumed to be in the default address space.

The !cir.ptr type can point to any type, including fundamental types, records, arrays, vectors, functions, and other pointers. It can also point to incomplete types, such as incomplete records.

Examples:

!cir.ptr<!cir.int<u, 8>>
!cir.ptr<!cir.float>
!cir.ptr<!cir.record<struct "MyStruct">>
!cir.ptr<!cir.int<u, 8>, target_address_space(1)>
!cir.ptr<!cir.record<struct "MyStruct">, target_address_space(5)>

Parameters:#

Parameter

C++ type

Description

pointee

mlir::Type

addrSpace

mlir::ptr::MemorySpaceAttrInterface

SingleType#

CIR single-precision 32-bit float type

Syntax: !cir.float

A 32-bit floating-point type whose format is IEEE-754 binary32. It represents the types float, _Float32, and std::float32_t in C and C++.

StructType#

CIR struct/class type

Each unique clang::RecordDecl with struct or class kind is mapped to a cir.struct type. Any object in C/C++ that has a struct or class type will have a !cir.struct in CIR.

There are three possible formats:

  • Identified and complete: unique name and a known body.

  • Identified and incomplete: unique name and unknown body.

  • Anonymous: no name and a known body.

Typically, the full data size of a struct object is that which is calculated by adding the aligned sizes of all the members. However, note that there is one exception to this Flexible Array Members. When the last element is an array type of size zero(in CIR), this represents the C/C++ concept of ‘flexible array member’, where as long as the type is allocated properly (or a global constant), an access through the array member may access outside of its bounds. This is necessary to represent C/C++ semantics.

The optional class keyword distinguishes C++ class declarations from plain struct declarations. Both are semantically identical; the keyword preserves the original source spelling.

Every member has a kind, described by CIR_RecordMemberKind, saying what it holds, and every member is spelled with its mark.

Examples:

    !rec_complete = !cir.struct<"complete" {data !u8i}>
    !rec_class    = !cir.struct<class "MyClass" {data !s32i}>
    !rec_incomplete = !cir.struct<"incomplete" incomplete>
    !anonymous    = !cir.struct<{data !u8i}>
    !rec_packed   = !cir.struct<"p1" packed {data !u8i, data !u8i}>
    !rec_pad      = !cir.struct<"p3" {data !u8i, pad !cir.array<!u8i x 3>}>
    !rec_empty    = !cir.struct<"e" {empty !u8i}>
    !rec_bits     = !cir.struct<"b"
        {bitfield !cir.bitfield<!u8i, [#cir.bitfield_decl<!s32i, 4>]>,
         empty !cir.bitfield<[#cir.bitfield_decl<!s32i, 0, unnamed>]>}>
    !recursive    = !cir.struct<"Node" {data !cir.ptr<!cir.struct<"Node">>}>

Parameters:#

Parameter

C++ type

Description

members

::llvm::ArrayRef<mlir::Type>

name

mlir::StringAttr

incomplete

bool

packed

bool

member_kinds

::llvm::ArrayRef<cir::RecordMemberKind>

is_class

bool

UnionType#

CIR union type

Each unique clang::RecordDecl with union kind is mapped to a cir.union type. Any object in C/C++ that has a union type will have a !cir.union in CIR.

There are three possible formats:

  • Identified and complete: unique name and a known body.

  • Identified and incomplete: unique name and unknown body.

  • Anonymous: no name and a known body.

Padded unions carry an explicit tail-padding type to ensure the LLVM struct that models the union has the correct byte size. That slot is separate from the per-member kinds described by CIR_RecordMemberKind, which say what each variant holds. The parser rejects a mark on that slot.

Examples:

    !u_complete   = !cir.union<"U" {data !s32i, data !u8i}>
    !u_incomplete = !cir.union<"U" incomplete>
    !u_anonymous  = !cir.union<{data !s32i, data !u8i}>
    !u_padded     = !cir.union<"U" {data !s32i, data !u8i}, padding = {!u8i}>
    !u_empty      = !cir.union<"U" {empty !u8i}>
    !u_bits       = !cir.union<"U"
        {bitfield !cir.bitfield<!u8i, [#cir.bitfield_decl<!s32i, 4>]>,
         empty !cir.bitfield<!u8i, [#cir.bitfield_decl<!s32i, 3, unnamed>]>}>

Parameters:#

Parameter

C++ type

Description

members

::llvm::ArrayRef<mlir::Type>

name

mlir::StringAttr

incomplete

bool

packed

bool

padding

mlir::Type

member_kinds

::llvm::ArrayRef<cir::RecordMemberKind>

VPtrType#

CIR type that is used for the vptr member of C++ objects

Syntax: !cir.vptr

cir.vptr is a special type used as the type for the vptr member of a C++ object. This avoids using arbitrary pointer types to declare vptr values and allows stronger type-based checking for operations that use or provide access to the vptr.

This type will be the element type of the ‘vptr’ member of structures that require a vtable pointer. The cir.vtable.address_point operation returns this type. The cir.vtable.get_vptr operations returns a pointer to this type. This pointer may be passed to the cir.vtable.get_virtual_fn_addr operation to get the address of a virtual function pointer.

The pointer may also be cast to other pointer types in order to perform pointer arithmetic based on information encoded in the AST layout to get the offset from a pointer to a dynamic object to the base object pointer, the base object offset value from the vtable, or the type information entry for an object. TODO: We should have special operations to do that too.

VectorType#

CIR vector type

The !cir.vector type represents a one-dimensional vector. It takes two parameters: the element type and an element count, which records both the known minimum number of elements and whether the vector is scalable.

Syntax:

vector-type ::= !cir.vector<size x element-type>
size ::= (decimal-literal | `[` decimal-literal `]`)
element-type ::= float-type | integer-type | bool-type

The element-type must be a scalar CIR type. Zero-sized vectors are not allowed. The size must be a positive integer.

Examples:

!cir.vector<4 x !cir.int<u, 8>>
!cir.vector<2 x !cir.float>

A fixed-length vector of !cir.bool is packed one bit per element, and its size is rounded up to a power of two of at least one byte, so !cir.vector<4 x !cir.bool> occupies one byte and !cir.vector<17 x !cir.bool> occupies four.

Scalable vectors are indicated by enclosing size in square brackets.

Example:

!cir.vector<[4] x !cir.int<u, 8>>

Parameters:#

Parameter

C++ type

Description

element_type

::mlir::Type

any cir boolean, integer, floating point

size

llvm::ElementCount

VoidType#

CIR void type

Syntax: !cir.void

The !cir.void type represents the C and C++ void type.

Enums#

ArgPassingKind#

Record argument passing eligibility

Cases:#

Symbol

Value

String

CanPassInRegs

0

can_pass_in_regs

CannotPassInRegs

1

cannot_pass_in_regs

CanNeverPassInRegs

2

can_never_pass_in_regs

AsmFlavor#

ATT or Intel

Cases:#

Symbol

Value

String

x86_att

0

x86_att

x86_intel

1

x86_intel

AssignKind#

CXX Assignment Operator Kind

Cases:#

Symbol

Value

String

Copy

0

copy

Move

1

move

AssumeBundleKind#

Kind of cir.assume operand bundle

Cases:#

Symbol

Value

String

None

0

None

Align

1

align

SeparateStorage

2

separate_storage

Dereferenceable

3

dereferenceable

AtomicFetchKind#

Binary opcode for atomic fetch-and-update operations

Cases:#

Symbol

Value

String

Add

0

add

Sub

1

sub

And

2

and

Xor

3

xor

Or

4

or

Nand

5

nand

Max

6

max

Min

7

min

UIncWrap

8

uinc_wrap

UDecWrap

9

udec_wrap

Maximum

10

maximum

Minimum

11

minimum

MaximumNum

12

maximum_num

MinimumNum

13

minimum_num

AwaitKind#

Await kind

Cases:#

Symbol

Value

String

Init

0

init

User

1

user

Yield

2

yield

Final

3

final

CUDADeviceVarKind#

CUDA device variable kind

Cases:#

Symbol

Value

String

Variable

0

Variable

Surface

1

Surface

Texture

2

Texture

CallingConv#

Calling convention

Cases:#

Symbol

Value

String

C

0

c

PTXKernel

1

ptx_kernel

SpirFunction

2

spir_function

SpirKernel

3

spir_kernel

AMDGPUKernel

4

amdgpu_kernel

CaseOpKind#

Case kind

Cases:#

Symbol

Value

String

Default

0

default

Equal

1

equal

Anyof

2

anyof

Range

3

range

CastKind#

Cast kind

Cases:#

Symbol

Value

String

bitcast

1

bitcast

array_to_ptrdecay

11

array_to_ptrdecay

member_ptr_to_bool

17

member_ptr_to_bool

int_to_ptr

21

int_to_ptr

ptr_to_int

22

ptr_to_int

ptr_to_bool

23

ptr_to_bool

integral

27

integral

int_to_bool

28

int_to_bool

int_to_float

29

int_to_float

float_to_int

36

float_to_int

float_to_bool

37

float_to_bool

bool_to_int

38

bool_to_int

floating

39

floating

float_to_complex

44

float_to_complex

float_complex_to_real

45

float_complex_to_real

float_complex_to_bool

46

float_complex_to_bool

float_complex

47

float_complex

float_complex_to_int_complex

48

float_complex_to_int_complex

int_to_complex

49

int_to_complex

int_complex_to_real

50

int_complex_to_real

int_complex_to_bool

51

int_complex_to_bool

int_complex

52

int_complex

int_complex_to_float_complex

53

int_complex_to_float_complex

address_space

63

address_space

bool_to_float

1000

bool_to_float

CleanupKind#

Cleanup kind

Cases:#

Symbol

Value

String

Normal

1

normal

EH

2

eh

All

3

all

CmpOpKind#

Compare operation kind

Cases:#

Symbol

Value

String

lt

0

lt

le

1

le

gt

2

gt

ge

3

ge

eq

4

eq

ne

5

ne

one

6

one

uno

7

uno

CmpOrdering#

Three-way comparison ordering kind

Cases:#

Symbol

Value

String

Strong

0

strong

Weak

1

weak

Partial

2

partial

ComplexRangeKind#

Complex multiplication and division implementation

Cases:#

Symbol

Value

String

Full

0

full

Improved

1

improved

Promoted

2

promoted

Basic

3

basic

CtorKind#

CXX Constructor Kind

Cases:#

Symbol

Value

String

Custom

0

custom

Default

1

default

Copy

2

copy

Move

3

move

DynamicCastKind#

Dynamic cast kind

Cases:#

Symbol

Value

String

Ptr

0

ptr

Ref

1

ref

FPDynamicRoundingMode#

Floating-point dynamic rounding mode

Cases:#

Symbol

Value

String

ToNearest

0

tonearest

Downward

1

downward

Upward

2

upward

UpwardZero

3

upwardzero

ToNearestAway

4

tonearestaway

Unknown

7

unknown

FPExceptionMode#

Floating-point exception mode

Cases:#

Symbol

Value

String

Unknown

0

unknown

Masked

1

masked

Unmasked

2

unmasked

FastMathFlags#

Fast-math flags

Cases:#

Symbol

Value

String

none

0

none

nnan

1

nnan

ninf

2

ninf

nsz

4

nsz

arcp

8

arcp

contract

16

contract

afn

32

afn

reassoc

64

reassoc

fast

127

fast

FramePointerKind#

Frame pointer kind

Cases:#

Symbol

Value

String

None

0

none

NonLeaf

1

non_leaf

All

2

all

Reserved

3

reserved

NonLeafNoReserve

4

non_leaf_no_reserve

GlobalLinkageKind#

Linkage kind

Cases:#

Symbol

Value

String

ExternalLinkage

0

external

AvailableExternallyLinkage

1

available_externally

LinkOnceAnyLinkage

2

linkonce

LinkOnceODRLinkage

3

linkonce_odr

WeakAnyLinkage

4

weak

WeakODRLinkage

5

weak_odr

AppendingLinkage

6

appending

InternalLinkage

7

internal

PrivateLinkage

8

cir_private

ExternalWeakLinkage

9

extern_weak

CommonLinkage

10

common

InitCatchKind#

Allowed i32 cases: 0, 1, 2, 3, 4, 5, 6, 7

Cases:#

Symbol

Value

String

Reference

0

reference

Pointer

1

pointer

Scalar

2

scalar

Objc

3

objc

TrivialCopy

4

trivial_copy

NonTrivialCopy

5

non_trivial_copy

ReferenceToPointer

6

reference_to_pointer

ReferenceToRecordPointer

7

reference_to_record_pointer

InlineKind#

Inline kind

Cases:#

Symbol

Value

String

NoInline

1

no_inline

AlwaysInline

2

always_inline

InlineHint

3

inline_hint

KnownFuncKind#

Known standard library entity

Cases:#

Symbol

Value

String

StdFind

1

std::find

LangAddressSpace#

Language address space kind

Cases:#

Symbol

Value

String

Default

0

default

OffloadPrivate

1

offload_private

OffloadLocal

2

offload_local

OffloadGlobal

3

offload_global

OffloadConstant

4

offload_constant

OffloadGeneric

5

offload_generic

OffloadGlobalDevice

6

offload_global_device

OffloadGlobalHost

7

offload_global_host

LoopUnrollMode#

Loop unrolling mode

Cases:#

Symbol

Value

String

Enable

0

enable

Disable

1

disable

Full

2

full

MemOrder#

Memory order according to C++11 memory model

Cases:#

Symbol

Value

String

Relaxed

0

relaxed

Consume

1

consume

Acquire

2

acquire

Release

3

release

AcquireRelease

4

acq_rel

SequentiallyConsistent

5

seq_cst

ModRefInfo#

Whether memory may be read and/or written

Cases:#

Symbol

Value

String

NoModRef

0

none

Ref

1

read

Mod

2

write

ModRef

3

readwrite

OffloadKind#

Offload kind

Cases:#

Symbol

Value

String

Host

0

host

Device

1

device

RecordMemberKind#

What a record member holds

Cases:#

Symbol

Value

String

Data

0

data

Pad

1

pad

Empty

2

empty

BitField

3

bitfield

SourceLanguage#

Source language

Cases:#

Symbol

Value

String

C

1

c

CXX

2

cxx

OpenCLC

3

opencl_c

OpenCLCXX

4

opencl_cxx

SyncScopeKind#

Sync scope kind

Cases:#

Symbol

Value

String

SingleThread

0

single_thread

System

1

system

Device

2

device

Workgroup

3

workgroup

Wavefront

4

wavefront

Cluster

5

cluster

HIPSingleThread

6

hip_single_thread

HIPSystem

7

hip_system

HIPAgent

8

hip_agent

HIPWorkgroup

9

hip_workgroup

HIPWavefront

10

hip_wavefront

HIPCluster

11

hip_cluster

OpenCLWorkGroup

12

opencl_work_group

OpenCLDevice

13

opencl_device

OpenCLAllSVMDevices

14

opencl_all_svm_devices

OpenCLSubGroup

15

opencl_sub_group

TLSKind#

Thread-local storage kind

Cases:#

Symbol

Value

String

None

0

none

Static

1

static

Dynamic

2

dynamic

TLSModel#

TLS model

Cases:#

Symbol

Value

String

GeneralDynamic

1

tls_dyn

LocalDynamic

2

tls_local_dyn

InitialExec

3

tls_init_exec

LocalExec

4

tls_local_exec

TemplateSpecializationKind#

Template specialization kind

Cases:#

Symbol

Value

String

Undeclared

0

undeclared

ImplicitInstantiation

1

implicit_instantiation

ExplicitSpecialization

2

explicit_specialization

ExplicitInstantiationDeclaration

3

explicit_instantiation_declaration

ExplicitInstantiationDefinition

4

explicit_instantiation_definition

UnwindTableKind#

Unwind Table Kind

Cases:#

Symbol

Value

String

None

0

none

Sync

1

sync

Async

2

async

VisibilityKind#

C/C++ visibility

Cases:#

Symbol

Value

String

Default

0

default

Hidden

1

hidden

Protected

2

protected

FPClassTest#

Floating-point class test flags

Cases:#

Symbol

Value

String

None

0

fcNone

SignalingNaN

1

fcSNan

QuietNaN

2

fcQNan

NegativeInfinity

4

fcNegInf

NegativeNormal

8

fcNegNormal

NegativeSubnormal

16

fcNegSubnormal

NegativeZero

32

fcNegZero

PositiveZero

64

fcPosZero

PositiveSubnormal

128

fcPosSubnormal

PositiveNormal

256

fcPosNormal

PositiveInfinity

512

fcPosInf

Nan

3

fcNan

Infinity

516

fcInf

Normal

264

fcNormal

Subnormal

144

fcSubnormal

Zero

96

fcZero

PositiveFinite

448

fcPosFinite

NegativeFinite

56

fcNegFinite

Finite

504

fcFinite

Positive

960

fcPositive

Negative

60

fcNegative

All

1023

fcAllFlags