[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