Skip to content

[CIR][Upstream] Local initialization for ArrayType #132974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Apr 3, 2025

Conversation

AmrDeveloper
Copy link
Member

This change adds local initialization for ArrayType

Issue #130197

@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Mar 25, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 25, 2025

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

Changes

This change adds local initialization for ArrayType

Issue #130197


Patch is 59.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132974.diff

25 Files Affected:

  • (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+35)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.h (+25)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+44)
  • (added) clang/include/clang/CIR/LoweringHelpers.h (+40)
  • (modified) clang/lib/CIR/CodeGen/Address.h (+10)
  • (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenDecl.cpp (+1-1)
  • (added) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+277)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+23)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+46)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+8-4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+12)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+5)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypeCache.h (+13)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+24)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenValue.h (+42-2)
  • (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+1)
  • (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+35-7)
  • (modified) clang/lib/CIR/Lowering/CMakeLists.txt (+1)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+109)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+15)
  • (added) clang/lib/CIR/Lowering/LoweringHelpers.cpp (+150)
  • (modified) clang/test/CIR/CodeGen/array.cpp (+91-6)
  • (modified) clang/test/CIR/Lowering/array.cpp (+72-5)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..4c7e6ec061d46 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -32,6 +32,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return create<cir::ConstantOp>(loc, attr.getType(), attr);
   }
 
+  // Creates constant null value for integral type ty.
+  cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
+    return create<cir::ConstantOp>(loc, ty, getZeroInitAttr(ty));
+  }
+
   cir::ConstantOp getBool(bool state, mlir::Location loc) {
     return create<cir::ConstantOp>(loc, getBoolTy(), getCIRBoolAttr(state));
   }
@@ -68,6 +73,36 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
         getContext(), mlir::cast<cir::PointerType>(type), valueAttr);
   }
 
+  mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
+    assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
+    return getConstPtrAttr(t, 0);
+  }
+
+  mlir::TypedAttr getZeroAttr(mlir::Type t) {
+    return cir::ZeroAttr::get(getContext(), t);
+  }
+
+  mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
+    if (mlir::isa<cir::IntType>(ty))
+      return cir::IntAttr::get(ty, 0);
+    if (auto fltType = mlir::dyn_cast<cir::SingleType>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto fltType = mlir::dyn_cast<cir::DoubleType>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto fltType = mlir::dyn_cast<cir::FP16Type>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto fltType = mlir::dyn_cast<cir::BF16Type>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
+      return getZeroAttr(arrTy);
+    if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
+      return getConstNullPtrAttr(ptrTy);
+    if (mlir::isa<cir::BoolType>(ty)) {
+      return getCIRBoolAttr(false);
+    }
+    llvm_unreachable("Zero initializer for given type is NYI");
+  }
+
   mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
                            mlir::Type type, llvm::StringRef name,
                            mlir::IntegerAttr alignment) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index da3b41371b9ab..ba7bbedf4714e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -32,6 +32,31 @@
 #include "clang/CIR/Interfaces/CIRLoopOpInterface.h"
 #include "clang/CIR/Interfaces/CIROpInterfaces.h"
 
+namespace mlir {
+namespace OpTrait {
+
+namespace impl {
+// These functions are out-of-line implementations of the methods in the
+// corresponding trait classes.  This avoids them being template
+// instantiated/duplicated.
+LogicalResult verifySameFirstOperandAndResultType(Operation *op);
+} // namespace impl
+
+/// This class provides verification for ops that are known to have the same
+/// first operand and result type.
+///
+template <typename ConcreteType>
+class SameFirstOperandAndResultType
+    : public TraitBase<ConcreteType, SameFirstOperandAndResultType> {
+public:
+  static llvm::LogicalResult verifyTrait(Operation *op) {
+    return impl::verifySameFirstOperandAndResultType(op);
+  }
+};
+
+} // namespace OpTrait
+} // namespace mlir
+
 // TableGen'erated files for MLIR dialects require that a macro be defined when
 // they are included.  GET_OP_CLASSES tells the file to define the classes for
 // the operations of that dialect.
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d7d63e040a2ba..7784c8a51fdf3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -79,6 +79,13 @@ class LLVMLoweringInfo {
 class CIR_Op<string mnemonic, list<Trait> traits = []> :
     Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;
 
+//===----------------------------------------------------------------------===//
+// CIR Op Traits
+//===----------------------------------------------------------------------===//
+
+def SameFirstOperandAndResultType :
+  NativeOpTrait<"SameFirstOperandAndResultType">;
+
 //===----------------------------------------------------------------------===//
 // CastOp
 //===----------------------------------------------------------------------===//
@@ -229,6 +236,43 @@ def CastOp : CIR_Op<"cast",
   let hasFolder = 1;
 }
 
+
+//===----------------------------------------------------------------------===//
+// PtrStrideOp
+//===----------------------------------------------------------------------===//
+
+def PtrStrideOp : CIR_Op<"ptr_stride",
+                         [Pure, SameFirstOperandAndResultType]> {
+  let summary = "Pointer access with stride";
+  let description = [{
+    Given a base pointer as first operand, provides a new pointer after applying
+    a stride (second operand).
+
+    ```mlir
+    %3 = cir.const 0 : i32
+    %4 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32), !cir.ptr<i32>
+    ```
+  }];
+
+  let arguments = (ins CIR_PointerType:$base, PrimitiveInt:$stride);
+  let results = (outs CIR_PointerType:$result);
+
+  let assemblyFormat = [{
+    `(` $base `:` qualified(type($base)) `,` $stride `:` qualified(type($stride)) `)`
+    `,` qualified(type($result)) attr-dict
+  }];
+
+  let extraClassDeclaration = [{
+    // Get type pointed by the base pointer.
+    mlir::Type getElementTy() {
+      return mlir::cast<cir::PointerType>(getBase().getType()).getPointee();
+    }
+  }];
+
+  // SameFirstOperandAndResultType already checks all we need.
+  let hasVerifier = 0;
+}
+
 //===----------------------------------------------------------------------===//
 // ConstantOp
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/LoweringHelpers.h b/clang/include/clang/CIR/LoweringHelpers.h
new file mode 100644
index 0000000000000..3077010ee5ffe
--- /dev/null
+++ b/clang/include/clang/CIR/LoweringHelpers.h
@@ -0,0 +1,40 @@
+//====- LoweringHelpers.h - Lowering helper functions ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares helper functions for lowering from CIR to LLVM or MLIR.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_CIR_LOWERINGHELPERS_H
+#define LLVM_CLANG_CIR_LOWERINGHELPERS_H
+
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+
+mlir::DenseElementsAttr
+convertStringAttrToDenseElementsAttr(cir::ConstArrayAttr attr, mlir::Type type);
+
+template <typename StorageTy> StorageTy getZeroInitFromType(mlir::Type ty);
+template <> mlir::APInt getZeroInitFromType(mlir::Type ty);
+template <> mlir::APFloat getZeroInitFromType(mlir::Type ty);
+
+template <typename AttrTy, typename StorageTy>
+void convertToDenseElementsAttrImpl(cir::ConstArrayAttr attr,
+                                    llvm::SmallVectorImpl<StorageTy> &values);
+
+template <typename AttrTy, typename StorageTy>
+mlir::DenseElementsAttr
+convertToDenseElementsAttr(cir::ConstArrayAttr attr,
+                           const llvm::SmallVectorImpl<int64_t> &dims,
+                           mlir::Type type);
+
+std::optional<mlir::Attribute>
+lowerConstArrayAttr(cir::ConstArrayAttr constArr,
+                    const mlir::TypeConverter *converter);
+
+#endif
diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
index fba1ffd90877b..2cc8ada783197 100644
--- a/clang/lib/CIR/CodeGen/Address.h
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -70,6 +70,14 @@ class Address {
     return pointerAndKnownNonNull.getPointer();
   }
 
