@@ -4457,6 +4457,79 @@ def CIR_TryOp : CIR_Op<"try",[
44574457// Atomic operations
44584458//===----------------------------------------------------------------------===//
44594459
4460+ def CIR_AtomicFetchKind : CIR_I32EnumAttr<
4461+ "AtomicFetchKind", "Binary opcode for atomic fetch-and-update operations", [
4462+ I32EnumAttrCase<"Add", 0, "add">,
4463+ I32EnumAttrCase<"Sub", 1, "sub">,
4464+ I32EnumAttrCase<"And", 2, "and">,
4465+ I32EnumAttrCase<"Xor", 3, "xor">,
4466+ I32EnumAttrCase<"Or", 4, "or">,
4467+ I32EnumAttrCase<"Nand", 5, "nand">,
4468+ I32EnumAttrCase<"Max", 6, "max">,
4469+ I32EnumAttrCase<"Min", 7, "min">
4470+ ]>;
4471+
4472+ def CIR_AtomicFetchOp : CIR_Op<"atomic.fetch", [
4473+ AllTypesMatch<["result", "val"]>,
4474+ TypesMatchWith<"type of 'val' must match the pointee type of 'ptr'",
4475+ "ptr", "val", "mlir::cast<cir::PointerType>($_self).getPointee()">
4476+ ]> {
4477+ let summary = "Atomic fetch-and-update operation";
4478+ let description = [{
4479+ C/C++ atomic fetch-and-update operation. This operation implements the C/C++
4480+ builtin functions `__atomic_<binop>_fetch`, `__atomic_fetch_<binop>`, and
4481+ `__c11_atomic_fetch_<binop>`, where `<binop>` is one of the following binary
4482+ opcodes: `add`, `sub`, `and`, `xor`, `or`, `nand`, `max`, and `min`.
4483+
4484+ This operation takes 2 arguments: a pointer `ptr` and a value `val`. The
4485+ type of `val` must match the pointee type of `ptr`. If the binary operation
4486+ is `add`, `sub`, `max`, or `min`, the type of `val` may either be an integer
4487+ type or a floating-point type. Otherwise, `val` must be an integer.
4488+
4489+ This operation atomically loads the value from `ptr`, performs the binary
4490+ operation as indicated by `binop` on the loaded value and `val`, and stores
4491+ the result back to `ptr`. If the `fetch_first` flag is present, the result
4492+ of this operation is the old value loaded from `ptr` before the binary
4493+ operation. Otherwise, the result of this operation is the result of the
4494+ binary operation.
4495+
4496+ Example:
4497+ %res = cir.atomic.fetch add seq_cst %ptr, %val
4498+ : (!cir.ptr<!s32i>, !s32i) -> !s32i
4499+ }];
4500+ let results = (outs CIR_AnyIntOrFloatType:$result);
4501+ let arguments = (ins
4502+ Arg<CIR_PtrToIntOrFloatType, "", [MemRead, MemWrite]>:$ptr,
4503+ CIR_AnyIntOrFloatType:$val,
4504+ CIR_AtomicFetchKind:$binop,
4505+ Arg<CIR_MemOrder, "memory order">:$mem_order,
4506+ UnitAttr:$is_volatile,
4507+ UnitAttr:$fetch_first
4508+ );
4509+
4510+ let assemblyFormat = [{
4511+ $binop $mem_order
4512+ (`fetch_first` $fetch_first^)?
4513+ $ptr `,` $val
4514+ (`volatile` $is_volatile^)?
4515+ `:` `(` qualified(type($ptr)) `,` qualified(type($val)) `)`
4516+ `->` type($result) attr-dict
4517+ }];
4518+
4519+ let hasVerifier = 1;
4520+
4521+ let extraLLVMLoweringPatternDecl = [{
4522+ mlir::Value buildPostOp(cir::AtomicFetchOp op, OpAdaptor adaptor,
4523+ mlir::ConversionPatternRewriter &rewriter,
4524+ mlir::Value rmwVal, bool isInt) const;
4525+
4526+ mlir::Value buildMinMaxPostOp(cir::AtomicFetchOp op, OpAdaptor adaptor,
4527+ mlir::ConversionPatternRewriter &rewriter,
4528+ mlir::Value rmwVal, bool isInt,
4529+ bool isSigned) const;
4530+ }];
4531+ }
4532+
44604533def CIR_AtomicXchgOp : CIR_Op<"atomic.xchg", [
44614534 AllTypesMatch<["result", "val"]>,
44624535 TypesMatchWith<"type of 'val' must match the pointee type of 'ptr'",
0 commit comments