The XXOptUtils.h convention is already established and parallels
the SIL/XXUtils convention.
New:
- InstOptUtils.h
- CFGOptUtils.h
- BasicBlockOptUtils.h
- ValueLifetime.h
Removed:
- Local.h
- Two conflicting CFG.h files
This reorganization is helpful before I introduce more
utilities for block cloning similar to SinkAddressProjections.
Move the control flow utilies out of Local.h, which was an
unreadable, unprincipled mess. Rename it to InstOptUtils.h, and
confine it to small APIs for working with individual instructions.
These are the optimizer's additions to /SIL/InstUtils.h.
Rename CFG.h to CFGOptUtils.h and remove the one in /Analysis. Now
there is only SIL/CFG.h, resolving the naming conflict within the
swift project (this has always been a problem for source tools). Limit
this header to low-level APIs for working with branches and CFG edges.
Add BasicBlockOptUtils.h for block level transforms (it makes me sad
that I can't use BBOptUtils.h, but SIL already has
BasicBlockUtils.h). These are larger APIs for cloning or removing
whole blocks.
Previously, CallerAnalysis::FunctionInfo.foundAllCallers(), which is
documented to return true only when specialization of a function will
not require a thunk, returned true for functions which are possibly used
externally. Now, that member function only returns false for functions
which may be used externally since dead code elimination will not be
able to remove them.
Added getPartiallyPostDomReleaseSet to
ConsumedArgToEpilogueReleaseMatcher. Given an argument, the new method
returns the array of releases of the argument if there is an array
thereof and if the releases therein do not jointly post-dominate the
argument.
Excerpted from @gottesm's https://github.com/apple/swift/pull/16756.
- Replaced usage of raw map and vector with the type that wraps the
combination (BlotSetVector); that provided a significant deduplication
since a sizeable portion of the worklist's implementation was in
vector and map management now provided by the BlotSetVector.
- Templated over the type of map and vector used by the blot set vector.
- Added SmallSILInstructionWorklist where the map and vector are
specified to be SmallDenseMap and SmallVector respectively.
- Replaced usages of bare ValueBase with usages of SILValue.
- Renamed zap to resetChecked.
Added a bit of functionality to BlotSetVector, specifically to support
SILInstructionWorklist:
- Made insert return not just the index that the potentially-inserted
item is at on return but additionally whether an insertion occurred,
matching the behavior of llvm::DenseMap::insert.
- Added a method to reserve capacity in the backing vector and map:
BlotSetVector::reserve.
- Added a method to free extra storage used by the backing vector and
map: BlotSetVector::clear.
- Modified SmallBlotSetVector's template parameters so that only a value
and size can be specified--that type will always use SmallVector and
SmallDenseMap for its superclass' VectorT and MapT template
parameters.
- Updated variable names.
Now that we've moved to C++14, we no longer need the llvm::make_unique
implementation from STLExtras.h. This patch is a mechanical replacement
of (hopefully) all the llvm::make_unique instances in the swift repo.
Describe the algorithm in the file-level doc comment. The basic
algorithm in the referenced paper is similar, but the most
interesting/important information is how it is adapted to SIL.
This analysis helper was inverting the result for builtins. Builtins
such as "copyMemory" were treated as never using a value.
This manifested in a crash in TestFoundation. NSDictionary's
initializer released the incoming array before copying it. This
crashed later during dictionary destruction.
The crash was hidden by a secondary bug in mayHaveSymmetricInterference
that effectively ignored the result from canNeverUseValue.
Rename the helper to canUseObject, invert the result for builtins, and
fix mayHaveSymmetricInterference to respect the result of
canUseObject.
Note that instructions that cannot access a referenced object
obviously cannot not "interfere" with a release.
Fixing these bugs now allows ARC optimization around dealloc_stack and
other operations that don't care about the reference count.
PointerUnion was generalized to be variadic. Replaced uses of
PointerUnion3 with PointerUnion
See also: git-svn-id:
https://llvm.org/svn/llvm-project/llvm/trunk@360962
91177308-0d34-0410-b5e6-96231b3b80d8
This will make the forthcoming CanonicalizeInstruction interface more
clear.
This is generally the better approach to utilities that mutate the
instruction stream. It avoids the temptation to assume that only a
single instruction will be deleted or that only instructions before
the current iterator will be deleted. This often happens to work but
eventually fails in the presense of debug and end-of-scope
instructions.
A function returning an iterator has a more clear contract than one
accepting some iterator reference of unknown
providence. Unfortunately, it doesn't work at the lowest level of
utilities, such as recursivelyDeleteTriviallyDeadInstructions, where
we want to handle instruction batches.
This is a large patch; I couldn't split it up further while still
keeping things working. There are four things being changed at
once here:
- Places that call SILType::isAddressOnly()/isLoadable() now call
the SILFunction overload and not the SILModule one.
- SILFunction's overloads of getTypeLowering() and getLoweredType()
now pass the function's resilience expansion down, instead of
hardcoding ResilienceExpansion::Minimal.
- Various other places with '// FIXME: Expansion' now use a better
resilience expansion.
- A few tests were updated to reflect SILGen's improved code
generation, and some new tests are added to cover more code paths
that previously were uncovered and only manifested themselves as
standard library build failures while I was working on this change.
Directly implement the data flow. Eliminate the extraneous work.
Remove cubic behavior. Do a single iteration of the data flow state at
each program point only performing the necessary set operations. At
unidentified access, clear the sets for simplicity and efficiency.
This cleanup results in significant functional changes:
- Allowing scopes to merge even if they are enclosed.
- Handling unidentified access conservatively.
Note that most of the added lines of code are comments.
Somehow this cleanup incidentally fixes:
<rdar://problem/48514339> swift compiler hangs building project
(I expected the subsequent loop summary cleanup to fix that problem.)
The previous design was customized to perfoming IPO with
GenericSideEffectAnalysis. Expose the underlying logic as a utility so
that AccessEnforcementOpts can use it to summarize loops (in addition
to call sites).
Improves SwiftSyntax release build speed by 4x.
Limit the size of the sets tracked by inter procedural
AccessedStorageAnalysis. There is a lot of leeway in this limit since
"normal" code doesn't come close to hitting it and SwiftSyntax compile
time isn't noticeably affected until 10x this limit.
This change also avoids reanalyzing function bodies once results have
bottomed out and avoids copying sets in the common case.
Fixes <rdar://problem/46905624> Release build time regression, a lot of time spent on AccessEnforcementOpts::run().
This is just a band aid. The fundamental problem is really:
<rdar://problem/47195282> Recomputing BottomUpIPAnalysis takes most of
the SwiftSyntax compile time.
SwiftSyntax compile time is still at least an order of magnitude
longer than it should be.
We've been running doxygen with the autobrief option for a couple of
years now. This makes the \brief markers into our comments
redundant. Since they are a visual distraction and we don't want to
encourage more \brief markers in new code either, this patch removes
them all.
Patch produced by
for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
In the included, test case, the optimization was sinking
releases past is_escaping_closure.
Rewrite the isBarrier logic to be conservative and define the
mayCheckRefCount property in SIL/InstructionUtils. Properties that may
need to be updated when SIL changes belong there.
Note that it is particularly bad behavior if the presence of access
markers in the code cause miscompiles unrelated to access enforcement.
Fixes <rdar://problem/45846920> TestFoundation, TestProcess, closure
argument passed as @noescape to Objective-C has escaped.
This patch augments the infinite recursion checker to not warn if a
branch terminates, but still warns if a branch calls into something with
`@_semantics("arc.programtermination_point")`. This way, calling `fatalError`
doesn't disqualify you for the diagnostic, but calling `exit` does.
This also removes the warning workaround in the standard library, and
annotates the internal _assertionFailure functions as
`programtermination_point`s, so they get this treatment too.
I believe that these were in SILInstruction for historic reasons. This is a
separate API on top of SILInstruction so it makes sense to pull it out into its
own header.
Visual Studio objects to the existing construct with:
swift/SILOptimizer/Analysis/ARCAnalysis.h(233): warning C4927: illegal conversion; more than one user-defined conversion has been implicitly applied
swift/SILOptimizer/Analysis/ARCAnalysis.h(233): note: while calling the constructor 'llvm::Optional<llvm::ArrayRef<swift::SILInstruction *>>::Optiona(T &&)'
with
[
T=llvm::ArrayRef<swift::SILInstruction *>
]
llvm/ADT/Optional.h(143): note: see declaration of 'llvm::Optional<llvm::ArrayRef<swift::SILInstruction *>>::Optional'
This is a verification routine that is only invoked in PassManager
destructors. I am going to use this to ensure that the
PassManagerVerifierAnalysis only runs at such points (even when sil-verify-all
is enabled) since it is too expensive to run otherwise.
NOTE: The default implementation of verifyFull in this commit is a no-op. I
wanted to have verify() be the default implementation of verifyFull(), but I do
not have more time to invest in this and it seems to catch /real/ bugs, albeit
bugs unrelated to pass manager notification verification. Instead I am going to
file an SR for someone to look at it since I need to move on from this work back
to semantic SIL. At least we will not have notification failure issues anymore
and thus a large correctness issue in the compiler has been fixed. Forward
progress!
rdar://42301529
This enables us to have state independent of the liveness of the SILFunction's
that we are tracking.
I also changed the verifier to implement only verifyFull instead of verify to
ensure that when we run with sil-verify-all this only runs at the end of pass
manager pipelines.
rdar://42301529
I also thought I was fixing a performance issue by changing
invalidateFunction not to /insert/ new entries into the map, but
I guess those entries were present in practice. So this is just
a cleanup to make ownership easier.
The invariant is that this analysis should be able to stay in sync with the list
of functions stored in SILModule's function list. If any functions are
added/deleted then analyses can get out of sync with the state of the underlying
SILModule.
Some notes:
1. This is currently disabled by default since there are a bunch of
violations of this in the compiler. I am in the process of fixing violations.
Some examples: the linker and global opt.
2. This is a no-op in non-assert builds.
3. The full verification will only happen when -sil-verify-all is enabled.
Otherwise, we only check that when we delete a function, we had state for the
function.
rdar://42301529
This name makes it clear that the function has not yet been deleted and also
contrasts with the past tense used in the API notifyAddedOrModifiedFunction to
show that said function has already added/modified the function.