llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Erich Keane (erichkeane)

<details>
<summary>Changes</summary>

Most of the code that CIR lowers to LLVM counts on the fact that our 
alignnments are correct/calculated in LLVM to get our layout correctly. This 
works for the most part, and unions have the storage type of the 'highest' 
alignment type.

However, when creating a constant, we have to convert the type of the union to 
have a 'storage' type that matches the data being inserted (not the union's 
storage type!).  The result was that if we had a storage type where the 
alignment was smaller than the actual storage type, LLVM would mis-calculate 
the padding.

This patch adds the padding explicitly when we make that conversion to get the 
alignment set up correctly.

Note: there is one mild IR-equivilency-regression to this patch. There isn't 
really a great way to tell the difference between a union-tail-padding needing 
zero-init vs undef-init in this case. This patch chooses to make it always 
zero-init, which is harmless.  While it MIGHT suppress some optimizations 
(facts not in evidence?), it seems like something we can figure out later if 
necessary.

---

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


7 Files Affected:

- (modified) clang/include/clang/CIR/LoweringHelpers.h (+8) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+14-3) 
- (modified) clang/lib/CIR/Lowering/LoweringHelpers.cpp (+105-20) 
- (modified) clang/test/CIR/CodeGen/bitfields.cpp (+1-1) 
- (modified) clang/test/CIR/CodeGen/union-agg-init.c (+56-3) 
- (modified) clang/test/CIR/CodeGen/union-agg-init.cpp (+14) 
- (modified) clang/test/CIR/CodeGen/unions-with-zero-init.cpp (+3-3) 


``````````diff
diff --git a/clang/include/clang/CIR/LoweringHelpers.h 
b/clang/include/clang/CIR/LoweringHelpers.h
index 92633c89e1369..f0f65bb317521 100644
--- a/clang/include/clang/CIR/LoweringHelpers.h
+++ b/clang/include/clang/CIR/LoweringHelpers.h
@@ -54,6 +54,14 @@ mlir::Type adjustGlobalTypeForInit(mlir::Type llvmType, 
mlir::Attribute init,
                                    const mlir::TypeConverter &converter,
                                    const mlir::DataLayout &dataLayout);
 
+// A version of adjustGlobalTypeForInit which records where additional padding
+// was added in the middle, so we can properly adjust field indexes.
+mlir::Type
+adjustGlobalTypeForInit(mlir::Type llvmType, mlir::Attribute init,
+                        const mlir::TypeConverter &converter,
+                        const mlir::DataLayout &dataLayout,
+                        llvm::SmallVectorImpl<unsigned> &paddingAddedIndexes);
+
 mlir::Value getConstAPInt(mlir::OpBuilder &bld, mlir::Location loc,
                           mlir::Type typ, const llvm::APInt &val);
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4ae4b7693d982..7986227a2d035 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -825,15 +825,26 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
 mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
   mlir::Type llvmTy = converter->convertType(constRecord.getType());
   mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
-  llvmTy = adjustGlobalTypeForInit(llvmTy, constRecord, *converter, 
dataLayout);
+  llvm::SmallVector<unsigned> paddingAddedIndexes;
+  llvmTy = adjustGlobalTypeForInit(llvmTy, constRecord, *converter, dataLayout,
+                                   paddingAddedIndexes);
   const mlir::Location loc = parentOp->getLoc();
   mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
 
+  uint64_t insertIdx = 0;
+  auto paddingItr = paddingAddedIndexes.begin();
+
   // Iteratively lower each constant element of the record.
   for (auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
+    if (paddingItr != paddingAddedIndexes.end() && *paddingItr == idx) {
+      ++insertIdx;
+      ++paddingItr;
+    }
+
     mlir::Value init = visit(elt);
-    result =
-        mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
+    result = mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init,
+                                               insertIdx);
+    ++insertIdx;
   }
 
   return result;
diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp 
b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
index 3b927ad759c7a..db6448ee0023f 100644
--- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp
+++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
@@ -416,13 +416,23 @@ static bool shouldPackFAMStruct(const mlir::DataLayout 
&dataLayout,
 // Additionally, the struct itself could contain a struct with a FAM or a union
 // that needed adjustment, so it recurses to check those.  If no such type has
 // been found/no adjustment needed, this returns the type unchanged.
+//
+// Additionally, a union having an active member of the not-the-largest
+// alignment can cause the need for a small padding array. We also capture the
+// original indices of the fields that had this padding prepended, so the
+// lowerConstRecordAttr can later put in a 'zero' init there.
 static mlir::Type adjustGlobalStructTypeForInit(
     mlir::LLVM::LLVMStructType structTy, cir::ConstRecordAttr constRecord,
-    const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout) {
-
+    const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout,
+    llvm::SmallVectorImpl<unsigned> &paddingAddedIndexes) {
+  assert(paddingAddedIndexes.empty() &&
+         "Not for accumulation, just single depth");
   llvm::ArrayRef<mlir::Attribute> initMembers =
       constRecord.getMembers().getValue();
-  llvm::SmallVector<mlir::Type> newBody{structTy.getBody()};
+  llvm::SmallVector<mlir::Type> origBody{structTy.getBody()};
+  llvm::SmallVector<mlir::Type> newBody{};
+  bool packed = structTy.isPacked();
+  uint64_t curOffset = 0;
   bool changed = false;
 
   // Recursively adjust each member. A member that is itself a union (or a
@@ -430,14 +440,45 @@ static mlir::Type adjustGlobalStructTypeForInit(
   // field type, and this struct has to adopt that adjusted type so the
   // enclosing insertvalue chain type-checks.
   for (auto [idx, member] : llvm::enumerate(initMembers)) {
-    if (idx >= newBody.size())
+    if (idx >= origBody.size())
       break;
-    mlir::Type adjusted =
-        adjustGlobalTypeForInit(newBody[idx], member, converter, dataLayout);
-    if (adjusted != newBody[idx]) {
-      newBody[idx] = adjusted;
+    mlir::Type adjusted = adjustGlobalTypeForInit(
+        origBody[idx], member, converter, dataLayout);
+    unsigned adjustedAlign = dataLayout.getTypeABIAlignment(adjusted);
+
+    if (adjusted != origBody[idx]) {
+      // We're always going to 'change' the layout if it has changed, but we
+      // need to see if there is new 'padding' that won't happen automatically
+      // here based on alignment.
+      unsigned origAlign = dataLayout.getTypeABIAlignment(origBody[idx]);
+
+      uint64_t origOffset =
+          packed ? curOffset : llvm::alignTo(curOffset, origAlign);
+      uint64_t adjustedOffset =
+          packed ? curOffset : llvm::alignTo(curOffset, adjustedAlign);
+
+      if (adjustedOffset != origOffset) {
+        // If the offset would change, we have to insert padding to make up for
+        // it. This should only happen since alignment will decrease with
+        // unions, so we should be able to assume adjusted-offset < origOffset?
+        assert(adjustedOffset < origOffset);
+        // Rather than just pad the difference between the offsets, we have to
+        // fill in since the end of the last field, else we leave room thanks 
to
+        // alignment between this field and the padding.
+        uint64_t difference = origOffset - curOffset;
+        newBody.push_back(mlir::LLVM::LLVMArrayType::get(
+            mlir::IntegerType::get(structTy.getContext(), 8),
+            difference));
+        paddingAddedIndexes.push_back(idx);
+        curOffset = origOffset;
+      }
       changed = true;
     }
+    newBody.push_back(adjusted);
+
+    if (!packed)
+      curOffset = llvm::alignTo(curOffset, adjustedAlign);
+    curOffset += dataLayout.getTypeSize(adjusted).getFixedValue();
   }
 
   // CIR supports flexible-array-members in its struct types. That is, a
@@ -446,7 +487,7 @@ static mlir::Type adjustGlobalStructTypeForInit(
   // these, and our verifier allows it. However, the LLVM implementation does
   // NOT permit this, so we widen that trailing member to the initializer's
   // array type (packing the struct if that changes the layout).
-  bool packed = structTy.isPacked();
+  bool widenedFAM = false;
   if (auto fam =
           mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(structTy.getBody().back());
       fam && fam.getNumElements() == 0) {
@@ -455,6 +496,7 @@ static mlir::Type adjustGlobalStructTypeForInit(
     if (mlir::cast<cir::ArrayType>(lastInitType).getSize() != 0) {
       newBody.back() = converter.convertType(lastInitType);
       packed = packed || shouldPackFAMStruct(dataLayout, newBody);
+      widenedFAM = true;
       changed = true;
     }
   }
@@ -462,6 +504,19 @@ static mlir::Type adjustGlobalStructTypeForInit(
   if (!changed)
     return structTy;
 
+  // We've likely reduced the alignment, so make sure we put padding 'behind'
+  // it.  We can skip this in the FAM case, since a Flexible array member is 
not
+  // allowed to be initialized unless it is the 'last' element.  So it doesn't
+  // need to be padded out.
+  if (!widenedFAM) {
+    uint64_t declaredSize = dataLayout.getTypeSize(structTy).getFixedValue();
+    assert(curOffset <= declaredSize && "body bigger than type?");
+    if (curOffset < declaredSize)
+      newBody.push_back(mlir::LLVM::LLVMArrayType::get(
+          mlir::IntegerType::get(structTy.getContext(), 8),
+          declaredSize - curOffset));
+  }
+
   return mlir::LLVM::LLVMStructType::getLiteral(structTy.getContext(), newBody,
                                                 packed);
 }
@@ -515,9 +570,11 @@ static mlir::Type adjustGlobalUnionTypeForInit(
 }
 
 // Apply various adjustments required for struct/union types.
-mlir::Type adjustGlobalTypeForInit(mlir::Type llvmType, mlir::Attribute init,
-                                   const mlir::TypeConverter &converter,
-                                   const mlir::DataLayout &dataLayout) {
+mlir::Type
+adjustGlobalTypeForInit(mlir::Type llvmType, mlir::Attribute init,
+                        const mlir::TypeConverter &converter,
+                        const mlir::DataLayout &dataLayout,
+                        llvm::SmallVectorImpl<unsigned> &paddingAddedIndexes) {
   // Conversions for both only happen if we have a record init.
   auto constRecord = mlir::dyn_cast_if_present<cir::ConstRecordAttr>(init);
   if (!constRecord)
@@ -532,16 +589,25 @@ mlir::Type adjustGlobalTypeForInit(mlir::Type llvmType, 
mlir::Attribute init,
   // Structs can have a flexible array member, adjust that.
   if (mlir::isa<cir::StructType>(constRecord.getType()))
     return adjustGlobalStructTypeForInit(structTy, constRecord, converter,
-                                         dataLayout);
+                                         dataLayout, paddingAddedIndexes);
   if (mlir::isa<cir::UnionType>(constRecord.getType()))
     return adjustGlobalUnionTypeForInit(structTy, constRecord, converter,
                                         dataLayout);
   return llvmType;
 }
 
+mlir::Type adjustGlobalTypeForInit(mlir::Type llvmType, mlir::Attribute init,
+                                   const mlir::TypeConverter &converter,
+                                   const mlir::DataLayout &dataLayout) {
+  llvm::SmallVector<unsigned> ignoredAddedIndexes;
+  return adjustGlobalTypeForInit(llvmType, init, converter, dataLayout,
+                                 ignoredAddedIndexes);
+}
+
 std::optional<mlir::Attribute> lowerConstRecordAttr(
     cir::ConstRecordAttr constRecord, mlir::SymbolTableCollection 
&symbolTables,
     const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp) {
+
   // Build one constant attribute per record member. The LLVM dialect global
   // translation accepts an ArrayAttr (one element per struct field) and emits
   // an llvm::ConstantStruct, so the whole initializer can be a single
@@ -558,18 +624,37 @@ std::optional<mlir::Attribute> lowerConstRecordAttr(
   }
 
   // The lowered LLVM type may have more fields than the CIR record has members
-  // -- e.g. a union lowers to { active-member, [pad x i8] } (see
-  // adjustGlobalTypeForInit, the single source of truth for the shape). Fill
-  // any such synthesized (padding) fields with undef so this ArrayAttr has
-  // exactly one entry per LLVM field, matching the type the global is declared
-  // with.
+  // for a few reasons: 
+  // 1- a union lowers to { active-member, [pad x i8]). 
+  // 2- A struct that contains such a union can have its alignment changed too,
+  //    so it needs tail padding to fill that in.
+  // 3- A struct containing a union whose initializer doesn't use the 
highest-aligned
+  // field will have to prepend a bit of padding, such as struct { i32, union {
+  // i64, i32 } }.  Typically the union gets lowered to a struct { i64 } (as 
i64
+  // has the greatest alignment), but if the init causes it to be the i32(or 
any
+  // such smaller field) we have to prepend it with padding: 
+  // struct { i32, [4 x i8], struct { i32 }}
+  // instead of (with no init):
+  // struct { i32, struct { i64 }}
+  llvm::SmallVector<unsigned> paddingAddedIndexes;
   mlir::Type adjustedTy = adjustGlobalTypeForInit(
       converter->convertType(constRecord.getType()), constRecord, *converter,
-      mlir::DataLayout(moduleOp));
+      mlir::DataLayout(moduleOp), paddingAddedIndexes);
+
+  // This handles #3 from above. adjustGlobalTypeForInit ensures the
+  // indexes are in increasing order, so we can insert 'backwards' without
+  // causing problems.
+  for (unsigned paddedElt : llvm::reverse(paddingAddedIndexes))
+    loweredMembers.insert(loweredMembers.begin() + paddedElt,
+        mlir::LLVM::ZeroAttr::get(constRecord.getContext()));
+
+  // Any remaining difference will be the union/struct padding case. We don't
+  // have a great handle/way to tell when to zero-vs-undef init, so always
+  // zero init, as it is always safe to do so.
   if (auto structTy = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(adjustedTy))
     while (loweredMembers.size() < structTy.getBody().size())
       loweredMembers.push_back(
-          mlir::LLVM::UndefAttr::get(constRecord.getContext()));
+          mlir::LLVM::ZeroAttr::get(constRecord.getContext()));
 
   return mlir::ArrayAttr::get(constRecord.getContext(), loweredMembers);
 }
diff --git a/clang/test/CIR/CodeGen/bitfields.cpp 
b/clang/test/CIR/CodeGen/bitfields.cpp
index f1d2561dc2e44..7dce9bf29cd4a 100644
--- a/clang/test/CIR/CodeGen/bitfields.cpp
+++ b/clang/test/CIR/CodeGen/bitfields.cpp
@@ -32,7 +32,7 @@ typedef struct {
 union U { int x : 3; };
 const U u = {5};
 // CIR-DAG: cir.global "private" {{.*}}@_ZL1u = #cir.const_record<{#cir.int<5> 
: !u8i}> : !rec_U
-// LLVM-DAG: @_ZL1u = internal constant %union.U { i8 5, [3 x i8] undef }
+// LLVM-DAG: @_ZL1u = internal constant %union.U { i8 5, [3 x i8] 
zeroinitializer }
 // OGCG-DAG: @_ZL1u = internal constant %union.U { i8 5, [3 x i8] undef }
 auto use() {
   return u;
diff --git a/clang/test/CIR/CodeGen/union-agg-init.c 
b/clang/test/CIR/CodeGen/union-agg-init.c
index ab603d24d8712..ca390d25461d6 100644
--- a/clang/test/CIR/CodeGen/union-agg-init.c
+++ b/clang/test/CIR/CodeGen/union-agg-init.c
@@ -5,15 +5,67 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
 // RUN: FileCheck --check-prefix=LLVM,OGCG --input-file=%t.ll %s
 
+union PtrToIntUnion { int id; char *str; };
+struct HasPtoIU { int info; union PtrToIntUnion u; };
+struct HasPtoIU ptoIU = { 101, { 1 } };
+// CIR-DAG: cir.global external @ptoIU = #cir.const_record<{#cir.int<101> : 
!s32i, #cir.const_record<{#cir.int<1> : !s32i}> : !rec_PtrToIntUnion}> : 
!rec_HasPtoIU
+// LLVM-DAG: @ptoIU = global { i32, [4 x i8], { i32, [4 x i8] } } { i32 101, 
[4 x i8] zeroinitializer, { i32, [4 x i8] } { i32 1, [4 x i8] zeroinitializer } 
}
+
+struct WithTailPadding { int info; union PtrToIntUnion u; int tail; };
+struct WithTailPadding  tailPadding = { 101, { 1 }, 42 };
+// CIR-DAG: cir.global external @tailPadding = 
#cir.const_record<{#cir.int<101> : !s32i, #cir.const_record<{#cir.int<1> : 
!s32i}> : !rec_PtrToIntUnion, #cir.int<42> : !s32i}> : !rec_WithTailPadding
+// LLVM-DAG: @tailPadding = global { i32, [4 x i8], { i32, [4 x i8] }, i32, [4 
x i8] } { i32 101, [4 x i8] zeroinitializer, { i32, [4 x i8] } { i32 1, [4 x 
i8] zeroinitializer }, i32 42, [4 x i8] zeroinitializer }
+
+struct AtStart { union PtrToIntUnion u; int x; };
+struct AtStart start = { 7, 9 };
+// CIR-DAG: cir.global external @start = 
#cir.const_record<{#cir.const_record<{#cir.int<7> : !s32i}> : 
!rec_PtrToIntUnion, #cir.int<9> : !s32i}> : !rec_AtStart
+// LLVM-DAG: @start = global { { i32, [4 x i8] }, i32, [4 x i8] } { { i32, [4 
x i8] } { i32 7, [4 x i8] zeroinitializer }, i32 9, [4 x i8] zeroinitializer }
+
+struct NotToplevel { char c; struct WithTailPadding inner; };
+struct NotToplevel notTop = { 'x', { 101, { 1 }, 42 } };
+// CIR-DAG: cir.global external @notTop = #cir.const_record<{#cir.int<120> : 
!s8i, #cir.const_record<{#cir.int<101> : !s32i, #cir.const_record<{#cir.int<1> 
: !s32i}> : !rec_PtrToIntUnion, #cir.int<42> : !s32i}> : !rec_WithTailPadding}> 
: !rec_NotToplevel
+// LLVM-DAG: @notTop = global { i8, [7 x i8], { i32, [4 x i8], { i32, [4 x i8] 
}, i32, [4 x i8] } } { i8 120, [7 x i8] zeroinitializer, { i32, [4 x i8], { 
i32, [4 x i8] }, i32, [4 x i8] } { i32 101, [4 x i8] zeroinitializer, { i32, [4 
x i8] } { i32 1, [4 x i8] zeroinitializer }, i32 42, [4 x i8] zeroinitializer } 
}
+
+struct TwoUnions {
+  int a;
+  union PtrToIntUnion u1;
+  int b;
+  union PtrToIntUnion u2;
+};
+struct TwoUnions two_unions = { 1, { 2 }, 3, { 4 } };
+// CIR-DAG: cir.global external @two_unions = #cir.const_record<{#cir.int<1> : 
!s32i, #cir.const_record<{#cir.int<2> : !s32i}> : !rec_PtrToIntUnion, 
#cir.int<3> : !s32i, #cir.const_record<{#cir.int<4> : !s32i}> : 
!rec_PtrToIntUnion}> : !rec_TwoUnions
+// LLVM-DAG: @two_unions = global { i32, [4 x i8], { i32, [4 x i8] }, i32, [4 
x i8], { i32, [4 x i8] } } { i32 1, [4 x i8] zeroinitializer, { i32, [4 x i8] } 
{ i32 2, [4 x i8] zeroinitializer }, i32 3, [4 x i8] zeroinitializer, { i32, [4 
x i8] } { i32 4, [4 x i8] zeroinitializer } }
+
+struct Anon { int info; union { int id; char *str; } u; };
+struct Anon anon = { 101, 1 };
+// CIR-DAG: cir.global external @anon = #cir.const_record<{#cir.int<101> : 
!s32i, #cir.const_record<{#cir.int<1> : !s32i}> : !rec_anon2E0}> : !rec_Anon
+// LLVM-DAG: @anon = global { i32, [4 x i8], { i32, [4 x i8] } } { i32 101, [4 
x i8] zeroinitializer, { i32, [4 x i8] } { i32 1, [4 x i8] zeroinitializer } }
+
+struct Bitfields { int a : 3; int b : 4; union PtrToIntUnion u; };
+struct Bitfields bitfields = { 1, 2, { 9 } };
+// CIR-DAG: cir.global external @bitfields = #cir.const_record<{#cir.int<17> : 
!u8i, #cir.const_record<{#cir.int<9> : !s32i}> : !rec_PtrToIntUnion}> : 
!rec_Bitfields {alignment = 8 : i64} loc(#loc42)
+// LLVM-DAG: @bitfields = global { i8, [7 x i8], { i32, [4 x i8] } } { i8 17, 
[7 x i8] zeroinitializer, { i32, [4 x i8] } { i32 9, [4 x i8] zeroinitializer } 
}
+
+struct FamUnion { int n; union PtrToIntUnion u; char fam[]; };
+struct FamUnion fam_union = { 3, { 7 }, { 'a','b','c' } };
+// CIR-DAG: cir.global external @fam_union = #cir.const_record<{#cir.int<3> : 
!s32i, #cir.const_record<{#cir.int<7> : !s32i}> : !rec_PtrToIntUnion, 
#cir.const_array<[#cir.int<97> : !s8i, #cir.int<98> : !s8i, #cir.int<99> : 
!s8i]> : !cir.array<!s8i x 3>}> : !rec_FamUnion
+// LLVM-DAG: @fam_union = global <{ i32, [4 x i8], { i32, [4 x i8] }, [3 x i8] 
}> <{ i32 3, [4 x i8] zeroinitializer, { i32, [4 x i8] } { i32 7, [4 x i8] 
zeroinitializer }, [3 x i8] c"abc" }>
+
+struct FamMoves { char c; union PtrToIntUnion u; char fam[]; };
+struct FamMoves fam_realign = { 'q', { 7 }, { 'a','b','c' } };
+// CIR-DAG: cir.global external @fam_realign = 
#cir.const_record<{#cir.int<113> : !s8i, #cir.const_record<{#cir.int<7> : 
!s32i}> : !rec_PtrToIntUnion, #cir.const_array<[#cir.int<97> : !s8i, 
#cir.int<98> : !s8i, #cir.int<99> : !s8i]> : !cir.array<!s8i x 3>}> : 
!rec_FamMoves
+// LLVM-DAG: @fam_realign = global <{ i8, [7 x i8], { i32, [4 x i8] }, [3 x 
i8] }> <{ i8 113, [7 x i8] zeroinitializer, { i32, [4 x i8] } { i32 7, [4 x i8] 
zeroinitializer }, [3 x i8] c"abc" }>
+
+
 typedef union vec3 {
   struct { double x, y, z; };
   double component[3];
 } vec3;
 