+  mlir::Type getType() const {
+    assert(mlir::cast<cir::PointerType>(
+               pointerAndKnownNonNull.getPointer().getType())
+               .getPointee() == elementType);
+
+    return mlir::cast<cir::PointerType>(getPointer().getType());
+  }
+
   mlir::Type getElementType() const {
     assert(isValid());
     assert(mlir::cast<cir::PointerType>(
@@ -77,6 +85,8 @@ class Address {
                .getPointee() == elementType);
     return elementType;
   }
+
+  clang::CharUnits getAlignment() const { return alignment; }
 };
 
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index fef290612149a..d1a81f85b66fc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -83,6 +83,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
 
   bool isInt(mlir::Type i) { return mlir::isa<cir::IntType>(i); }
 
+  bool isInt8Ty(mlir::Type i) {
+    return i == typeCache.UInt8Ty || i == typeCache.SInt8Ty;
+  }
+
   // Creates constant nullptr for pointer type ty.
   cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
     assert(!cir::MissingFeatures::targetCodeGenInfoGetNullPointer());
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index a93e8dbcb42de..a0c6b832faa24 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -250,7 +250,7 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
     return;
   }
   case cir::TEK_Aggregate:
-    cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: aggregate type");
+    emitAggExpr(init, AggValueSlot::forLValue(lvalue));
     return;
   }
   llvm_unreachable("bad evaluation kind");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
new file mode 100644
index 0000000000000..3bd898422f4d6
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -0,0 +1,277 @@
+//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Aggregate Expr nodes as CIR code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenBuilder.h"
+#include "CIRGenFunction.h"
+#include "CIRGenValue.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include <cstdint>
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+namespace {
+class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
+
+  CIRGenFunction &cgf;
+  AggValueSlot dest;
+
+  AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
+    if (!dest.isIgnored())
+      return dest;
+    llvm_unreachable("Slot for ignored address NTI");
+  }
+
+public:
+  AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
+      : cgf(cgf), dest(dest) {}
+
+  void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
+                     Expr *exprToVisit, ArrayRef<Expr *> args,
+                     Expr *arrayFiller);
+
+  void emitInitializationToLValue(Expr *e, LValue lv);
+
+  void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
+
+  void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
+
+  void VisitInitListExpr(InitListExpr *e);
+
+  void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
+                                       FieldDecl *initializedFieldInUnion,
+                                       Expr *arrayFiller);
+};
+
+} // namespace
+
+static bool isTrivialFiller(Expr *e) {
+  if (!e)
+    return true;
+
+  if (isa<ImplicitValueInitExpr>(e))
+    return true;
+
+  if (auto *ile = dyn_cast<InitListExpr>(e)) {
+    if (ile->getNumInits())
+      return false;
+    return isTrivialFiller(ile->getArrayFiller());
+  }
+
+  if (const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))
+    return cons->getConstructor()->isDefaultConstructor() &&
+           cons->getConstructor()->isTrivial();
+
+  return false;
+}
+
+void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
+                                   QualType arrayQTy, Expr *e,
+                                   ArrayRef<Expr *> args, Expr *arrayFiller) {
+  CIRGenBuilderTy &builder = cgf.getBuilder();
+  const mlir::Location loc = cgf.getLoc(e->getSourceRange());
+
+  const uint64_t numInitElements = args.size();
+
+  const QualType elementType =
+      cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
+
+  if (elementType.isDestructedType()) {
+    llvm_unreachable("dtorKind NYI");
+  }
+
+  const QualType elementPtrType = cgf.getContext().getPointerType(elementType);
+
+  const mlir::Type cirElementType = cgf.convertType(elementType);
+  const cir::PointerType cirElementPtrType =
+      builder.getPointerTo(cirElementType);
+
+  auto begin = builder.create<cir::CastOp>(loc, cirElementPtrType,
+                                           cir::CastKind::array_to_ptrdecay,
+                                           destPtr.getPointer());
+
+  const CharUnits elementSize =
+      cgf.getContext().getTypeSizeInChars(elementType);
+  const CharUnits elementAlign =
+      destPtr.getAlignment().alignmentOfArrayElement(elementSize);
+
+  // The 'current element to initialize'.  The invariants on this
+  // variable are complicated.  Essentially, after each iteration of
+  // the loop, it points to the last initialized element, except
+  // that it points to the beginning of the array before any
+  // elements have been initialized.
+  mlir::Value element = begin;
+
+  // Don't build the 'one' before the cycle to avoid
+  // emmiting the redundant `cir.const 1` instrs.
+  mlir::Value one;
+
+  // Emit the explicit initializers.
+  for (uint64_t i = 0; i != numInitElements; ++i) {
+    // Advance to the next element.
+    if (i > 0) {
+      one = builder.create<cir::ConstantOp>(
+          loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, i));
+      element =
+          builder.create<cir::PtrStrideOp>(loc, cirElementPtrType, begin, one);
+    }
+
+    const Address address = Address(element, cirElementType, elementAlign);
+    const LValue elementLV = LValue::makeAddr(address, elementType);
+    emitInitializationToLValue(args[i], elementLV);
+  }
+
+  const uint64_t numArrayElements = arrayTy.getSize();
+
+  // Check whether there's a non-trivial array-fill expression.
+  const bool hasTrivialFiller = isTrivialFiller(arrayFiller);
+
+  // Any remaining elements need to be zero-initialized, possibly
+  // using the filler expression.  We can skip this if the we're
+  // emitting to zeroed memory.
+  if (numInitElements != numArrayElements &&
+      !(dest.isZeroed() && hasTrivialFiller &&
+        cgf.getTypes().isZeroInitializable(elementType))) {
+    // Advance to the start of the rest of the array.
+    if (numInitElements) {
+      one = builder.create<cir::ConstantOp>(
+          loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, 1));
+      element = builder.create<cir::PtrStrideOp>(loc, cirElementPtrType,
+                                                 element, one);
+    }
+
+    // Allocate the temporary variable
+    // to store the pointer to first unitialized element
+    auto tmpAddr = cgf.createTempAlloca(
+        cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");
+    LValue tmpLV = LValue::makeAddr(tmpAddr, elementPtrType);
+    cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
+
+    // TODO:Replace this part later with cir::DoWhileOp
+    for (unsigned i = numInitElements; i != numArrayElements; ++i) {
+      auto currentElement = builder.createLoad(loc, tmpAddr.getPointer());
+
+      // Emit the actual filler expression.
+      const LValue elementLV = LValue::makeAddr(
+          Address(currentElement, cirElementType, elementAlign), elementType);
+
+      if (arrayFiller)
+        emitInitializationToLValue(arrayFiller, elementLV);
+      else
+        emitNullInitializationToLValue(loc, elementLV);
+
+      // Advance pointer and store them to temporary variable
+      one = builder.create<cir::ConstantOp>(
+          loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, 1));
+
+      auto nextElement = builder.create<cir::PtrStrideOp>(
+          loc, cirElementPtrType, currentElement, one);
+      cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
+    }
+  }
+}
+
+void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
+  const QualType type = lv.getType();
+
+  if (isa<ImplicitValueInitExpr, CXXScalarValueInitExpr>(e)) {
+    const auto loc = e->getSourceRange().isValid()
+                         ? cgf.getLoc(e->getSourceRange())
+                         : *cgf.currSrcLoc;
+    return emitNullInitializationToLValue(loc, lv);
+  }
+
+  if (isa<NoInitExpr>(e))
+    return;
+
+  if (type->isReferenceType()) {
+    llvm_unreachable("NTI");
+  }
+
+  switch (cgf.getEvaluationKind(type)) {
+  case cir::TEK_Complex:
+    llvm_unreachable("TEK_Complex NYI");
+    break;
+  case cir::TEK_Aggregate:
+    cgf.emitAggExpr(e, AggValueSlot::forLValue(lv));
+    return;
+  case cir::TEK_Scalar:
+    if (lv.isSimple())
+      cgf.emitScalarInit(e, cgf.getLoc(e->getSourceRange()), lv);
+    else
+      cgf.emitStoreThroughLValue(RValue::get(cgf.emitScalarExpr(e)), lv);
+    return;
+  }
+}
+
+void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
+                                                    LValue lv) {
+  const QualType type = lv.getType();
+
+  // If the destination slot is already zeroed out before the aggregate is
+  // copied into it, we don't have to emit any zeros here.
+  if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
+    return;
+
+  if (cgf.hasScalarEvaluationKind(type)) {
+    // For non-aggregates, we can store the appropriate null constant.
+    auto null = cgf.cgm.emitNullConstant(type, loc);
+    if (lv.isSimple()) {
+      cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
+      return;
+    }
+
+    llvm_unreachable("emitStoreThroughBitfieldLValue NYI");
+    return;
+  }
+
+  // There's a potential optimization opportunity in combining
+  // memsets; that would be easy for arrays, but relatively
+  // difficult for structures with the current code.
+  cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
+}
+
+void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
+  if (e->hadArrayRangeDesignator())
+    llvm_unreachable("GNU array range designator extension");
+
+  if (e->isTransparent())
+    return Visit(e->getInit(0));
+
+  visitCXXParenListOrInitListExpr(
+      e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());
+}
+
+void AggExprEmitter::visitCXXParenListOrInitListExpr(
+    Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
+    Expr *arrayFiller) {
+
+  const AggValueSlot dest =
+      ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
+
+  if (e->getType()->isConstantArrayType()) {
+    cir::ArrayType arrayTy =
+        cast<cir::ArrayType>(dest.getAddress().getElementType());
+    emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,
+                  arrayFiller);
+    return;
+  }
+
+  llvm_unreachable("NYI");
+}
+
+void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {
+  AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index fc49d6da97206..06fcc0e2c040a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -412,3 +412,26 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
   }
   llvm_unreachable("Unknown APValue kind");
 }
