mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The main changes are: *) Rewrite everything in swift. So far, parts of memory-behavior analysis were already implemented in swift. Now everything is done in swift and lives in `AliasAnalysis.swift`. This is a big code simplification. *) Support many more instructions in the memory-behavior analysis - especially OSSA instructions, like `begin_borrow`, `end_borrow`, `store_borrow`, `load_borrow`. The computation of end_borrow effects is now much more precise. Also, partial_apply is now handled more precisely. *) Simplify and reduce type-based alias analysis (TBAA). The complexity of the old TBAA comes from old days where the language and SIL didn't have strict aliasing and exclusivity rules (e.g. for inout arguments). Now TBAA is only needed for code using unsafe pointers. The new TBAA handles this - and not more. Note that TBAA for classes is already done in `AccessBase.isDistinct`. *) Handle aliasing in `begin_access [modify]` scopes. We already supported truly immutable scopes like `begin_access [read]` or `ref_element_addr [immutable]`. For `begin_access [modify]` we know that there are no other reads or writes to the access-address within the scope. *) Don't cache memory-behavior results. It turned out that the hit-miss rate was pretty bad (~ 1:7). The overhead of the cache lookup took as long as recomputing the memory behavior.
144 lines
5.0 KiB
C++
144 lines
5.0 KiB
C++
//===--- AliasAnalysis.cpp - SIL Alias 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-aa"
|
|
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
|
|
#include "swift/Basic/Assertions.h"
|
|
#include "swift/SIL/SILFunction.h"
|
|
#include "swift/SILOptimizer/PassManager/PassManager.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "swift/SILOptimizer/OptimizerBridging.h"
|
|
|
|
using namespace swift;
|
|
|
|
// Bridging functions.
|
|
static BridgedAliasAnalysis::InitFn initFunction = nullptr;
|
|
static BridgedAliasAnalysis::DestroyFn destroyFunction = nullptr;
|
|
static BridgedAliasAnalysis::GetMemEffectFn getMemEffectsFunction = nullptr;
|
|
static BridgedAliasAnalysis::Escaping2InstFn isObjReleasedFunction = nullptr;
|
|
static BridgedAliasAnalysis::Escaping2ValIntFn isAddrVisibleFromObjFunction = nullptr;
|
|
static BridgedAliasAnalysis::MayAliasFn mayAliasFunction = nullptr;
|
|
|
|
void AliasAnalysis::initSwiftSpecificData() {
|
|
if (initFunction)
|
|
initFunction({this}, sizeof(swiftSpecificData));
|
|
}
|
|
|
|
AliasAnalysis::~AliasAnalysis() {
|
|
if (destroyFunction)
|
|
destroyFunction({this});
|
|
}
|
|
|
|
bool AliasAnalysis::canApplyDecrementRefCount(FullApplySite FAS, SILValue Ptr) {
|
|
// Treat applications of no-return functions as decrementing ref counts. This
|
|
// causes the apply to become a sink barrier for ref count increments.
|
|
if (FAS.isCalleeNoReturn())
|
|
return true;
|
|
|
|
/// If the pointer cannot escape to the function we are done.
|
|
bool result = isObjectReleasedByInst(Ptr, FAS.getInstruction());
|
|
return result;
|
|
}
|
|
|
|
bool AliasAnalysis::canBuiltinDecrementRefCount(BuiltinInst *BI, SILValue Ptr) {
|
|
return isObjectReleasedByInst(Ptr, BI);
|
|
}
|
|
|
|
namespace {
|
|
|
|
class AliasAnalysisContainer : public FunctionAnalysisBase<AliasAnalysis> {
|
|
SILPassManager *PM = nullptr;
|
|
|
|
public:
|
|
AliasAnalysisContainer() : FunctionAnalysisBase(SILAnalysisKind::Alias) {}
|
|
|
|
virtual bool shouldInvalidate(SILAnalysis::InvalidationKind K) override {
|
|
return K & InvalidationKind::Instructions;
|
|
}
|
|
|
|
virtual void invalidate(SILFunction *f,
|
|
SILAnalysis::InvalidationKind k) override {
|
|
if (k & InvalidationKind::Effects) {
|
|
FunctionAnalysisBase::invalidate();
|
|
} else {
|
|
FunctionAnalysisBase::invalidate(f, k);
|
|
}
|
|
}
|
|
|
|
// Computes loop information for the given function using dominance
|
|
// information.
|
|
virtual std::unique_ptr<AliasAnalysis>
|
|
newFunctionAnalysis(SILFunction *F) override {
|
|
assert(PM && "dependent analysis not initialized");
|
|
return std::make_unique<AliasAnalysis>(PM);
|
|
}
|
|
|
|
virtual void initialize(SILPassManager *PM) override {
|
|
this->PM = PM;
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
SILAnalysis *swift::createAliasAnalysis(SILModule *M) {
|
|
return new AliasAnalysisContainer();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Swift Bridging
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void BridgedAliasAnalysis::registerAnalysis(InitFn initFn,
|
|
DestroyFn destroyFn,
|
|
GetMemEffectFn getMemEffectsFn,
|
|
Escaping2InstFn isObjReleasedFn,
|
|
Escaping2ValIntFn isAddrVisibleFromObjFn,
|
|
MayAliasFn mayAliasFn) {
|
|
initFunction = initFn;
|
|
destroyFunction = destroyFn;
|
|
getMemEffectsFunction = getMemEffectsFn;
|
|
isObjReleasedFunction = isObjReleasedFn;
|
|
isAddrVisibleFromObjFunction = isAddrVisibleFromObjFn;
|
|
mayAliasFunction = mayAliasFn;
|
|
}
|
|
|
|
MemoryBehavior AliasAnalysis::computeMemoryBehavior(SILInstruction *toInst, SILValue addr) {
|
|
if (getMemEffectsFunction) {
|
|
return (MemoryBehavior)getMemEffectsFunction({PM->getSwiftPassInvocation()},
|
|
{this},
|
|
{addr},
|
|
{toInst->asSILNode()});
|
|
}
|
|
return MemoryBehavior::MayHaveSideEffects;
|
|
}
|
|
|
|
bool AliasAnalysis::isObjectReleasedByInst(SILValue obj, SILInstruction *inst) {
|
|
if (isObjReleasedFunction) {
|
|
return isObjReleasedFunction({PM->getSwiftPassInvocation()}, {this}, {obj}, {inst->asSILNode()});
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool AliasAnalysis::isAddrVisibleFromObject(SILValue addr, SILValue obj) {
|
|
if (isAddrVisibleFromObjFunction) {
|
|
return isAddrVisibleFromObjFunction({PM->getSwiftPassInvocation()}, {this}, {addr}, {obj});
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool AliasAnalysis::mayAlias(SILValue lhs, SILValue rhs) {
|
|
if (mayAliasFunction) {
|
|
return mayAliasFunction({PM->getSwiftPassInvocation()}, {this}, {lhs}, {rhs});
|
|
}
|
|
return true;
|
|
}
|