[clang] [CIR] Emit trailing-zero array constants as a compact split (PR #205918)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 29 11:57:43 PDT 2026


================
@@ -1163,6 +1163,27 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
 
   const unsigned trailingZeroes = arrayBound - nonzeroLength;
 
+  // If we have a significant block of trailing zeros and a common scalar
+  // (integer or floating-point) element type, prefer a single ConstArrayAttr
+  // of the desired array type with a `trailingZerosNum` hint instead of
+  // synthesizing a packed anonymous record around a `[N x t] zeroinitializer`
+  // tail. This keeps the array's type in agreement with what the enclosing
+  // record layout expects.  The element-type guard must stay in sync with the
+  // CIR-to-LLVM split predicate (shouldSplitTrailingZeros): pointer/bool arrays
+  // are not split there, so emitting the hint for them would just materialize
+  // the whole tail.  Those keep the anonymous-record path below.
+  if (trailingZeroes >= 8 && commonElementType &&
----------------
adams381 wrote:

I'm dropping the `CIRGenExprConstant.cpp` change -- #206137 makes it redundant anyway, since it already emits arrays as `#cir.const_array<[...], trailing_zeros>` straight from CIRGen.  That leaves this PR as just the CIR-to-LLVM side you described in #206137 ("lowered to full-arrays in LLVM...  #205918 intends to fix this"): the `ConstArrayAttr` value converter emitting a compact `{ init, [zeros x T] zeroinitializer }` instead of materializing the whole tail.

The compact form changes the global's LLVM type from `[N x T]` to a packed struct (the shape classic emits), and a `cir.global_view`'s indices stay relative to the original array, so the GEP goes out of bounds unless it's rebased onto that array type.  That's what the basis lookup in the `global_view` visitor does -- `const-array-trailing-zeros-split.cir` pins it (the `@top_lt8, [50]` view walks the original `!llvm.array<111 x i32>`).  The nested case is the same shape: an array split inside a record makes the record's produced type diverge, so the enclosing aggregate has to follow.  So that bookkeeping falls out of the type change rather than being something I added on top.

I considered just not splitting globals that have a view into them, but that's more conditional logic, not less, and a view can land mid-array.  So: do you want the `global_view`/nesting handling kept here (stacked on #206137), moved into #206137, or done some other way?  I'll cut it to the minimum either way.  I just don't want to delete something load-bearing to look simpler and bring back the out-of-bounds GEP.

https://github.com/llvm/llvm-project/pull/205918


More information about the cfe-commits mailing list