Operations
- Operations
cir.acos(::cir::ACosOp)cir.asin(::cir::ASinOp)cir.atan2(::cir::ATan2Op)cir.atan(::cir::ATanOp)cir.abs(::cir::AbsOp)cir.alloc.exception(::cir::AllocExceptionOp)cir.alloca(::cir::AllocaOp)cir.array.ctor(::cir::ArrayCtor)cir.array.dtor(::cir::ArrayDtor)cir.assume.aligned(::cir::AssumeAlignedOp)cir.assume(::cir::AssumeOp)cir.assume.separate_storage(::cir::AssumeSepStorageOp)cir.atomic.clear(::cir::AtomicClearOp)cir.atomic.cmp_xchg(::cir::AtomicCmpXchg)cir.atomic.fence(::cir::AtomicFence)cir.atomic.fetch(::cir::AtomicFetch)cir.atomic.test_and_set(::cir::AtomicTestAndSetOp)cir.atomic.xchg(::cir::AtomicXchg)cir.await(::cir::AwaitOp)cir.base_class_addr(::cir::BaseClassAddrOp)cir.base_data_member(::cir::BaseDataMemberOp)cir.base_method(::cir::BaseMethodOp)cir.binop(::cir::BinOp)cir.binop.overflow(::cir::BinOpOverflowOp)cir.clrsb(::cir::BitClrsbOp)cir.clz(::cir::BitClzOp)cir.ctz(::cir::BitCtzOp)cir.ffs(::cir::BitFfsOp)cir.parity(::cir::BitParityOp)cir.popcount(::cir::BitPopcountOp)cir.bit_reverse(::cir::BitReverseOp)cir.blockaddress(::cir::BlockAddressOp)cir.brcond(::cir::BrCondOp)cir.br(::cir::BrOp)cir.break(::cir::BreakOp)cir.byte_swap(::cir::ByteswapOp)cir.call(::cir::CallOp)cir.case(::cir::CaseOp)cir.cast(::cir::CastOp)cir.catch_param(::cir::CatchParamOp)cir.ceil(::cir::CeilOp)cir.clear_cache(::cir::ClearCacheOp)cir.cmp(::cir::CmpOp)cir.cmp3way(::cir::CmpThreeWayOp)cir.complex.binop(::cir::ComplexBinOp)cir.complex.create(::cir::ComplexCreateOp)cir.complex.imag(::cir::ComplexImagOp)cir.complex.imag_ptr(::cir::ComplexImagPtrOp)cir.complex.real(::cir::ComplexRealOp)cir.complex.real_ptr(::cir::ComplexRealPtrOp)cir.condition(::cir::ConditionOp)cir.const(::cir::ConstantOp)cir.continue(::cir::ContinueOp)cir.copy(::cir::CopyOp)cir.copysign(::cir::CopysignOp)cir.cos(::cir::CosOp)cir.delete.array(::cir::DeleteArrayOp)cir.derived_class_addr(::cir::DerivedClassAddrOp)cir.derived_data_member(::cir::DerivedDataMemberOp)cir.derived_method(::cir::DerivedMethodOp)cir.do(::cir::DoWhileOp)cir.dyn_cast(::cir::DynamicCastOp)cir.eh.inflight_exception(::cir::EhInflightOp)cir.eh.setjmp(::cir::EhSetjmpOp)cir.eh.typeid(::cir::EhTypeIdOp)cir.exp2(::cir::Exp2Op)cir.exp(::cir::ExpOp)cir.expect(::cir::ExpectOp)cir.extract_member(::cir::ExtractMemberOp)cir.fabs(::cir::FAbsOp)cir.fmaxnum(::cir::FMaxNumOp)cir.fmaximum(::cir::FMaximumOp)cir.fminnum(::cir::FMinNumOp)cir.fminimum(::cir::FMinimumOp)cir.fmod(::cir::FModOp)cir.floor(::cir::FloorOp)cir.for(::cir::ForOp)cir.frame_address(::cir::FrameAddrOp)cir.free.exception(::cir::FreeExceptionOp)cir.get_bitfield(::cir::GetBitfieldOp)cir.get_element(::cir::GetElementOp)cir.get_global(::cir::GetGlobalOp)cir.get_member(::cir::GetMemberOp)cir.get_method(::cir::GetMethodOp)cir.get_runtime_member(::cir::GetRuntimeMemberOp)cir.global(::cir::GlobalOp)cir.goto(::cir::GotoOp)cir.if(::cir::IfOp)cir.asm(::cir::InlineAsmOp)cir.insert_member(::cir::InsertMemberOp)cir.invariant_group(::cir::InvariantGroupOp)cir.is_constant(::cir::IsConstantOp)cir.is_fp_class(::cir::IsFPClassOp)cir.std.begin(::cir::IterBeginOp)cir.std.end(::cir::IterEndOp)cir.llvm.intrinsic(::cir::LLVMIntrinsicCallOp)cir.llrint(::cir::LLrintOp)cir.llround(::cir::LLroundOp)cir.label(::cir::LabelOp)cir.linker_options(::cir::LinkerOptionsOp)cir.load(::cir::LoadOp)cir.log10(::cir::Log10Op)cir.log2(::cir::Log2Op)cir.log(::cir::LogOp)cir.lrint(::cir::LrintOp)cir.lround(::cir::LroundOp)cir.libc.memchr(::cir::MemChrOp)cir.memcpy_inline(::cir::MemCpyInlineOp)cir.libc.memcpy(::cir::MemCpyOp)cir.libc.memmove(::cir::MemMoveOp)cir.memset_inline(::cir::MemSetInlineOp)cir.libc.memset(::cir::MemSetOp)cir.nearbyint(::cir::NearbyintOp)cir.objsize(::cir::ObjSizeOp)cir.pow(::cir::PowOp)cir.prefetch(::cir::PrefetchOp)cir.ptr_diff(::cir::PtrDiffOp)cir.ptr_mask(::cir::PtrMaskOp)cir.ptr_stride(::cir::PtrStrideOp)cir.resume(::cir::ResumeOp)cir.return(::cir::ReturnOp)cir.rint(::cir::RintOp)cir.rotate(::cir::RotateOp)cir.roundeven(::cir::RoundEvenOp)cir.round(::cir::RoundOp)cir.scope(::cir::ScopeOp)cir.select(::cir::SelectOp)cir.set_bitfield(::cir::SetBitfieldOp)cir.shift(::cir::ShiftOp)cir.signbit(::cir::SignBitOp)cir.sin(::cir::SinOp)cir.sqrt(::cir::SqrtOp)cir.stack_restore(::cir::StackRestoreOp)cir.stack_save(::cir::StackSaveOp)cir.std.find(::cir::StdFindOp)cir.store(::cir::StoreOp)cir.switch.flat(::cir::SwitchFlatOp)cir.switch(::cir::SwitchOp)cir.tan(::cir::TanOp)cir.ternary(::cir::TernaryOp)cir.throw(::cir::ThrowOp)cir.trap(::cir::TrapOp)cir.trunc(::cir::TruncOp)cir.try_call(::cir::TryCallOp)cir.try(::cir::TryOp)cir.unary(::cir::UnaryOp)cir.unreachable(::cir::UnreachableOp)cir.va.arg(::cir::VAArgOp)cir.va.copy(::cir::VACopyOp)cir.va.end(::cir::VAEndOp)cir.va.start(::cir::VAStartOp)cir.vtt.address_point(::cir::VTTAddrPointOp)cir.vtable.address_point(::cir::VTableAddrPointOp)cir.vtable.get_vptr(::cir::VTableGetVPtrOp)cir.vtable.get_virtual_fn_addr(::cir::VTableGetVirtualFnAddrOp)cir.vec.cmp(::cir::VecCmpOp)cir.vec.create(::cir::VecCreateOp)cir.vec.extract(::cir::VecExtractOp)cir.vec.insert(::cir::VecInsertOp)cir.vec.shuffle.dynamic(::cir::VecShuffleDynamicOp)cir.vec.shuffle(::cir::VecShuffleOp)cir.vec.splat(::cir::VecSplatOp)cir.vec.ternary(::cir::VecTernaryOp)cir.while(::cir::WhileOp)cir.yield(::cir::YieldOp)cir.func(::cir::FuncOp)
cir.acos (::cir::ACosOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.acos` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.asin (::cir::ASinOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.asin` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.atan2` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.atan (::cir::ATanOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.atan` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.abs (::cir::AbsOp)
_Libc builtin equivalent abs, labs, llabs
The `poison` argument indicate whether the result value
is a poison value if the first argument is statically or
dynamically an INT_MIN value.
Example:
```mlir
%0 = cir.const #cir.int<-42> : s32i
%1 = cir.abs %0 poison : s32i
%2 = cir.abs %3 : !cir.vector<!s32i x 4>
```_
Syntax:
operation ::= `cir.abs` $src ( `poison` $poison^ )? `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
poison | ::mlir::UnitAttr | unit 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.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 operation fails, program terminates, not 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:
| Attribute | MLIR Type | Description |
|---|---|---|
size | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Results:
| Result | Description |
|---|---|
addr | CIR pointer type |
cir.alloca (::cir::AllocaOp)
Defines a scope-local variable
Syntax:
operation ::= `cir.alloca` $allocaType `,` qualified(type($addr)) `,`
($dynAllocSize^ `:` type($dynAllocSize) `,`)?
`[` $name
(`,` `init` $init^)?
(`,` `const` $constant^)?
`]`
($annotations^)?
(`ast` $ast^)? attr-dict
The cir.alloca operation defines a scope-local variable.
The presence init attribute indicates that the local variable represented by this alloca was originally initialized in C/C++ source code. In such cases, the first use contains the initialization (a cir.store, a cir.call to a ctor, etc).
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 and is omitted when declaring regular local variables.
The result type is a pointer to the input’s type.
Example:
// int count = 3;
%0 = cir.alloca i32, !cir.ptr<i32>, ["count", init] {alignment = 4 : i64}
// int *ptr;
%1 = cir.alloca !cir.ptr<i32>, !cir.ptr<!cir.ptr<i32>>, ["ptr"] {alignment = 8 : i64}
...
Interfaces: PromotableAllocationOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
allocaType | ::mlir::TypeAttr | any type attribute |
name | ::mlir::StringAttr | string attribute |
init | ::mlir::UnitAttr | unit attribute |
constant | ::mlir::UnitAttr | unit attribute |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute whose minimum value is 0 |
annotations | ::mlir::ArrayAttr | array attribute |
ast | ::cir::ASTVarDeclInterface | ASTVarDeclInterface instance |
Operands:
| Operand | Description |
|---|---|
dynAllocSize | fundamental integer type |
Results:
| Result | Description |
|---|---|
addr | CIR pointer type |
cir.array.ctor (::cir::ArrayCtor)
Initialize array elements with C++ constructors
Syntax:
operation ::= `cir.array.ctor` `(` $addr `:` qualified(type($addr)) `)` $body attr-dict
Initialize each array element using the same C++ constructor. This operation has one region, with one single block. The block has an incoming argument for the current array index to initialize.
Operands:
| Operand | Description |
|---|---|
addr | pointer to array type |
cir.array.dtor (::cir::ArrayDtor)
Destroy array elements with C++ dtors
Syntax:
operation ::= `cir.array.dtor` `(` $addr `:` qualified(type($addr)) `)` $body attr-dict
Destroy each array element using the same C++ destructor. This operation has one region, with one single block. The block has an incoming argument for the current array index to initialize.
Operands:
| Operand | Description |
|---|---|
addr | pointer to array type |
cir.assume.aligned (::cir::AssumeAlignedOp)
Tell the optimizer that a pointer is aligned
Syntax:
operation ::= `cir.assume.aligned` $pointer `:` qualified(type($pointer))
`[` `alignment` $alignment (`,` `offset` $offset^ `:` type($offset))? `]`
attr-dict
The cir.assume.aligned operation takes two or three arguments.
When the 3rd argument offset is absent, this operation tells the optimizer that the pointer given by the pointer argument is aligned to the alignment given by the align argument.
When the offset argument is given, it represents an offset from the alignment. This operation then tells the optimizer that the pointer given by the pointer argument is always misaligned by the alignment given by the align argument by offset bytes, a.k.a. the pointer yielded by (char *)pointer - offset is aligned to the specified alignment.
The align argument is a constant integer represented as an integer attribute instead of an SSA value. It must be a positive integer.
The result of this operation has the same value as the pointer argument, but the optimizer has additional knowledge about its alignment.
This operation corresponds to the __builtin_assume_aligned builtin function.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Operands:
| Operand | Description |
|---|---|
pointer | CIR pointer type |
offset | Integer type with arbitrary precision up to a fixed limit |
Results:
| Result | Description |
|---|---|
result | CIR pointer type |
cir.assume (::cir::AssumeOp)
Tell the optimizer that a boolean value is true
Syntax:
operation ::= `cir.assume` $predicate `:` type($predicate) attr-dict
The cir.assume operation takes a single boolean prediate as its only argument and does not have any results. The operation tells the optimizer that the predicate’s value is true.
This operation corresponds to the __assume and the __builtin_assume builtin function.
Operands:
| Operand | Description |
|---|---|
predicate | CIR bool type |
cir.assume.separate_storage (::cir::AssumeSepStorageOp)
Tell the optimizer that two pointers point to different allocations
Syntax:
operation ::= `cir.assume.separate_storage` $ptr1 `,` $ptr2 `:` qualified(type($ptr1)) attr-dict
The cir.assume.separate_storage operation takes two pointers as arguments, and the operation tells the optimizer that these two pointers point to different allocations.
This operation corresponds to the __builtin_assume_separate_storage builtin function.
Traits: SameTypeOperands
Operands:
| Operand | Description |
|---|---|
ptr1 | pointer to void type |
ptr2 | pointer to void type |
cir.atomic.clear (::cir::AtomicClearOp)
Atomic clear
Syntax:
operation ::= `cir.atomic.clear` $mem_order $ptr
(`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:
| Attribute | MLIR Type | Description |
|---|---|---|
mem_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
syncscope | ::cir::MemScopeKindAttr | memory scope kind |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
ptr | pointer to 8-bit signed integer |
cir.atomic.cmp_xchg (::cir::AtomicCmpXchg)
Atomic compare exchange
Syntax:
operation ::= `cir.atomic.cmp_xchg` `(`
$ptr `:` qualified(type($ptr)) `,`
$expected `:` type($expected) `,`
$desired `:` type($desired) `,`
`success` `=` $succ_order `,`
`failure` `=` $fail_order
`)`
(`syncscope` `(` $syncscope^ `)`)?
(`align` `(` $alignment^ `)`)?
(`weak` $weak^)?
(`volatile` $is_volatile^)?
`:` `(` type($old) `,` type($cmp) `)` attr-dict
C/C++ Atomic compare and exchange operation. Implements builtins like __atomic_compare_exchange_n and __atomic_compare_exchange.
Example: %old, %cmp = cir.atomic.cmp_xchg(%ptr : !cir.ptr<!some_record>, %expected : !u64i, %desired : !u64i, success = seq_cst, failure = seq_cst) weak : (!u64i, !cir.bool)
Interfaces: InferTypeOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
succ_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
fail_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
syncscope | ::cir::MemScopeKindAttr | memory scope kind |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
weak | ::mlir::UnitAttr | unit attribute |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
ptr | CIR pointer type |
expected | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
desired | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
old | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cmp | CIR bool type |
cir.atomic.fence (::cir::AtomicFence)
Atomic thread fence
Syntax:
operation ::= `cir.atomic.fence` (`syncscope` `(` $syncscope^ `)`)? $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:
| Attribute | MLIR Type | Description |
|---|---|---|
ordering | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
syncscope | ::cir::MemScopeKindAttr | memory scope kind |
cir.atomic.fetch (::cir::AtomicFetch)
Atomic fetch with unary and binary operations
Syntax:
operation ::= `cir.atomic.fetch` `(`$binop `,`
$ptr `:` qualified(type($ptr)) `,`
$val `:` type($val) `,`
$mem_order `)`
(`volatile` $is_volatile^)?
(`fetch_first` $fetch_first^)?
`:` type($result) attr-dict
Represents __atomic_<binop>_fetch and __atomic_fetch_<binop> builtins, where binop is on of the binary opcodes : add, sub, and, xor, or, nand, max and min.
ptr is an integer or fp pointer, followed by val, which must be an integer or fp (only supported for add and sub). The operation can also be marked volatile.
If fetch_first is present, the operation works like __atomic_fetch_binop and returns the value that had previously been in *ptr, otherwise it returns the final result of the computation (__atomic_binop_fetch).
Example: %res = cir.atomic.fetch(add, %ptr : !cir.ptr<!s32i>, %val : !s32i, seq_cst) : !s32i
Interfaces: InferTypeOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
binop | ::cir::AtomicFetchKindAttr | Binary opcode for atomic fetch operations |
mem_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
is_volatile | ::mlir::UnitAttr | unit attribute |
fetch_first | ::mlir::UnitAttr | unit 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` $mem_order $ptr
(`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:
| Attribute | MLIR Type | Description |
|---|---|---|
mem_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
syncscope | ::cir::MemScopeKindAttr | memory scope kind |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
ptr | pointer to 8-bit signed integer |
Results:
| Result | Description |
|---|---|
result | CIR bool type |
cir.atomic.xchg (::cir::AtomicXchg)
Atomic exchange
Syntax:
operation ::= `cir.atomic.xchg` `(`
$ptr `:` qualified(type($ptr)) `,`
$val `:` type($val) `,`
$mem_order `)`
(`volatile` $is_volatile^)?
`:` type($result) attr-dict
Atomic exchange operations. Implements C/C++ builtins such as __atomic_exchangeand __atomic_exchange_n.
Example: %res = cir.atomic.xchg(%ptr : !cir.ptr<!some_record>, %val : !u64i, seq_cst) : !u64i
Interfaces: InferTypeOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
mem_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
ptr | CIR pointer type |
val | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.await (::cir::AwaitOp)
Wraps C++ co_await implicit logic
Syntax:
operation ::= `cir.await` `(` $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 allow 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 implicitco_await.user: also known as normal, representing user written co_await’s.yield: user writtenco_yieldexpressions.final: compiler generated final suspend via implicitco_await.
From the C++ snippet we get:
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: NoRegionArguments, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable, RegionBranchOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::AwaitKindAttr | await kind |
cir.base_class_addr (::cir::BaseClassAddrOp)
Get the base class address for a class/struct
Syntax:
operation ::= `cir.base_class_addr` $derived_addr `:` qualified(type($derived_addr))
(`nonnull` $assume_not_null^)?
` ` `[` $offset `]` `->` qualified(type($base_addr)) 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.
Example:
struct Base { };
struct Derived : Base { };
Derived d;
Base& b = d;
will generate
%3 = cir.base_class_addr %1 : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
offset | ::mlir::IntegerAttr | index attribute |
assume_not_null | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
derived_addr | CIR pointer type |
Results:
| Result | Description |
|---|---|
base_addr | 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 `:` qualified(type($src))
` ` `[` $offset `]` `->` 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:
| Attribute | MLIR Type | Description |
|---|---|---|
offset | ::mlir::IntegerAttr | index attribute |
Operands:
| Operand | Description |
|---|---|
src | CIR type that represents pointer-to-data-member type in C++ |
Results:
| Result | Description |
|---|---|
result | CIR type that represents pointer-to-data-member type 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 `:` qualified(type($src))
` ` `[` $offset `]` `->` 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 : !cir.method<!cir.func<(!s32i)> in !rec_Derived> [16] -> !cir.method<!cir.func<(!s32i)> in !rec_Base>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
offset | ::mlir::IntegerAttr | index 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.binop (::cir::BinOp)
Binary operations (arith and logic)
Syntax:
operation ::= `cir.binop` `(` $kind `,` $lhs `,` $rhs `)`
(`nsw` $no_signed_wrap^)?
(`nuw` $no_unsigned_wrap^)?
(`sat` $saturated^)?
`:` type($lhs) attr-dict
cir.binop performs the binary operation according to the specified opcode kind: [mul, div, rem, add, sub, and, xor, or].
It requires two input operands and has one result, all types should be the same.
%7 = cir.binop(add, %1, %2) : !s32i
%7 = cir.binop(mul, %1, %2) : !u8i
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType, SameTypeOperands
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::BinOpKindAttr | binary operation (arith and logic) kind |
no_unsigned_wrap | ::mlir::UnitAttr | unit attribute |
no_signed_wrap | ::mlir::UnitAttr | unit attribute |
saturated | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
lhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
rhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.binop.overflow (::cir::BinOpOverflowOp)
Perform binary integral arithmetic with overflow checking
Syntax:
operation ::= `cir.binop.overflow` `(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `,`
`(` type($result) `,` type($overflow) `)`
attr-dict
cir.binop.overflow performs binary arithmetic operations with overflow checking on integral operands.
The kind argument specifies the kind of arithmetic operation to perform. It can be either add, sub, or mul. The lhs and rhs arguments specify the input operands of the arithmetic operation. The types of lhs and rhs must be the same.
cir.binop.overflow produces two SSA values. result is the result of the arithmetic operation truncated to its specified type. overflow is a boolean value indicating whether overflow happens during the operation.
The exact semantic of this operation is as follows:
lhsandrhsare promoted to an imaginary integral type that has infinite precision.- The arithmetic operation is performed on the promoted operands.
- The infinite-precision result is truncated to the type of
result. The truncated result is assigned toresult. - If the truncated result is equal to the un-truncated result,
overflowis assigned to false. Otherwise,overflowis assigned to true.
Traits: AlwaysSpeculatableImplTrait, SameTypeOperands
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::BinOpOverflowKindAttr | checked binary arithmetic operation kind |
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 type with arbitrary precision up to a fixed limit |
overflow | CIR bool 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 redundant sign bits in the input, that is, the number of bits following the most significant bit that are identical to it.
The bit width of the input integer must be either 32 or 64.
Examples:
!s32i = !cir.int<s, 32>
// %0 = 0xDEADBEEF, 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) : !s32i
// %2 = 1, 0b0000_0000_0000_0000_0000_0000_0000_0001
%2 = cir.const #cir.int<1> : !s32i
// %3 will be 30
%3 = cir.clrsb(%2 : !s32i) : !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 (`zero_poison` $is_zero_poison^)?
`:` 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.
Zero_poison attribute means this operation invokes undefined behavior if the input value is 0.
Example:
!u32i = !cir.int<u, 32>
// %0 = 0b0000_0000_0000_0000_0000_0000_0000_1000
%0 = cir.const #cir.int<8> : !u32i
// %1 will be 28
%1 = cir.clz(%0 : !u32i) zero_poison : !u32i
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
is_zero_poison | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
input | unsigned integer type of widths 16/32/64 |
Results:
| Result | Description |
|---|---|
result | unsigned integer type of widths 16/32/64 |
cir.ctz (::cir::BitCtzOp)
Get the number of trailing 0-bits in the input
Syntax:
operation ::= `cir.ctz` $input (`zero_poison` $is_zero_poison^)?
`:` 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 returns the number of consecutive 0-bits at the least significant bit position in the input.
Zero_poison attribute means this operation invokes undefined behavior if the input value is 0.
Example:
!s32i = !cir.int<s, 32>
!u32i = !cir.int<u, 32>
// %0 = 0b1000
%0 = cir.const #cir.int<8> : !u32i
// %1 will be 3
%1 = cir.ctz(%0 : !u32i) : !u32i
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
is_zero_poison | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
input | unsigned integer type of widths 16/32/64 |
Results:
| Result | Description |
|---|---|
result | unsigned integer type of widths 16/32/64 |
cir.ffs (::cir::BitFfsOp)
Get the position of the least significant 1-bit of input
Syntax:
operation ::= `cir.ffs` $input `:` type($result) attr-dict
Compute the 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. As a special case, if the input integer is 0, cir.ffs returns 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) : !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.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:
!s32i = !cir.int<s, 32>
!u32i = !cir.int<u, 32>
// %0 = 0x0110_1000
%0 = cir.const #cir.int<104> : !u32i
// %1 will be 1 since there are 3 1-bits in %0
%1 = cir.parity(%0 : !u32i) : !u32i
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:
!u32i = !cir.int<u, 32>
// %0 = 0x0110_1000
%0 = cir.const #cir.int<104> : !u32i
// %1 will be 3 since there are 3 1-bits in %0
%1 = cir.popcount(%0 : !u32i) : !u32i
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
input | unsigned integer type of widths 16/32/64 |
Results:
| Result | Description |
|---|---|
result | unsigned integer type of widths 16/32/64 |
cir.bit_reverse (::cir::BitReverseOp)
Reverse the bit pattern of the operand integer
Syntax:
operation ::= `cir.bit_reverse` $src `:` type($result) attr-dict
The cir.bit_reverse operation reverses the bit pattern of the operand integer. Its only argument must be of unsigned integer types of width 8, 16, 32, or 64.
This operation covers the C/C++ builtin function __builtin_bitreverse.
Example:
%1 = cir.bit_reverse %0 : !u32i
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
src | unsigned integer type of widths 8/16/32/64 |
Results:
| Result | Description |
|---|---|
result | unsigned integer type of widths 8/16/32/64 |
cir.blockaddress (::cir::BlockAddressOp)
Get the address of a cir.label within a function
Syntax:
operation ::= `cir.blockaddress` $blockAddrInfo `->` 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 !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64}
%addr = cir.blockaddress("foo", "label") -> !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:
| Attribute | MLIR Type | Description |
|---|---|---|
blockAddrInfo | ::cir::BlockAddrInfoAttr | Block Addres attribute |
Results:
| Result | Description |
|---|---|
addr | pointer to void type |
cir.brcond (::cir::BrCondOp)
Conditional branch
Syntax:
operation ::= `cir.brcond` $cond
$destTrue (`(` $destOperandsTrue^ `:` type($destOperandsTrue) `)`)?
`,`
$destFalse (`(` $destOperandsFalse^ `:` type($destOperandsFalse) `)`)?
attr-dict
The cir.brcond %cond, ^bb0, ^bb1 branches to ‘bb0’ block in case %cond (which must be a !cir.bool type) evaluates to true, otherwise it branches to ‘bb1’.
Example:
...
cir.brcond %a, ^bb3, ^bb4
^bb3:
cir.return
^bb4:
cir.yield
Traits: AlwaysSpeculatableImplTrait, AttrSizedOperandSegments, Terminator
Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
cond | CIR bool type |
destOperandsTrue | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
destOperandsFalse | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Successors:
| Successor | Description |
|---|---|
destTrue | any successor |
destFalse | any successor |
cir.br (::cir::BrOp)
Unconditional branch
Syntax:
operation ::= `cir.br` $dest (`(` $destOperands^ `:` type($destOperands) `)`)? 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.
Example:
...
cir.br ^bb3
^bb3:
cir.return
Traits: AlwaysSpeculatableImplTrait, Terminator
Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
destOperands | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Successors:
| Successor | Description |
|---|---|
dest | 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 control flow to the parent operation, exiting its region’s control flow. It is only allowed if it is within a breakable operation (loops and switch).
Traits: Terminator
cir.byte_swap (::cir::ByteswapOp)
Reverse the bytes that constitute the operand integer
Syntax:
operation ::= `cir.byte_swap` $input `:` type($result) attr-dict
The cir.byte_swap operation takes an integer as operand, and returns it with the order of bytes that constitute the operand reversed.
The operand integer must be an unsigned integer. Its widths must be either 16, 32, or 64.
Example:
!u32i = !cir.int<u, 32>
// %0 = 0x12345678
%0 = cir.const #cir.int<305419896> : !u32i
// %1 should be 0x78563412
%1 = cir.byte_swap(%0 : !u32i) : !u32i
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
input | unsigned integer type of widths 16/32/64 |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.call (::cir::CallOp)
Call operation
Direct and indirect calls.
For direct calls, the call operation represents a direct call to a function that is within the same symbol scope as the call. The operands and result types of the call must match the specified function type. The callee is encoded as a aymbol reference attribute named “callee”.
For indirect calls, the first mlir::Operation operand is the call target.
Given the way indirect calls are encoded, avoid using mlir::Operation methods to walk the operands for this operation, instead use the methods provided by CIRCallOpInterface.
If the cir.call has the exception keyword, the call can throw. In this case, cleanups can be added in the cleanup region.
Example:
// Direct call
%2 = cir.call @my_add(%0, %1) : (f32, f32) -> f32
...
// Indirect call
%20 = cir.call %18(%17)
...
// Call that might throw
cir.call exception @my_div() -> () cleanup {
// call dtor...
}
Traits: NoRegionArguments
Interfaces: CIRCallOpInterface, CallOpInterface, SymbolUserOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
exception | ::mlir::UnitAttr | unit attribute |
callee | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
calling_conv | ::cir::CallingConvAttr | calling convention |
side_effect | ::cir::SideEffectAttr | allowed side effects of a function |
extra_attrs | ::cir::ExtraFuncAttributesAttr | Represents aggregated attributes for a function |
ast | ::cir::ASTCallExprInterface | ASTCallExprInterface instance |
Operands:
| Operand | Description |
|---|---|
arg_ops | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.case (::cir::CaseOp)
Case operation
Syntax:
operation ::= `cir.case` `(` $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:
| Attribute | MLIR Type | Description |
|---|---|---|
value | ::mlir::ArrayAttr | array attribute |
kind | ::cir::CaseOpKindAttr | case kind |
cir.cast (::cir::CastOp)
Conversion between values of different types
Syntax:
operation ::= `cir.cast` $kind $src `:` type($src) `->` type($result) 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:
bitcastarray_to_ptrdecay- `member_ptr_to_bool
int_to_ptrptr_to_intptr_to_boolintegralint_to_boolint_to_floatfloat_to_intfloat_to_boolbool_to_intfloatingfloat_to_complexfloat_complex_to_realfloat_complex_to_boolfloat_complexfloat_complex_to_int_complexint_to_complexint_complex_to_realint_complex_to_boolint_complexint_complex_to_float_complexaddress_space
CIR also supports some additional conversions that are not part of the classic Clang codegen:
bool_to_float
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>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), PromotableOpInterface
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::CastKindAttr | cast kind |
Operands:
| Operand | Description |
|---|---|
src | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.catch_param (::cir::CatchParamOp)
Represents catch clause formal parameter
Syntax:
operation ::= `cir.catch_param` ($kind^)?
($exception_ptr^)?
(`->` qualified(type($param))^)?
attr-dict
The cir.catch_param can operate in two modes: within catch regions of cir.try or anywhere else with the begin or end markers. The begin version requires an exception pointer of cir.ptr<!void>.
Example:
// TBD
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::CatchParamKindAttr | Designate limits for begin/end of catch param handling |
Operands:
| Operand | Description |
|---|---|
exception_ptr | pointer to void type |
Results:
| Result | Description |
|---|---|
param | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.ceil (::cir::CeilOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.ceil` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.clear_cache (::cir::ClearCacheOp)
Clear cache operation
Syntax:
operation ::= `cir.clear_cache` $begin `:` qualified(type($begin)) `,`
$end `,`
attr-dict
CIR representation for __builtin___clear_cache.
Operands:
| Operand | Description |
|---|---|
begin | pointer to void type |
end | pointer to void type |
cir.cmp (::cir::CmpOp)
Compare values two values and produce a boolean result
Syntax:
operation ::= `cir.cmp` `(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `,` type($result) attr-dict
cir.cmp compares two input operands of the same type and produces a cir.bool result. The kinds of comparison available are: [lt,gt,ge,eq,ne]
%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool
Traits: AlwaysSpeculatableImplTrait, SameTypeOperands
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::CmpOpKindAttr | compare operation kind |
Operands:
| Operand | Description |
|---|---|
lhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
rhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | CIR bool type |
cir.cmp3way (::cir::CmpThreeWayOp)
Compare two values with C++ three-way comparison semantics
Syntax:
operation ::= `cir.cmp3way` `(` $lhs `:` type($lhs) `,` $rhs `,` qualified($info) `)`
`:` type($result) attr-dict
The cir.cmp3way operation models the <=> 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 two kinds of ordering: strong ordering 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>
#cmp3way_strong = #cmp3way_info<strong, lt = -1, eq = 0, gt = 1>
#cmp3way_partial = #cmp3way_info<strong, lt = -1, eq = 0, gt = 1, unordered = 2>
%0 = cir.const #cir.int<0> : !s32i
%1 = cir.const #cir.int<1> : !s32i
%2 = cir.cmp3way(%0 : !s32i, %1, #cmp3way_strong) : !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, #cmp3way_partial) : !s8i
Traits: AlwaysSpeculatableImplTrait, SameTypeOperands
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
info | ::cir::CmpThreeWayInfoAttr | Holds information about a three-way comparison operation |
Operands:
| Operand | Description |
|---|---|
lhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
rhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | signed integer type |
cir.complex.binop (::cir::ComplexBinOp)
Binary operations on operands of complex type
Syntax:
operation ::= `cir.complex.binop` $kind $lhs `,` $rhs `range` `(` $range `)` (`promoted` $promoted^)?
`:` qualified(type($lhs)) attr-dict
The cir.complex.binop operation represents a binary operation on operands of C complex type (e.g. float _Complex). The operation can only represent binary multiplication or division on complex numbers; other binary operations, such as addition and subtraction, are represented by the cir.binop operation.
The operation requires two input operands and has one result. The types of all the operands and the result should be of the same !cir.complex type.
The operation also takes a range attribute that specifies the complex range of the binary operation.
Examples:
%2 = cir.complex.binop add %0, %1 : !cir.complex<!cir.float>
%2 = cir.complex.binop mul %0, %1 : !cir.complex<!cir.float>
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType, SameTypeOperands
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::ComplexBinOpKindAttr | complex number binary operation kind |
range | ::cir::ComplexRangeKindAttr | complex multiplication and division implementation |
promoted | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
lhs | CIR complex type |
rhs | 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
cir.complex.create operation takes two operands that represent the real and imaginary part of a complex number, and yields the complex number.
Example:
%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.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.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 type and yields the imaginary part of it.
Example:
%1 = cir.complex.imag %0 : !cir.complex<!cir.float> -> !cir.float
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
operand | CIR complex type |
Results:
| Result | Description |
|---|---|
result | integer 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.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 type and yields the real part of it.
Example:
%1 = cir.complex.real %0 : !cir.complex<!cir.float> -> !cir.float
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
operand | CIR complex type |
Results:
| Result | Description |
|---|---|
result | integer 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.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
condregion of acir.loop, it continues the loop if true, or exits it if false. - When in the
readyregion of acir.await, it branches to theresumeregion when true, and to thesuspendregion when false.
Example:
cir.loop for(cond : {
cir.condition(%arg0) // Branches to `step` region or exits.
}, step : {
[...]
}) {
[...]
}
cir.await(user, ready : {
cir.condition(%arg0) // Branches to `resume` or `suspend` region.
}, suspend : {
[...]
}, resume : {
[...]
},)
Traits: Terminator
Interfaces: CIR_ConditionOpInterface, 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:
| Attribute | MLIR Type | Description |
|---|---|---|
value | ::mlir::TypedAttr | TypedAttr instance |
Results:
| Result | Description |
|---|---|
res | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.continue (::cir::ContinueOp)
C/C++ continue statement equivalent
Syntax:
operation ::= `cir.continue` attr-dict
The cir.continue operation is used to continue execution to the next iteration of a loop. It is only allowed within cir.loop regions.
Traits: Terminator
cir.copy (::cir::CopyOp)
Copies contents from a CIR pointer to another
Syntax:
operation ::= `cir.copy` $src `to` $dst (`volatile` $is_volatile^)?
attr-dict `:` qualified(type($dst))
(`tbaa` `(` $tbaa^ `)`)?
Given two CIR pointers, src and dst, cir.copy will copy the memory pointed by src to the memory pointed by dst.
The amount of bytes copied is inferred from the pointee type. Naturally, the pointee type of both src and dst must match and must implement the DataLayoutTypeInterface.
Examples:
// Copying contents from one record to another:
cir.copy %0 to %1 : !cir.ptr<!record_ty>
Traits: SameTypeOperands
Interfaces: PromotableMemOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
is_volatile | ::mlir::UnitAttr | unit attribute |
tbaa | ::mlir::Attribute | base attribute for TBAA or Omnipotent char type or VTable pointer type or Scalar type with identifier or Struct type or Member of a TBAA struct type |
Operands:
| Operand | Description |
|---|---|
dst | CIR pointer type |
src | CIR pointer type |
cir.copysign (::cir::CopysignOp)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.copysign` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.cos (::cir::CosOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.cos` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.delete.array (::cir::DeleteArrayOp)
Delete address representing an array
Syntax:
operation ::= `cir.delete.array` $address `:` type($address) attr-dict
cir.delete.array operation deletes an array. For example, delete[] ptr; will be translated to cir.delete.array %ptr.
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` $base_addr `:` qualified(type($base_addr))
(`nonnull` $assume_not_null^)?
` ` `[` $offset `]` `->` qualified(type($derived_addr)) 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 (In the itanium ABI 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.
Example:
class A { int a; };
class B { int b;
public:
A *getAsA();
};
class X : public A, public B { int x; };
A *B::getAsA() {
return static_cast<X*>(this);
leads to
%2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>
%3 = cir.derived_class_addr %2 : !cir.ptr<!rec_B> nonnull [4] -> !cir.ptr<!rec_X>
%4 = cir.base_class_addr %3 : !cir.ptr<!rec_X> [0] -> !cir.ptr<!rec_A>
cir.return %4
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
offset | ::mlir::IntegerAttr | index attribute |
assume_not_null | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
base_addr | CIR pointer type |
Results:
| Result | Description |
|---|---|
derived_addr | 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 `:` qualified(type($src))
` ` `[` $offset `]` `->` 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:
| Attribute | MLIR Type | Description |
|---|---|---|
offset | ::mlir::IntegerAttr | index attribute |
Operands:
| Operand | Description |
|---|---|
src | CIR type that represents pointer-to-data-member type in C++ |
Results:
| Result | Description |
|---|---|
result | CIR type that represents pointer-to-data-member type 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 `:` qualified(type($src))
` ` `[` $offset `]` `->` 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 : !cir.method<!cir.func<(!s32i)> in !rec_Base> [16] -> !cir.method<!cir.func<(!s32i)> in !rec_Derived>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
offset | ::mlir::IntegerAttr | index 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.do (::cir::DoWhileOp)
C/C++ do-while loop
Syntax:
operation ::= `cir.do` $body `while` $cond attr-dict
Represents a C/C++ do-while loop. Identical to cir.while but the condition is evaluated after the body.
Example:
cir.do {
cir.break
^bb2:
cir.yield
} while {
cir.condition %cond : cir.bool
}
Traits: CIR_Breakable, NoRegionArguments
Interfaces: CIR_LoopOpInterface, LoopLikeOpInterface, RegionBranchOpInterface
cir.dyn_cast (::cir::DynamicCastOp)
Perform dynamic cast on record pointers
Syntax:
operation ::= `cir.dyn_cast` $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
kindisref, 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.
- If
- When the runtime type check fails:
- If
kindisref, the operation will throw abad_castexception. - Otherwise, the operation will return a null pointer value as its result.
- If
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.
Example:
%res = cir.dyn_cast ptr %ptr: !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
%res = cir.dyn_cast ptr relative_layout %ptr: !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::DynamicCastKindAttr | dynamic cast kind |
info | ::cir::DynamicCastInfoAttr | ABI specific information about a dynamic cast |
relative_layout | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
src | pointer to record type |
Results:
| Result | Description |
|---|---|
result | pointer to any of CIR void type, CIR record type |
cir.eh.inflight_exception (::cir::EhInflightOp)
Materialize the catch clause formal parameter
Syntax:
operation ::= `cir.eh.inflight_exception` (`cleanup` $cleanup^)?
($sym_type_list^)?
attr-dict
cir.eh.inflight_exception returns two values:
exception_ptr: The exception pointer for the inflight exceptiontype_id: pointer to the exception object This operation is expected to be the first one basic blocks on the exception path out ofcir.try_calloperations.
The cleanup attribute indicates that clean up code might run before the values produced by this operation are used to gather exception information. This helps CIR to pass down more accurate information for LLVM lowering to landingpads.
Interfaces: InferTypeOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
cleanup | ::mlir::UnitAttr | unit attribute |
sym_type_list | ::mlir::ArrayAttr | flat symbol ref array attribute |
Results:
| Result | Description |
|---|---|
exception_ptr | pointer to void type |
type_id | 32-bit unsigned integer |
cir.eh.setjmp (::cir::EhSetjmpOp)
CIR setjmp operation
Syntax:
operation ::= `cir.eh.setjmp` (`builtin` $is_builtin^)?
$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.
The presence of the builtin attribute refers to the setjmp() function; the lack of the attribute refers to the _setjmp() function.
Examples:
// Specify setjmp is builtin.
%0 = cir.eh.setjmp builtin %arg0 : (!cir.ptr<!cir.void>) -> !s32i
// Specify setjmp is not builtin.
%0 = cir.eh.setjmp %arg0 : (!cir.ptr<!cir.void>) -> !s32i
Interfaces: InferTypeOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
is_builtin | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
env | CIR pointer type |
Results:
| Result | Description |
|---|---|
res | 32-bit signed integer |
cir.eh.typeid (::cir::EhTypeIdOp)
Compute exception type id from it’s 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.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
type_sym | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Results:
| Result | Description |
|---|---|
type_id | 32-bit unsigned integer |
cir.exp2 (::cir::Exp2Op)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.exp2` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.exp (::cir::ExpOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.exp` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Compute whether expression is likely to evaluate to a specified value
Syntax:
operation ::= `cir.expect` `(` $val`,` $expected (`,` $prob^)? `)` `:` type($val) attr-dict
Provides __builtin_expect functionality in Clang IR.
If $prob is not specified, then behaviour is same as __builtin_expect. If specified, then behaviour is same as __builtin_expect_with_probability, where probability = $prob.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
prob | ::mlir::FloatAttr | 64-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 extract 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:
| Attribute | MLIR Type | Description |
|---|---|---|
index | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Operands:
| Operand | Description |
|---|---|
record | CIR record type |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.fabs (::cir::FAbsOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.fabs` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.fmaxnum (::cir::FMaxNumOp)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.fmaxnum` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.fmaximum (::cir::FMaximumOp)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.fmaximum` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.fminnum` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.fminimum` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.fmod` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.floor (::cir::FloorOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.floor` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.for (::cir::ForOp)
C/C++ for loop counterpart
Syntax:
operation ::= `cir.for` `:` `cond` $cond
`body` $body
`step` $step
attr-dict
Represents a C/C++ for loop. It consists of three regions:
cond: single block region with the loop’s condition. Should be terminated with acir.conditionoperation.body: contains the loop body and an arbitrary number of blocks.step: single block region with the loop’s step.
Example:
cir.for cond {
cir.condition(%val)
} body {
cir.break
^bb2:
cir.yield
} step {
cir.yield
}
Traits: CIR_Breakable, NoRegionArguments
Interfaces: CIR_LoopOpInterface, LoopLikeOpInterface, RegionBranchOpInterface
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
Represents 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<!void>
Interfaces: InferTypeOpInterface
Operands:
| Operand | Description |
|---|---|
level | 32-bit unsigned integer |
Results:
| Result | Description |
|---|---|
result | pointer to void type |
cir.free.exception (::cir::FreeExceptionOp)
Frees an exception according to Itanium ABI
Syntax:
operation ::= `cir.free.exception` $ptr attr-dict
Implements a slightly higher level version of: void __cxa_free_exception(void *thrown_exception);
Example:
%0 = cir.alloc.exception 16 -> !cir.ptr<!some_record>
%1 = cir.get_global @d2 : !cir.ptr<!some_record>
cir.try synthetic cleanup {
cir.call exception @_ZN7test2_DC1ERKS_(%0, %1) : (!cir.ptr<!some_record>, !cir.ptr<!some_record>) -> () cleanup {
%2 = cir.cast bitcast %0 : !cir.ptr<!some_record> -> !cir.ptr<!void>
cir.free.exception %2
cir.yield
}
...
}
Operands:
| Operand | Description |
|---|---|
ptr | pointer to void type |
cir.get_bitfield (::cir::GetBitfieldOp)
Get a bitfield
Syntax:
operation ::= `cir.get_bitfield` (`align` `(` $alignment^ `)`)?
`(`$bitfield_info `,` $addr 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.
Example: Suppose we have a struct with multiple bitfields stored in different storages. 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.d;
}
// 'd' is in the storage with the index 1
!record_type = !cir.record<struct "S" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>
#bfi_d = #cir.bitfield_info<name = "d", storage_type = !u32i, size = 2, offset = 17, is_signed = true>
%2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
%3 = cir.get_member %2[1] {name = "d"} : !cir.ptr<!record_type> -> !cir.ptr<!u32i>
%4 = cir.get_bitfield align(4) (#bfi_d, %3 : !cir.ptr<!u32i>) -> !s32i
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
bitfield_info | ::cir::BitfieldInfoAttr | Represents a bit field info |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
addr | CIR pointer type |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.get_element (::cir::GetElementOp)
Get the address of an array element
Syntax:
operation ::= `cir.get_element` $base `[` $index `]` `:` `(` qualified(type($base)) `,` qualified(type($index)) `)`
`->` qualified(type($result)) attr-dict
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.
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] : (!cir.ptr<!array_ty>, !s32i) -> !cir.ptr<!s32i>
// Get the address of the element at index %i.
%i = ...
%elem_i = cir.get_element %0[%i] : (!cir.ptr<!array_ty>, !s32i) -> !cir.ptr<!s32i>
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^)?
$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. 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.
Example:
%x = cir.get_global @foo : !cir.ptr<i32>
...
%y = cir.get_global thread_local @batata : !cir.ptr<i32>
...
cir.global external addrspace(offload_global) @gv = #cir.int<0> : !s32i
%z = cir.get_global @gv : !cir.ptr<!s32i, addrspace(offload_global)>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
name | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
tls | ::mlir::UnitAttr | unit 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-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, 32>
!record_ty = !cir.record<"struct.Bar" {!s32i, !s8i}>
// Get the address of the member at index 1.
%1 = cir.get_member %0[1] {name = "i"} : (!cir.ptr<!record_ty>) -> !cir.ptr<!s8i>
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
name | ::mlir::StringAttr | string attribute |
index | ::mlir::IntegerAttr | 64-bit signless integer 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 method and an object 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 as:
// %object = ...
// %arg = ...
// %method = ...
%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 parameters of the method.
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)f->*member; // cir.get_runtime_member
This operation expects a pointer to the base record as well as the pointer to the target member.
Operands:
| Operand | Description |
|---|---|
addr | pointer to record type |
member | CIR type that represents pointer-to-data-member type in C++ |
Results:
| Result | Description |
|---|---|
result | CIR pointer type |
cir.global (::cir::GlobalOp)
Declares or defines a global variable
Syntax:
operation ::= `cir.global` ($sym_visibility^)?
(`` $global_visibility^)?
(`constant` $constant^)?
$linkage
(`comdat` $comdat^)?
($tls_model^)?
(`dso_local` $dso_local^)?
(`addrspace` `` $addr_space^)?
$sym_name
custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value, $ctorRegion, $dtorRegion)
($annotations^)?
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 operation is a declaration if no inital_value is specified, else it is a definition.
The global variable can also be marked constant using the constant unit attribute. Writing to such constant global variables is undefined.
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.
visibility_attr is defined in terms of CIR’s visibility.
Example:
// Public and constant variable with initial value.
cir.global public constant @c : i32 = 4;
Traits: NoRegionArguments
Interfaces: CIRGlobalValueInterface, RegionBranchOpInterface, Symbol
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
sym_name | ::mlir::StringAttr | string attribute |
global_visibility | ::cir::VisibilityAttr | Visibility attribute |
sym_visibility | ::mlir::StringAttr | string attribute |
sym_type | ::mlir::TypeAttr | any type attribute |
linkage | ::cir::GlobalLinkageKindAttr | linkage kind |
addr_space | ::cir::AddressSpaceAttr | address space kind |
tls_model | ::cir::TLS_ModelAttr | TLS model |
initial_value | ::mlir::Attribute | any attribute |
comdat | ::mlir::UnitAttr | unit attribute |
constant | ::mlir::UnitAttr | unit attribute |
dso_local | ::mlir::UnitAttr | unit attribute |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
ast | ::cir::ASTVarDeclInterface | ASTVarDeclInterface instance |
section | ::mlir::StringAttr | string attribute |
annotations | ::mlir::ArrayAttr | array 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:
| Attribute | MLIR Type | Description |
|---|---|---|
label | ::mlir::StringAttr | string 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 %b {
...
} else {
...
}
cir.if %c {
...
}
cir.if %c {
...
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.asm (::cir::InlineAsmOp)
The cir.asm operation represents C/C++ asm inline.
CIR constraints strings follow barelly 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 is a storage, where each element corresponds to the operand with the same index. The first index relates to the operation result (if any). Note, the operands themselves are stored as VariadicOfVariadic in the next order: output, input and then in/out operands.
Note, when several output operands are present, the result type may be represented as an anon 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 !s32i, !cir.ptr<!s32i>, ["x", init]
%1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init]
...
%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
Traits: RecursiveMemoryEffects
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
asm_string | ::mlir::StringAttr | string attribute |
constraints | ::mlir::StringAttr | string attribute |
side_effects | ::mlir::UnitAttr | unit attribute |
asm_flavor | ::cir::AsmFlavorAttr | ATT or Intel |
operand_attrs | ::mlir::ArrayAttr | array attribute |
operands_segments | ::mlir::DenseI32ArrayAttr | i32 dense array attribute |
Operands:
| Operand | Description |
|---|---|
asm_operands | variadic of any type |
Results:
| Result | Description |
|---|---|
res | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
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 value, and returns the modified record value. The result of this operation is equal to the input record value, 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:
| Attribute | MLIR Type | Description |
|---|---|---|
index | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Operands:
| Operand | Description |
|---|---|
record | CIR record type |
value | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | CIR record type |
cir.invariant_group (::cir::InvariantGroupOp)
Start an invariant group
Syntax:
operation ::= `cir.invariant_group` $ptr `:` type($result) attr-dict
The cir.invariant_group operation takes a single pointer value as argument and returns the same pointer value with fresh invariant group information. All loads and stores that access the returned pointer value are presumed by the optimizer to load or store the same value.
This operation is not emitted during CIRGen. Instead, it is created when hoisting constant alloca operations to the entry block of a function. This operation effectively marks the syntactic scope of the constant local variable represented by the hosited alloca operation, and it allows for better LLVMIR generation with potentially more optimizations.
For example, if we have the following CIR before alloca hoisting:
cir.func @foo() {
cir.scope {
%0 = cir.alloca !s32i : !cir.ptr<!s32i>
use(%0)
}
}
After alloca hoisting:
cir.func @foo() {
%0 = cir.alloca !s32i : !cir.ptr<!s32i>
cir.scope {
%1 = cir.invariant_group %0 : !cir.ptr<!s32i>
use(%1)
}
}
During LLVMIR lowering, load and store operations whose pointer operand comes from cir.invariant_group are lowered to corresponding LLVM instructions with invariant group metadata attached.
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
ptr | CIR pointer type |
Results:
| Result | Description |
|---|---|
result | CIR pointer type |
cir.is_constant (::cir::IsConstantOp)
Syntax:
operation ::= `cir.is_constant` `(` $val `:` type($val) `)` `:` type($result) attr-dict
Returns true if the argument is known to be a compile-time constant otherwise returns ‘false’.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
val | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
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 `,` $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 |
Interfaces: InferTypeOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
flags | ::mlir::IntegerAttr | 32-bit signless integer attribute |
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.std.begin (::cir::IterBeginOp)
Std::begin()
Syntax:
operation ::= `cir.std.begin` `(` $container `:` type($container) `,` $original_fn `)` `->` type($result) attr-dict
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
original_fn | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operands:
| Operand | Description |
|---|---|
container | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.std.end (::cir::IterEndOp)
Std::end()
Syntax:
operation ::= `cir.std.end` `(` $container `:` type($container) `,` $original_fn `)` `->` type($result) attr-dict
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
original_fn | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operands:
| Operand | Description |
|---|---|
container | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.llvm.intrinsic (::cir::LLVMIntrinsicCallOp)
Call to llvm intrinsic functions that is not defined in CIR
Syntax:
operation ::= `cir.llvm.intrinsic` $intrinsic_name $arg_ops `:` functional-type($arg_ops, $result) attr-dict
cir.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:
| Attribute | MLIR Type | Description |
|---|---|---|
intrinsic_name | ::mlir::StringAttr | string attribute |
Operands:
| Operand | Description |
|---|---|
arg_ops | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.llrint (::cir::LLrintOp)
Builtin function that takes a floating-point value as input and produces an integral value as output.
Syntax:
operation ::= `cir.llrint` $src `:` type($src) `->` type($result) attr-dict
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 | Integer type with arbitrary precision up to a fixed limit |
cir.llround (::cir::LLroundOp)
Builtin function that takes a floating-point value as input and produces an integral value as output.
Syntax:
operation ::= `cir.llround` $src `:` type($src) `->` type($result) attr-dict
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 | Integer type with arbitrary precision up to a fixed limit |
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:
| Attribute | MLIR Type | Description |
|---|---|---|
label | ::mlir::StringAttr | string attribute |
cir.linker_options (::cir::LinkerOptionsOp)
Options to pass to the linker when the object file is linked
Syntax:
operation ::= `cir.linker_options` $options attr-dict
Pass the given options to the linker when the resulting object file is linked. This is used extensively on Windows to determine the C runtime that the object files should link against.
Examples:
// Link against the MSVC static threaded CRT.
cir.linker_options ["/DEFAULTLIB:", "libcmt"]
// Link against aarch64 compiler-rt builtins
cir.linker_options ["-l", "clang_rt.builtins-aarch64"]
Traits: HasParent<mlir::ModuleOp>
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
options | ::mlir::ArrayAttr | string array attribute |
cir.load (::cir::LoadOp)
Load value from memory adddress
Syntax:
operation ::= `cir.load` (`deref` $isDeref^)?
(`volatile` $is_volatile^)?
(`nontemporal` $is_nontemporal^)?
(`align` `(` $alignment^ `)`)?
(`atomic` `(` $mem_order^ `)`)?
$addr `:` qualified(type($addr)) `,` type($result) attr-dict
(`tbaa` `(` $tbaa^ `)`)?
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>).
align can be used to specify an alignment that’s different from the default, which is computed from result’s type ABI data layout.
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
// Others
%x = cir.load align(16) atomic(seq_cst) %0 : !cir.ptr<i32>, i32
Interfaces: InferTypeOpInterface, PromotableMemOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
isDeref | ::mlir::UnitAttr | unit attribute |
is_volatile | ::mlir::UnitAttr | unit attribute |
is_nontemporal | ::mlir::UnitAttr | unit attribute |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
mem_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
tbaa | ::mlir::Attribute | base attribute for TBAA or Omnipotent char type or VTable pointer type or Scalar type with identifier or Struct type or Member of a TBAA struct type |
Operands:
| Operand | Description |
|---|---|
addr | CIR pointer type |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.log10 (::cir::Log10Op)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.log10` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.log2` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.log (::cir::LogOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.log` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Builtin function that takes a floating-point value as input and produces an integral value as output.
Syntax:
operation ::= `cir.lrint` $src `:` type($src) `->` type($result) attr-dict
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 | Integer type with arbitrary precision up to a fixed limit |
cir.lround (::cir::LroundOp)
Builtin function that takes a floating-point value as input and produces an integral value as output.
Syntax:
operation ::= `cir.lround` $src `:` type($src) `->` type($result) attr-dict
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 | Integer type with arbitrary precision up to a fixed limit |
cir.libc.memchr (::cir::MemChrOp)
Libc’s memchr
Syntax:
operation ::= `cir.libc.memchr` `(`
$src `,` $pattern `,` $len `)` attr-dict
Search for pattern in data range from src to src + len. provides a bound to the search in src. result is a pointer to found pattern or a null pointer.
Examples:
%p = cir.libc.memchr(%src, %pattern, %len) -> !cir.ptr<!void>
Interfaces: InferTypeOpInterface
Operands:
| Operand | Description |
|---|---|
src | pointer to void type |
pattern | 32-bit signed integer |
len | 64-bit unsigned integer |
Results:
| Result | Description |
|---|---|
result | pointer to void type |
cir.memcpy_inline (::cir::MemCpyInlineOp)
Memory copy with constant length without callingany external function
Syntax:
operation ::= `cir.memcpy_inline` $len `bytes` `from` $src `to` $dst attr-dict
`:` qualified(type($src)) `->` qualified(type($dst))
Given two CIR pointers, src and dst, memcpy_inline will copy len bytes from the memory pointed by src to the memory pointed by dst.
Unlike cir.libc.memcpy, this Op guarantees that no external functions are called, and length of copied bytes is a constant.
Examples:
// Copying 2 bytes from one array to a record:
cir.memcpy_inline 2 bytes from %arr to %record : !cir.ptr<!arr> -> !cir.ptr<!record>
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
len | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Operands:
| Operand | Description |
|---|---|
dst | pointer to void type |
src | pointer to void type |
cir.libc.memcpy (::cir::MemCpyOp)
Equivalent to libc’s memcpy
Syntax:
operation ::= `cir.libc.memcpy` $len `bytes` `from` $src `to` $dst 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.
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>
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 `to` $dst 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
Operands:
| Operand | Description |
|---|---|
dst | pointer to void type |
src | pointer to void type |
len | fundamental unsigned integer type |
cir.memset_inline (::cir::MemSetInlineOp)
Fill a block of memory with constant length without callingany external function
Syntax:
operation ::= `cir.memset_inline` $len `bytes` `from` $dst `set` `to` $val attr-dict
`:` qualified(type($dst)) `,` type($val)
Given the CIR pointer, dst, cir.memset_inline will set the first len bytes of the memory pointed by dst to the specified val.
The len argument must be a constant integer argument specifying the number of bytes to fill.
Examples:
// Set 2 bytes from a record to 0
cir.memset_inline 2 bytes from %record set to %zero : !cir.ptr<!void>, !s32i
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
len | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Operands:
| Operand | Description |
|---|---|
dst | pointer to void type |
val | 32-bit signed integer |
cir.libc.memset (::cir::MemSetOp)
Equivalent to libc’s memset
Syntax:
operation ::= `cir.libc.memset` $len `bytes` `from` $dst `set` `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 from a record to 0:
%2 = cir.const #cir.int<2> : !u32i
%3 = cir.const #cir.int<0> : !u32i
%zero = cir.cast integral %3 : !s32i -> !u8i
cir.libc.memset %2 bytes from %record set to %zero : !cir.ptr<!void>, !s32i, !u64i
Operands:
| Operand | Description |
|---|---|
dst | pointer to void type |
val | 32-bit signed integer |
len | fundamental unsigned integer type |
cir.nearbyint (::cir::NearbyintOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.nearbyint` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.objsize (::cir::ObjSizeOp)
Implements llvm.objsize builtin.
Syntax:
operation ::= `cir.objsize` (`min` $min^) : (`max`)?
(`dynamic` $dynamic^)?
$ptr `:` qualified(type($ptr)) `->` qualified(type($result)) attr-dict
The cir.objsize operation models the behavior of the llvm.objectsize builtins in Clang. It returns the number of accessible bytes past ptr.
The kind argument determines whether cir.objsize returns 0 (if true) or -1 (if false) when the object size is unknown. 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.
Example:
%size = cir.objsize min %ptr : !cir.ptr<i32> -> i64
%dsize = cir.objsize max dynamic %ptr : !cir.ptr<i32> -> i64
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
min | ::mlir::UnitAttr | unit attribute |
dynamic | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
ptr | CIR pointer type |
Results:
| Result | Description |
|---|---|
result | fundamental integer type |
cir.pow (::cir::PowOp)
Libc builtin equivalent ignoring floating-point exceptions and errno.
Syntax:
operation ::= `cir.pow` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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` `(` $addr `:` qualified(type($addr)) `)`
`locality``(` $locality `)`
(`write` $isWrite^) : (`read`)?
attr-dict
The cir.prefetch op prefetches data from the memmory address.
cir.prefetch(%0 : !cir.ptr<!void>) locality(1) write
This opcode has the three attributes:
- The $locality is a temporal locality specifier ranging from (0) - no locality, to (3) - extremely local keep in cache.
- The $isWrite is the specifier determining if the prefetch is prepaired for a ‘read’ or ‘write’. If $isWrite doesn’t specified it means that prefetch is prepared for ‘read’.
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
locality | ::mlir::IntegerAttr | 32-bit signless integer attribute whose minimum value is 0 whose maximum value is 3 |
isWrite | ::mlir::UnitAttr | unit attribute |
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.
Example:
%7 = cir.ptr_diff %0, %1 : !cir.ptr<!u64i> -> !u64i
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)
Masks out bits of the pointer according to a mask
Syntax:
operation ::= `cir.ptr_mask` `(` $ptr `,` $mask `:` type($mask) `)` `:` qualified(type($result)) attr-dict
The cir.ptr_mask operation takes a pointer and an interger mask as its argument and return the masked pointer type according to the mask.
Interfaces: InferTypeOpInterface
Operands:
| Operand | Description |
|---|---|
ptr | CIR pointer type |
mask | Integer type with arbitrary precision up to a fixed limit |
Results:
| Result | Description |
|---|---|
result | CIR pointer type |
cir.ptr_stride (::cir::PtrStrideOp)
Pointer access with stride
Syntax:
operation ::= `cir.ptr_stride` ($noWrapFlags^)? $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.
Optional no-wrap flags refine pointer arithmetic semantics, that mirror LLVM’s GEP no-wrap semantics.
Example:
%3 = cir.ptr_stride %1, %2 : (!cir.ptr<i32>, i32) ->!cir.ptr<i32>
%4 = cir.ptr_stride inbounds %1, %2 : (!cir.ptr<i32>, i32) -> !cir.ptr<i32>
%5 = cir.ptr_stride inbounds|nuw %1, %2 : (!cir.ptr<i32>, i32) -> !cir.ptr<i32>
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.resume (::cir::ResumeOp)
Resumes execution after not catching exceptions
Syntax:
operation ::= `cir.resume` (`rethrow` $rethrow^)?
($exception_ptr^ (`,` $type_id^)?)?
attr-dict
The cir.resume operation handles an uncaught exception scenario and behaves in two different modes:
- As the terminator of a
CatchUnwindregion ofcir.try, where it does not receive any arguments (implied from thecir.tryscope), or - The terminator of a regular basic block without an enclosing
cir.tryoperation, where it requires anexception_ptrand atype_id.
The rethrow attribute is used to denote rethrowing behavior for the resume operation (versus default terminaton).
Traits: `AttrSizedOperandSegments`, `ReturnLike`, `Terminator`
Interfaces: `RegionBranchTerminatorOpInterface`
#### Attributes:
<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>rethrow</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>
#### Operands:
| Operand | Description |
| :-----: | ----------- |
| `exception_ptr` | pointer to void type |
| `type_id` | 32-bit unsigned integer |
### `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 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:
```mlir
%p = return_address(%level) -> !cir.ptr<!void>
Interfaces: InferTypeOpInterface
Operands:
| Operand | Description |
|---|---|
level | 32-bit unsigned integer |
Results:
| Result | Description |
|---|---|
result | pointer to void type |
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, DoWhileOp, WhileOp, ForOp, CaseOp, TryOp>, Terminator
Operands:
| Operand | Description |
|---|---|
input | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.rint (::cir::RintOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.rint` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Reverse the bytes that constitute the operand integer
Syntax:
operation ::= `cir.rotate` (`left` $left^) : (`right`)?
$src `,` $amt `->` type($result) attr-dict
The cir.rotate rotates operand in src by the given bit amount amt. Its widths must be either 8, 16, 32, or 64 and both src, amt and result be of the same type. The rotate direction is specified by a left/right keyword.
This operation covers different C/C++ builtins, some examples: __builtin_rotateleft8, __builtin_rotateleft16, __builtin_rotateleft32, __builtin_rotateleft64, _rotl8, _rotl16, _rotl, _lrotl, _rotl64, etc and their “right” variants.
Example:
%r = cir.rotate left %0, %1 -> !u32i
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
left | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
src | Integer type with arbitrary precision up to a fixed limit |
amt | 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.roundeven (::cir::RoundEvenOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.roundeven` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.round (::cir::RoundOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.round` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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<OmittedTerminatorRegion>($scopeRegion, $cleanupRegion) (`:` 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:
%rvalue = cir.scope {
...
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.
The scope might also have an associated cleanup region, providing code that run destruction of automatic variables. Note that in order to lower the cleanup region while keeping C++ semantics, all immediate control-flow breaking operations not under a children scope should jump to this cleanup code.
Traits: AutomaticAllocationScope, NoRegionArguments, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable, RegionBranchOpInterface
Results:
| Result | Description |
|---|---|
results | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
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 a boolean value 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.
Example:
%0 = cir.const #cir.bool<true> : !cir.bool
%1 = cir.const #cir.int<42> : !s32i
%2 = cir.const #cir.int<72> : !s32i
%3 = cir.select if %0 then %1 else %2 : (!cir.bool, !s32i, !s32i) -> !s32i
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
condition | CIR bool type |
true_value | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
false_value | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.set_bitfield (::cir::SetBitfieldOp)
Set a bitfield
Syntax:
operation ::= `cir.set_bitfield` (`align` `(` $alignment^ `)`)?
`(`$bitfield_info`,` $addr`:`qualified(type($addr))`,`
$src`:`type($src) `)` attr-dict `->` type($result)
The cir.set_bitfield operation provides a store-like access to a bit field of a record.
It expects an address of a storage where to store, a type of the storage, a value being stored, a name of a bit field, a pointer to the storage in the base record, a size of the storage, a size the bit field, an offset of the bit field and a sign. Returns a value being stored.
A unit attribute volatile can be used to indicate a volatile load of the bitfield.
Example. Suppose we have a struct with multiple bitfields stored in different storages. The cir.set_bitfield operation sets the value of the bitfield.
typedef struct {
int a : 4;
int b : 27;
int c : 17;
int d : 2;
int e : 15;
} S;
void store_bitfield(S& s) {
s.d = 3;
}
// 'd' is in the storage with the index 1
!record_type = !cir.record<struct "S" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>
#bfi_d = #cir.bitfield_info<name = "d", storage_type = !u32i, size = 2, offset = 17, 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 = "d"} : !cir.ptr<!record_type> -> !cir.ptr<!u32i>
%4 = cir.set_bitfield align(4) (#bfi_d, %3 : !cir.ptr<!u32i>, %1 : !s32i) -> !s32i
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
bitfield_info | ::cir::BitfieldInfoAttr | Represents a bit field info |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
addr | CIR pointer type |
src | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.shift (::cir::ShiftOp)
Shift
Syntax:
operation ::= `cir.shift` `(`
(`left` $isShiftleft^) : (```right`)?
`,` $value `:` type($value)
`,` $amount `:` type($amount)
`)` `->` type($result) attr-dict
Shift left or right, according to the first operand. Second operand is the shift target and the third the amount. Second and the thrid operand can be either integer type or vector of integer type. However, 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.
%7 = cir.shift(left, %1 : !u64i, %4 : !s32i) -> !u64i
%8 = cir.shift(left, %2 : !cir.vector<!s32i x 2>, %3 : !cir.vector<!s32i x 2>) -> !cir.vector<!s32i x 2>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
isShiftleft | ::mlir::UnitAttr | unit 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)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.sin` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.sqrt` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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.stack_restore (::cir::StackRestoreOp)
Restores the state of the function stack
Syntax:
operation ::= `cir.stack_restore` $ptr attr-dict `:` qualified(type($ptr))
Restore the state of the function stack to the state it was in when the corresponding cir.stack_save executed. Useful for implementing language features like variable length arrays.
%0 = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] {alignment = 8 : i64}
%1 = cir.stack_save : <!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.stack_restore %2 : !cir.ptr<!u8i>
Operands:
| Operand | Description |
|---|---|
ptr | CIR pointer type |
cir.stack_save (::cir::StackSaveOp)
Remembers the current state of the function stack
Syntax:
operation ::= `cir.stack_save` attr-dict `:` qualified(type($result))
Remembers the current state of the function stack. Returns a pointer that later can be passed into cir.stack_restore. Useful for implementing language features like variable length arrays.
%0 = cir.stack_save : <!u8i>
Results:
| Result | Description |
|---|---|
result | CIR pointer type |
cir.std.find (::cir::StdFindOp)
Std::find()
Syntax:
operation ::= `cir.std.find` `(` $first `:` type($first) `,` $last `:` type($last) `,` $pattern `:` type($pattern) `,` $original_fn `)` `->` type($result) attr-dict
Interfaces: InferTypeOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
original_fn | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operands:
| Operand | Description |
|---|---|
first | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
last | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
pattern | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.store (::cir::StoreOp)
Store value to memory address
Syntax:
operation ::= `cir.store` (`volatile` $is_volatile^)?
(`nontemporal` $is_nontemporal^)?
(`align` `(` $alignment^ `)`)?
(`atomic` `(` $mem_order^ `)`)?
$value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr))
(`tbaa` `(` $tbaa^ `)`)?
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>).
align 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:
| Attribute | MLIR Type | Description |
|---|---|---|
is_volatile | ::mlir::UnitAttr | unit attribute |
is_nontemporal | ::mlir::UnitAttr | unit attribute |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
mem_order | ::cir::MemOrderAttr | Memory order according to C++11 memory model |
tbaa | ::mlir::Attribute | base attribute for TBAA or Omnipotent char type or VTable pointer type or Scalar type with identifier or Struct type or Member of a TBAA struct type |
Operands:
| Operand | Description |
|---|---|
value | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
addr | CIR pointer type |
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)), $case_values, $caseDestinations,
$caseOperands, type($caseOperands))
attr-dict
The cir.switch.flat operation is a region-less and simplified version of the cir.switch. It’s representation is closer to LLVM IR dialect than the C/C++ language feature.
Traits: AttrSizedOperandSegments, Terminator
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
case_values | ::mlir::ArrayAttr | array attribute |
case_operand_segments | ::mlir::DenseI32ArrayAttr | i32 dense array attribute |
Operands:
| Operand | Description |
|---|---|
condition | Integer type with arbitrary precision up to a fixed limit |
defaultOperands | variadic of any type |
caseOperands | variadic of any type |
Successors:
| Successor | Description |
|---|---|
defaultDestination | any successor |
caseDestinations | any successor |
cir.switch (::cir::SwitchOp)
Switch operation
Syntax:
operation ::= `cir.switch` custom<SwitchOp>(
$body, $condition, type($condition)
)
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.
The set of cir.case operations and their enclosing cir.switch represents 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 doesn’t have to be in the region of cir.switch directly. However, when all the cir.case operations lives in the region of cir.switch directly and there is no other operations except the ending cir.yield operation in the region of cir.switch directly, we call 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 analysis easier to handle the cir.switch operation and makes the boundary to give up pretty 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 might not be considered “simple” if any of the following is true:
- There are case statements of the switch statement lives in other scopes 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 are codes 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, CIR_Breakable, NoRegionArguments, RecursivelySpeculatableImplTrait, SameVariadicOperandSize
Interfaces: ConditionallySpeculatable, RegionBranchOpInterface
Operands:
| Operand | Description |
|---|---|
condition | Integer type with arbitrary precision up to a fixed limit |
cir.tan (::cir::TanOp)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.tan` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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. 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.
Example:
// x = 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 | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.throw (::cir::ThrowOp)
(Re)Throws an exception
Syntax:
operation ::= `cir.throw` ($exception_ptr^ `:` type($exception_ptr))?
(`,` $type_info^)?
(`,` $dtor^)?
attr-dict
Very similar to __cxa_throw:
void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
void (*dest) (void *));
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.cxa.allocate_exception) and finally an optional dtor, which might run as part of this operation.
// if (b == 0)
// throw "Division by zero condition!";
cir.if %10 {
%11 = cir.alloc_exception 8 -> !cir.ptr<!void>
...
cir.store %13, %11 : // Store string addr for "Division by zero condition!"
cir.throw %11 : !cir.ptr<!cir.ptr<!u8i>>, @"typeinfo for char const*"
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
type_info | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
dtor | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operands:
| Operand | Description |
|---|---|
exception_ptr | CIR pointer type |
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)
Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.trunc` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
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_call (::cir::TryCallOp)
Try_call operation
Mostly similar to cir.call but requires two destination branches, one for handling exceptions in case its thrown and the other one to follow on regular control-flow.
Example:
// Direct call
%2 = cir.try_call @my_add(%0, %1) ^continue, ^landing_pad : (f32, f32) -> f32
Traits: AttrSizedOperandSegments, Terminator
Interfaces: BranchOpInterface, CIRCallOpInterface, CallOpInterface, SymbolUserOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
callee | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
calling_conv | ::cir::CallingConvAttr | calling convention |
side_effect | ::cir::SideEffectAttr | allowed side effects of a function |
extra_attrs | ::cir::ExtraFuncAttributesAttr | Represents aggregated attributes for a function |
ast | ::cir::ASTCallExprInterface | ASTCallExprInterface instance |
Operands:
| Operand | Description |
|---|---|
contOperands | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
landingPadOperands | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
arg_ops | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Successors:
| Successor | Description |
|---|---|
cont | any successor |
landing_pad | any successor |
cir.try (::cir::TryOp)
C++ try block
Syntax:
operation ::= `cir.try` (`synthetic` $synthetic^)?
(`cleanup` $cleanup^)?
$try_region
custom<CatchRegions>($catch_regions, $catch_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`.
`synthetic`: use `cir.try` to represent try/catches not originally
present in the source code (e.g. `g = new Class` under `-fexceptions`).
`cleanup`: signal to targets (LLVM for now) that this try/catch, needs
to specially tag their landing pads as needing "cleanup".
Example: TBD
Traits: AutomaticAllocationScope, NoRegionArguments, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable, RegionBranchOpInterface
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
synthetic | ::mlir::UnitAttr | unit attribute |
cleanup | ::mlir::UnitAttr | unit attribute |
catch_types | ::mlir::ArrayAttr | array attribute |
cir.unary (::cir::UnaryOp)
Unary operations
Syntax:
operation ::= `cir.unary` `(` $kind `,` $input `)`
(`nsw` $no_signed_wrap^)?
`:` type($input) `,` type($result) attr-dict
cir.unary performs the unary operation according to the specified opcode kind: [inc, dec, plus, minus, not].
It requires one input operand and has one result, both types should be the same.
%7 = cir.unary(inc, %1) : i32 -> i32
%8 = cir.unary(dec, %2) : i32 -> i32
Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::UnaryOpKindAttr | unary operation kind |
no_signed_wrap | ::mlir::UnitAttr | unit attribute |
Operands:
| Operand | Description |
|---|---|
input | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
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)
Operands:
| Operand | Description |
|---|---|
arg_list | CIR pointer type |
Results:
| Result | Description |
|---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.va.copy (::cir::VACopyOp)
Copies a variable argument list
Syntax:
operation ::= `cir.va.copy` $src_list `to` $dst_list attr-dict `:` type(operands)
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)
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)
Operands:
| Operand | Description |
|---|---|
arg_list | CIR pointer 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 VTT, which is the address point of a C++ vtable. In virtual inheritance, A set of internal __vptr 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 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 addresses 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:
| Attribute | MLIR Type | Description |
|---|---|---|
name | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
offset | ::mlir::IntegerAttr | 32-bit signless integer attribute |
Operands:
| Operand | Description |
|---|---|
sym_addr | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
Results:
| Result | Description |
|---|---|
addr | CIR pointer 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 name argument to this operation must be the name of a C++ vtable object. The return value is the address of the virtual function pointer array within the vtable (the vptr). This value will be written to the vptr member of a dynamic class by the constructor of the class. Derived classes have their own vtable, which is used to obtain the vptr stored in instances of the derived class.
The return type is always !cir.vptr.
Examples:
struct Base {
Base();
virtual void f();
};
struct Derived : public Base {
Derived();
};
!rec_Base = !cir.record<struct "Base" {!cir.vptr}
!rec_Derived = !cir.record<struct "Derived" {!rec_Base}
...
// VTable for Base
cir.global linkonce_odr @_ZTV1Base = ...
...
// Constructor for Base
cir.func dso_local @_ZN4BaseC2Ev ...
...
%2 = cir.vtable.address_point(@_ZTV1Base,
address_point = <index = 0, offset = 2>) : !cir.vptr
%3 = cir.vtable.get_vptr %1 : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>
cir.store align(8) %2, %3 : !cir.vptr, !cir.ptr<!cir.vptr>
...
// VTable for Derived
cir.global linkonce_odr @_ZTV7Derived = ...
...
// Constructor for Derived
cir.func dso_local @_ZN7DerivedC2Ev ...
// Get the address of Base within this Derived instance
%2 = cir.base_class_addr %1 : !cir.ptr<!rec_Derived> nonnull [0]
cir.call @_ZN4BaseC2Ev(%2)
%3 = cir.vtable.address_point(@_ZTV7Derived,
address_point = <index = 0, offset = 2>) : !cir.vptr
// The vptr is still at the start of the object in this case
%4 = cir.vtable.get_vptr %1 : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
// This overwrites the vptr that was stored in the Base constructor call
cir.store align(8) %3, %4 : !cir.vptr, !cir.ptr<!cir.vptr>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
name | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
address_point | ::cir::AddressPointAttr | Address point attribute |
Results:
| Result | Description |
|---|---|
addr | CIR type that is used for the vptr member of C++ objects |
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:
struct S {
virtual void f1();
virtual void f2();
};
void f3(S *s) {
s->f2();
}
// VTable for S
cir.global external @_ZTV1S = #cir.vtable<{
#cir.const_array<[
// Offset to the base object
#cir.ptr<null> : !cir.ptr<!u8i>,
// Type info for S
#cir.global_view<@_ZTI1S> : !cir.ptr<!u8i>,
// Pointer to S::f1
#cir.global_view<@_ZN1S2f1Ev> : !cir.ptr<!u8i>,
// Pointer to S::f2
#cir.global_view<@_ZN1S2f2Ev> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 4>}> ...
// f3()
cir.func dso_local @_Z2f3P1S(%s: !cir.ptr<!rec_S>) {
// Get the vptr -- This points to offset 2 in the vtable.
%1 = cir.vtable.get_vptr %s : !cir.ptr<!rec_S> -> !cir.ptr<!cir.vptr>
%2 = cir.load align(8) %1 : !cir.ptr<!cir.vptr>, !cir.vptr
// Get the address of b->f2() -- may be Base::f2() or Derived::f2()
%3 = cir.vtable.get_virtual_fn_addr %2[1] : !cir.vptr
-> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>
%4 = cir.load align(8) %3
: !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>,
!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>
cir.call %4(%b)
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
src | CIR pointer type |
Results:
| Result | Description |
|---|---|
result | pointer to vptr 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.vatble.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 1: Suppose we have two classes, Base and Derived, where Derived overrides virtual functions that were defined in Base. When a pointer to a Base object is used to call one of these function, we may not know at compile time whether it points to an instance of Base or an instance of Derived. The compiler does not need to know. It will load the vptr from the object and use that to get the address of the correct function to call. The vptr will have been initialized in the object’s constructor to point to the correct vtable for the object being instantiated.
// In this example, when f3 is called, we don't know at compile-time
// whether
struct Base {
virtual void f1();
virtual void f2();
};
struct Derived : public Base {
void f1() override;
void f2() override;
};
void f3(Base *b) {
b->f2();
}
// VTable for Base
cir.global external @_ZTV4Base = #cir.vtable<{
#cir.const_array<[
#cir.ptr<null> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN4Base2f1Ev> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN4Base2f2Ev> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 4>}> ...
// VTable for Derived
cir.global external @_ZTV7Derived = #cir.vtable<{
#cir.const_array<[
#cir.ptr<null> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN7Derived2f1Ev> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN7Derived2f2Ev> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 4>}> ...
// f3()
cir.func dso_local @_Z2f3P4Base(%b: !cir.ptr<!rec_Base>)
// Get the vptr
%1 = cir.vtable.get_vptr %b : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>
%2 = cir.load align(8) %1 : !cir.ptr<!cir.vptr>, !cir.vptr
// Get the address of b->f2() -- may be Base::f2() or Derived::f2()
%3 = cir.vtable.get_virtual_fn_addr %2[1] : !cir.vptr
-> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>
%4 = cir.load align(8) %3
: !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>,
!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>
cir.call %4(%b)
Example 2: Consider the case of multiple inheritance, where Base1 and Base2 both provide virtual functions and a third class, Derived, inherits from both bases. When a pointer to a Derived is used to call a virtual function in Base2, we must retrieve a pointer to the Base2 portion of the Derived object and use that pointer to get the vptr for Base2 as a base class.
struct Base1 {
virtual void f1();
};
struct Base2 {
virtual void f2();
};
struct Derived : public Base1, Base2 { };
void f3(Derived *d) {
d->f2();
}
!rec_Base1 = !cir.record<struct "Base1" {!cir.vptr}
!rec_Base2 = !cir.record<struct "Base2" {!cir.vptr}
!rec_Derived = !cir.record<struct "Derived" {!rec_Base1, !rec_Base2}
cir.func dso_local @_Z2f3P7Derived(%d: !cir.ptr<!rec_Derived>)
%2 = cir.base_class_addr %d : !cir.ptr<!rec_Derived> nonnull [8]
-> !cir.ptr<!rec_Base2>
%3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_Base2> -> !cir.ptr<!cir.vptr>
%4 = cir.load align(8) %3 : !cir.ptr<!cir.vptr>, !cir.vptr
%5 = cir.vtable.get_virtual_fn_addr %4[0] : !cir.vptr
-> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>>
%6 = cir.load align(8) %5
: !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>>,
!cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>
cir.call %6(%2) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_Base2>)>>,
!cir.ptr<!rec_Base2>) -> ()
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
index | ::mlir::IntegerAttr | 64-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.vec.cmp (::cir::VecCmpOp)
Compare two vectors
Syntax:
operation ::= `cir.vec.cmp` `(` $kind `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
qualified(type($result)) 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.
Traits: AlwaysSpeculatableImplTrait, SameTypeOperands
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
kind | ::cir::CmpOpKindAttr | compare operation kind |
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 integer, floating point or pointer type |
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.
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 integer, floating point or pointer type |
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 replaces the element of the given vector at the given index with the given value. The new vector with the inserted element is returned.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
vec | CIR vector type |
value | any cir integer, floating point or pointer type |
index | fundamental integer 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.
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.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.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
indices | ::mlir::ArrayAttr | array attribute |
Operands:
| Operand | Description |
|---|---|
vec1 | CIR vector type |
vec2 | CIR vector type |
Results:
| Result | Description |
|---|---|
result | CIR vector type |
cir.vec.splat (::cir::VecSplatOp)
Convert a scalar into a vector
Syntax:
operation ::= `cir.vec.splat` $value `:` type($value) `,` qualified(type($result)) attr-dict
The cir.vec.splat operation creates a vector value from a scalar value. All elements of the vector have the same value, that of the given scalar.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands:
| Operand | Description |
|---|---|
value | any cir integer, floating point or pointer type |
Results:
| Result | Description |
|---|---|
result | CIR vector 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 integer type |
lhs | CIR vector type |
rhs | CIR vector type |
Results:
| Result | Description |
|---|---|
result | CIR vector type |
cir.while (::cir::WhileOp)
C/C++ while loop
Syntax:
operation ::= `cir.while` $cond `do` $body attr-dict
Represents a C/C++ while loop. It consists of two regions:
cond: single block region with the loop’s condition. Should be terminated with acir.conditionoperation.body: contains the loop body and an arbitrary number of blocks.
Example:
cir.while {
cir.break
^bb2:
cir.yield
} do {
cir.condition %cond : cir.bool
}
Traits: CIR_Breakable, NoRegionArguments
Interfaces: CIR_LoopOpInterface, LoopLikeOpInterface, RegionBranchOpInterface
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, CallOp, CaseOp, DoWhileOp, ForOp, GlobalOp, IfOp, ScopeOp, SwitchOp, TernaryOp, TryOp, WhileOp>, ReturnLike, Terminator
Interfaces: RegionBranchTerminatorOpInterface
Operands:
| Operand | Description |
|---|---|
args | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR type that represents pointer-to-data-member type in C++ or CIR type that represents C++ pointer-to-member-function type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR record type or CIR exception info 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 complex type or CIR type that is used for the vptr member of C++ objects |
cir.func (::cir::FuncOp)
Declare or define a function
Similar to mlir::FuncOp built-in:
Operations within the function cannot implicitly capture values defined outside of the function, i.e. Functions are
IsolatedFromAbove. All external references must use function arguments or attributes that establish a symbolic connection (e.g. symbols referenced by name via a string attribute like SymbolRefAttr). An external function declaration (used when referring to a function declared in some other module) has no body. While the MLIR textual form provides a nice inline syntax for function arguments, they are internally represented as “block arguments” to the first block in the region.Only dialect attribute names may be specified in the attribute dictionaries for function arguments, results, or the function itself.
The function linkage information is specified by linkage, as defined by GlobalLinkageKind attribute.
The calling_conv attribute specifies the calling convention of the function. The default calling convention is CallingConv::C.
A compiler builtin function must be marked as builtin for further processing when lowering from CIR.
The coroutine keyword is used to mark 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 verifier should, but do act on this keyword yet.
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 extra_attrs, which is an aggregate of function-specific attributes is required and mandatory to describle additional attributes that are not listed above. Though mandatory, the prining of the attribute can be omitted if it is empty.
The global_ctor indicates whether a function should execute before main() function, as specified by __attribute__((constructor)). A execution priority can also be specified global_ctor(<prio>). Similarly, for global destructors both global_dtor and global_dtor(<prio>) are available.
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 @another_func(...) cc(spir_kernel) extra(#fn_attr)
// 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
Interfaces: CIRGlobalValueInterface, CallableOpInterface, FunctionOpInterface, Symbol
Attributes:
| Attribute | MLIR Type | Description |
|---|---|---|
sym_name | ::mlir::StringAttr | string attribute |
global_visibility | ::cir::VisibilityAttr | Visibility attribute |
function_type | ::mlir::TypeAttr | type attribute of CIR function type |
builtin | ::mlir::UnitAttr | unit attribute |
coroutine | ::mlir::UnitAttr | unit attribute |
lambda | ::mlir::UnitAttr | unit attribute |
no_proto | ::mlir::UnitAttr | unit attribute |
dso_local | ::mlir::UnitAttr | unit attribute |
linkage | ::cir::GlobalLinkageKindAttr | linkage kind |
calling_conv | ::cir::CallingConvAttr | calling convention |
extra_attrs | ::cir::ExtraFuncAttributesAttr | Represents aggregated attributes for a function |
sym_visibility | ::mlir::StringAttr | string attribute |
comdat | ::mlir::UnitAttr | unit attribute |
arg_attrs | ::mlir::ArrayAttr | Array of dictionary attributes |
res_attrs | ::mlir::ArrayAttr | Array of dictionary attributes |
aliasee | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
global_ctor_priority | ::mlir::IntegerAttr | 32-bit signless integer attribute whose minimum value is 101 whose maximum value is 65535 |
global_dtor_priority | ::mlir::IntegerAttr | 32-bit signless integer attribute whose minimum value is 101 whose maximum value is 65535 |
annotations | ::mlir::ArrayAttr | array attribute |
cxx_special_member | ::mlir::Attribute | Marks a function as a CXX constructor or Marks a function as a CXX destructor or Marks a function as a CXX assignment operator |
ast | ::mlir::Attribute | AST Function attribute |