+
+mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
+  if (t->getAs<PointerType>()) {
+    return builder.getNullPtr(getTypes().convertTypeForM...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 25, 2025

@llvm/pr-subscribers-clangir

Author: Amr Hesham (AmrDeveloper)

Changes

This change adds local initialization for ArrayType

Issue #130197


Patch is 59.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132974.diff

25 Files Affected:

  • (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+35)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.h (+25)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+44)
  • (added) clang/include/clang/CIR/LoweringHelpers.h (+40)
  • (modified) clang/lib/CIR/CodeGen/Address.h (+10)
  • (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenDecl.cpp (+1-1)
  • (added) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+277)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+23)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+46)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+8-4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+12)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+5)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypeCache.h (+13)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+24)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+4)
  • (modified) clang/lib/CIR/CodeGen/CIRGenValue.h (+42-2)
  • (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+1)
  • (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+35-7)
  • (modified) clang/lib/CIR/Lowering/CMakeLists.txt (+1)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+109)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+15)
  • (added) clang/lib/CIR/Lowering/LoweringHelpers.cpp (+150)
  • (modified) clang/test/CIR/CodeGen/array.cpp (+91-6)
  • (modified) clang/test/CIR/Lowering/array.cpp (+72-5)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..4c7e6ec061d46 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -32,6 +32,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return create<cir::ConstantOp>(loc, attr.getType(), attr);
   }
 
+  // Creates constant null value for integral type ty.
+  cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
+    return create<cir::ConstantOp>(loc, ty, getZeroInitAttr(ty));
+  }
+
   cir::ConstantOp getBool(bool state, mlir::Location loc) {
     return create<cir::ConstantOp>(loc, getBoolTy(), getCIRBoolAttr(state));
   }
@@ -68,6 +73,36 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
         getContext(), mlir::cast<cir::PointerType>(type), valueAttr);
   }
 
+  mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
+    assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
+    return getConstPtrAttr(t, 0);
+  }
+
+  mlir::TypedAttr getZeroAttr(mlir::Type t) {
+    return cir::ZeroAttr::get(getContext(), t);
+  }
+
+  mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
+    if (mlir::isa<cir::IntType>(ty))
+      return cir::IntAttr::get(ty, 0);
+    if (auto fltType = mlir::dyn_cast<cir::SingleType>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto fltType = mlir::dyn_cast<cir::DoubleType>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto fltType = mlir::dyn_cast<cir::FP16Type>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto fltType = mlir::dyn_cast<cir::BF16Type>(ty))
+      return cir::FPAttr::getZero(fltType);
+    if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
+      return getZeroAttr(arrTy);
+    if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
+      return getConstNullPtrAttr(ptrTy);
+    if (mlir::isa<cir::BoolType>(ty)) {
+      return getCIRBoolAttr(false);
+    }
+    llvm_unreachable("Zero initializer for given type is NYI");
+  }
+
   mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
                            mlir::Type type, llvm::StringRef name,
                            mlir::IntegerAttr alignment) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index da3b41371b9ab..ba7bbedf4714e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -32,6 +32,31 @@
 #include "clang/CIR/Interfaces/CIRLoopOpInterface.h"
 #include "clang/CIR/Interfaces/CIROpInterfaces.h"
 
