llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Sirui Mu (Lancern) <details> <summary>Changes</summary> This patch updates the definitions of `cir.atomic.xchg` and `cir.atomic.cmpxchg` to make them follow the established CIR assembly conventions. Some other minor changes are also made along the way: - The verifier for `cir.atomic.cmpxchg` is now fully declared in TableGen. - The `Op` suffix is appended to `CIR_AtomicXchg` and `CIR_AtomicCmpXchg` to follow the naming conventions for TableGen operation records. --- Full diff: https://github.com/llvm/llvm-project/pull/161543.diff 7 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+15-23) - (modified) clang/lib/CIR/CodeGen/CIRGenAtomic.cpp (+2-2) - (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+48-14) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+4-4) - (modified) clang/test/CIR/CodeGen/atomic.c (+6-6) - (modified) clang/test/CIR/IR/atomic.cir (+13) - (added) clang/test/CIR/IR/invalid-atomic.cir (+29) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index f857cf82a5192..41c921df091d9 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4151,7 +4151,7 @@ def CIR_ThrowOp : CIR_Op<"throw"> { // Atomic operations //===----------------------------------------------------------------------===// -def CIR_AtomicXchg : CIR_Op<"atomic.xchg", [ +def CIR_AtomicXchgOp : CIR_Op<"atomic.xchg", [ AllTypesMatch<["result", "val"]>, TypesMatchWith<"type of 'val' must match the pointee type of 'ptr'", "ptr", "val", "mlir::cast<cir::PointerType>($_self).getPointee()"> @@ -4169,9 +4169,7 @@ def CIR_AtomicXchg : CIR_Op<"atomic.xchg", [ Example: ```mlir - %res = cir.atomic.xchg(%ptr : !cir.ptr<!u64i>, - %val : !u64i, - seq_cst) : !u64i + %res = cir.atomic.xchg seq_cst %ptr, %val : !cir.ptr<!u64i> -> !u64i ``` }]; @@ -4190,8 +4188,12 @@ def CIR_AtomicXchg : CIR_Op<"atomic.xchg", [ }]; } -def CIR_AtomicCmpXchg : CIR_Op<"atomic.cmpxchg", [ - AllTypesMatch<["old", "expected", "desired"]> +def CIR_AtomicCmpXchgOp : CIR_Op<"atomic.cmpxchg", [ + AllTypesMatch<["old", "expected", "desired"]>, + TypesMatchWith<"type of 'expected' must match the pointee type of 'ptr'", + "ptr", "expected", "mlir::cast<cir::PointerType>($_self).getPointee()">, + TypesMatchWith<"type of 'desired' must match the pointee type of 'ptr'", + "ptr", "desired", "mlir::cast<cir::PointerType>($_self).getPointee()"> ]> { let summary = "Atomic compare and exchange"; let description = [{ @@ -4224,12 +4226,8 @@ def CIR_AtomicCmpXchg : CIR_Op<"atomic.cmpxchg", [ Example: ```mlir - %old, %success = cir.atomic.cmpxchg(%ptr : !cir.ptr<!u64i>, - %expected : !u64i, - %desired : !u64i, - success = seq_cst, - failure = seq_cst) weak - : (!u64i, !cir.bool) + %old, %success = cir.atomic.cmpxchg weak seq_cst %ptr, %expected, %desired : !cir.ptr<!u64i> -> (!u64i, !cir.bool) + %old, %success = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %ptr, %expected, %desired : !cir.ptr<!u64i> -> (!u64i, !cir.bool) ``` }]; let results = (outs CIR_AnyType:$old, CIR_BoolType:$success); @@ -4243,20 +4241,14 @@ def CIR_AtomicCmpXchg : CIR_Op<"atomic.cmpxchg", [ UnitAttr:$is_volatile); let assemblyFormat = [{ - `(` - $ptr `:` qualified(type($ptr)) `,` - $expected `:` type($expected) `,` - $desired `:` type($desired) `,` - `success` `=` $succ_order `,` - `failure` `=` $fail_order - `)` - (`align` `(` $alignment^ `)`)? (`weak` $weak^)? + custom<AtomicCmpXchgMemOrder>($succ_order, $fail_order) + $ptr `,` $expected `,` $desired + (`align` `(` $alignment^ `)`)? (`volatile` $is_volatile^)? - `:` `(` type($old) `,` type($success) `)` attr-dict + `:` qualified(type($ptr)) `->` `(` type($old) `,` type($success) `)` + attr-dict }]; - - let hasVerifier = 1; } #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index e943b0252bf4e..daa5bf9905df5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -255,7 +255,7 @@ static void emitAtomicCmpXchg(CIRGenFunction &cgf, AtomicExpr *e, bool isWeak, mlir::Value expected = builder.createLoad(loc, val1); mlir::Value desired = builder.createLoad(loc, val2); - auto cmpxchg = cir::AtomicCmpXchg::create( + auto cmpxchg = cir::AtomicCmpXchgOp::create( builder, loc, expected.getType(), builder.getBoolTy(), ptr.getPointer(), expected, desired, cir::MemOrderAttr::get(&cgf.getMLIRContext(), successOrder), @@ -404,7 +404,7 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest, case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__atomic_exchange: - opName = cir::AtomicXchg::getOperationName(); + opName = cir::AtomicXchgOp::getOperationName(); break; case AtomicExpr::AO__opencl_atomic_init: diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index fb87036fdfe21..caa39e88de1ec 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -235,6 +235,54 @@ static void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer, /*printBlockTerminators=*/!omitRegionTerm(region)); } +static mlir::ParseResult +parseAtomicCmpXchgMemOrder(mlir::OpAsmParser &parser, + cir::MemOrderAttr &successOrder, + cir::MemOrderAttr &failureOrder) { + auto parseMemOrder = [&](cir::MemOrderAttr *output) -> mlir::ParseResult { + mlir::SMLoc loc = parser.getCurrentLocation(); + llvm::StringRef memOrderStr; + if (parser.parseKeyword(&memOrderStr)) + return failure(); + std::optional<cir::MemOrder> memOrder = symbolizeMemOrder(memOrderStr); + if (!memOrder.has_value()) + return parser.emitError(loc, "unknown memory order \"") + << memOrderStr << "\""; + *output = cir::MemOrderAttr::get(parser.getContext(), *memOrder); + return success(); + }; + + if (parser.parseOptionalKeyword("success")) { + // No "success" keyword found. successOrder and failureOrder will have the + // same value. + if (parseMemOrder(&successOrder)) + return failure(); + failureOrder = successOrder; + return success(); + } + + if (parser.parseLParen() || parseMemOrder(&successOrder) || + parser.parseRParen()) + return failure(); + + if (parser.parseKeyword("failure") || parser.parseLParen() || + parseMemOrder(&failureOrder) || parser.parseRParen()) + return failure(); + + return success(); +} + +static void printAtomicCmpXchgMemOrder(mlir::OpAsmPrinter &printer, + cir::AtomicCmpXchgOp &op, + cir::MemOrderAttr successOrder, + cir::MemOrderAttr failureOrder) { + if (successOrder.getValue() == failureOrder.getValue()) + printer << stringifyMemOrder(successOrder.getValue()); + else + printer << "success(" << stringifyMemOrder(successOrder.getValue()) << ") " + << "failure(" << stringifyMemOrder(failureOrder.getValue()) << ")"; +} + //===----------------------------------------------------------------------===// // AllocaOp //===----------------------------------------------------------------------===// @@ -2817,20 +2865,6 @@ mlir::LogicalResult cir::ThrowOp::verify() { return failure(); } -//===----------------------------------------------------------------------===// -// AtomicCmpXchg -//===----------------------------------------------------------------------===// - -LogicalResult cir::AtomicCmpXchg::verify() { - mlir::Type pointeeType = getPtr().getType().getPointee(); - - if (pointeeType != getExpected().getType() || - pointeeType != getDesired().getType()) - return emitOpError("ptr, expected and desired types must match"); - - return success(); -} - //===----------------------------------------------------------------------===// // TypeInfoAttr //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 22f069d9cead0..064a39fd822d7 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -693,8 +693,8 @@ getLLVMMemOrder(std::optional<cir::MemOrder> memorder) { llvm_unreachable("unknown memory order"); } -mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite( - cir::AtomicCmpXchg op, OpAdaptor adaptor, +mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite( + cir::AtomicCmpXchgOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Value expected = adaptor.getExpected(); mlir::Value desired = adaptor.getDesired(); @@ -718,8 +718,8 @@ mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite( return mlir::success(); } -mlir::LogicalResult CIRToLLVMAtomicXchgLowering::matchAndRewrite( - cir::AtomicXchg op, OpAdaptor adaptor, +mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite( + cir::AtomicXchgOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { assert(!cir::MissingFeatures::atomicSyncScopeID()); mlir::LLVM::AtomicOrdering llvmOrder = getLLVMMemOrder(adaptor.getMemOrder()); diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c index 76289c597a2b5..228457376cf58 100644 --- a/clang/test/CIR/CodeGen/atomic.c +++ b/clang/test/CIR/CodeGen/atomic.c @@ -211,7 +211,7 @@ void c11_atomic_cmpxchg_strong(_Atomic(int) *ptr, int *expected, int desired) { __c11_atomic_compare_exchange_strong(ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); - // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) : (!s32i, !cir.bool) + // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : !cir.ptr<!s32i> -> (!s32i, !cir.bool) // CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool // CIR-NEXT: cir.if %[[FAILED]] { // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i> @@ -249,7 +249,7 @@ void c11_atomic_cmpxchg_weak(_Atomic(int) *ptr, int *expected, int desired) { __c11_atomic_compare_exchange_weak(ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); - // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) weak : (!s32i, !cir.bool) + // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : !cir.ptr<!s32i> -> (!s32i, !cir.bool) // CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool // CIR-NEXT: cir.if %[[FAILED]] { // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i> @@ -286,7 +286,7 @@ void atomic_cmpxchg(int *ptr, int *expected, int *desired) { // OGCG-LABEL: @atomic_cmpxchg __atomic_compare_exchange(ptr, expected, desired, /*weak=*/0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); - // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) : (!s32i, !cir.bool) + // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : !cir.ptr<!s32i> -> (!s32i, !cir.bool) // CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool // CIR-NEXT: cir.if %[[FAILED]] { // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i> @@ -317,7 +317,7 @@ void atomic_cmpxchg(int *ptr, int *expected, int *desired) { // OGCG-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1 __atomic_compare_exchange(ptr, expected, desired, /*weak=*/1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); - // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) weak : (!s32i, !cir.bool) + // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : !cir.ptr<!s32i> -> (!s32i, !cir.bool) // CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool // CIR-NEXT: cir.if %[[FAILED]] { // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i> @@ -354,7 +354,7 @@ void atomic_cmpxchg_n(int *ptr, int *expected, int desired) { // OGCG-LABEL: @atomic_cmpxchg_n __atomic_compare_exchange_n(ptr, expected, desired, /*weak=*/0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); - // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) : (!s32i, !cir.bool) + // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : !cir.ptr<!s32i> -> (!s32i, !cir.bool) // CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool // CIR-NEXT: cir.if %[[FAILED]] { // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i> @@ -385,7 +385,7 @@ void atomic_cmpxchg_n(int *ptr, int *expected, int desired) { // OGCG-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1 __atomic_compare_exchange_n(ptr, expected, desired, /*weak=*/1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); - // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) weak : (!s32i, !cir.bool) + // CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : !cir.ptr<!s32i> -> (!s32i, !cir.bool) // CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool // CIR-NEXT: cir.if %[[FAILED]] { // CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i> diff --git a/clang/test/CIR/IR/atomic.cir b/clang/test/CIR/IR/atomic.cir index 6ca5af2aac175..e04019762c034 100644 --- a/clang/test/CIR/IR/atomic.cir +++ b/clang/test/CIR/IR/atomic.cir @@ -19,3 +19,16 @@ cir.func @atomic_xchg(%ptr: !cir.ptr<!s32i>, %val: !s32i) { // CHECK: cir.atomic.xchg seq_cst %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i cir.return } + +cir.func @atomic_cmpxchg(%ptr: !cir.ptr<!s32i>, %expected: !s32i, %desired: !s32i) { + // CHECK-LABEL: @atomic_cmpxchg + %0, %1 = cir.atomic.cmpxchg relaxed %ptr, %expected, %desired : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + // CHECK: cir.atomic.cmpxchg relaxed %{{.+}}, %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + %2, %3 = cir.atomic.cmpxchg weak relaxed %ptr, %expected, %desired : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + // CHECK: cir.atomic.cmpxchg weak relaxed %{{.+}}, %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + %4, %5 = cir.atomic.cmpxchg success(seq_cst) failure(acquire) %ptr, %expected, %desired : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + // CHECK: cir.atomic.cmpxchg success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + %6, %7 = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %ptr, %expected, %desired : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + // CHECK: cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + cir.return +} diff --git a/clang/test/CIR/IR/invalid-atomic.cir b/clang/test/CIR/IR/invalid-atomic.cir new file mode 100644 index 0000000000000..6da4c72996bc2 --- /dev/null +++ b/clang/test/CIR/IR/invalid-atomic.cir @@ -0,0 +1,29 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +!s32i = !cir.int<s, 32> + +cir.func @f1(%ptr: !cir.ptr<!s32i>, %expected: !s32i, %desired: !s32i) { + // expected-error @below {{custom op 'cir.atomic.cmpxchg' expected valid keyword}} + %0, %1 = cir.atomic.cmpxchg %ptr, %expected, %desired : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + cir.return +} + +// ----- + +!s32i = !cir.int<s, 32> + +cir.func @f2(%ptr: !cir.ptr<!s32i>, %expected: !s32i, %desired: !s32i) { + // expected-error @below {{unknown memory order "relax"}} + %0, %1 = cir.atomic.cmpxchg relax %ptr, %expected, %desired : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + cir.return +} + +// ----- + +!s32i = !cir.int<s, 32> + +cir.func @f3(%ptr: !cir.ptr<!s32i>, %expected: !s32i, %desired: !s32i) { + // expected-error @below {{custom op 'cir.atomic.cmpxchg' expected 'failure'}} + %0, %1 = cir.atomic.cmpxchg success(relaxed) %ptr, %expected, %desired : !cir.ptr<!s32i> -> (!s32i, !cir.bool) + cir.return +} `````````` </details> https://github.com/llvm/llvm-project/pull/161543 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
