If we know that we have a FunctionRefInst (and not another variant of FunctionRefBaseInst), we know that getting the referenced function will not be null (in contrast to FunctionRefBaseInst::getReferencedFunctionOrNull).
NFC
Store the 1-byte kindAndFlags of SILLocation in the instruction's SILNode bitfield and only store SILLocation::storage in SILInstruction directly.
This reduces the space for the location from 2 to 1 word in SILInstruction.
This removes the ambiguity when casting from a SingleValueInstruction to SILNode, which makes the code simpler. E.g. the "isRepresentativeSILNode" logic is not needed anymore.
Also, it reduces the size of the most used instruction class - SingleValueInstruction - by one pointer.
Conceptually, SILInstruction is still a SILNode. But implementation-wise SILNode is not a base class of SILInstruction anymore.
Only the two sub-classes of SILInstruction - SingleValueInstruction and NonSingleValueInstruction - inherit from SILNode. SingleValueInstruction's SILNode is embedded into a ValueBase and its relative offset in the class is the same as in NonSingleValueInstruction (see SILNodeOffsetChecker).
This makes it possible to cast from a SILInstruction to a SILNode without knowing which SILInstruction sub-class it is.
Casting to SILNode cannot be done implicitly, but only with an LLVM `cast` or with SILInstruction::asSILNode(). But this is a rare case anyway.
Apparently this API was never called from any OSSA passes.
Fixes rdar://73507733 ([SR-14090]: [Source Compat] swift-futures 5.1
fails to build from main branch)
load, store in ossa can have side-effects and stores can release. Specifically:
Memory Behavior
---------------
* Load: unqualified, trivial, take have a read side-effect, but copy retains so
has side-effects.
* Store: unqualified, trivial, init may write but assign releases so it may have
side-effects.
Release Behavior
----------------
* Load: No changes.
* Store: May release if store has assign as an ownership qualifier.
When casting from existentials to class - and vice versa - it can happen that a cast is not RC identity preserving (because of potential bridging).
This also affects mayRelease() of such cast instructions.
For details see the comments in SILDynamicCastInst::isRCIdentityPreserving().
This change also includes some refactoring: I centralized the logic in SILDynamicCastInst::isRCIdentityPreserving().
rdar://problem/70454804
* a new [immutable] attribute on ref_element_addr and ref_tail_addr
* new instructions: begin_cow_mutation and end_cow_mutation
These new instructions are intended to be used for the stdlib's COW containers, e.g. Array.
They allow more aggressive optimizations, especially for Array.
Global variables with resilient types might be allocated into a buffer and not statically in the data segment.
In this case, the global_addr depends on alloc_global being executed first.
We model this by letting global_addr have a side effect.
It prevents e.g. LICM to move a global_addr out of a loop while keeping the alloc_global inside the loop.
rdar://problem/61602640
Add a private scratch context to the ASTContext and allow IntrinsicInfo sole access to it so it can allocate attributes into it. This removes the final dependency on the global context.
Specifically, I split it into 3 initial categories: IR, Utils, Verifier. I just
did this quickly, we can always split it more later if we want.
I followed the model that we use in SILOptimizer: ./lib/SIL/CMakeLists.txt vends
a macro (sil_register_sources) to the sub-folders that register the sources of
the subdirectory with a global state variable that ./lib/SIL/CMakeLists.txt
defines. Then after including those subdirs, the parent cmake declares the SIL
library. So the output is the same, but we have the flexibility of having
subdirectories to categorize source files.