llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Sirui Mu (Lancern)

<details>
<summary>Changes</summary>

This patch adds support for the initialization of atomic aggregates with 
padding. The changes include:

  - During CIRGen, the type `_Atomic(T)` is represented by a CIR struct `{T, 
sint8[padding_size]}` if the size of `_Atomic(T)` does not match the size of 
`T`. `padding_size` is the difference between the size of `_Atomic(T)` and `T`.
  - CIRGen for the initialization process is updated to handle the 
initialization of such CIR struct values.

---
Full diff: https://github.com/llvm/llvm-project/pull/200668.diff


4 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenAtomic.cpp (+11-6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+23) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+7-1) 
- (modified) clang/test/CIR/CodeGen/atomic.c (+47) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp 
b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 3df0cd23d570e..0a961c177be8e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -124,9 +124,9 @@ class AtomicInfo {
   LValue projectValue() const {
     assert(lvalue.isSimple());
     Address addr = getAtomicAddress();
-    if (hasPadding()) {
-      cgf.cgm.errorNYI(loc, "AtomicInfo::projectValue: padding");
-    }
+    if (hasPadding())
+      addr = cgf.getBuilder().createGetMember(loc, addr, /*name=*/"value",
+                                              /*index=*/0);
 
     assert(!cir::MissingFeatures::opTBAA());
     return LValue::makeAddr(addr, getValueType(), lvalue.getBaseInfo());
@@ -262,9 +262,14 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const {
   if (!requiresMemSetZero(addr.getElementType()))
     return false;
 
-  cgf.cgm.errorNYI(loc,
-                   "AtomicInfo::emitMemSetZeroIfNecaessary: emit memset zero");
-  return false;
+  addr = addr.withElementType(cgf.getBuilder(), cgf.cgm.voidTy);
+  mlir::Value zero = cgf.getBuilder().getConstInt(loc, cgf.cgm.uInt8Ty, 0);
+  mlir::Value memSetSize = cgf.getBuilder().getConstInt(
+      loc, cgf.cgm.uInt64Ty,
+      cgf.getContext().toCharUnitsFromBits(atomicSizeInBits).getQuantity());
+
+  cgf.getBuilder().createMemSet(loc, addr, zero, memSetSize);
+  return true;
 }
 
 /// Return true if \param valueTy is a type that should be casted to integer
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index aeb1a122429e2..e78c8928de854 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -692,6 +692,29 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
                    addr.getAlignment()};
   }
 
+  using CIRBaseBuilderTy::createGetMember;
+  Address createGetMember(mlir::Location loc, Address base,
+                          llvm::StringRef name, unsigned index) {
+    auto recordTy = mlir::cast<cir::RecordType>(base.getElementType());
+
+    assert(index < recordTy.getMembers().size() &&
+           "member index out of bounds");
+    mlir::Type memberTy = recordTy.getMembers()[index];
+    mlir::Type memberPtrTy = getPointerTo(memberTy);
+
+    auto moduleOp =
+        getInsertionBlock()->getParentOp()->getParentOfType<mlir::ModuleOp>();
+    mlir::DataLayout layout(moduleOp);
+    auto memberOffset =
+        CharUnits::fromQuantity(recordTy.getElementOffset(layout, index));
+
+    mlir::Value memberPtr =
+        createGetMember(loc, memberPtrTy, base.getBasePointer(), name, index);
+    return Address(memberPtr, memberTy,
+                   base.getAlignment().alignmentAtOffset(memberOffset),
+                   base.isKnownNonNull());
+  }
+
   cir::GetRuntimeMemberOp createGetIndirectMember(mlir::Location loc,
                                                   mlir::Value objectPtr,
                                                   mlir::Value memberPtr) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 61e2365bd5255..e6452f8592d22 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -639,7 +639,13 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
     uint64_t valueSize = astContext.getTypeSize(valueType);
     uint64_t atomicSize = astContext.getTypeSize(ty);
     if (valueSize != atomicSize) {
-      cgm.errorNYI("convertType: atomic type value size != atomic size");
+      assert(valueSize < atomicSize);
+      auto paddingArray =
+          cir::ArrayType::get(cgm.sInt8Ty, (atomicSize - valueSize) / 8);
+      mlir::Type elements[] = {resultType, paddingArray};
+      resultType = cir::RecordType::get(&getMLIRContext(), 
/*members=*/elements,
+                                        /*packed=*/false, /*padded=*/false,
+                                        /*kind=*/cir::RecordType::Struct);
     }
 
     break;
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index e4f3fe82310a4..aae9792ba2b76 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -5,6 +5,10 @@
 // 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
 
+struct S1 {
+  short x, y, z;
+};
+
 _Atomic int g1;
 _Atomic int g2 = 42;
 // CIR: cir.global external @g2 = #cir.int<42> : !s32i {alignment = 4 : i64}
