Files
swift-mirror/include/swift/SILOptimizer/OptimizerBridging.h
Erik Eckstein f9b524b1cb AliasAnalysis: a complete overhaul of alias- and memory-behavior analysis
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.
2024-07-29 17:33:46 +02:00

434 lines
19 KiB
C++

//===--- OptimizerBridging.h - header for the OptimizerBridging module ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILOPTIMIZER_OPTIMIZERBRIDGING_H
#define SWIFT_SILOPTIMIZER_OPTIMIZERBRIDGING_H
// Do not add other C++/llvm/swift header files here!
// Function implementations should be placed into OptimizerBridgingImpl.h or PassManager.cpp
// (under OptimizerBridging) andrequired header files should be added there.
//
// Pure bridging mode does not permit including any C++/llvm/swift headers.
// See also the comments for `BRIDGING_MODE` in the top-level CMakeLists.txt file.
//
#include "swift/AST/ASTBridging.h"
#include "swift/SIL/SILBridging.h"
#ifdef USED_IN_CPP_SOURCE
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
#else // USED_IN_CPP_SOURCE
// Pure bridging mode does not permit including any C++/llvm/swift headers.
// See also the comments for `BRIDGING_MODE` in the top-level CMakeLists.txt file.
#ifdef SWIFT_SIL_SILVALUE_H
#error "should not include swift headers into bridging header"
#endif
#ifdef LLVM_SUPPORT_COMPILER_H
#error "should not include llvm headers into bridging header"
#endif
#endif // USED_IN_CPP_SOURCE
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
namespace swift {
class AliasAnalysis;
class BasicCalleeAnalysis;
class DeadEndBlocks;
class DominanceInfo;
class PostDominanceInfo;
class BasicBlockSet;
class NodeSet;
class OperandSet;
class ClonerWithFixedLocation;
class SwiftPassInvocation;
class FixedSizeSlabPayload;
class FixedSizeSlab;
class SILVTable;
class ClosureSpecializationCloner;
}
struct BridgedPassContext;
struct BridgedAliasAnalysis {
swift::AliasAnalysis * _Nonnull aa;
// Workaround for a compiler bug.
// When this unused function is removed, the compiler gives an error.
BRIDGED_INLINE bool unused(BridgedValue address1, BridgedValue address2) const;
typedef void (* _Nonnull InitFn)(BridgedAliasAnalysis aliasAnalysis, SwiftInt size);
typedef void (* _Nonnull DestroyFn)(BridgedAliasAnalysis aliasAnalysis);
typedef BridgedMemoryBehavior (* _Nonnull GetMemEffectFn)(
BridgedPassContext context, BridgedAliasAnalysis aliasAnalysis,
BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull Escaping2InstFn)(
BridgedPassContext context, BridgedAliasAnalysis aliasAnalysis, BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull Escaping2ValIntFn)(
BridgedPassContext context, BridgedAliasAnalysis aliasAnalysis, BridgedValue, BridgedValue);
typedef bool (* _Nonnull MayAliasFn)(
BridgedPassContext context, BridgedAliasAnalysis aliasAnalysis, BridgedValue, BridgedValue);
static void registerAnalysis(InitFn initFn,
DestroyFn destroyFn,
GetMemEffectFn getMemEffectsFn,
Escaping2InstFn isObjReleasedFn,
Escaping2ValIntFn isAddrVisibleFromObjFn,
MayAliasFn mayAliasFn);
};
struct BridgedCalleeAnalysis {
swift::BasicCalleeAnalysis * _Nonnull ca;
struct CalleeList {
uint64_t storage[3];
#ifdef USED_IN_CPP_SOURCE
CalleeList(swift::CalleeList list) {
*reinterpret_cast<swift::CalleeList *>(&storage) = list;
}
swift::CalleeList unbridged() const {
return *reinterpret_cast<const swift::CalleeList *>(&storage);
}
#endif
BRIDGED_INLINE bool isIncomplete() const;
BRIDGED_INLINE SwiftInt getCount() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedFunction getCallee(SwiftInt index) const;
};
SWIFT_IMPORT_UNSAFE CalleeList getCallees(BridgedValue callee) const;
SWIFT_IMPORT_UNSAFE CalleeList getDestructors(BridgedType type, bool isExactType) const;
typedef bool (* _Nonnull IsDeinitBarrierFn)(BridgedInstruction, BridgedCalleeAnalysis bca);
typedef BridgedMemoryBehavior (* _Nonnull GetMemBehvaiorFn)(
BridgedInstruction apply, bool observeRetains, BridgedCalleeAnalysis bca);
static void registerAnalysis(IsDeinitBarrierFn isDeinitBarrierFn,
GetMemBehvaiorFn getEffectsFn);
};
struct BridgedDeadEndBlocksAnalysis {
swift::DeadEndBlocks * _Nonnull deb;
BRIDGED_INLINE bool isDeadEnd(BridgedBasicBlock block) const;
};
struct BridgedDomTree {
swift::DominanceInfo * _Nonnull di;
BRIDGED_INLINE bool dominates(BridgedBasicBlock dominating, BridgedBasicBlock dominated) const;
};
struct BridgedPostDomTree {
swift::PostDominanceInfo * _Nonnull pdi;
BRIDGED_INLINE bool postDominates(BridgedBasicBlock dominating, BridgedBasicBlock dominated) const;
};
struct BridgedUtilities {
typedef void (* _Nonnull VerifyFunctionFn)(BridgedPassContext, BridgedFunction);
typedef void (* _Nonnull UpdateBorrowedFromFn)(BridgedPassContext, BridgedFunction);
typedef void (* _Nonnull UpdateBorrowedFromPhisFn)(BridgedPassContext, BridgedArrayRef);
static void registerVerifier(VerifyFunctionFn verifyFunctionFn);
static void registerBorrowedFromUpdater(UpdateBorrowedFromFn updateBorrowedFromFn,
UpdateBorrowedFromPhisFn updateBorrowedFromPhisFn);
};
struct BridgedBasicBlockSet {
swift::BasicBlockSet * _Nonnull set;
BRIDGED_INLINE bool contains(BridgedBasicBlock block) const;
BRIDGED_INLINE bool insert(BridgedBasicBlock block) const;
BRIDGED_INLINE void erase(BridgedBasicBlock block) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedFunction getFunction() const;
};
struct BridgedNodeSet {
swift::NodeSet * _Nonnull set;
BRIDGED_INLINE bool containsValue(BridgedValue value) const;
BRIDGED_INLINE bool insertValue(BridgedValue value) const;
BRIDGED_INLINE void eraseValue(BridgedValue value) const;
BRIDGED_INLINE bool containsInstruction(BridgedInstruction inst) const;
BRIDGED_INLINE bool insertInstruction(BridgedInstruction inst) const;
BRIDGED_INLINE void eraseInstruction(BridgedInstruction inst) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedFunction getFunction() const;
};
struct BridgedOperandSet {
swift::OperandSet * _Nonnull set;
BRIDGED_INLINE bool contains(BridgedOperand operand) const;
BRIDGED_INLINE bool insert(BridgedOperand operand) const;
BRIDGED_INLINE void erase(BridgedOperand operand) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedFunction getFunction() const;
};
struct BridgedCloner {
swift::ClonerWithFixedLocation * _Nonnull cloner;
BridgedCloner(BridgedGlobalVar var, BridgedPassContext context);
BridgedCloner(BridgedInstruction inst, BridgedPassContext context);
void destroy(BridgedPassContext context);
SWIFT_IMPORT_UNSAFE BridgedValue getClonedValue(BridgedValue v);
bool isValueCloned(BridgedValue v) const;
void clone(BridgedInstruction inst);
};
struct BridgedSpecializationCloner {
swift::ClosureSpecializationCloner * _Nonnull closureSpecCloner;
SWIFT_IMPORT_UNSAFE BridgedSpecializationCloner(BridgedFunction emptySpecializedFunction);
SWIFT_IMPORT_UNSAFE BridgedFunction getCloned() const;
SWIFT_IMPORT_UNSAFE BridgedBasicBlock getClonedBasicBlock(BridgedBasicBlock originalBasicBlock) const;
void cloneFunctionBody(BridgedFunction originalFunction, BridgedBasicBlock clonedEntryBlock, BridgedValueArray clonedEntryBlockArgs) const;
};
struct BridgedPassContext {
swift::SwiftPassInvocation * _Nonnull invocation;
enum class SILStage {
Raw,
Canonical,
Lowered
};
SWIFT_IMPORT_UNSAFE BridgedOwnedString getModuleDescription() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedChangeNotificationHandler asNotificationHandler() const;
BRIDGED_INLINE void notifyDependencyOnBodyOf(BridgedFunction otherFunction) const;
BRIDGED_INLINE SILStage getSILStage() const;
BRIDGED_INLINE bool hadError() const;
BRIDGED_INLINE bool moduleIsSerialized() const;
BRIDGED_INLINE bool isTransforming(BridgedFunction function) const;
// Analysis
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedAliasAnalysis getAliasAnalysis() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCalleeAnalysis getCalleeAnalysis() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeadEndBlocksAnalysis getDeadEndBlocksAnalysis() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDomTree getDomTree() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedPostDomTree getPostDomTree() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedNominalTypeDecl getSwiftArrayDecl() const;
// AST
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE
BridgedDiagnosticEngine getDiagnosticEngine() const;
// SIL modifications
struct DevirtResult {
OptionalBridgedInstruction newApply;
bool cfgChanged;
};
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock splitBlockBefore(BridgedInstruction bridgedInst) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock splitBlockAfter(BridgedInstruction bridgedInst) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock createBlockAfter(BridgedBasicBlock bridgedBlock) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock appendBlock(BridgedFunction bridgedFunction) const;
BRIDGED_INLINE void eraseInstruction(BridgedInstruction inst) const;
BRIDGED_INLINE void eraseBlock(BridgedBasicBlock block) const;
static BRIDGED_INLINE void moveInstructionBefore(BridgedInstruction inst, BridgedInstruction beforeInst);
bool tryOptimizeApplyOfPartialApply(BridgedInstruction closure) const;
bool tryDeleteDeadClosure(BridgedInstruction closure, bool needKeepArgsAlive) const;
SWIFT_IMPORT_UNSAFE DevirtResult tryDevirtualizeApply(BridgedInstruction apply, bool isMandatory) const;
bool tryOptimizeKeypath(BridgedInstruction apply) const;
SWIFT_IMPORT_UNSAFE OptionalBridgedValue constantFoldBuiltin(BridgedInstruction builtin) const;
SWIFT_IMPORT_UNSAFE swift::SILVTable * _Nullable specializeVTableForType(BridgedType type,
BridgedFunction function) const;
bool specializeClassMethodInst(BridgedInstruction cm) const;
bool specializeAppliesInFunction(BridgedFunction function, bool isMandatory) const;
SWIFT_IMPORT_UNSAFE BridgedOwnedString mangleOutlinedVariable(BridgedFunction function) const;
SWIFT_IMPORT_UNSAFE BridgedOwnedString mangleAsyncRemoved(BridgedFunction function) const;
SWIFT_IMPORT_UNSAFE BridgedOwnedString mangleWithDeadArgs(const SwiftInt * _Nullable deadArgs,
SwiftInt numDeadArgs,
BridgedFunction function) const;
SWIFT_IMPORT_UNSAFE BridgedOwnedString mangleWithClosureArgs(BridgedValueArray closureArgs,
BridgedArrayRef closureArgIndices,
BridgedFunction applySiteCallee) const;
SWIFT_IMPORT_UNSAFE BridgedGlobalVar createGlobalVariable(BridgedStringRef name, BridgedType type,
bool isPrivate) const;
void inlineFunction(BridgedInstruction apply, bool mandatoryInline) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedValue getSILUndef(BridgedType type) const;
BRIDGED_INLINE bool optimizeMemoryAccesses(BridgedFunction f) const;
BRIDGED_INLINE bool eliminateDeadAllocations(BridgedFunction f) const;
// IRGen
SwiftInt getStaticSize(BridgedType type) const;
SwiftInt getStaticAlignment(BridgedType type) const;
SwiftInt getStaticStride(BridgedType type) const;
bool canMakeStaticObjectReadOnly(BridgedType type) const;
// Sets
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlockSet allocBasicBlockSet() const;
BRIDGED_INLINE void freeBasicBlockSet(BridgedBasicBlockSet set) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedNodeSet allocNodeSet() const;
BRIDGED_INLINE void freeNodeSet(BridgedNodeSet set) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedOperandSet allocOperandSet() const;
BRIDGED_INLINE void freeOperandSet(BridgedOperandSet set) const;
// Stack nesting
BRIDGED_INLINE void notifyInvalidatedStackNesting() const;
BRIDGED_INLINE bool getNeedFixStackNesting() const;
void fixStackNesting(BridgedFunction function) const;
// Slabs
struct Slab {
swift::FixedSizeSlabPayload * _Nullable data = nullptr;
BRIDGED_INLINE static SwiftInt getCapacity();
BRIDGED_INLINE Slab(swift::FixedSizeSlab * _Nullable slab);
BRIDGED_INLINE swift::FixedSizeSlab * _Nullable getSlab() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE Slab getNext() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE Slab getPrevious() const;
};
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE Slab allocSlab(Slab afterSlab) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE Slab freeSlab(Slab slab) const;
// Access SIL module data structures
struct VTableArray {
swift::SILVTable * const _Nonnull * _Nullable base;
SwiftInt count;
};
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedFunction getFirstFunctionInModule() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE static OptionalBridgedFunction getNextFunctionInModule(BridgedFunction function);
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedGlobalVar getFirstGlobalInModule() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE static OptionalBridgedGlobalVar getNextGlobalInModule(BridgedGlobalVar global);
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE VTableArray getVTables() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedWitnessTable getFirstWitnessTableInModule() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE static OptionalBridgedWitnessTable getNextWitnessTableInModule(
BridgedWitnessTable table);
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedDefaultWitnessTable getFirstDefaultWitnessTableInModule() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE static OptionalBridgedDefaultWitnessTable getNextDefaultWitnessTableInModule(
BridgedDefaultWitnessTable table);
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedFunction lookupFunction(BridgedStringRef name) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedFunction loadFunction(BridgedStringRef name,
bool loadCalleesRecursively) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE void loadFunction(BridgedFunction function, bool loadCalleesRecursively) const;
SWIFT_IMPORT_UNSAFE OptionalBridgedFunction lookupStdlibFunction(BridgedStringRef name) const;
SWIFT_IMPORT_UNSAFE OptionalBridgedFunction lookUpNominalDeinitFunction(BridgedNominalTypeDecl nominal) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap getContextSubstitutionMap(BridgedType type) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getBuiltinIntegerType(SwiftInt bitWidth) const;
SWIFT_IMPORT_UNSAFE BridgedFunction createEmptyFunction(BridgedStringRef name,
const BridgedParameterInfo * _Nullable bridgedParams,
SwiftInt paramCount,
bool hasSelfParam,
BridgedFunction fromFunc) const;
void moveFunctionBody(BridgedFunction sourceFunc, BridgedFunction destFunc) const;
// Passmanager housekeeping
BRIDGED_INLINE void beginTransformFunction(BridgedFunction function) const;
BRIDGED_INLINE void endTransformFunction() const;
BRIDGED_INLINE bool continueWithNextSubpassRun(OptionalBridgedInstruction inst) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedPassContext initializeNestedPassContext(BridgedFunction newFunction) const;
BRIDGED_INLINE void deinitializedNestedPassContext() const;
BRIDGED_INLINE void
addFunctionToPassManagerWorklist(BridgedFunction newFunction,
BridgedFunction oldFunction) const;
// SSAUpdater
BRIDGED_INLINE void
SSAUpdater_initialize(BridgedFunction function, BridgedType type,
BridgedValue::Ownership ownership) const;
BRIDGED_INLINE void SSAUpdater_addAvailableValue(BridgedBasicBlock block, BridgedValue value) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedValue SSAUpdater_getValueAtEndOfBlock(BridgedBasicBlock block) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedValue SSAUpdater_getValueInMiddleOfBlock(BridgedBasicBlock block) const;
// Options
enum class AssertConfiguration {
Debug = 0,
Release = 1,
Unchecked = 2
};
BRIDGED_INLINE bool enableStackProtection() const;
BRIDGED_INLINE bool hasFeature(BridgedFeature feature) const;
BRIDGED_INLINE bool enableMoveInoutStackProtection() const;
BRIDGED_INLINE AssertConfiguration getAssertConfiguration() const;
bool enableSimplificationFor(BridgedInstruction inst) const;
// Closure specializer
SWIFT_IMPORT_UNSAFE BridgedFunction ClosureSpecializer_createEmptyFunctionWithSpecializedSignature(BridgedStringRef specializedName,
const BridgedParameterInfo * _Nullable specializedBridgedParams,
SwiftInt paramCount,
BridgedFunction bridgedApplySiteCallee,
bool isSerialized) const;
};
bool FullApplySite_canInline(BridgedInstruction apply);
enum class BridgedDynamicCastResult {
willSucceed,
maySucceed,
willFail
};
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedType sourceTy, BridgedType destTy,
BridgedFunction function,
bool sourceTypeIsExact);
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedInstruction inst);
void verifierError(BridgedStringRef message, OptionalBridgedInstruction atInstruction, OptionalBridgedArgument atArgument);
//===----------------------------------------------------------------------===//
// Pass registration
//===----------------------------------------------------------------------===//
struct BridgedFunctionPassCtxt {
BridgedFunction function;
BridgedPassContext passContext;
} ;
struct BridgedInstructionPassCtxt {
BridgedInstruction instruction;
BridgedPassContext passContext;
};
typedef void (* _Nonnull BridgedModulePassRunFn)(BridgedPassContext);
typedef void (* _Nonnull BridgedFunctionPassRunFn)(BridgedFunctionPassCtxt);
typedef void (* _Nonnull BridgedInstructionPassRunFn)(BridgedInstructionPassCtxt);
void SILPassManager_registerModulePass(BridgedStringRef name,
BridgedModulePassRunFn runFn);
void SILPassManager_registerFunctionPass(BridgedStringRef name,
BridgedFunctionPassRunFn runFn);
void SILCombine_registerInstructionPass(BridgedStringRef instClassName,
BridgedInstructionPassRunFn runFn);
#ifndef PURE_BRIDGING_MODE
// In _not_ PURE_BRIDGING_MODE, briding functions are inlined and therefore inluded in the header file.
#include "OptimizerBridgingImpl.h"
#else
// For fflush and stdout
#include <stdio.h>
#endif
SWIFT_END_NULLABILITY_ANNOTATIONS
#endif