4276 Commits

Author SHA1 Message Date
Fangrui Song
c889454f1d
[MC] Rename PrivateGlobalPrefix to InternalSymbolPrefix. NFC (#185164)
The "private global" terminology, likely came from
llvm/lib/IR/Mangler.cpp, is misleading: "private" is the opposite of
"global", and these prefixed symbols are not global in the object file
format sense (e.g. ELF has STB_GLOBAL while these symbols are always
STB_LOCAL). The term "internal symbol" better describes their purpose:
symbols for internal use by compilers and assemblers, not meant to be
visible externally.

This rename is a step toward adopting the "internal symbol prefix"
terminology agreed with GNU as
(https://sourceware.org/pipermail/binutils/2026-March/148448.html).
2026-03-10 01:03:27 -07:00
paperchalice
a266f60ddf
[SelectionDAG] Remove NoNaNsFPMath uses (#183448)
This pr removes the rest uses in LLVMCodeGen.
2026-03-10 14:06:42 +08:00
Maryam Moghadas
f7a48fbefa
[PowerPC] Add AMO load with Compare and Swap Not Equal (#178061)
This commit adds support for lwat/ldat atomic operations with function
code 16 (Compare and Swap Not Equal) via 4 clang builtins:

__builtin_amo_lwat_csne for 32-bit unsigned operations 
__builtin_amo_ldat_csne for 64-bit unsigned operations
 __builtin_amo_lwat_csne_s for 32-bit signed operations 
__builtin_amo_ldat_csne_s for 64-bit signed operations
2026-03-09 13:50:08 -04:00
Sean Fertile
c2db12daa1
[AIX] Sort relocations in XCOFF object writer. (#180807)
Some relocations (like R_REF) are emitted to an offset 0 within the CSECT. If other relocations have already been emitted then the relocations are not in increasing order and the linker will emit an error. Sort the relocations before emitting to fix the problem.
2026-03-04 12:25:11 -05:00
Craig Topper
98c46261d9
[TargetLowering][PowerPC] Don't unroll vector CLMUL when MUL is not supported. (#184238)
We can use the bittest lowering instead.
2026-03-03 17:25:54 -08:00
Craig Topper
d20395cfa3
[LegalizeVectorOps][RISCV][PowerPC][AArch64][X86] Enable the clmul/clmulr/clmulh expansion code. (#184257)
These opcodes weren't added to the master switch statement that
determines if they should be considered vector ops.
2026-03-02 21:50:40 -08:00
zhijian lin
67a51ea34d
[NFC][POWER] add Pre-Commit test case for Inefficient std::bit_floor(x) (#183363)
add a pre-commit test case for Inefficient asm of std::bit_floor(x) for
powerpc.
2026-02-27 13:24:34 -05:00
paperchalice
dc66b51a70
[PowerPC] Remove NoNaNsFPMath uses (#183449) 2026-02-27 04:45:54 +08:00
zhijian lin
da851db4bb
[PowerPC] using milicode call for memccpy instead of lib call (#182563)
AIX has "millicode" routines, which are functions loaded at boot time
into fixed addresses in kernel memory. This allows them to be customized
for the processor. The __memccpy routine is a millicode implementation;
we use millicode for the memccpy function instead of a library call to
improve performance

---------

Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
2026-02-26 13:09:22 -05:00
paperchalice
d46a400767
[PowerPC] Remove NoSignedZerosFPMath uses (#180087)
Users should use `nsz` flag only.
2026-02-26 11:13:42 +00:00
Simon Pilgrim
efcf64e898
[DAG] visitOR - attempt to fold (or buildvector(), buildvector()) -> buildvector() (#183032)
See if we can fold all elements of an OR of buildvectors: OR(-1,X) ->
-1, OR(0,X) -> X, etc.
2026-02-25 10:03:15 +00:00
zhijian lin
ce2a9cbf15
[PowerPC] Fix inefficient code for __builtin_ppc_test_data_class (#181420)
emit a more efficient asm for  llvm.ppc.test.data.class.f64
2026-02-23 10:44:38 -05:00
Jay Foad
594e889b7f
[PowerPC] Fix duplicate RUN lines in tests (#182275) 2026-02-23 10:32:01 +00:00
Peter Collingbourne
ebe9c6eabd
CodeGen: Introduce MachineFunction::getPreferredAlignment().
MachineFunction can now be queried for the preferred alignment which
comes from the function attributes (optsize, minsize, prefalign) and
TargetLowering.

Part of this RFC:
https://discourse.llvm.org/t/rfc-enhancing-function-alignment-attributes/88019

Reviewers: vitalybuka, nikic, efriedma-quic, MaskRay

Reviewed By: vitalybuka

Pull Request: https://github.com/llvm/llvm-project/pull/158368
2026-02-20 11:16:45 -08:00
Simon Pilgrim
9b3470d56f
[DAG] expandCLMUL - unroll vector clmul if vector multiplies are not supported (#182041)
Fixes powerpc cases reported on #182039

I'm hoping #177566 can be adapted to improve upon this.
2026-02-18 19:03:36 +00:00
Bill Wendling
9a0d65cdfd
[NFC][CodeGen] Rename CallBrPrepare pass to InlineAsmPrepare (#181547)
This is an NFC change to make room for a more generalized "prepare" pass
for inline assembly beyond CallBrInsts. In particular, changing how we
generate code for inline assembly with "rm" constraints.
2026-02-17 15:37:35 -08:00
Nikita Popov
c4721872af Revert "[Clang][inlineasm] Add special support for "rm" output constraints (#92040)"
This change landed without approval.

This reverts commit 45e666a8531c1148bdb170b9a120f99e1500c427.
This reverts commit a636dd4c37f12594275de2fe180ca35bc04d76ea.
2026-02-14 15:59:04 +01:00
Bill Wendling
45e666a853
[Clang][inlineasm] Add special support for "rm" output constraints (#92040)
Clang isn't able to support multiple constraints on inputs and outputs,
like "rm". Instead, it picks the "safest" one to use, i.e. the memory
constraint for "rm". This leads to obviously horrible code:

  asm __volatile__ ("pushf\n\t"
                    "popq %0"
                    : "=rm" (x));

is compiled to:

        pushf
	popq -8(%rsp)
	movq	-8(%rsp), %rax

It gets worse when inlined into other functions, because it may
introduce
a stack where none is needed.

With this change, Clang now generates IR for the more optimistic choice
("r"). All but the fast register allocator are able to fold registers if
it turns out that register pressure is too high.

This leaves the fast register allocator. The fast register allocator, as
the name suggests, is built for execution speed, not code quality. Thus,
we add special processing to convert the "optimistic" IR into the
"conservative" choice (again at the IR level), which we know it can
handle.

We focus on "rm" for the initial commit, but that can be expanded in the
future for other constraints where Clang generates ++ungood code (like
"g").

Fixes: https://github.com/llvm/llvm-project/issues/20571
2026-02-14 05:02:24 -08:00
zhijian lin
343103a680
[NFC] Pre-Commit test case for __builtin_ppc_test_data_class (#181181)
add a pre-commit test case for __builtin_ppc_test_data_class
2026-02-13 15:07:01 -05:00
paperchalice
c53acf0443
[SelectionDAGBuilder] Remove NoNaNsFPMath uses (#169904)
Replaced by checking fast-math flags or value tracking results.
2026-02-09 09:48:07 +08:00
Wael Yehia
13c9276daa [AIX] fix aix-ifunc-toc-restore-query-neg.ll (#153049) 2026-02-05 19:00:23 +00:00
Matt Arsenault
2502e3b7ba
IR: Promote "denormal-fp-math" to a first class attribute (#174293)
Convert "denormal-fp-math" and "denormal-fp-math-f32" into a first
class denormal_fpenv attribute. Previously the query for the effective
denormal mode involved two string attribute queries with parsing. I'm
introducing more uses of this, so it makes sense to convert this
to a more efficient encoding. The old representation was also awkward
since it was split across two separate attributes. The new encoding
just stores the default and float modes as bitfields, largely avoiding
the need to consider if the other mode is set.

The syntax in the common cases looks like this:
  `denormal_fpenv(preservesign,preservesign)`
  `denormal_fpenv(float: preservesign,preservesign)`
  `denormal_fpenv(dynamic,dynamic float: preservesign,preservesign)`

I wasn't sure about reusing the float type name instead of adding a
new keyword. It's parsed as a type but only accepts float. I'm also
debating switching the name to subnormal to match the current
preferred IEEE terminology (also used by nofpclass and other
contexts).

This has a behavior change when using the command flag debug
options to set the denormal mode. The behavior of the flag
ignored functions with an explicit attribute set, per
the default and f32 version. Now that these are one attribute,
the flag logic can't distinguish which of the two components
were explicitly set on the function. Only one test appeared to
rely on this behavior, so I just avoided using the flags in it.

This also does not perform all the code cleanups this enables.
In particular the attributor handling could be cleaned up.

I also guessed at how to support this in MLIR. I followed
MemoryEffects as a reference; it appears bitfields are expanded
into arguments to attributes, so the representation there is
a bit uglier with the 2 2-element fields flattened into 4 arguments.
2026-02-05 13:31:26 +00:00
Jay Foad
7ea33e6848
[CodeGen] Remove unused first operand of SUBREG_TO_REG (#179690)
The first input operand of SUBREG_TO_REG was an immediate that most
targets set to 0. In practice it had no effect on codegen. Remove it.
2026-02-04 17:35:21 +00:00
Nikita Popov
90c632ab48
[PowerPC] Only set QualName symbol on first section switch (#179253)
We were setting it every time when switching to the section. This caused
problems when the debug_aranges emission performed a switch at the end
of the section, resulting in symbols incorrectly pointing to the end
instead of the start of the function.
2026-02-04 10:21:07 +01:00
Wael Yehia
e2061328a8 [AIX] fix aix-ifunc-toc-restore-query.ll (#153049) 2026-02-04 03:53:59 +00:00
Wael Yehia
cc5859671d [AIX] disable aix-ifunc-toc-restore-query-neg.ll on all platforms except ppc for now (#153049) 2026-02-04 03:44:28 +00:00
paperchalice
1ffe78811e
[PowerPC] Remove NoInfsFPMath uses (#163029)
Only `ninf` should be used.
This is the PowerPC part.
2026-02-04 00:35:15 +00:00
Wael Yehia
e1f69ee8e8
[AIX] Implement the ifunc attribute. (#153049)
Currently, the AIX linker and loader do not provide a mechanism to
implement ifuncs similar to GNU_ifunc on ELF Linux.
On AIX, we will lower `__attribute__((ifunc("resolver"))` to the llvm
`ifunc` as other platforms do. The llvm `ifunc` in turn will get lowered
at late stages of the optimization pipeline to an AIX-specific
implementation. No special linkage or relocations are needed when
generating assembly/object output.

On AIX, a function `foo` has two symbols associated with it: a function
descriptor (`foo`) residing in the `.data` section, and an entry point
(`.foo`) residing in the `.text` section. The first field of the
descriptor is the address of the entry point. Typically, the address
field in the descriptor is initialized once: statically, at load time
(?), or at runtime if runtime linking is enabled.

Here we would like to use the address field in the descriptor to
implement the `ifunc` semantics. Specifically, the ifunc function will
become a stub that jumps to the entry point in the address field. A
constructor function is linked into every linkage module. The
constructor walks an array of `{descriptor, resolver}` pairs, calling
the resolver and saving the result in the address field in the
descriptor (thus setting `foo`'s descriptor to point to the resolved
version early during program runtime).

Known limitations:
- Due to bug #161576, which affects object generation path, you will
need either `-ffunction-sections` or `-fno-integrated-as` to generate a
correct/linkable object file.
- aliases to ifuncs are not supported, a testcase has been added and
marked XFAIL. I'm planning to address in a follow-up PR because it's not
important enough, IMHO, for this PR
- dead ifuncs in a CU that contains at least one live ifunc, will result
in all ifuncs being kept by the linker. The fix for this is common with
a similar problem we have with PGO. PR #159435 is trying to provide a
mechanism that will allow the ifunc and PGO implementations to avoid the
dead code retention at the link step.
- the resolver must return a function that is in the same DSO as the
ifunc; the compiler will try to detect if this condition is violated and
report it, but it cannot detect it in general. To be safe, all candidate
functions (returned by a particular resolver) must either be static or
have hidden/protected visibility. This is so that the ifunc stub doesn't
have to save and restore the TOC register r2. In future work, this case
will be supported and the requirement will be lifted.

---------

Co-authored-by: Wael Yehia <wyehia@ca.ibm.com>
2026-02-03 14:15:16 -05:00
zhijian lin
dc520ea4af
[PowerPC] using milicode call for strcmp instead of lib call (#177009)
1. AIX has "millicode" routines, which are functions loaded at boot time
into fixed addresses in kernel memory. This allows them to be customized
for the processor. The __strcmp routine is a millicode implementation;
we use millicode for the strcmp function instead of a library call to
improve performance.
2026-02-02 09:34:53 -05:00
SiliconA-Z
b4797d4c03
[PowerPC] Fix miscompilation when using 32-bit ucmp on 64-bit PowerPC (#178979)
I forgot that you need to clear the upper 32 bits for the carry flag to
work properly on ppc64 or else there will be garbage and possibly
incorrect results.

Fixes: https://github.com/llvm/llvm-project/issues/179119

I do not have merge permissions.
2026-02-02 09:00:40 +01:00
陈子昂
a994198906
[DAG] Reland: Enable bitcast STLF for Constant/Undef (#178890)
This is a reland of #172523.

The original patch caused an assertion failure on RISC-V because it
attempted to create a bitcast from an illegal type (i32 on RV64) during
the post-type-legalization DAGCombine stage.

Added a `TLI.isTypeLegal(Val.getValueType())` check to ensure we only
proceed with the bitcast STLF optimization when the source value's type
is legal for the target.
2026-01-30 18:21:32 +01:00
Alex Bradbury
41f453efe2
Revert "[DAG] Enable bitcast STLF for Constant/Undef" (#178872)
Reverts llvm/llvm-project#172523

As explained in
https://github.com/llvm/llvm-project/pull/172523#issuecomment-3823234270
(along with reproducer), this causes compiler crashes building
llvm-test-suite for RVV targets.
2026-01-30 12:18:38 +00:00
陈子昂
d3c64633c3
[DAG] Enable bitcast STLF for Constant/Undef (#172523)
This patch introduces support for Store-to-Load Forwarding (STLF) in
`DAGCombiner::ForwardStoreValueToDirectLoad` when the store and load
have **different types but equal memory size** (e.g., storing an `i32`
then loading a `float` from the same location).

### What this patch does:
**Enables Optimization:** It allows for the safe forwarding of the
stored value as a Bitcast when the value is:
* A **Constant** (`ConstantSDNode`, `ConstantFPSDNode`,
`ConstantPoolSDNode`).
    * **Undef**.
    * And the memory sizes (`LdMemSize` == `StMemSize`) match.

### Scope and Next Steps:

This patch **only implements forwarding for constant and undef values
that has the same memory size** so far.

**I am submitting this initial patch to get early review feedback on the
core logic and fix the immediate crashes before tackling the more
complex scenarios.**

For the simple case:
```llvm
; Case Handled by this PR so far (e.g., zeroinitializer is a constant)
define float @test_stlf_integer(ptr %p, float %v) {
  store i32 0, ptr %p, align 4 
  %f = load float, ptr %p, align 4 
  ; ...
}
```
Fixes: #151683
2026-01-30 10:11:59 +01:00
Maryam Moghadas
c41691c8b6
[PowerPC] Fix XXPERMDI peephole and ISEL LiveVariables bugs (#172122)
Fixes https://github.com/llvm/llvm-project/issues/159116
Prevent XXPERMDI splat optimization when the splat output register is
used in other instructions, which caused undefined register references. 
Also track removed ISEL operands in simplifyToLI to prevent 
LiveVariables corruption during ISEL-to-COPY conversion.
2026-01-27 09:44:23 -05:00
Nikita Popov
1bad00adc4
[SDAG] Remove non-canonical fabs libcall handling (#177967)
This is a followup to https://github.com/llvm/llvm-project/pull/171288,
which removed lowering of libcalls to SDAG nodes for most libcalls that
get unconditionally canonicalized to intrinsics. This handles the
remaining fabs case, which I originally skipped due to larger test
impact.
2026-01-26 15:11:17 +00:00
Matt Arsenault
aa53f6f3db
ValueTracking: Improve handling for fma/fmuladd (#175614)
The handling for fma was very basic and only handled the
repeated input case. Re-use the fmul and fadd handling for more
accurate sign bit and nan handling.
2026-01-24 11:35:14 +01:00
Sean Fertile
30fc5c1cdf
[PPC64] Convert assert in patchpoint emission to usage error. (#177453)
If the patchpoint intrinsic has requested less bytes then it takes to
make the call then report a fatal usage error. Also fixed a bug where we
forgot to count one of the instructions emitted.
2026-01-22 18:08:49 -05:00
Simon Pilgrim
7e01b33a42
[PPC] Fix suspicious AltiVec VAVG patterns (#176891)
The existing ((X+Y+1)>>1) patterns didn't correct handle overflow, like
the VAVG instructions would

Remove the old patterns and correctly mark the altivec VAVGS/VAVGU
patterns as matching the ISD::AVGCEIL opcodes - the generic DAG folds
will handle everything else

I've updated the vavg.ll tests to correct match ISD::AVGCEILS/U patterns
and added the old tests as negative "overflow" patterns that shouldn't
fold to VAVG instructions

Fixes #174718
2026-01-21 16:48:26 +00:00
Aditi Medhane
7cf30a7d3d
[PowerPC] Add Support for BCDSHIFT, BCDSHIFTR, BCDTRUNC, BCDUTRUNC, and BCDUSHIFT instruction support (#154715)
Support the following BCD format conversion builtins for PowerPC.

- `__builtin_bcdshift` – Shifts a packed decimal value by a specified
number of decimal digits.
- `__builtin_bcdshiftround` – Shifts a packed decimal value by a
specified number of decimal digits, with rounding applied.
- `__builtin_bcdtruncate` –Truncates a packed decimal value to a
specified number of digits.
- `__builtin_bcdunsignedtruncate` – Truncates a packed decimal value and
returns the result as an unsigned packed decimal.
- `__builtin_bcdunsignedshift` – Shifts an unsigned packed decimal value
by a specified number of digits.

> Note: This built-in functions are valid only when all following
conditions are met:
> -qarch is set to utilize POWER9 technology.
> The bcd.h file is included.

## Prototypes

```c
vector unsigned char __builtin_bcdshift(vector unsigned char, int, unsigned char);
vector unsigned char __builtin_bcdshiftround(vector unsigned char, int, unsigned char);
vector unsigned char __builtin_bcdtruncate(vector unsigned char, int, unsigned char);
vector unsigned char __builtin_bcdunsignedtruncate(vector unsigned char, int);
vector unsigned char __builtin_bcdunsignedshift(vector unsigned char, int);
```

---------
2026-01-21 21:34:06 +05:30
Matt Arsenault
0d4a35d560
IR: Remove llvm.convert.to.fp16 and llvm.convert.from.fp16 intrinsics (#174484)
These are long overdue for removal. These were originally a hack
to support loading half values before there was any / decent support
for the half type through the backend. There's no reason to continue
supporting these, they're equivalent to fpext/fptrunc with a bitcast.

SelectionDAG stopped translating these directly, and used the
bitcast + fp cast since f7a02c17628e825, so there's been no reason
to use these since 2014.
2026-01-21 09:50:28 +00:00
Simon Pilgrim
39028cc55a
[DAG] foldAddToAvg - add patterns to form avgceil(A, B) from ((A >> 1) + (B >> 1)) + ((A | B) & 1) (#174719)
Alive2 proof: https://alive2.llvm.org/ce/z/mcatXZ

I've raised #174718 as supposedly PPC has AVGCEIL instructions, but the
patterns in PPCInstrAltivec.td are either incorrect or the instructions
don't account for overflow.

Fixes #128377
2026-01-20 12:12:51 +00:00
Maryam Moghadas
196548988e
[PowerPC] Add support for AMO store builtins (#170933)
This commit adds 4 Clang builtins for PowerPC AMO store operations:

__builtin_amo_stwat for 32-bit unsigned operations
__builtin_amo_stdat for 64-bit unsigned operations
__builtin_amo_stwat_s for 32-bit signed operations
__builtin_amo_stdat_s for 64-bit signed operations

and maps GCC's AMO store functions to these Clang builtins for
compatibility.
2026-01-19 10:58:32 -05:00
Maryam Moghadas
6f8a7e79db
[PowerPC] Add AMO load builtins for conditional increment/decrement (#169435)
This commit adds 4 Clang builtins for PowerPC AMO load conditional 
increment and decrement operations: 

 __builtin_amo_lwat_cond for 32-bit unsigned operations
 __builtin_amo_ldat_cond for 64-bit unsigned operations
 __builtin_amo_lwat_cond_s for 32-bit signed operations
 __builtin_amo_ldat_cond_s for 64-bit signed operations
2026-01-16 12:11:45 -05:00
Tony Linthicum
15b9109bc7
Make MachineBlockFrequencyInfo a required pass for the MachineScheduler pass. (#176172)
This is needed to support functionality in the AMDGPU scheduler. Various
passes have been modified to preserve MBFI to ensure that this change
does not introduce new invocations of MBFI. Some targets have passes
reordered, but there are no new runs of MBFI.
2026-01-15 20:26:51 +00:00
zhijian lin
7b90f426a6
[PowerPC] using milicode call for strstr instead of lib call (#176002)
AIX has "millicode" routines, which are functions loaded at boot time
into fixed addresses in kernel memory. This allows them to be customized
for the processor. The __strstr routine is a millicode implementation;
we use millicode for the strstr function instead of a library call to
improve performance.

I add a helper function `getRuntimeCallSDValueHelper` in the patch. I
will refactor the function `SelectionDAG::getStrlen`
`SelectionDAG::getStrcpy` etc later in another patch.
2026-01-15 14:58:17 -05:00
zhijian lin
cfefd3e46c
[NFC][PowerPC] add test cases for milicode (#175559)
In this PR, we do the following:

1. Simplify the test case for the millicode function  `___memmove`.
2. Add test cases for the millicode functions `___memcpy` ,
`____memset`, `____memmove` which are supported in the patch
https://reviews.llvm.org/D143997.
3. Add pre-commit test cases for the functions `___strstr`,
`___memccpy`, `___strcmp`
2026-01-14 11:46:39 -05:00
zhijian lin
b983b0e92a
[PowerPC] using milicode call for strcpy instead of lib call (#174782)
AIX has "millicode" routines, which are functions loaded at boot time
into fixed addresses in kernel memory. This allows them to be customized
for the processor. The __strcpy routine is a millicode implementation;
we use millicode for the strcpy function instead of a library call to
improve performance.

---------

Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
2026-01-12 08:58:45 -05:00
Himadhith
743f0a4fdb
[PowerPC] Optimize not equal compares against zero vectors (#150422)
This patch is for special cases involving 0 vectors. During the
comparison of vector operands, current code generation checks with
`vcmpequh (vector compare equal unsigned halfword)` followed by a
negation `xxlnor (VSX Vector Logical NOR XX3-form)`.

This means that for the special case, instead of using `vcmpequh` and
then negating the result, we can directly use `vcmpgtuh (vector compare
greater than unsigned halfword)`.

As a result the negation is avoided since the only condition where this
will be false is for 0 as it is an `unsigned halfword`.

---------

Co-authored-by: himadhith <himadhith.v@ibm.com>
2026-01-12 12:29:55 +05:30
Yingwei Zheng
b8892b9a9b
[SDAG] Add freeze when simplifying select with undef arms (#175199)
Consider the following pattern:
```
%trunc = trunc nuw i64 %x to i48
%sel = select i1 %cmp, i48 %trunc, i48 undef
```
We cannot simplify `%sel` to `%trunc` as `%trunc` may be poison, which
cannot be refined into undef.

This patch checks whether the replacement may be poison. If so, it will
insert a freeze.
We may need SDAG's version of `impliesPoison` if it causes significant
regressions.
Compile-time impact:
https://llvm-compile-time-tracker.com/compare.php?from=ded109c0cff41714ebf9bd60b073aaab07fa4ca8&to=103e605ce6b33bc9145526faf805ee38b972c215&stat=instructions%3Au

Closes https://github.com/llvm/llvm-project/issues/175018.
2026-01-10 13:49:53 +08:00
Sean Fertile
b6212a4caf
XCOFF associated metadata (#159096)
Add a new metadata node `!implicit.ref` to represent an implicit
dependency between 2 symbols. The metadata is unique to AIX and gets
lowered to a relocation that adds an explicit link between the section
the global that the metadata is placed on is allocated in, to the
asscoiated symbol. This relocation will cause the associated symbol to
remain live if the section is not garbage collected. This is used mainly
for compiler features where there is some hidden runtime dependency
between the symbols that isn't otherwise obvious to the linker.
2026-01-09 13:49:21 -05:00