@@ -83,6 +87,49 @@ void f4(_Atomic(float) *p) {
 // OGCG-LABEL: @f4
 // OGCG: store atomic float 3.140000e+00, ptr %{{.+}} seq_cst, align 4
 
+void init_with_padding(_Atomic struct S1 *p) {
+  // CIR-LABEL: @init_with_padding
+  // LLVM-LABEL: @init_with_padding
+  // OGCG-LABEL: @init_with_padding
+
+  __c11_atomic_init(p, (struct S1){1, 2, 3});
+
+  // CIR:      %[[PTR_VOID:.+]] = cir.cast bitcast %[[PTR:.+]] : 
!cir.ptr<!rec_anon_struct> -> !cir.ptr<!void>
+  // CIR-NEXT: %[[MEMSET_VALUE:.+]] = cir.const #cir.int<0> : !u8i
+  // CIR-NEXT: %[[MEMSET_SIZE:.+]] = cir.const #cir.int<8> : !u64i
+  // CIR-NEXT: cir.libc.memset %[[MEMSET_SIZE]] bytes at %[[PTR_VOID]] 
align(8) to %[[MEMSET_VALUE]] : !cir.ptr<!void>, !u8i, !u64i
+  // CIR-NEXT: %[[VALUE_PTR:.+]] = cir.get_member %[[PTR]][0] {name = "value"} 
: !cir.ptr<!rec_anon_struct> -> !cir.ptr<!rec_S1>
+  // CIR-NEXT: %[[X_PTR:.+]] = cir.get_member %[[VALUE_PTR]][0] {name = "x"} : 
!cir.ptr<!rec_S1> -> !cir.ptr<!s16i>
+  // CIR-NEXT: %[[X_INIT:.+]] = cir.const #cir.int<1> : !s16i
+  // CIR-NEXT: cir.store align(8) %[[X_INIT]], %[[X_PTR]] : !s16i, 
!cir.ptr<!s16i>
+  // CIR-NEXT: %[[Y_PTR:.+]] = cir.get_member %[[VALUE_PTR]][1] {name = "y"} : 
!cir.ptr<!rec_S1> -> !cir.ptr<!s16i>
+  // CIR-NEXT: %[[Y_INIT:.+]] = cir.const #cir.int<2> : !s16i
+  // CIR-NEXT: cir.store align(2) %[[Y_INIT]], %[[Y_PTR]] : !s16i, 
!cir.ptr<!s16i>
+  // CIR-NEXT: %[[Z_PTR:.+]] = cir.get_member %[[VALUE_PTR]][2] {name = "z"} : 
!cir.ptr<!rec_S1> -> !cir.ptr<!s16i>
+  // CIR-NEXT: %[[Z_INIT:.+]] = cir.const #cir.int<3> : !s16i
+  // CIR-NEXT: cir.store align(4) %[[Z_INIT]], %[[Z_PTR]] : !s16i, 
!cir.ptr<!s16i>
+
+  // LLVM:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // LLVM-NEXT: call void @llvm.memset.p0.i64(ptr align 8 %[[PTR]], i8 0, i64 
8, i1 false)
+  // LLVM-NEXT: %[[VALUE_PTR:.+]] = getelementptr inbounds nuw { %struct.S1, 
[2 x i8] }, ptr %[[PTR]], i32 0, i32 0
+  // LLVM-NEXT: %[[X_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr 
%[[VALUE_PTR]], i32 0, i32 0
+  // LLVM-NEXT: store i16 1, ptr %[[X_PTR]], align 8
+  // LLVM-NEXT: %[[Y_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr 
%[[VALUE_PTR]], i32 0, i32 1
+  // LLVM-NEXT: store i16 2, ptr %[[Y_PTR]], align 2
+  // LLVM-NEXT: %[[Z_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr 
%[[VALUE_PTR]], i32 0, i32 2
+  // LLVM-NEXT: store i16 3, ptr %[[Z_PTR]], align 4
+
+  // OGCG:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // OGCG-NEXT: call void @llvm.memset.p0.i64(ptr align 8 %[[PTR]], i8 0, i64 
8, i1 false)
+  // OGCG-NEXT: %[[VALUE_PTR:.+]] = getelementptr inbounds nuw { %struct.S1, 
[2 x i8] }, ptr %[[PTR]], i32 0, i32 0
+  // OGCG-NEXT: %[[X_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr 
%[[VALUE_PTR]], i32 0, i32 0
+  // OGCG-NEXT: store i16 1, ptr %[[X_PTR]], align 8
+  // OGCG-NEXT: %[[Y_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr 
%[[VALUE_PTR]], i32 0, i32 1
+  // OGCG-NEXT: store i16 2, ptr %[[Y_PTR]], align 2
+  // OGCG-NEXT: %[[Z_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr 
%[[VALUE_PTR]], i32 0, i32 2
+  // OGCG-NEXT: store i16 3, ptr %[[Z_PTR]], align 4
+}
+
 void atomic_to_non_atomic(_Atomic int *ptr, _Atomic volatile int *vptr) {
   // CIR-LABEL: @atomic_to_non_atomic
   // LLVM-LABEL: @atomic_to_non_atomic

``````````

</details>


https://github.com/llvm/llvm-project/pull/200668
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to