https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/178806

>From 284889dcb1164cafcc86b9b0d1b8e7ed19c766d2 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Thu, 29 Jan 2026 17:05:23 -0800
Subject: [PATCH 1/3] [CIR] Upstream support for array new with empty
 initializer list

This adds CIR support for array new with an empty initializer list for
zero-initializable types.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  35 ++++++
 clang/include/clang/CIR/MissingFeatures.h     |   1 +
 clang/lib/CIR/CodeGen/CIRGenBuilder.h         |   6 +
 clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp       | 114 +++++++++++++++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  12 ++
 clang/test/CIR/CodeGen/new.cpp                |  66 ++++++----
 6 files changed, 208 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index ee84df93b4933..b6db00e11c639 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3540,6 +3540,41 @@ def CIR_MemCpyOp : CIR_MemOp<"libc.memcpy"> {
 
 // TODO: MemMoveOp
 
+//===----------------------------------------------------------------------===//
+// MemSetOp
+//===----------------------------------------------------------------------===//
+
+def CIR_MemSetOp : CIR_Op<"libc.memset"> {
+  let summary = "Equivalent to libc's `memset`";
+  let description = [{
+    Given the CIR pointer, `dst`, `cir.libc.memset` will set the first `len`
+    bytes of the memory pointed by `dst` to the specified `val`.
+
+    Examples:
+
+    ```mlir
+      // Set 2 bytes from a record to 0:
+      %2 = cir.const #cir.int<2> : !u32i
+      %3 = cir.const #cir.int<0> : !u32i
+      %zero = cir.cast integral %3 : !s32i -> !u8i
+      cir.libc.memset %2 bytes from %record set to %zero : !cir.ptr<!void>,
+                                                           !s32i, !u64i
+    ```
+  }];
+
+  let arguments = (ins
+    Arg<CIR_VoidPtrType, "", [MemWrite]>:$dst,
+    CIR_SInt32:$val,
+    CIR_AnyFundamentalUIntType:$len
+  );
+
+  let assemblyFormat = [{
+    $len `bytes` `from` $dst `set` `to` $val attr-dict
+    `:` qualified(type($dst)) `,` type($val) `,` type($len)
+  }];
+}
+
+
 
//===----------------------------------------------------------------------===//
 // ReturnAddrOp and FrameAddrOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index cdd9fb950b8b2..12575f51366fa 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -238,6 +238,7 @@ struct MissingFeatures {
   static bool cleanupAfterErrorDiags() { return false; }
   static bool cleanupAppendInsts() { return false; }
   static bool cleanupBranchThrough() { return false; }
+  static bool cleanupDeactivationScope() { return false; }
   static bool cleanupIndexAndBIAdjustment() { return false; }
   static bool cleanupWithPreservedValues() { return false; }
   static bool cleanupsToDeactivate() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index dedb369bf3f67..51c5a238cf258 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -197,6 +197,12 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
                              mlir::Value src, mlir::Value len) {
     return cir::MemCpyOp::create(*this, loc, dst, src, len);
   }
+
+  cir::MemSetOp createMemSet(mlir::Location loc, mlir::Value dst,
+                             mlir::Value val, mlir::Value len) {
+    val = createIntCast(val, cir::IntType::get(getContext(), 32, true));
+    return cir::MemSetOp::create(*this, loc, dst, val, len);
+  }
   // ---------------------------
 
   cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty,
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 98cf75f0d69e0..087607f19e332 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -16,6 +16,7 @@
 
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/CIR/MissingFeatures.h"
 
