[clang] [CodeGen] Refactor accumulateBitFields into two passes (PR #182814)
Fangrui Song via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 6 10:52:14 PST 2026
MaskRay wrote:
I understand the review cost and appreciate the work that went into the original algorithm #65742.
I wouldn't propose this refactoring purely for code structure.
The motivation is practical: I need to ensure all bit-field memory accesses are 8 bytes (for a specific use case). This worked before #65742 changed how int64_t/uint64_t bit-fields are handled. After that change broke it, I spent many hours studying the algorithm to figure out a workaround (and then many hours to develop this refactoring).
The interleaved loop made it genuinely difficult to understand where and how access unit sizing decisions are made.
**The is still the same algorithm with the two logical phases made explicit.
The output is unchanged.**
Extracting some helpers would reduce `if/for` nesting but the structural complexity will remain, e.g. `InstallBest` set in 5 places. I believe no helper extraction will fix that without splitting the loop.
That said, I'm happy to land the getLimitOffset extraction as a first step if you'd prefer an incremental approach.
To be more concrete, these local variables are eliminated by this refactoring
```
AtAlignedBoundary (bool)
Flag: true iff Field is the (potential) start of a new span (or the end of
the bitfields). Drove the main control flow branch in the single loop.
Eliminated because Pass 1 handles span detection explicitly.
Barrier (bool, loop-scoped)
Flag: true when the current boundary is a zero-width bitfield or non-bitfield,
preventing merging with the next span. Eliminated because Pass 1 records this
as the Barrier field in BitFieldSpan.
InstallBest (bool)
Flag: true when the loop should emit the best access unit and reset.
Had 5 separate sites that set it to true. Eliminated because Pass 2 uses
explicit break/continue control flow instead of flag-driven dispatch.
BitSizeSinceBegin (uint64_t)
Running bit count of the current accumulation, including padding when
advanced past a subsequent bitfield run. Eliminated because Pass 2
computes AccessSize directly from span offsets and sizes.
LimitOffset (CharUnits)
Per-iteration limit offset (next field with storage or tail clipping).
Eliminated as a variable; now computed on demand by the getLimitOffset lambda.
Begin (RecordDecl::field_iterator, mutable)
Start of the current span, mutated throughout the loop.
Eliminated because Pass 2 indexes spans via Spans[I].Begin.
```
https://github.com/llvm/llvm-project/pull/182814
More information about the cfe-commits
mailing list