+namespace mlir {
+namespace OpTrait {
+
+namespace impl {
+// These functions are out-of-line implementations of the methods in the
+// corresponding trait classes.  This avoids them being template
+// instantiated/duplicated.
+LogicalResult verifySameFirstOperandAndResultType(Operation *op);
+} // namespace impl
+
+/// This class provides verification for ops that are known to have the same
+/// first operand and result type.
+///
+template <typename ConcreteType>
+class SameFirstOperandAndResultType
+    : public TraitBase<ConcreteType, SameFirstOperandAndResultType> {
+public:
+  static llvm::LogicalResult verifyTrait(Operation *op) {
+    return impl::verifySameFirstOperandAndResultType(op);
+  }
+};
+
+} // namespace OpTrait
+} // namespace mlir
+
 // TableGen'erated files for MLIR dialects require that a macro be defined when
 // they are included.  GET_OP_CLASSES tells the file to define the classes for
 // the operations of that dialect.
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d7d63e040a2ba..7784c8a51fdf3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -79,6 +79,13 @@ class LLVMLoweringInfo {
 class CIR_Op<string mnemonic, list<Trait> traits = []> :
     Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;
 
+//===----------------------------------------------------------------------===//
+// CIR Op Traits
+//===----------------------------------------------------------------------===//
+
+def SameFirstOperandAndResultType :
+  NativeOpTrait<"SameFirstOperandAndResultType">;
+
 //===----------------------------------------------------------------------===//
 // CastOp
 //===----------------------------------------------------------------------===//
@@ -229,6 +236,43 @@ def CastOp : CIR_Op<"cast",
   let hasFolder = 1;
 }
 
+
+//===----------------------------------------------------------------------===//
+// PtrStrideOp
+//===----------------------------------------------------------------------===//
+
+def PtrStrideOp : CIR_Op<"ptr_stride",
+                         [Pure, SameFirstOperandAndResultType]> {
+  let summary = "Pointer access with stride";
+  let description = [{
+    Given a base pointer as first operand, provides a new pointer after applying
+    a stride (second operand).
+
+    ```mlir
+    %3 = cir.const 0 : i32
+    %4 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32), !cir.ptr<i32>
+    ```
+  }];
+
+  let arguments = (ins CIR_PointerType:$base, PrimitiveInt:$stride);
+  let results = (outs CIR_PointerType:$result);
+
+  let assemblyFormat = [{
+    `(` $base `:` qualified(type($base)) `,` $stride `:` qualified(type($stride)) `)`
+    `,` qualified(type($result)) attr-dict
+  }];
+
+  let extraClassDeclaration = [{
+    // Get type pointed by the base pointer.
+    mlir::Type getElementTy() {
+      return mlir::cast<cir::PointerType>(getBase().getType()).getPointee();
+    }
+  }];
+
+  // SameFirstOperandAndResultType already checks all we need.
+  let hasVerifier = 0;
+}
+
 //===----------------------------------------------------------------------===//
 // ConstantOp
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/LoweringHelpers.h b/clang/include/clang/CIR/LoweringHelpers.h
new file mode 100644
index 0000000000000..3077010ee5ffe
--- /dev/null
+++ b/clang/include/clang/CIR/LoweringHelpers.h
@@ -0,0 +1,40 @@
+//====- LoweringHelpers.h - Lowering helper functions ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares helper functions for lowering from CIR to LLVM or MLIR.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_CIR_LOWERINGHELPERS_H
+#define LLVM_CLANG_CIR_LOWERINGHELPERS_H
+
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+
+mlir::DenseElementsAttr
+convertStringAttrToDenseElementsAttr(cir::ConstArrayAttr attr, mlir::Type type);
+
+template <typename StorageTy> StorageTy getZeroInitFromType(mlir::Type ty);
+template <> mlir::APInt getZeroInitFromType(mlir::Type ty);
+template <> mlir::APFloat getZeroInitFromType(mlir::Type ty);
+
+template <typename AttrTy, typename StorageTy>
+void convertToDenseElementsAttrImpl(cir::ConstArrayAttr attr,
+                                    llvm::SmallVectorImpl<StorageTy> &values);
+
+template <typename AttrTy, typename StorageTy>
+mlir::DenseElementsAttr
+convertToDenseElementsAttr(cir::ConstArrayAttr attr,
+                           const llvm::SmallVectorImpl<int64_t> &dims,
+                           mlir::Type type);
+
+std::optional<mlir::Attribute>
+lowerConstArrayAttr(cir::ConstArrayAttr constArr,
+                    const mlir::TypeConverter *converter);
+
+#endif
diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
index fba1ffd90877b..2cc8ada783197 100644
--- a/clang/lib/CIR/CodeGen/Address.h
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -70,6 +70,14 @@ class Address {
     return pointerAndKnownNonNull.getPointer();
   }
 
+  mlir::Type getType() const {
+    assert(mlir::cast<cir::PointerType>(
+               pointerAndKnownNonNull.getPointer().getType())
+               .getPointee() == elementType);
+
+    return mlir::cast<cir::PointerType>(getPointer().getType());
+  }
+
   mlir::Type getElementType() const {
     assert(isValid());
     assert(mlir::cast<cir::PointerType>(
@@ -77,6 +85,8 @@ class Address {
                .getPointee() == elementType);
     return elementType;
   }
+
+  clang::CharUnits getAlignment() const { return alignment; }
 };
 
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index fef290612149a..d1a81f85b66fc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -83,6 +83,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
 
   bool isInt(mlir::Type i) { return mlir::isa<cir::IntType>(i); }
 
+  bool isInt8Ty(mlir::Type i) {
+    return i == typeCache.UInt8Ty || i == typeCache.SInt8Ty;
+  }
+
   // Creates constant nullptr for pointer type ty.
   cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
     assert(!cir::MissingFeatures::targetCodeGenInfoGetNullPointer());
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index a93e8dbcb42de..a0c6b832faa24 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -250,7 +250,7 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
     return;
   }
   case cir::TEK_Aggregate:
-    cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: aggregate type");
+    emitAggExpr(init, AggValueSlot::forLValue(lvalue));
     return;
   }
   llvm_unreachable("bad evaluation kind");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