@@ -568,13 +569,111 @@ void CIRGenFunction::emitNewArrayInitializer(
   if (!e->hasInitializer())
     return;
 
+  Address curPtr = beginPtr;
+
   unsigned initListElements = 0;
 
   const Expr *init = e->getInitializer();
+  Address endOfInit = Address::invalid();
+  QualType::DestructionKind dtorKind = elementType.isDestructedType();
+  assert(!cir::MissingFeatures::cleanupDeactivationScope());
+
+  // Attempt to perform zero-initialization using memset.
+  auto tryMemsetInitialization = [&]() -> bool {
+    mlir::Location loc = numElements.getLoc();
+
+    // FIXME: If the type is a pointer-to-data-member under the Itanium ABI,
+    // we can initialize with a memset to -1.
+    if (!cgm.getTypes().isZeroInitializable(elementType))
+      return false;
+
+    // Optimization: since zero initialization will just set the memory
+    // to all zeroes, generate a single memset to do it in one shot.
+
+    // Subtract out the size of any elements we've already initialized.
+    auto remainingSize = allocSizeWithoutCookie;
+    if (initListElements) {
+      // We know this can't overflow; we check this when doing the allocation.
+      unsigned initializedSize =
+          getContext().getTypeSizeInChars(elementType).getQuantity() *
+          initListElements;
+      cir::ConstantOp initSizeOp =
+          builder.getConstInt(loc, remainingSize.getType(), initializedSize);
+      remainingSize = builder.createSub(loc, remainingSize, initSizeOp);
+    }
+
+    // Create the memset.
+    mlir::Value castOp =
+        builder.createPtrBitcast(curPtr.getPointer(), cgm.voidTy);
+    builder.createMemSet(loc, castOp, builder.getConstInt(loc, cgm.sInt32Ty, 
0),
+                         remainingSize);
+    return true;
+  };
+
   const InitListExpr *ile = dyn_cast<InitListExpr>(init);
-  if (ile) {
-    cgm.errorNYI(ile->getSourceRange(), "emitNewArrayInitializer: init list");
-    return;
+  const CXXParenListInitExpr *cplie = nullptr;
+  const StringLiteral *sl = nullptr;
+  const ObjCEncodeExpr *ocee = nullptr;
+  const Expr *ignoreParen = nullptr;
+  if (!ile) {
+    ignoreParen = init->IgnoreParenImpCasts();
+    cplie = dyn_cast<CXXParenListInitExpr>(ignoreParen);
+    sl = dyn_cast<StringLiteral>(ignoreParen);
+    ocee = dyn_cast<ObjCEncodeExpr>(ignoreParen);
+  }
+  // If the initializer is an initializer list, first do the explicit elements.
+  if (ile || cplie || sl || ocee) {
+    // Initializing from a (braced) string literal is a special case; the init
+    // list element does not initialize a (single) array element.
+    if ((ile && ile->isStringLiteralInit()) || sl || ocee) {
+      cgm.errorNYI(ile->getSourceRange(),
+                   "emitNewArrayInitializer: string literal init");
+      return;
+    }
+
+    ArrayRef<const Expr *> initExprs =
+        ile ? ile->inits() : cplie->getInitExprs();
+    initListElements = initExprs.size();
+
+    // If this is a multi-dimensional array new, we will initialize multiple
+    // elements with each init list element.
+    QualType allocType = e->getAllocatedType();
+    if (const ConstantArrayType *cat = dyn_cast_or_null<ConstantArrayType>(
+            allocType->getAsArrayTypeUnsafe())) {
+      cgm.errorNYI(ile->getSourceRange(),
+                   "emitNewArrayInitializer: constant array init");
+      return;
+    }
+
+    // Enter a partial-destruction Cleanup if necessary.
+    if (dtorKind) {
+      cgm.errorNYI(ile->getSourceRange(),
+                   "emitNewArrayInitializer: init requires dtor");
+      return;
+    }
+
+    if (!initExprs.empty()) {
+      cgm.errorNYI(ile->getSourceRange(),
+                   "emitNewArrayInitializer: non-empty init list");
+      return;
+    }
+
+    // The remaining elements are filled with the array filler expression.
+    init = ile ? ile->getArrayFiller() : cplie->getArrayFiller();
+
+    // Extract the initializer for the individual array elements by pulling
+    // out the array filler from all the nested initializer lists. This avoids
+    // generating a nested loop for the initialization.
+    while (init && init->getType()->isConstantArrayType()) {
+      auto *subIle = dyn_cast<InitListExpr>(init);
+      if (!subIle)
+        break;
+      assert(subIle->getNumInits() == 0 && "explicit inits in array filler?");
+      init = subIle->getArrayFiller();
+    }
+
+    // Switch back to initializing one base element at a time.
+    curPtr = curPtr.withElementType(builder, beginPtr.getElementType());
   }
 
   // If all elements have already been initialized, skip any further
@@ -609,6 +708,15 @@ void CIRGenFunction::emitNewArrayInitializer(
     return;
   }
 
+  // If this is value-initialization, we can usually use memset.
+  if (isa<ImplicitValueInitExpr>(init)) {
+    if (tryMemsetInitialization())
+      return;
+    cgm.errorNYI(init->getSourceRange(),
+                 "emitNewArrayInitializer: implicit value init");
+    return;
+  }
+
   cgm.errorNYI(init->getSourceRange(),
                "emitNewArrayInitializer: unsupported initializer");
   return;
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 091489c404642..871eb2920d170 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -196,6 +196,18 @@ mlir::LogicalResult 
CIRToLLVMMemCpyOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
+    cir::MemSetOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  auto converted = mlir::LLVM::TruncOp::create(
+      rewriter, op.getLoc(), mlir::IntegerType::get(op.getContext(), 8),
+      adaptor.getVal());
+  rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(op, adaptor.getDst(),
+                                                    converted, 
adaptor.getLen(),
+                                                    /*isVolatile=*/false);
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRToLLVMSqrtOpLowering::matchAndRewrite(
     cir::SqrtOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGen/new.cpp b/clang/test/CIR/CodeGen/new.cpp
index 80a4b476226af..c097d88c9114d 100644
--- a/clang/test/CIR/CodeGen/new.cpp
+++ b/clang/test/CIR/CodeGen/new.cpp
@@ -187,8 +187,8 @@ void t_new_constant_size() {
 
 // CHECK:   cir.func{{.*}} @_Z19t_new_constant_sizev()
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!cir.double>, 
!cir.ptr<!cir.ptr<!cir.double>>, ["p", init] {alignment = 8 : i64}
-// CHECK:    %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<128> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : 
(!u64i) -> !cir.ptr<!void>
+// CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<128> : !u64i
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) : (!u64i) 
-> !cir.ptr<!void>
 // CHECK:    %[[TYPED_PTR:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.double>
 // CHECK:    cir.store align(8) %[[TYPED_PTR]], %[[P_ADDR]] : 
!cir.ptr<!cir.double>, !cir.ptr<!cir.ptr<!cir.double>>
 // CHECK:    cir.return
@@ -215,14 +215,14 @@ void t_constant_size_nontrivial() {
 
 // CHECK:  cir.func{{.*}} @_Z26t_constant_size_nontrivialv()
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C>, 
!cir.ptr<!cir.ptr<!rec_C>>, ["p", init] {alignment = 8 : i64}
-// CHECK:    %[[#NUM_ELEMENTS:]] = cir.const #cir.int<3> : !u64i
-// CHECK:    %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<11> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : 
(!u64i) -> !cir.ptr<!void>
+// CHECK:    %[[NUM_ELEMENTS:.*]] = cir.const #cir.int<3> : !u64i
+// CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<11> : !u64i
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) : (!u64i) 
-> !cir.ptr<!void>
 // CHECK:    %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_BASE]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
-// CHECK:    cir.store align(8) %[[#NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
-// CHECK:    %[[#COOKIE_SIZE:]] = cir.const #cir.int<8> : !s32i
-// CHECK:    %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[#COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> 
!cir.ptr<!cir.ptr<!u8i>>
+// CHECK:    cir.store align(8) %[[NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
+// CHECK:    %[[COOKIE_SIZE:.*]] = cir.const #cir.int<8> : !s32i
+// CHECK:    %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[DATA_PTR_VOID:.*]] = cir.cast bitcast %[[DATA_PTR_RAW]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!void>
 // CHECK:    %[[DATA_PTR:.*]] = cir.cast bitcast %[[DATA_PTR_VOID]] : 
!cir.ptr<!void> -> !cir.ptr<!rec_C>
 // CHECK:    cir.store align(8) %[[DATA_PTR]], %[[P_ADDR]] : !cir.ptr<!rec_C>, 
!cir.ptr<!cir.ptr<!rec_C>>
@@ -255,14 +255,14 @@ void t_constant_size_nontrivial2() {
 
 // CHECK:  cir.func{{.*}} @_Z27t_constant_size_nontrivial2v()
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_D>, 
!cir.ptr<!cir.ptr<!rec_D>>, ["p", init] {alignment = 8 : i64}
-// CHECK:    %[[#NUM_ELEMENTS:]] = cir.const #cir.int<3> : !u64i
-// CHECK:    %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<20> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : 
(!u64i) -> !cir.ptr<!void>
+// CHECK:    %[[NUM_ELEMENTS:.*]] = cir.const #cir.int<3> : !u64i
+// CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<20> : !u64i
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) : (!u64i) 
-> !cir.ptr<!void>
 // CHECK:    %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_BASE]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
-// CHECK:    cir.store align(8) %[[#NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
-// CHECK:    %[[#COOKIE_SIZE:]] = cir.const #cir.int<8> : !s32i
-// CHECK:    %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[#COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> 
!cir.ptr<!cir.ptr<!u8i>>
+// CHECK:    cir.store align(8) %[[NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
+// CHECK:    %[[COOKIE_SIZE:.*]] = cir.const #cir.int<8> : !s32i
+// CHECK:    %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[DATA_PTR_VOID:.*]] = cir.cast bitcast %[[DATA_PTR_RAW]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!void>
 // CHECK:    %[[DATA_PTR:.*]] = cir.cast bitcast %[[DATA_PTR_VOID]] : 
!cir.ptr<!void> -> !cir.ptr<!rec_D>
 // CHECK:    cir.store align(8) %[[DATA_PTR]], %[[P_ADDR]] : !cir.ptr<!rec_D>, 
!cir.ptr<!cir.ptr<!rec_D>>
@@ -287,16 +287,16 @@ void t_align16_nontrivial() {
 
 // CHECK:  cir.func{{.*}} @_Z20t_align16_nontrivialv()
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_E>, 
!cir.ptr<!cir.ptr<!rec_E>>, ["p", init] {alignment = 8 : i64}
-// CHECK:    %[[#NUM_ELEMENTS:]] = cir.const #cir.int<2> : !u64i
-// CHECK:    %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<48> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : 
(!u64i) -> !cir.ptr<!void>
+// CHECK:    %[[NUM_ELEMENTS:.*]] = cir.const #cir.int<2> : !u64i
+// CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<48> : !u64i
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) : (!u64i) 
-> !cir.ptr<!void>
 // CHECK:    %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[COOKIE_OFFSET:.*]] = cir.const #cir.int<8> : !s32i
 // CHECK:    %[[COOKIE_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[COOKIE_OFFSET]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> 
!cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_RAW]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
-// CHECK:    cir.store align(8) %[[#NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
-// CHECK:    %[[#COOKIE_SIZE:]] = cir.const #cir.int<16> : !s32i
-// CHECK:    %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[#COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> 
!cir.ptr<!cir.ptr<!u8i>>
+// CHECK:    cir.store align(8) %[[NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
+// CHECK:    %[[COOKIE_SIZE:.*]] = cir.const #cir.int<16> : !s32i
+// CHECK:    %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[DATA_PTR_VOID:.*]] = cir.cast bitcast %[[DATA_PTR_RAW]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!void>
 // CHECK:    %[[DATA_PTR:.*]] = cir.cast bitcast %[[DATA_PTR_VOID]] : 
!cir.ptr<!void> -> !cir.ptr<!rec_E>
 // CHECK:    cir.store align(8) %[[DATA_PTR]], %[[P_ADDR]] : !cir.ptr<!rec_E>, 
!cir.ptr<!cir.ptr<!rec_E>>
@@ -324,10 +324,10 @@ void t_new_multidim_constant_size() {
   auto p = new double[2][3][4];
 }
 
-// CHECK:   cir.func{{.*}} @_Z28t_new_multidim_constant_sizev()
+// CHECK:  cir.func{{.*}} @_Z28t_new_multidim_constant_sizev()
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca 
!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>, 
!cir.ptr<!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>>, ["p", init] 
{alignment = 8 : i64}
-// CHECK:    %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<192> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : 
(!u64i) -> !cir.ptr<!void>
+// CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<192> : !u64i
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) : (!u64i) 
-> !cir.ptr<!void>
 // CHECK:    %[[TYPED_PTR:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>
 // CHECK:    cir.store align(8) %[[TYPED_PTR]], %[[P_ADDR]] : 
!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>, 
!cir.ptr<!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>>
 // CHECK:  }
@@ -341,3 +341,23 @@ void t_new_multidim_constant_size() {
 // OGCG:   %[[P_ADDR:.*]] = alloca ptr, align 8
 // OGCG:   %[[CALL:.*]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 
192)
 // OGCG:   store ptr %[[CALL]], ptr %[[P_ADDR]], align 8
+
+void t_constant_size_memset_init() {
+  auto p = new int[16] {};
+}
+
+// CHECK:  cir.func {{.*}} @_Z27t_constant_size_memset_initv()
+// CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<64> : !u64i
+// CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) : 
(!u64i) -> !cir.ptr<!void>
+// CHECK:    %[[ELEM_PTR:.*]] = cir.cast bitcast %[[ALLOC_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!s32i>
+// CHECK:    %[[VOID_PTR:.*]] = cir.cast bitcast %[[ELEM_PTR]] : 
!cir.ptr<!s32i> -> !cir.ptr<!void>
+// CHECK:    %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
+// CHECK:    cir.libc.memset %[[ALLOCATION_SIZE]] bytes from %[[VOID_PTR]] set 
to %[[ZERO]] : !cir.ptr<!void>, !s32i, !u64i
+
+// LLVM: define {{.*}} void @_Z27t_constant_size_memset_initv()
+// LLVM:   %[[P:.*]] = call ptr @_Znam(i64 64)
+// LLVM:   call void @llvm.memset.p0.i64(ptr %[[P]], i8 0, i64 64, i1 false)
+
+// OGCG: define {{.*}} void @_Z27t_constant_size_memset_initv()
+// OGCG:   %[[P:.*]] = call{{.*}} ptr @_Znam(i64{{.*}} 64)
+// OGCG:   call void @llvm.memset.p0.i64(ptr{{.*}} %[[P]], i8 0, i64 64, i1 
false)

