[clang] [CIR] Implement Aggregate atomic to non-atomic cast (PR #206322)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 28 03:04:04 PDT 2026
https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/206322
Implement support for the Aggregate atomic to non-atomic cast
>From 41289ffba3513cbb1a85aea394a9ae51f354ea27 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sun, 28 Jun 2026 12:03:10 +0200
Subject: [PATCH] [CIR] Implement Aggregate atomic to non-atomic cast
---
clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 27 +++++-----
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 10 ++--
clang/test/CIR/CodeGen/agg-atomic-cast.c | 50 +++++++++++++++++++
clang/test/CIR/CodeGen/agg-atomic-cast.cpp | 27 ----------
4 files changed, 68 insertions(+), 46 deletions(-)
create mode 100644 clang/test/CIR/CodeGen/agg-atomic-cast.c
delete mode 100644 clang/test/CIR/CodeGen/agg-atomic-cast.cpp
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 4d774761b975a..42e027887b9c4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -112,8 +112,8 @@ class AtomicInfo {
Address convertToAtomicIntPointer(Address addr) const;
/// Turn an atomic-layout object into an r-value.
- RValue convertAtomicTempToRValue(Address addr, SourceLocation loc,
- bool asValue) const;
+ RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
+ SourceLocation loc, bool asValue) const;
/// Converts a rvalue to integer value.
mlir::Value convertRValueToInt(RValue rvalue, mlir::Location loc,
@@ -211,15 +211,13 @@ Address AtomicInfo::convertToAtomicIntPointer(Address addr) const {
return castToAtomicIntPointer(addr);
}
-RValue AtomicInfo::convertAtomicTempToRValue(Address addr, SourceLocation loc,
+RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
+ AggValueSlot resultSlot,
+ SourceLocation loc,
bool asValue) const {
if (lvalue.isSimple()) {
- if (evaluationKind == TEK_Aggregate) {
- cgf.cgm.errorNYI(
- loc,
- "AtomicInfo::convertAtomicTempToRValue: evaluationKind is aggregate");
- return RValue::get(nullptr);
- }
+ if (evaluationKind == TEK_Aggregate)
+ return resultSlot.asRValue();
// Drill into the padding structure if we have one.
if (hasPadding()) {
@@ -384,17 +382,20 @@ RValue AtomicInfo::convertToValueOrAtomic(mlir::Value intVal,
// Create a temporary. This needs to be big enough to hold the
// atomic integer.
Address temp = Address::invalid();
+ bool tempIsVolatile = false;
if (asValue && getEvaluationKind() == TEK_Aggregate) {
- cgf.cgm.errorNYI("convertToValueOrAtomic: temporary aggregate");
- return RValue::get(nullptr);
+ assert(!resultSlot.isIgnored());
+ temp = resultSlot.getAddress();
+ tempIsVolatile = resultSlot.isVolatile();
} else {
temp = createTempAlloca();
}
// Slam the integer into the temporary.
Address castTemp = castToAtomicIntPointer(temp);
- cgf.getBuilder().createStore(cgf.getLoc(loc), intVal, castTemp);
- return convertAtomicTempToRValue(temp, loc, asValue);
+ cgf.getBuilder().createStore(cgf.getLoc(loc), intVal, castTemp,
+ tempIsVolatile);
+ return convertAtomicTempToRValue(temp, resultSlot, loc, asValue);
}
/// Copy an r-value into memory as part of storing to an atomic type.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 4d54519e4d25f..75435696ef915 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -262,11 +262,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
case CK_NonAtomicToAtomic:
case CK_AtomicToNonAtomic: {
bool isToAtomic = (e->getCastKind() == CK_NonAtomicToAtomic);
- if (!isToAtomic) {
- cgf.cgm.errorNYI(e->getSourceRange(),
- "AggExprEmitter: CK_AtomicToNonAtomic");
- return;
- }
// Determine the atomic and value types.
QualType atomicType = e->getSubExpr()->getType();
@@ -691,7 +686,10 @@ void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
LValue lv = cgf.emitLValue(e);
// If the type of the l-value is atomic, then do an atomic load.
- assert(!cir::MissingFeatures::opLoadStoreAtomic());
+ if (lv.getType()->isAtomicType() || cgf.isLValueSuitableForInlineAtomic(lv)) {
+ cgf.emitAtomicLoad(lv, e->getExprLoc(), dest);
+ return;
+ }
emitFinalDestCopy(e->getType(), lv);
}
diff --git a/clang/test/CIR/CodeGen/agg-atomic-cast.c b/clang/test/CIR/CodeGen/agg-atomic-cast.c
new file mode 100644
index 0000000000000..f9af8ae317e03
--- /dev/null
+++ b/clang/test/CIR/CodeGen/agg-atomic-cast.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+typedef struct S {
+ int x;
+} S;
+
+void non_atomic_to_atomic_cast() {
+ S s;
+ _Atomic(S) as = s;
+}
+
+// CIR: %[[S_ADDR:.*]] = cir.alloca "s" {{.*}} : !cir.ptr<!rec_S>
+// CIR: %[[SA_ADDR:.*]] = cir.alloca "as" {{.*}} init : !cir.ptr<!rec_S>
+// CIR: cir.copy %[[S_ADDR]] to %[[SA_ADDR]] : !cir.ptr<!rec_S>
+
+// LLVM: %[[S_ADDR:.*]] = alloca %struct.S, i64 1, align 4
+// LLVM: %[[SA_ADDR:.*]] = alloca %struct.S, i64 1, align 4
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[SA_ADDR]], ptr %[[S_ADDR]], i64 4, i1 false)
+
+// OGCG: %[[S_ADDR:.*]] = alloca %struct.S, align 4
+// OGCG: %[[SA_ADDR:.*]] = alloca %struct.S, align 4
+// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[SA_ADDR]], ptr align 4 %[[S_ADDR]], i64 4, i1 false)
+
+void atomic_to_non_atomic_cast() {
+ _Atomic S as;
+ S s;
+ s = as;
+}
+
+// CIR: %[[AS_ADDR:.*]] = cir.alloca "as" {{.*}} : !cir.ptr<!rec_S>
+// CIR: %[[S_ADDR:.*]] = cir.alloca "s" {{.*}} : !cir.ptr<!rec_S>
+// CIR: %[[SA_PTR:.*]] = cir.cast bitcast %[[AS_ADDR]] : !cir.ptr<!rec_S> -> !cir.ptr<!u32i>
+// CIR: %[[ATOMIC_LOAD:.*]] = cir.load {{.*}} atomic(seq_cst) %[[SA_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[S_PTR:.*]] = cir.cast bitcast %[[S_ADDR]] : !cir.ptr<!rec_S> -> !cir.ptr<!u32i>
+// CIR: cir.store {{.*}} %[[ATOMIC_LOAD]], %[[S_PTR]] : !u32i, !cir.ptr<!u32i>
+
+// LLVM: %[[AS_ADDR:.*]] = alloca %struct.S, i64 1, align 4
+// LLVM: %[[S_ADDR:.*]] = alloca %struct.S, i64 1, align 4
+// LLVM: %[[ATOMIC_LOAD:.*]] = load atomic i32, ptr %[[AS_ADDR]] seq_cst, align 4
+// LLVM: store i32 %[[ATOMIC_LOAD]], ptr %[[S_ADDR]], align 4
+
+// OGCG: %[[AS_ADDR:.*]] = alloca %struct.S, align 4
+// OGCG: %[[S_ADDR:.*]] = alloca %struct.S, align 4
+// OGCG: %[[ATOMIC_LOAD:.*]] = load atomic i32, ptr %[[AS_ADDR]] seq_cst, align 4
+// OGCG: store i32 %[[ATOMIC_LOAD]], ptr %[[S_ADDR]], align 4
diff --git a/clang/test/CIR/CodeGen/agg-atomic-cast.cpp b/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
deleted file mode 100644
index 12ed04f14edf2..0000000000000
--- a/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
-// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
-// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
-
-struct S {
- int data[4];
-};
-
-void non_atomic_to_atomic_cast() {
- S s;
- _Atomic(S) as = s;
-}
-
-// CIR: %[[S_ADDR:.*]] = cir.alloca "s" {{.*}} : !cir.ptr<!rec_S>
-// CIR: %[[SA_ADDR:.*]] = cir.alloca "as" {{.*}} init : !cir.ptr<!rec_S>
-// CIR: cir.copy %[[S_ADDR]] to %[[SA_ADDR]] : !cir.ptr<!rec_S>
-
-// LLVM: %[[S_ADDR:.*]] = alloca %struct.S, i64 1, align 4
-// LLVM: %[[SA_ADDR:.*]] = alloca %struct.S, i64 1, align 16
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[SA_ADDR]], ptr %[[S_ADDR]], i64 16, i1 false)
-
-// OGCG: %[[S_ADDR:.*]] = alloca %struct.S, align 4
-// OGCG: %[[SA_ADDR:.*]] = alloca %struct.S, align 16
-// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[SA_ADDR]], ptr align 4 %[[S_ADDR]], i64 16, i1 false)
More information about the cfe-commits
mailing list