new file mode 100644
index 0000000000000..3bd898422f4d6
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -0,0 +1,277 @@
+//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Aggregate Expr nodes as CIR code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenBuilder.h"
+#include "CIRGenFunction.h"
+#include "CIRGenValue.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include <cstdint>
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+namespace {
+class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
+
+  CIRGenFunction &cgf;
+  AggValueSlot dest;
+
+  AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
+    if (!dest.isIgnored())
+      return dest;
+    llvm_unreachable("Slot for ignored address NTI");
+  }
+
+public:
+  AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
+      : cgf(cgf), dest(dest) {}
+
+  void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
+                     Expr *exprToVisit, ArrayRef<Expr *> args,
+                     Expr *arrayFiller);
+
+  void emitInitializationToLValue(Expr *e, LValue lv);
+
+  void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
+
+  void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
+
+  void VisitInitListExpr(InitListExpr *e);
+
+  void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
+                                       FieldDecl *initializedFieldInUnion,
+                                       Expr *arrayFiller);
+};
+
+} // namespace
+
+static bool isTrivialFiller(Expr *e) {
+  if (!e)
+    return true;
+
+  if (isa<ImplicitValueInitExpr>(e))
+    return true;
+
+  if (auto *ile = dyn_cast<InitListExpr>(e)) {
+    if (ile->getNumInits())
+      return false;
+    return isTrivialFiller(ile->getArrayFiller());
+  }
+
+  if (const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))
+    return cons->getConstructor()->isDefaultConstructor() &&
+           cons->getConstructor()->isTrivial();
+
+  return false;
+}
+
+void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
+                                   QualType arrayQTy, Expr *e,
+                                   ArrayRef<Expr *> args, Expr *arrayFiller) {
+  CIRGenBuilderTy &builder = cgf.getBuilder();
+  const mlir::Location loc = cgf.getLoc(e->getSourceRange());
+
+  const uint64_t numInitElements = args.size();
+
+  const QualType elementType =
+      cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
+
+  if (elementType.isDestructedType()) {
+    llvm_unreachable("dtorKind NYI");
+  }
+
+  const QualType elementPtrType = cgf.getContext().getPointerType(elementType);
+
+  const mlir::Type cirElementType = cgf.convertType(elementType);
+  const cir::PointerType cirElementPtrType =
+      builder.getPointerTo(cirElementType);
+
+  auto begin = builder.create<cir::CastOp>(loc, cirElementPtrType,
+                                           cir::CastKind::array_to_ptrdecay,
+                                           destPtr.getPointer());
+
+  const CharUnits elementSize =
+      cgf.getContext().getTypeSizeInChars(elementType);
+  const CharUnits elementAlign =
+      destPtr.getAlignment().alignmentOfArrayElement(elementSize);
+
+  // The 'current element to initialize'.  The invariants on this
+  // variable are complicated.  Essentially, after each iteration of
+  // the loop, it points to the last initialized element, except
+  // that it points to the beginning of the array before any
+  // elements have been initialized.
+  mlir::Value element = begin;
+
+  // Don't build the 'one' before the cycle to avoid
+  // emmiting the redundant `cir.const 1` instrs.
+  mlir::Value one;
+
+  // Emit the explicit initializers.
+  for (uint64_t i = 0; i != numInitElements; ++i) {
+    // Advance to the next element.
+    if (i > 0) {
+      one = builder.create<cir::ConstantOp>(
+          loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, i));
+      element =
+          builder.create<cir::PtrStrideOp>(loc, cirElementPtrType, begin, one);
+    }
+
+    const Address address = Address(element, cirElementType, elementAlign);
+    const LValue elementLV = LValue::makeAddr(address, elementType);
+    emitInitializationToLValue(args[i], elementLV);
+  }
+
+  const uint64_t numArrayElements = arrayTy.getSize();
+
+  // Check whether there's a non-trivial array-fill expression.
+  const bool hasTrivialFiller = isTrivialFiller(arrayFiller);
+
+  // Any remaining elements need to be zero-initialized, possibly
+  // using the filler expression.  We can skip this if the we're
+  // emitting to zeroed memory.
+  if (numInitElements != numArrayElements &&
+      !(dest.isZeroed() && hasTrivialFiller &&
+        cgf.getTypes().isZeroInitializable(elementType))) {
+    // Advance to the start of the rest of the array.
+    if (numInitElements) {
+      one = builder.create<cir::ConstantOp>(
+          loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, 1));
+      element = builder.create<cir::PtrStrideOp>(loc, cirElementPtrType,
+                                                 element, one);
+    }
+
+    // Allocate the temporary variable
+    // to store the pointer to first unitialized element
+    auto tmpAddr = cgf.createTempAlloca(
+        cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");
+    LValue tmpLV = LValue::makeAddr(tmpAddr, elementPtrType);
+    cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
+
+    // TODO:Replace this part later with cir::DoWhileOp
+    for (unsigned i = numInitElements; i != numArrayElements; ++i) {
+      auto currentElement = builder.createLoad(loc, tmpAddr.getPointer());
+
+      // Emit the actual filler expression.
+      const LValue elementLV = LValue::makeAddr(
+          Address(currentElement, cirElementType, elementAlign), elementType);
+
+      if (arrayFiller)
+        emitInitializationToLValue(arrayFiller, elementLV);
+      else
+        emitNullInitializationToLValue(loc, elementLV);
+
+      // Advance pointer and store them to temporary variable
+      one = builder.create<cir::ConstantOp>(
+          loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, 1));
+
+      auto nextElement = builder.create<cir::PtrStrideOp>(
+          loc, cirElementPtrType, currentElement, one);
+      cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
+    }
+  }
+}
+
+void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
+  const QualType type = lv.getType();
+
+  if (isa<ImplicitValueInitExpr, CXXScalarValueInitExpr>(e)) {
+    const auto loc = e->getSourceRange().isValid()
+                         ? cgf.getLoc(e->getSourceRange())
+                         : *cgf.currSrcLoc;
+    return emitNullInitializationToLValue(loc, lv);
+  }
+
+  if (isa<NoInitExpr>(e))
+    return;
+
+  if (type->isReferenceType()) {
+    llvm_unreachable("NTI");
+  }
+
+  switch (cgf.getEvaluationKind(type)) {
+  case cir::TEK_Complex:
+    llvm_unreachable("TEK_Complex NYI");
+    break;
+  case cir::TEK_Aggregate:
+    cgf.emitAggExpr(e, AggValueSlot::forLValue(lv));
+    return;
+  case cir::TEK_Scalar:
+    if (lv.isSimple())
+      cgf.emitScalarInit(e, cgf.getLoc(e->getSourceRange()), lv);
+    else
+      cgf.emitStoreThroughLValue(RValue::get(cgf.emitScalarExpr(e)), lv);
+    return;
+  }
+}
+
+void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
+                                                    LValue lv) {
+  const QualType type = lv.getType();
+
+  // If the destination slot is already zeroed out before the aggregate is
+  // copied into it, we don't have to emit any zeros here.
+  if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
+    return;
+
+  if (cgf.hasScalarEvaluationKind(type)) {
+    // For non-aggregates, we can store the appropriate null constant.
+    auto null = cgf.cgm.emitNullConstant(type, loc);
+    if (lv.isSimple()) {
+      cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
+      return;
+    }
+
+    llvm_unreachable("emitStoreThroughBitfieldLValue NYI");
+    return;
+  }
+
+  // There's a potential optimization opportunity in combining
+  // memsets; that would be easy for arrays, but relatively
+  // difficult for structures with the current code.
+  cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
+}
+
+void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
+  if (e->hadArrayRangeDesignator())
+    llvm_unreachable("GNU array range designator extension");
+
+  if (e->isTransparent())
+    return Visit(e->getInit(0));
+
+  visitCXXParenListOrInitListExpr(
+      e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());
+}
+
+void AggExprEmitter::visitCXXParenListOrInitListExpr(
+    Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
+    Expr *arrayFiller) {
+
+  const AggValueSlot dest =
+      ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
+
+  if (e->getType()->isConstantArrayType()) {
+    cir::ArrayType arrayTy =
+        cast<cir::ArrayType>(dest.getAddress().getElementType());
+    emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,
+                  arrayFiller);
+    return;
+  }
+
+  llvm_unreachable("NYI");
+}
+
+void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {
+  AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index fc49d6da97206..06fcc0e2c040a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -412,3 +412,26 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
   }
   llvm_unreachable("Unknown APValue kind");
 }