>From c4d56169dedf9fbb638c0c8aa8bbe76ef800196d Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Thu, 29 Jan 2026 18:01:52 -0800
Subject: [PATCH 2/3] Fix unused variables

---
 clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 087607f19e332..7f87d9b0f73b7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -574,7 +574,6 @@ void CIRGenFunction::emitNewArrayInitializer(
   unsigned initListElements = 0;
 
   const Expr *init = e->getInitializer();
-  Address endOfInit = Address::invalid();
   QualType::DestructionKind dtorKind = elementType.isDestructedType();
   assert(!cir::MissingFeatures::cleanupDeactivationScope());
 
@@ -640,6 +639,7 @@ void CIRGenFunction::emitNewArrayInitializer(
     QualType allocType = e->getAllocatedType();
     if (const ConstantArrayType *cat = dyn_cast_or_null<ConstantArrayType>(
             allocType->getAsArrayTypeUnsafe())) {
+      (void)cat;
       cgm.errorNYI(ile->getSourceRange(),
                    "emitNewArrayInitializer: constant array init");
       return;

>From a57c4cbf5d03311cdb63c445b53b14ce0a4cc974 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Fri, 30 Jan 2026 11:01:30 -0800
Subject: [PATCH 3/3] Address review feedback

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td     | 16 +++++++---------
 clang/lib/CIR/CodeGen/CIRGenBuilder.h            |  2 +-
 clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp          |  2 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp    |  9 +++------
 clang/test/CIR/CodeGen/new.cpp                   |  4 ++--
 5 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index b6db00e11c639..344f2d20bdf9c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3553,28 +3553,26 @@ def CIR_MemSetOp : CIR_Op<"libc.memset"> {
     Examples:
 
     ```mlir
-      // Set 2 bytes from a record to 0:
-      %2 = cir.const #cir.int<2> : !u32i
-      %3 = cir.const #cir.int<0> : !u32i
-      %zero = cir.cast integral %3 : !s32i -> !u8i
-      cir.libc.memset %2 bytes from %record set to %zero : !cir.ptr<!void>,
-                                                           !s32i, !u64i
+      // Set 2 bytes in a record to 0:
+      %len = cir.const #cir.int<2> : !u32i
+      %zero = cir.const #cir.int<0> : !u8i
+      cir.libc.memset %len bytes at %record to %zero : !cir.ptr<!void>,
+                                                       !s32i, !u64i
     ```
   }];
 
   let arguments = (ins
     Arg<CIR_VoidPtrType, "", [MemWrite]>:$dst,
-    CIR_SInt32:$val,
+    CIR_UInt8:$val,
     CIR_AnyFundamentalUIntType:$len
   );
 
   let assemblyFormat = [{
-    $len `bytes` `from` $dst `set` `to` $val attr-dict
+    $len `bytes` `at` $dst `to` $val attr-dict
     `:` qualified(type($dst)) `,` type($val) `,` type($len)
   }];
 }
 
-
 
//===----------------------------------------------------------------------===//
 // ReturnAddrOp and FrameAddrOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 51c5a238cf258..af9c4fcdeb8c7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -200,7 +200,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
 
   cir::MemSetOp createMemSet(mlir::Location loc, mlir::Value dst,
                              mlir::Value val, mlir::Value len) {
-    val = createIntCast(val, cir::IntType::get(getContext(), 32, true));
+    val = createIntCast(val, getUInt8Ty());
     return cir::MemSetOp::create(*this, loc, dst, val, len);
   }
   // ---------------------------
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 7f87d9b0f73b7..3731773cffa45 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -604,7 +604,7 @@ void CIRGenFunction::emitNewArrayInitializer(
     // Create the memset.
     mlir::Value castOp =
         builder.createPtrBitcast(curPtr.getPointer(), cgm.voidTy);
-    builder.createMemSet(loc, castOp, builder.getConstInt(loc, cgm.sInt32Ty, 
0),
+    builder.createMemSet(loc, castOp, builder.getConstInt(loc, cgm.uInt8Ty, 0),
                          remainingSize);
     return true;
   };
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 871eb2920d170..485f61d3d6a9d 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -199,12 +199,9 @@ mlir::LogicalResult 
CIRToLLVMMemCpyOpLowering::matchAndRewrite(
 mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
     cir::MemSetOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  auto converted = mlir::LLVM::TruncOp::create(
-      rewriter, op.getLoc(), mlir::IntegerType::get(op.getContext(), 8),
-      adaptor.getVal());
-  rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(op, adaptor.getDst(),
-                                                    converted, 
adaptor.getLen(),
-                                                    /*isVolatile=*/false);
+  rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
+      op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
+      /*isVolatile=*/false);
   return mlir::success();
 }
 
diff --git a/clang/test/CIR/CodeGen/new.cpp b/clang/test/CIR/CodeGen/new.cpp
index c097d88c9114d..9f454770e3960 100644
--- a/clang/test/CIR/CodeGen/new.cpp
+++ b/clang/test/CIR/CodeGen/new.cpp
@@ -351,8 +351,8 @@ void t_constant_size_memset_init() {
 // CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) : 
(!u64i) -> !cir.ptr<!void>
 // CHECK:    %[[ELEM_PTR:.*]] = cir.cast bitcast %[[ALLOC_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!s32i>
 // CHECK:    %[[VOID_PTR:.*]] = cir.cast bitcast %[[ELEM_PTR]] : 
!cir.ptr<!s32i> -> !cir.ptr<!void>
-// CHECK:    %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
-// CHECK:    cir.libc.memset %[[ALLOCATION_SIZE]] bytes from %[[VOID_PTR]] set 
to %[[ZERO]] : !cir.ptr<!void>, !s32i, !u64i
+// CHECK:    %[[ZERO:.*]] = cir.const #cir.int<0> : !u8i
+// CHECK:    cir.libc.memset %[[ALLOCATION_SIZE]] bytes at %[[VOID_PTR]] to 
%[[ZERO]] : !cir.ptr<!void>, !u8i, !u64i
 
 // LLVM: define {{.*}} void @_Z27t_constant_size_memset_initv()
 // LLVM:   %[[P:.*]] = call ptr @_Znam(i64 64)

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

Reply via email to