[clang] [CIR] Implement Aggregate non-atomic to atomic cast (PR #204653)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 18 10:49:41 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
Implement support for Aggregate non-atomic to atomic cast
---
Full diff: https://github.com/llvm/llvm-project/pull/204653.diff
4 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+31)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+3)
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+9)
- (added) clang/test/CIR/CodeGen/agg-atomic-cast.cpp (+27)
``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 44f481508cd7e..23f62f4688f02 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -258,6 +258,37 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
break;
}
+
+ 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();
+ QualType valueType = e->getType();
+ if (isToAtomic)
+ std::swap(atomicType, valueType);
+
+ assert(atomicType->isAtomicType());
+ assert(cgf.getContext().hasSameUnqualifiedType(
+ valueType, atomicType->castAs<AtomicType>()->getValueType()));
+
+ // Just recurse normally if we're ignoring the result or the
+ // atomic type doesn't change representation.
+ if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(atomicType)) {
+ return Visit(e->getSubExpr());
+ }
+
+ cgf.cgm.errorNYI(
+ e->getSourceRange(),
+ "AggExprEmitter: AtomicCast not ignored or has padded atomic type");
+ return;
+ }
case CK_LValueToRValue:
// If we're loading from a volatile type, force the destination
// into existence.
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index fa166c1f39b69..0883a6b891c61 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -823,6 +823,9 @@ class CIRGenModule : public CIRGenTypeCache {
return *openMPRuntime;
}
+ bool isPaddedAtomicType(QualType type);
+ bool isPaddedAtomicType(const AtomicType *type);
+
mlir::IntegerAttr getSize(CharUnits size) {
return builder.getSizeFromCharUnits(size);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index ea37d82c82d79..3170666304a06 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -226,6 +226,15 @@ static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
return isSafeToConvert(rd, cgt, alreadyChecked);
}
+bool CIRGenModule::isPaddedAtomicType(QualType type) {
+ return isPaddedAtomicType(type->castAs<AtomicType>());
+}
+
+bool CIRGenModule::isPaddedAtomicType(const AtomicType *type) {
+ return astContext.getTypeSize(type) !=
+ astContext.getTypeSize(type->getValueType());
+}
+
/// Lay out a tagged decl type like struct or union.
mlir::Type CIRGenTypes::convertRecordDeclType(const clang::RecordDecl *rd) {
// TagDecl's are not necessarily unique, instead use the (clang) type
diff --git a/clang/test/CIR/CodeGen/agg-atomic-cast.cpp b/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
new file mode 100644
index 0000000000000..12ed04f14edf2
--- /dev/null
+++ b/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
@@ -0,0 +1,27 @@
+// 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)
``````````
</details>
https://github.com/llvm/llvm-project/pull/204653
More information about the cfe-commits
mailing list