-// LLVMCIR: @__const.ret_outer.__retval = {{.*}}%struct.outer { 
%union.needs_padding zeroinitializer, i32 1 }
-// OGCG: @__const.ret_outer.o = {{.*}}{ { i32, [4 x i8] }, i32, [4 x i8] } { { 
i32, [4 x i8] } zeroinitializer, i32 1, [4 x i8] zeroinitializer }
+// LLVMCIR-DAG: @__const.ret_outer.__retval = {{.*}}%struct.outer { 
%union.needs_padding zeroinitializer, i32 1 }
+// OGCG-DAG: @__const.ret_outer.o = {{.*}}{ { i32, [4 x i8] }, i32, [4 x i8] } 
{ { i32, [4 x i8] } zeroinitializer, i32 1, [4 x i8] zeroinitializer }
 
-// CIR: cir.global "private" constant cir_private @__const.ret_outer.__retval 
= #cir.const_record<{#cir.zero : !rec_needs_padding, #cir.int<1> : !s32i}> : 
!rec_outer
+// CIR-DAG: cir.global "private" constant cir_private 
@__const.ret_outer.__retval = #cir.const_record<{#cir.zero : 
!rec_needs_padding, #cir.int<1> : !s32i}> : !rec_outer
 
 // In C mode, this does do zero padding.
 vec3 ret_vec3() {
@@ -67,3 +119,4 @@ struct outer ret_outer() {
   // OGCG: %[[RET:.*]] = load { i64, i32 }, ptr %[[RET_ALLOCA]]
   // LLVM: ret { i64, i32 } %[[RET]]
 }
+
diff --git a/clang/test/CIR/CodeGen/union-agg-init.cpp 
b/clang/test/CIR/CodeGen/union-agg-init.cpp
index 86c94c596572c..8ce84648577e8 100644
--- a/clang/test/CIR/CodeGe...
[truncated]

``````````

</details>


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

Reply via email to