llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: adams381

<details>
<summary>Changes</summary>

`emitNewArrayInitializer` hit `errorNYI` for a value-initialized array new of
a trivially-constructible element -- `new T[n]()`, where the trailing
parentheses mean zero-initialization. The helper to do this already existed:
`tryMemsetInitialization()` (used by the string-init path) emits one zeroing
memset over the remaining elements, guarded by `isZeroInitializable`.

This routes the trivial-ctor branch through it, following classic CodeGen in
`CGExprCXX.cpp`. A zero-initializable element gets the `operator new[]` call
plus a single `memset` to 0. When the element isn't zero-initializable (an
array of pointers-to-data-member, whose null value is -1, not 0), the guard
declines the memset and we fall through to the existing constructor loop,
which value-initializes each element to `{0, -1}`. I also added the
`getParent()-&gt;isEmpty()` early return, since an empty class has nothing to
zero.

The test's lowered LLVM and OGCG checks are split only where CIR still omits
`align` on the memset and `noalias` on `operator new[]`; those are pre-existing
gaps, not part of this change.

Found building the SPEC CPU 2026 LLVM benchmark (723.llvm_r / 823.llvm_s) with
ClangIR.


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


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp (+3-4) 
- (added) clang/test/CIR/CodeGen/new-array-init.cpp (+94) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 1a565b077a2eb..3f394b8f1da64 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -1228,12 +1228,11 @@ void CIRGenFunction::emitNewArrayInitializer(
     if (ctor->isTrivial()) {
       // If new expression did not specify value-initialization, then there
       // is no initialization.
-      if (!cce->requiresZeroInitialization())
+      if (!cce->requiresZeroInitialization() || ctor->getParent()->isEmpty())
         return;
 
-      cgm.errorNYI(cce->getSourceRange(),
-                   "emitNewArrayInitializer: trivial ctor zero-init");
-      return;
+      if (tryMemsetInitialization())
+        return;
     }
 
     // Store the new Cleanup position for irregular Cleanups.
diff --git a/clang/test/CIR/CodeGen/new-array-init.cpp 
b/clang/test/CIR/CodeGen/new-array-init.cpp
new file mode 100644
index 0000000000000..e4f592dd0da64
--- /dev/null
+++ b/clang/test/CIR/CodeGen/new-array-init.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct S {
+  int a;
+  int b;
+};
+
+// Value-init array new of a trivial type: () means zero-init via memset.
+S *makeVar(unsigned n) { return new S[n](); }
+
+// CIR-LABEL: cir.func{{.*}}@_Z7makeVarj
+// CIR:   cir.call @_Znam(
+// CIR:   cir.libc.memset {{.*}} bytes at {{.*}} to
+
+// LLVM-LABEL: @_Z7makeVarj
+// LLVM:   call {{.*}} ptr @_Znam(
+// LLVM:   call void @llvm.memset.p0.i64(ptr %{{.*}}, i8 0, i64 %{{.*}}, i1 
false)
+
+// OGCG-LABEL: @_Z7makeVarj
+// OGCG:   call {{.*}} ptr @_Znam(
+// OGCG:   call void @llvm.memset.p0.i64(ptr align 8 %{{.*}}, i8 0, i64 
%{{.*}}, i1 false)
+
+// Constant element count: the size is folded to a constant.
+S *makeConst() { return new S[4](); }
+
+// CIR-LABEL: cir.func{{.*}}@_Z9makeConstv
+// CIR:   cir.call @_Znam(
+// CIR:   cir.libc.memset
+
+// LLVM-LABEL: @_Z9makeConstv
+// LLVM:   call {{.*}} ptr @_Znam(i64 noundef 32)
+// LLVM:   call void @llvm.memset.p0.i64(ptr %{{.*}}, i8 0, i64 32, i1 false)
+
+// OGCG-LABEL: @_Z9makeConstv
+// OGCG:   call {{.*}} ptr @_Znam(i64 noundef 32)
+// OGCG:   call void @llvm.memset.p0.i64(ptr align 8 %{{.*}}, i8 0, i64 32, i1 
false)
+
+// No parens: default-init of a trivial type is a no-op (no memset).
+S *makeNoInit(unsigned n) { return new S[n]; }
+
+// CIR-LABEL: cir.func{{.*}}@_Z10makeNoInitj
+// CIR:   cir.call @_Znam(
+// CIR-NOT: cir.libc.memset
+
+// LLVM-LABEL: @_Z10makeNoInitj
+// LLVM:   call {{.*}} ptr @_Znam(
+// LLVM-NOT: memset
+
+// OGCG-LABEL: @_Z10makeNoInitj
+// OGCG:   call {{.*}} ptr @_Znam(
+// OGCG-NOT: memset
+
+// Braced-empty value-init goes through the InitListExpr path (also memset).
+S *makeBraced(unsigned n) { return new S[n]{}; }
+
+// CIR-LABEL: cir.func{{.*}}@_Z10makeBracedj
+// CIR:   cir.call @_Znam(
+// CIR:   cir.libc.memset
+
+// LLVM-LABEL: @_Z10makeBracedj
+// LLVM:   call {{.*}} ptr @_Znam(
+// LLVM:   call void @llvm.memset.p0.i64(ptr %{{.*}}, i8 0, i64 %{{.*}}, i1 
false)
+
+// OGCG-LABEL: @_Z10makeBracedj
+// OGCG:   call {{.*}} ptr @_Znam(
+// OGCG:   call void @llvm.memset.p0.i64(ptr align 8 %{{.*}}, i8 0, i64 
%{{.*}}, i1 false)
+
+// Non-zero-initializable element (pointer to data member): the null member
+// representation is -1, not 0, so memset is not used; the constructor-loop
+// path value-initializes each element to {0, -1}.
+struct M {
+  int x;
+  int M::*p;
+};
+
+M *makeMember(unsigned n) { return new M[n](); }
+
+// CIR-LABEL: cir.func{{.*}}@_Z10makeMemberj
+// CIR:   cir.call @_Znam(
+// CIR-NOT: cir.libc.memset
+// CIR:   cir.const #cir.const_record<{#cir.int<0> : !s32i, #cir.int<-1> : 
!s64i}>
+
+// LLVM-LABEL: @_Z10makeMemberj
+// LLVM:   call {{.*}} ptr @_Znam(
+// LLVM:   store %struct.M { i32 0, i64 -1 }, ptr %{{.*}}
+
+// OGCG-LABEL: @_Z10makeMemberj
+// OGCG:   call {{.*}} ptr @_Znam(
+// OGCG:   call void @llvm.memcpy.p0.p0.i64(ptr align 16 %{{.*}}, ptr align 16 
@{{.*}}

``````````

</details>


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

Reply via email to