+
+mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
+  if (t->getAs<PointerType>()) {
+    return builder.getNullPtr(getTypes().convertTypeForM...
[truncated]

// respective address.
// Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);
auto zeroAttr = cir::ZeroAttr::get(builder.getContext(), convertType(ty));
auto zeroValue =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use builder.getNullValue instead explicit operation creation and duplicit type conversion.

Comment on lines 272 to 273
// SameFirstOperandAndResultType already checks all we need.
let hasVerifier = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for it as it is 0 by default.

Suggested change
// SameFirstOperandAndResultType already checks all we need.
let hasVerifier = 0;

for (uint64_t i = 0; i != numInitElements; ++i) {
// Advance to the next element.
if (i > 0) {
one = builder.create<cir::ConstantOp>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use builder.getConstant

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe worth adding builder.getConstantInt method as this repeats a lot

cgf.getTypes().isZeroInitializable(elementType))) {
// Advance to the start of the rest of the array.
if (numInitElements) {
one = builder.create<cir::ConstantOp>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use builder.getConstant

emitNullInitializationToLValue(loc, elementLV);

// Advance pointer and store them to temporary variable
one = builder.create<cir::ConstantOp>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use getConstant

@AmrDeveloper AmrDeveloper requested a review from erichkeane March 25, 2025 21:26
Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have only minor inline comments, good direction.

The PR is a bit big but I can see this requires touching everywhere in CIRGen and also LLVM lowering support, which is good end-to-end testing.

If there are things there are not needed right now, it'd be better to remove it for extra clarity. Have you checked that?

@AmrDeveloper
Copy link
Member Author

I have only minor inline comments, good direction.

The PR is a bit big but I can see this requires touching everywhere in CIRGen and also LLVM lowering support, which is good end-to-end testing.

If there are things there are not needed right now, it'd be better to remove it for extra clarity. Have you checked that?

I already removed some parts like TypeSizeInfoAttr and AddrSpace before creating the PR for that reason, I will double check again if I can remove anything else

return;
}

llvm_unreachable("emitStoreThroughBitfieldLValue NYI");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
llvm_unreachable("emitStoreThroughBitfieldLValue NYI");
cgf.cgm.errorNYI("emitStoreThroughBitfieldLValue");


void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
if (e->hadArrayRangeDesignator())
llvm_unreachable("GNU array range designator extension");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorNYI

return;
}

llvm_unreachable("NYI");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorNYI with more detail

if (getTypes().isZeroInitializable(t))
return builder.getNullValue(getTypes().convertTypeForMem(t), loc);

if (const ConstantArrayType *cat =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the unused variable here to avoid introducing a warning.


if (const ConstantArrayType *cat =
getASTContext().getAsConstantArrayType(t)) {
llvm_unreachable("NYI");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

erroNYI with more detail


// TODO:Replace this part later with cir::DoWhileOp
for (unsigned i = numInitElements; i != numArrayElements; ++i) {
auto currentElement = builder.createLoad(loc, tmpAddr.getPointer());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No auto here

const QualType type = lv.getType();

if (isa<ImplicitValueInitExpr, CXXScalarValueInitExpr>(e)) {
const auto loc = e->getSourceRange().isValid()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No auto

return;

if (type->isReferenceType()) {
llvm_unreachable("NTI");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorNYI


switch (cgf.getEvaluationKind(type)) {
case cir::TEK_Complex:
llvm_unreachable("TEK_Complex NYI");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorNYI

@andykaylor
Copy link
Contributor

I already removed some parts like TypeSizeInfoAttr and AddrSpace before creating the PR for that reason, I will double check again if I can remove anything else

I'm not sure it's worth splitting up now, but you probably could have implemented the zero-initialization case by itself as a preliminary patch.

@@ -620,6 +682,28 @@ mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
return mlir::LogicalResult::success();
}

/// Switches on the type of attribute and calls the appropriate conversion.
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was already a definition of this function. What you're adding here only differs in that it adds a dataLayout argument which isn't used.

std::optional<mlir::Attribute> denseAttr;
if (constArr && hasTrailingZeros(constArr)) {
const mlir::Value newOp = lowerCirAttrAsValue(
op, constArr, rewriter, getTypeConverter(), dataLayout);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
op, constArr, rewriter, getTypeConverter(), dataLayout);
op, constArr, rewriter, getTypeConverter());

attr = denseAttr.value();
} else {
const mlir::Value initVal = lowerCirAttrAsValue(
op, op.getValue(), rewriter, typeConverter, dataLayout);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
op, op.getValue(), rewriter, typeConverter, dataLayout);
op, op.getValue(), rewriter, typeConverter);

const auto arrayTy = mlir::dyn_cast<cir::ArrayType>(attr.getType());
assert(arrayTy && "String attribute must have an array type");
if (arrayTy.getSize() != stringAttr.size())
llvm_unreachable("array type of the length not equal to that of the string "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not suggesting errorNYI. I'm suggesting op.emitError(). We can't do that here either, but maybe we could do it in the function from which this is called?

Copy link

github-actions bot commented Mar 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@AmrDeveloper AmrDeveloper force-pushed the cir_upstream_array_local_init branch from a7f3849 to ed0a86b Compare March 26, 2025 22:39
@AmrDeveloper
Copy link
Member Author

I'm not suggesting errorNYI. I'm suggesting op.emitError(). We can't do that here either, but maybe we could do it in the function from which this is called?

I think it's easier to keep it as assert, llvm_unreachable or a missing features as the error message mention, because otherwise we will modify the function to return nullptr to flag this case and also to modify the caller to catch it and report, also we don't have Operator to use it to emitError, what do you think? @andykaylor

@andykaylor
Copy link
Contributor

I'm not suggesting errorNYI. I'm suggesting op.emitError(). We can't do that here either, but maybe we could do it in the function from which this is called?

I think it's easier to keep it as assert, llvm_unreachable or a missing features as the error message mention, because otherwise we will modify the function to return nullptr to flag this case and also to modify the caller to catch it and report, also we don't have Operator to use it to emitError, what do you think? @andykaylor

I suppose MissingFeatures would be fine.

@bcardosolopes bcardosolopes changed the title [CIR] [Upstream local initialization for ArrayType [CIR][Upstream] Local initialization for ArrayType Mar 28, 2025
Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have anything else to add, LGTM!

mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
if (mlir::isa<cir::IntType>(ty))
return cir::IntAttr::get(ty, 0);
if (auto fltType = mlir::dyn_cast<cir::SingleType>(ty))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let merge the zero-init change first and rebase this one to get the changes there.

@@ -327,4 +337,4 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {

} // namespace cir

#endif
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This indicates that you (or some tool you're using) removed the newline character at the end of the file. It's a good practice to configure your editor to automatically add a newline at the end if it's missing. If you use the VSCode editor, the text editor has a setting called "Insert Final Newline" that does this.

AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
if (!dest.isIgnored())
return dest;
llvm_unreachable("Slot for ignored address NTI");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
llvm_unreachable("Slot for ignored address NTI");
cgf.cgm.errorNYI(loc, "Slot for ignored address");

cgf.getContext().getAsArrayType(arrayQTy)->getElementType();

if (elementType.isDestructedType()) {
llvm_unreachable("dtorKind NYI");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorNYI

if (i > 0) {
one = builder.getConstantInt(loc, cgf.PtrDiffTy, i);
element =
builder.create<cir::PtrStrideOp>(loc, cirElementPtrType, begin, one);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer createPtrStride() added in the base builder class.

// Allocate the temporary variable
// to store the pointer to first unitialized element
auto tmpAddr = cgf.createTempAlloca(
cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp", false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp", false);
cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp",
/*insertIntoFnEntryBlock=*/false);


// Allocate the temporary variable
// to store the pointer to first unitialized element
auto tmpAddr = cgf.createTempAlloca(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use auto here.


// Advance pointer and store them to temporary variable
one = builder.getConstantInt(loc, cgf.PtrDiffTy, 1);
auto nextElement = builder.create<cir::PtrStrideOp>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, I'd prefer createPtrStride() and that will mean you shouldn't use auto.


if (cgf.hasScalarEvaluationKind(type)) {
// For non-aggregates, we can store the appropriate null constant.
auto null = cgf.cgm.emitNullConstant(type, loc);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No auto

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have comments here other than what Andy suggested, so get those fixed/make him happy, and I'm happy when he is.

@AmrDeveloper AmrDeveloper force-pushed the cir_upstream_array_local_init branch from 7d486df to 9a9e494 Compare April 1, 2025 16:39
@AmrDeveloper
Copy link
Member Author

I addressed all comments, CI is red because unrelated reason.

@andykaylor

@@ -110,6 +110,10 @@ class CIRGenFunction : public CIRGenTypeCache {
public:
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);

void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be moved to the place where other emit* functions are declared and inserted in alphabetical order.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks

Copy link
Contributor

@andykaylor andykaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks ready.

@@ -110,6 +110,8 @@ class CIRGenFunction : public CIRGenTypeCache {
public:
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);

void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two emit functions you've added are still not in the correct place, but that's fine. Some others have gotten out of order too, so I'll make another reordering patch after this is merged.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, Currently I have time if you prefer, I can handle it

@AmrDeveloper AmrDeveloper merged commit 262b9b5 into llvm:main Apr 3, 2025
11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 3, 2025

LLVM Buildbot has detected a new failure on builder clang-aarch64-sve-vla running on linaro-g3-04 while building clang at step 7 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/17/builds/7001

Here is the relevant piece of the build log for the reference
Step 7 (ninja check 1) failure: stage 1 checked (failure)
...
PASS: Flang :: Driver/config-file.f90 (25202 of 97629)
PASS: Clangd Unit Tests :: ./ClangdTests/75/81 (25203 of 97629)
PASS: Flang :: Driver/linker-flags.f90 (25204 of 97629)
PASS: Flang :: Driver/predefined-macros-compiler-version.F90 (25205 of 97629)
PASS: Flang :: Driver/phases.f90 (25206 of 97629)
PASS: Flang :: Driver/mlir-pass-pipeline.f90 (25207 of 97629)
PASS: Flang :: Driver/parse-fir-error.ll (25208 of 97629)
PASS: Flang :: Driver/print-effective-triple.f90 (25209 of 97629)
PASS: Flang :: Driver/parse-error.ll (25210 of 97629)
UNRESOLVED: Flang :: Driver/slp-vectorize.ll (25211 of 97629)
******************** TEST 'Flang :: Driver/slp-vectorize.ll' FAILED ********************
Test has no 'RUN:' line
********************
PASS: Flang :: Driver/implicit-none.f90 (25212 of 97629)
PASS: Flang :: Driver/print-resource-dir.F90 (25213 of 97629)
PASS: Flang :: Driver/scanning-error.f95 (25214 of 97629)
PASS: Flang :: Driver/missing-arg.f90 (25215 of 97629)
PASS: Flang :: Driver/print-pipeline-passes.f90 (25216 of 97629)
PASS: Flang :: Driver/lto-bc.f90 (25217 of 97629)
PASS: Flang :: Driver/parse-ir-error.f95 (25218 of 97629)
PASS: Flang :: Driver/print-target-triple.f90 (25219 of 97629)
PASS: Flang :: Driver/pthread.f90 (25220 of 97629)
PASS: Flang :: Driver/std2018-wrong.f90 (25221 of 97629)
PASS: Flang :: Driver/mlink-builtin-bc.f90 (25222 of 97629)
PASS: Clangd Unit Tests :: ./ClangdTests/71/81 (25223 of 97629)
PASS: DataFlowSanitizer-aarch64 :: origin_ldst.c (25224 of 97629)
PASS: Clangd Unit Tests :: ./ClangdTests/68/81 (25225 of 97629)
PASS: Flang :: Driver/include-header.f90 (25226 of 97629)
PASS: Flang :: Driver/supported-suffices/f08-suffix.f08 (25227 of 97629)
PASS: Flang :: Driver/macro-def-undef.F90 (25228 of 97629)
PASS: Flang :: Driver/supported-suffices/f03-suffix.f03 (25229 of 97629)
PASS: Flang :: Driver/pp-fixed-form.f90 (25230 of 97629)
PASS: Flang :: Driver/tco-code-gen-llvm.fir (25231 of 97629)
PASS: Clangd Unit Tests :: ./ClangdTests/36/81 (25232 of 97629)
PASS: Flang :: Driver/unsupported-vscale-max-min.f90 (25233 of 97629)
PASS: Flang :: Driver/mllvm.f90 (25234 of 97629)
PASS: Flang :: Driver/pass-plugin-not-found.f90 (25235 of 97629)
PASS: Flang :: Driver/target-gpu-features.f90 (25236 of 97629)
PASS: Flang :: Driver/q-unused-arguments.f90 (25237 of 97629)
PASS: Flang :: Driver/fixed-line-length.f90 (25238 of 97629)
PASS: Flang :: Driver/no-duplicate-main.f90 (25239 of 97629)
PASS: Flang :: Driver/target.f90 (25240 of 97629)
PASS: Clangd Unit Tests :: ./ClangdTests/80/81 (25241 of 97629)
PASS: Flang :: Driver/multiple-input-files.f90 (25242 of 97629)
PASS: Flang :: Driver/std2018.f90 (25243 of 97629)
PASS: Flang :: Driver/fsave-optimization-record.f90 (25244 of 97629)
PASS: Flang :: Driver/lto-flags.f90 (25245 of 97629)
PASS: Flang :: Driver/unparse-with-modules.f90 (25246 of 97629)
PASS: Flang :: Driver/optimization-remark-invalid.f90 (25247 of 97629)

@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 4, 2025

LLVM Buildbot has detected a new failure on builder ppc64-flang-aix running on ppc64-flang-aix-test while building clang at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/201/builds/3938

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
5367.238 [3209/10/4843] Building CXX object tools/mlir/lib/Dialect/Transform/IRDLExtension/CMakeFiles/obj.MLIRTransformDialectIRDLExtension.dir/IRDLExtension.cpp.o
5367.809 [3208/10/4844] Building CXX object tools/mlir/lib/Dialect/SPIRV/IR/CMakeFiles/obj.MLIRSPIRVDialect.dir/SPIRVDialect.cpp.o
5369.548 [3207/10/4845] Building CXX object tools/mlir/lib/Dialect/Tosa/Transforms/CMakeFiles/obj.MLIRTosaTransforms.dir/TosaValidation.cpp.o
5371.363 [3206/10/4846] Building CXX object tools/mlir/lib/Dialect/Transform/Interfaces/CMakeFiles/obj.MLIRTransformDialectInterfaces.dir/TransformInterfaces.cpp.o
5373.220 [3205/10/4847] Building CXX object tools/mlir/lib/Dialect/Tosa/Transforms/CMakeFiles/obj.MLIRTosaTransforms.dir/TosaProfileCompliance.cpp.o
5374.049 [3204/10/4848] Building CXX object tools/mlir/lib/Dialect/Transform/IRDLExtension/CMakeFiles/obj.MLIRTransformDialectIRDLExtension.dir/IRDLExtensionOps.cpp.o
5375.134 [3203/10/4849] Building CXX object tools/mlir/lib/Dialect/Transform/LoopExtension/CMakeFiles/obj.MLIRTransformLoopExtension.dir/LoopExtension.cpp.o
5375.425 [3202/10/4850] Building CXX object tools/mlir/lib/Dialect/Transform/LoopExtension/CMakeFiles/obj.MLIRTransformLoopExtension.dir/LoopExtensionOps.cpp.o
5379.308 [3201/10/4851] Building CXX object tools/mlir/lib/Dialect/Transform/IR/CMakeFiles/obj.MLIRTransformDialect.dir/TransformDialect.cpp.o
5379.445 [3200/10/4852] Building CXX object tools/mlir/lib/Dialect/Transform/Utils/CMakeFiles/obj.MLIRTransformDialectUtils.dir/DiagnosedSilenceableFailure.cpp.o
FAILED: tools/mlir/lib/Dialect/Transform/Utils/CMakeFiles/obj.MLIRTransformDialectUtils.dir/DiagnosedSilenceableFailure.cpp.o 
/home/llvm/llvm-external-buildbots/clang.17.0.2/bin/clang++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_LARGE_FILE_API -D_XOPEN_SOURCE=700 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/llvm/llvm-external-buildbots/workers/ppc64-flang-aix-test/ppc64-flang-aix-build/build/tools/mlir/lib/Dialect/Transform/Utils -I/home/llvm/llvm-external-buildbots/workers/ppc64-flang-aix-test/ppc64-flang-aix-build/llvm-project/mlir/lib/Dialect/Transform/Utils -I/home/llvm/llvm-external-buildbots/workers/ppc64-flang-aix-test/ppc64-flang-aix-build/build/tools/mlir/include -I/home/llvm/llvm-external-buildbots/workers/ppc64-flang-aix-test/ppc64-flang-aix-build/llvm-project/mlir/include -I/home/llvm/llvm-external-buildbots/workers/ppc64-flang-aix-test/ppc64-flang-aix-build/build/include -I/home/llvm/llvm-external-buildbots/workers/ppc64-flang-aix-test/ppc64-flang-aix-build/llvm-project/llvm/include -mcmodel=large -fPIC -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wundef -Werror=mismatched-tags -Werror=global-constructors -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -pthread -MD -MT tools/mlir/lib/Dialect/Transform/Utils/CMakeFiles/obj.MLIRTransformDialectUtils.dir/DiagnosedSilenceableFailure.cpp.o -MF tools/mlir/lib/Dialect/Transform/Utils/CMakeFiles/obj.MLIRTransformDialectUtils.dir/DiagnosedSilenceableFailure.cpp.o.d -o tools/mlir/lib/Dialect/Transform/Utils/CMakeFiles/obj.MLIRTransformDialectUtils.dir/DiagnosedSilenceableFailure.cpp.o -c /home/llvm/llvm-external-buildbots/workers/ppc64-flang-aix-test/ppc64-flang-aix-build/llvm-project/mlir/lib/Dialect/Transform/Utils/DiagnosedSilenceableFailure.cpp
Could not load program /home/llvm/llvm-external-buildbots/clang.17.0.2/bin/clang++:
	Dependent module libz.a(libz.so.1) could not be loaded.
Could not load module libz.a(libz.so.1).
System error: No such file or directory
5379.971 [3200/9/4853] Building CXX object tools/mlir/lib/Dialect/Transform/PDLExtension/CMakeFiles/obj.MLIRTransformPDLExtension.dir/PDLExtension.cpp.o
5382.473 [3200/8/4854] Building CXX object tools/mlir/lib/Dialect/Transform/Transforms/CMakeFiles/obj.MLIRTransformDialectTransforms.dir/InferEffects.cpp.o
5382.512 [3200/7/4855] Building CXX object tools/mlir/lib/Dialect/Transform/PDLExtension/CMakeFiles/obj.MLIRTransformPDLExtension.dir/PDLExtensionOps.cpp.o
5383.335 [3200/6/4856] Building CXX object tools/mlir/lib/Dialect/Transform/Transforms/CMakeFiles/obj.MLIRTransformDialectTransforms.dir/CheckUses.cpp.o
5385.355 [3200/5/4857] Building CXX object tools/mlir/lib/Dialect/Transform/Transforms/CMakeFiles/obj.MLIRTransformDialectTransforms.dir/PreloadLibraryPass.cpp.o
5387.500 [3200/4/4858] Building CXX object tools/mlir/lib/Dialect/Transform/Transforms/CMakeFiles/obj.MLIRTransformDialectTransforms.dir/TransformInterpreterUtils.cpp.o
5387.781 [3200/3/4859] Building CXX object tools/mlir/lib/Dialect/Transform/Transforms/CMakeFiles/obj.MLIRTransformDialectTransforms.dir/InterpreterPass.cpp.o
5398.032 [3200/2/4860] Building CXX object tools/mlir/lib/Dialect/Transform/IR/CMakeFiles/obj.MLIRTransformDialect.dir/TransformOps.cpp.o
5399.632 [3200/1/4861] Building CXX object tools/mlir/lib/Dialect/Tosa/CMakeFiles/obj.MLIRTosaDialect.dir/IR/TosaOps.cpp.o
ninja: build stopped: subcommand failed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants