[CIR] Handle an empty C++ class in x86_64 callconv lowering (#214742)
CIR lays a C++ empty class out as a record that is nothing but padding,
and isSupportedType rejected every padded record, so any signature
naming one failed the pass with an NYI. Ordinary C++ hits this
constantly through tag dispatch, allocators, and empty bases.
Implement empty C++ class support. Every record member now carries a
kind, so a record holds no data exactly when none of them is marked
data, which `RecordType::isEmptyForABI()` answers and the pass reads. An
empty record then maps with no fields, so the classifier drops it on its
own.
Assisted-by: Cursor / claude-opus-5
[llvm-nm][GOFF] Display archive attributes in GOFF archives through --print-armap
GOFF archive symbol table entries contain an attribute word in addition
to the archive member offset. The low three bits describe whether the symbol is
64-bit, uses XPLink, or belongs to the WSA namespace (which was briefly mentioned
in e2c8fa09872cfacba7f73599dcf8557971ebe865).
This patch extends `llvm-nm --print-armap` to print the attribute value (in hex) and
its decoded description beside a symbol and its corresponding member when processing
a GOFF archive. This will functionality will be used to help validate full support for writing
GOFF archives in a subsequent llvm-ar patch.
The output for non-z/OS archives is unchanged.
[BOLT] Skip data-hole filling unless data reordering is enabled
BinaryContext::postProcessSymbolTable unconditionally called
fixBinaryDataHoles(), which walks every allocatable section and, for
each gap in its address space, either grows a zero-sized data symbol
or creates a synthetic "HOLEat" BinaryData (plus an MCSymbol and
GlobalSymbols/BinaryDataMap entries). This machinery was introduced
(0e4d86bf, 2017) for one purpose: to give static data reordering
(-reorder-data) a movable object covering every byte of a section. It
has no other consumer.
On a large binary, these synthetic objects are live from
buildFunctionsCFG through the end of the run and, at the RSS peak
(during debug info rewriting), fixBinaryDataHoles accounted for 1669
MB (2.5%) of peak RSS -- memory spent entirely for a feature that is
off by default.
Gate fixBinaryDataHoles() (and the zero-sized-symbol validation loop
that presumes it ran) on a non-empty opts::ReorderData, keeping
generateSymbolHashes() unconditional.
[BOLT] Key GlobalSymbols on MCContext-owned names to reduce memory (#214891)
BinaryContext::registerNameAtAddress registers every symbol name twice.
It first calls MCContext::getOrCreateSymbol(Name), which interns the
name in MCContext's symbol table (the MCSymbol owns the string via its
table entry). It then also stored the name in the GlobalSymbols map,
which was a StringMap<BinaryData *>. StringMap owns its keys, so each
global name was duplicated: one copy in MCContext and a second copy in
GlobalSymbols. Both grow with the number of symbols and, for large
binaries with long mangled names, this duplication is a meaningful
source of memory use during file object discovery.
This change makes MCContext the single owner of these name strings and
have GlobalSymbols merely reference them. GlobalSymbols becomes a
DenseMap<StringRef, BinaryData *> keyed on the MCContext-owned name
(MCSymbol::getName() of the symbol just created/looked up). No string is
copied into the map: each entry is a fixed-size (StringRef, pointer)
pair regardless of name length. Lookups (getBinaryDataByName, count) are
unchanged because DenseMap<StringRef> hashes and compares by content,
[7 lines not shown]
[AMDGPU] Correct DS FIFO buffer size semantics
There was some ambiguity in how buffersize 0 and 1 are handled. The
correct semantics are:
- `BufferSize == 0`: unlimited, no FIFO stall
- `BufferSize == 1`: unbuffered, only one instruction in flight
- `BufferSize > 1`: buffered FIFO
[BOLT] Page out .dwo files (#214903)
Split-DWARF inputs at big binaries scale ship 100+ GiB of .dwo files.
BOLT opened a fair number of them during readDebugInfo, putting a lot of
pressure on the OS memory management: mmap'd reads always populate the
page cache; with every .dwo mapped at once those pages accumulated,
refaulted, and registered as memory pressure that got the process
oomd-killed.
Now, .dwo page-cache pages are reclaimed as soon as BOLT is done with
each file: madvise(MADV_PAGEOUT) on the live mapping, then
posix_fadvise(POSIX_FADV_DONTNEED) once it is unmapped. Controlled by
-drop-dwo-page-cache, OFF by default, as it is unlikely upstream will be
processing gigantic sets of dwo files.
[BOLT] Create and release .dwo DWARF contexts incrementally (#214900)
BOLT opened a DWARFContext for every .dwo during
readDebugInfo and kept them all alive until teardown. On large
split-DWARF targets that is tens of GiB held resident through emission,
the point of peak RSS.
Make the DWOCUs map a lazily-populated cache instead:
* Use the newly added DWARFUnit::clearDWO()/hasDWO() to directly manage
DWARFUnit's DIE caching mechanism.
* BinaryContext::getDWOCU() opens a context on demand (keyed off a
stable DWOId -> skeleton CU map).
* Release contexts as soon as they are done with: all of them at the end
of readDebugInfo, and per-bucket at the DWARF rewrite merge point.
* Remove DWOCUs map, which became redundant and whose purpose can now be
served by the new id-to-skeleton map, and then fetching the split CU
from the skeleton via getNonSkeletonUnitDIE().
[3 lines not shown]
[CIR][NFC] Fix loop op examples in CIROps.td (#216457)
### summary
The cir.while example had cond and body swapped, and several loop
examples used outdated cir.condition / cir.for syntax. Also add short
examples of the optional per-iteration cleanup region.
Generated by Grok 4.6, but manually reviewed.
[BOLT] Page out .dwo files
Split-DWARF inputs at big binaries scale ship 100+ GiB of .dwo
files. BOLT opened a fair number of them during readDebugInfo, putting
a lot of pressure on the OS memory management: mmap'd reads always
populate the page cache; with every .dwo mapped at once those pages
accumulated, refaulted, and registered as memory pressure that got the
process oomd-killed.
Now, .dwo page-cache pages are reclaimed as soon as BOLT is done with
each file: madvise(MADV_PAGEOUT) on the live mapping, then
posix_fadvise(POSIX_FADV_DONTNEED) once it is unmapped. Controlled by
-drop-dwo-page-cache, OFF by default, as it is unlikely upstream
will be processing gigantic sets of dwo files.
[BOLT] Create and release .dwo DWARF contexts incrementally
BOLT opened a DWARFContext for every .dwo during
readDebugInfo and kept them all alive until teardown. On large
split-DWARF targets that is tens of GiB held resident through
emission, the point of peak RSS.
Make the DWOCUs map a lazily-populated cache instead:
* Use the newly added DWARFUnit::clearDWO()/hasDWO() to directly
manage DWARFUnit's DIE caching mechanism.
* BinaryContext::getDWOCU() opens a context on demand (keyed off a
stable DWOId -> skeleton CU map).
* Release contexts as soon as they are done with: all of them at the
end of readDebugInfo, and per-bucket at the DWARF rewrite merge
point.
* Remove DWOCUs map, which became redundant and whose purpose can
now be served by the new id-to-skeleton map, and then fetching
the split CU from the skeleton via getNonSkeletonUnitDIE().
[5 lines not shown]
[DebugInfo] Add DWARFUnit::clearDWO() (#214899)
Add DWARFUnit::clearDWO() so a skeleton unit can drop the DWO context it
owns without being destroyed itself. Also add DWARFUnit::getDWO() to
answer, without creating a new one, if that skeleton CU is currently
caching a DWO context.
For example, BOLT opened a DWARFContext for every .dwo during
readDebugInfo and kept them all alive until teardown. On large
split-DWARF targets that is tens of GiB held
resident. clearDWO()/getDWO() expose to users DWARFUnit's caching
capacity, allowing them to spontaneously drop the cache/look it
up/re-load it for memory management. To demonstrate this, in
llvm-dwarfdump we now make use of the same technique to avoid ballooning
peak RSS when dumping binaries with dwos. Whenever --debug-info --dwo is
used, during the loop dumping non-skeleton DIEs, we clearDWO as soon as
we're done with that unit. Testing on a large binary, this was shown to
reduce peakRSS from 50GB to 590MB.
Handle DS FIFO accounting edge cases
Saturate hardware-unit pressure decrements and treat buffer sizes zero
and one as disabling buffering to avoid underflow and inconsistent stall
costs.
[AMDGPU] Use DS latency for FIFO scheduling
Use instruction latency for DS hardware-unit cycle accounting so the FIFO
model can identify a full buffer. Add focused MIR coverage for the resulting
stall cost and scheduling decision, and regenerate the integration checks.
Change-Id: I2f4df2e97d145af4935872dbd43108e1b55077ab
[orc-rt] Use StringOutputStream in executor error messages (#217167)
Replace std::ostringstream and std::to_string in the executor's
error-message construction with orc_rt::StringOutputStream, dropping
<sstream> (and its iostreams + locale machinery) from the executor,
which runs on-target including on freestanding platforms.
Converted SimpleNativeMemoryMap.cpp, ExecutorProcessInfo.cpp, and
Unix/NativeDylibAPIs.inc; NativeDylibManager.cpp no longer needs to
include <sstream> for the latter. Messages that only feed an error are
built from a StringOutputStream temporary; one all-literal message drops
the stream entirely.
Hex values now carry a "0x" prefix (StringOutputStream::hex always emits
one), where the old std::hex produced bare digits. No test depends on
the exact message text.
[flang][Lower] Rewrite present of device variable to deviceptr (#217164)
A cuda device variable is always "present" on the device. Rewrite such
occurrences to deviceptr in the front end while we still have the
information about which variable is a cuda device variable.
[AMDGPU] Re-implement splat scalar handling for packed 64-bit ops (#216896)
In instruction selection, we identify the splat scalar pattern and set opsel to 0.
The legalizer is responsible for moving SGPRs to VGPRs if opsel is not 0.
A future optimization could save SGPR copies for upper lanes since hardware
only reads the first SGPR.
This new implementation fixes the issue when an uniform value has to be
computed by a VALU-only instruction, and thus the result is in a VGPR. This will
lead to the missing data in the upper lane with the previous approach.
[docs] Parallelize Sphinx builds by default
Sphinx supports building documents in parallel with -j. Default LLVM_PARALLEL_SPHINX_JOBS to half the logical cores, rounded up, using CMake's native host system information query, and pass it to sphinx-build. If LLVM_PARALLEL_SPHINX_JOBS is explicitly set empty, omit the -j flag.
3-run hyperfine comparison for clean docs-llvm-html builds, removing the html output and doctree cache before each timing run:
before (no sphinx -j): 97.897 s +/- 1.231 s
after (-j 8): 52.334 s +/- 15.348 s
speedup: 1.87x +/- 0.55x
Validation:
- cmake -S llvm -B build-docs-preview-all
- ninja -C build-docs-preview-all docs-llvm-html
- hyperfine --runs 3 comparing docs-llvm-html before/after
- git diff --check
- scanned touched file for internal-only markers