@@ -1492,6 +1492,55 @@ def CIR_BrCondOp : CIR_Op<"brcond", [
14921492 }];
14931493}
14941494
1495+ //===----------------------------------------------------------------------===//
1496+ // IndirectBrOp
1497+ //===----------------------------------------------------------------------===//
1498+
1499+ def CIR_IndirectBrOp : CIR_Op<"indirect_br", [
1500+ DeclareOpInterfaceMethods<BranchOpInterface>,
1501+ SameVariadicOperandSize, Terminator, Pure
1502+ ]> {
1503+ let summary = "Indirect branch";
1504+ let description = [{
1505+ The `cir.indirectbr` operation represents an indirect branch to one of
1506+ several possible successor blocks. The target block is computed from
1507+ the value of the given address operand.
1508+
1509+ This operation is typically generated when handling constructs like
1510+ the GCC extension `&&label` combined with an indirect `goto *ptr;`.
1511+
1512+ The `poison` attribute is used to mark an `indirectbr` that was created
1513+ but is known to be invalid, for instance when a label address was
1514+ taken but no indirect branch was ever emitted.
1515+
1516+ Example:
1517+
1518+ ```mlir
1519+ %0 = cir.block_address <@A, "A"> : !cir.ptr<!void>
1520+ cir.indirectbr %0 poison : <!void>, [
1521+ ^bb1
1522+ ]
1523+ ```
1524+ }];
1525+
1526+ let arguments = (ins
1527+ CIR_VoidPtrType:$addr,
1528+ UnitAttr:$poison,
1529+ VariadicOfVariadic<AnyType, "operand_segments">:$succ_operands,
1530+ DenseI32ArrayAttr:$operand_segments
1531+ );
1532+
1533+ let successors = (successor VariadicSuccessor<AnySuccessor>:$successors);
1534+ let assemblyFormat = [{
1535+ $addr ( `poison` $poison^ )? `:` qualified(type($addr)) `,`
1536+ custom<IndirectBrOpSucessors>(ref(type($addr)),
1537+ $successors,
1538+ $succ_operands,
1539+ type($succ_operands))
1540+ attr-dict
1541+ }];
1542+ }
1543+
14951544//===----------------------------------------------------------------------===//
14961545// Common loop op definitions
14971546//===----------------------------------------------------------------------===//
@@ -5188,6 +5237,11 @@ def CIR_AtomicFetchKind : CIR_I32EnumAttr<
51885237 I32EnumAttrCase<"Min", 7, "min">
51895238]>;
51905239
5240+ def CIR_SyncScopeKind : CIR_I32EnumAttr<"SyncScopeKind", "sync scope kind", [
5241+ I32EnumAttrCase<"SingleThread", 0, "single_thread">,
5242+ I32EnumAttrCase<"System", 1, "system">
5243+ ]>;
5244+
51915245def CIR_AtomicFetchOp : CIR_Op<"atomic.fetch", [
51925246 AllTypesMatch<["result", "val"]>,
51935247 TypesMatchWith<"type of 'val' must match the pointee type of 'ptr'",
@@ -5411,6 +5465,36 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> {
54115465 }];
54125466}
54135467
5468+ def CIR_AtomicFence : CIR_Op<"atomic.fence"> {
5469+ let summary = "Atomic thread fence";
5470+ let description = [{
5471+ C/C++ Atomic thread fence synchronization primitive. Implements the builtin
5472+ `__atomic_thread_fence` which enforces memory ordering constraints across
5473+ threads within the specified synchronization scope.
5474+
5475+ This handles all variations including:
5476+ - `__atomic_thread_fence`
5477+ - `__atomic_signal_fence`
5478+ - `__c11_atomic_thread_fence`
5479+ - `__c11_atomic_signal_fence`
5480+
5481+ Example:
5482+ ```mlir
5483+ cir.atomic.fence syncscope(system) seq_cst
5484+ cir.atomic.fence syncscope(single_thread) seq_cst
5485+ ```
5486+ }];
5487+
5488+ let arguments = (ins
5489+ Arg<CIR_MemOrder, "memory order">:$ordering,
5490+ OptionalAttr<CIR_SyncScopeKind>:$syncscope
5491+ );
5492+
5493+ let assemblyFormat = [{
5494+ (`syncscope` `(` $syncscope^ `)`)? $ordering attr-dict
5495+ }];
5496+ }
5497+
54145498//===----------------------------------------------------------------------===//
54155499// BlockAddressOp
54165500//===----------------------------------------------------------------------===//
0 commit comments