mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Access scopes for enforcing exclusivity are currently the only
exception to our ability to canonicalize OSSA lifetime purely based on
the SSA value's known uses. This is because access scopes have
semantics relative to object deinitializers.
In general, deinitializers are asynchronous with respect to code that
is unrelated to the object's uses. Ignoring exclusivity, the optimizer
may always destroy objects as early as it wants, as long as the object
won't be used again. The optimizer may also extend the lifetime
(although in the future this lifetime extension should be limited by
"synchronization points").
The optimizer's freedom is however limited by exclusivity
enforcement. Optimization may never introduce new exclusivity
violations. Destroying an object within an access scope is an
exclusivity violation if the deinitializer accesses the same variable.
To handle this, OSSA canonicalization must detect access scopes that
overlap with the end of the pruned extended lifetime. Essentially:
%def
begin_access // access scope unrelated to def
use %def // pruned liveness ends here
end_access
destroy %def
Support for access scopes composes cleanly with the existing algorithm
without adding significant cost in the usual case. Overlapping access
scopes are unusual. A single CFG walk within the original extended
lifetime is normally sufficient. Only the blocks that are not already
LiveOut in the pruned liveness need to be visited. During this walk,
local overlapping access are detected by scanning for end_access
instructions after the last use point. Global overlapping accesses are
detected by checking NonLocalAccessBlockAnalysis. This avoids scanning
instructions in the common case. NonLocalAccessBlockAnalysis is a
trivial analysis that caches the rare occurence of nonlocal access
scopes. The analysis itself is a single linear scan over the
instruction stream. This analysis can be preserved across most
transformations and I expect it to be used to speed up other
optimizations related to access marker.
When an overlapping access is detected, pruned liveness is simply
extended to include the end_access as a new use point. Extending the
lifetime is iterative, but with each iteration, blocks that are now
marked LiveOut no longer need to be visited. Furthermore, interleaved
accessed scopes are not expected to happen in practice.
68 lines
2.3 KiB
C++
68 lines
2.3 KiB
C++
//===--- Analysis.cpp - Swift Analysis ------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "sil-analysis"
|
|
#include "swift/SILOptimizer/Analysis/Analysis.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/SILOptions.h"
|
|
#include "swift/SIL/SILFunction.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
|
|
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
|
|
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
|
|
#include "swift/SILOptimizer/Analysis/IVAnalysis.h"
|
|
#include "swift/SILOptimizer/Analysis/NonLocalAccessBlockAnalysis.h"
|
|
#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
|
|
#include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h"
|
|
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
using namespace swift;
|
|
|
|
void SILAnalysis::verifyFunction(SILFunction *F) {
|
|
// Only functions with bodies can be analyzed by the analysis.
|
|
assert(F->isDefinition() && "Can't analyze external functions");
|
|
}
|
|
|
|
SILAnalysis *swift::createDominanceAnalysis(SILModule *) {
|
|
return new DominanceAnalysis();
|
|
}
|
|
|
|
SILAnalysis *swift::createPostDominanceAnalysis(SILModule *) {
|
|
return new PostDominanceAnalysis();
|
|
}
|
|
|
|
SILAnalysis *swift::createInductionVariableAnalysis(SILModule *M) {
|
|
return new IVAnalysis(M);
|
|
}
|
|
|
|
SILAnalysis *swift::createPostOrderAnalysis(SILModule *M) {
|
|
return new PostOrderAnalysis();
|
|
}
|
|
|
|
SILAnalysis *swift::createClassHierarchyAnalysis(SILModule *M) {
|
|
return new ClassHierarchyAnalysis(M);
|
|
}
|
|
|
|
SILAnalysis *swift::createBasicCalleeAnalysis(SILModule *M) {
|
|
return new BasicCalleeAnalysis(M);
|
|
}
|
|
|
|
SILAnalysis *swift::createProtocolConformanceAnalysis(SILModule *M) {
|
|
return new ProtocolConformanceAnalysis(M);
|
|
}
|
|
|
|
SILAnalysis *swift::createNonLocalAccessBlockAnalysis(SILModule *M) {
|
|
return new NonLocalAccessBlockAnalysis();
|
|
}
|