Files
swift-mirror/include/swift/SILOptimizer/OptimizerBridging.h
Erik Eckstein 18063707b5 Optimizer: enable complete OSSA lifetimes throughout the pass pipeline
This new OSSA invariant simplifies many optimizations because they don't have to take care of the corner case of incomplete lifetimes in dead-end blocks.

The implementation basically consists of these changes:
* add the lifetime completion utility
* add a flag in SILFunction which tells optimization that they need to run the lifetime completion utility
* let all optimizations complete lifetimes if necessary
* enable the ownership verifier to check complete lifetimes
2026-01-22 17:41:48 +01:00

357 lines
16 KiB
C++

//===--- OptimizerBridging.h - header for the OptimizerBridging module ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 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
/// `OptimizerBridging.h` is imported into Swift. Be *very* careful with what
/// you include here and keep these includes minimal!
///
/// See include guidelines and caveats in `BasicBridging.h`.
#include "swift/AST/ASTBridging.h"
#include "swift/SIL/SILBridging.h"
#include "swift/SILOptimizer/Analysis/ArrayCallKind.h"
#ifndef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE
// 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 // #ifndef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
namespace swift {
class AliasAnalysis;
class ArraySemanticsCall;
class BasicCalleeAnalysis;
class CalleeList;
class DeadEndBlocks;
class DominanceInfo;
class PostDominanceInfo;
class SILLoopInfo;
class SILLoop;
class SwiftPassInvocation;
class SILVTable;
}
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)(
BridgedContext context, BridgedAliasAnalysis aliasAnalysis,
BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull Escaping2InstFn)(
BridgedContext context, BridgedAliasAnalysis aliasAnalysis, BridgedValue, BridgedInstruction);
typedef bool (* _Nonnull Escaping2ValIntFn)(
BridgedContext context, BridgedAliasAnalysis aliasAnalysis, BridgedValue, BridgedValue);
typedef bool (* _Nonnull MayAliasFn)(
BridgedContext 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];
BRIDGED_INLINE CalleeList(swift::CalleeList list);
BRIDGED_INLINE swift::CalleeList unbridged() const;
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;
BRIDGED_INLINE SwiftInt getNumberOfChildren(BridgedBasicBlock bb) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock getChildAt(BridgedBasicBlock bb, SwiftInt index) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedBasicBlock getImmediateDominator(BridgedBasicBlock block) const;
};
struct BridgedPostDomTree {
swift::PostDominanceInfo * _Nonnull pdi;
BRIDGED_INLINE bool postDominates(BridgedBasicBlock dominating, BridgedBasicBlock dominated) const;
};
struct BridgedOptimizerUtilities {
typedef void (* _Nonnull UpdateFunctionFn)(BridgedContext, BridgedFunction);
typedef void (* _Nonnull UpdateLifetimeFunctionFn)(BridgedContext, BridgedFunction, bool);
typedef void (* _Nonnull UpdateLifetimeValuesFn)(BridgedContext, BridgedArrayRef, BridgedArrayRef);
static void registerLifetimeCompletion(UpdateLifetimeFunctionFn completeAllLifetimesFn,
UpdateLifetimeValuesFn completeLifetimeFn);
static void registerControlFlowUtils(UpdateFunctionFn breakInfiniteLoopsFn);
};
struct BridgedLoopTree {
swift::SILLoopInfo * _Nonnull li;
BRIDGED_INLINE SwiftInt getTopLevelLoopCount() const;
BRIDGED_INLINE BridgedLoop getLoop(SwiftInt index) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock splitEdge(BridgedBasicBlock bb, SwiftInt edgeIndex, BridgedDomTree domTree) const;
};
struct BridgedPassContext {
swift::SwiftPassInvocation * _Nonnull invocation;
BridgedPassContext(swift::SwiftPassInvocation * _Nonnull invocation) : invocation(invocation) {}
BRIDGED_INLINE BridgedPassContext(BridgedContext ctxt);
BRIDGED_INLINE bool hadError() const;
BRIDGED_INLINE void notifyDependencyOnBodyOf(BridgedFunction otherFunction) const;
BRIDGED_INLINE void updateAnalysis() 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 BridgedDeclObj getSwiftArrayDecl() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeclObj getSwiftMutableSpanDecl() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedLoopTree getLoopTree() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedLoop getLoop() const;
// Array semantics call
static BRIDGED_INLINE ArrayCallKind getArraySemanticsCallKind(BridgedInstruction inst);
BRIDGED_INLINE bool canHoistArraySemanticsCall(BridgedInstruction inst, BridgedInstruction toInst) const;
BRIDGED_INLINE void hoistArraySemanticsCall(BridgedInstruction inst, BridgedInstruction beforeInst) const;
// AST
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE
BridgedDiagnosticEngine getDiagnosticEngine() const;
// SIL modifications
struct DevirtResult {
OptionalBridgedInstruction newApply;
bool cfgChanged;
};
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 OptionalBridgedFunction specializeFunction(BridgedFunction function,
BridgedSubstitutionMap substitutions,
bool convertIndirectToDirect,
bool isMandatory) const;
void deserializeAllCallees(BridgedFunction function, bool deserializeAll) const;
bool specializeClassMethodInst(BridgedInstruction cm) const;
bool specializeWitnessMethodInst(BridgedInstruction wm) const;
bool specializeAppliesInFunction(BridgedFunction function, bool isMandatory) const;
BridgedOwnedString mangleOutlinedVariable(BridgedFunction function) const;
BridgedOwnedString mangleAsyncRemoved(BridgedFunction function) const;
struct ClosureArgMangling {
SwiftInt argIdx;
OptionalBridgedInstruction inst;
SwiftInt otherArgIdx;
};
BridgedOwnedString mangleWithDeadArgs(BridgedArrayRef bridgedDeadArgIndices, BridgedFunction function) const;
BridgedOwnedString mangleWithClosureArgs(BridgedArrayRef closureArgManglings, BridgedFunction applySiteCallee) const;
BridgedOwnedString mangleWithConstCaptureArgs(BridgedArrayRef bridgedConstArgs,
BridgedFunction applySiteCallee) const;
BridgedOwnedString mangleWithBoxToStackPromotedArgs(BridgedArrayRef bridgedPromotedArgIndices,
BridgedFunction bridgedOriginalFunction) const;
BridgedOwnedString mangleWithExplodedPackArgs(BridgedArrayRef bridgedPackArgs,
BridgedFunction applySiteCallee) const;
BridgedOwnedString mangleWithChangedRepresentation(BridgedFunction applySiteCallee) const;
void inlineFunction(BridgedInstruction apply, bool mandatoryInline) const;
BRIDGED_INLINE bool eliminateDeadAllocations(BridgedFunction f) const;
void eraseFunction(BridgedFunction function) const;
BRIDGED_INLINE bool shouldExpand(BridgedType type) const;
// IRGen
SwiftInt getStaticSize(BridgedType type) const;
SwiftInt getStaticAlignment(BridgedType type) const;
SwiftInt getStaticStride(BridgedType type) const;
bool canMakeStaticObjectReadOnly(BridgedType type) const;
// Stack nesting and other notifications
BRIDGED_INLINE void notifyInvalidatedStackNesting() const;
BRIDGED_INLINE bool getNeedFixStackNesting() const;
void fixStackNesting(BridgedFunction function) const;
BRIDGED_INLINE bool getNeedBreakInfiniteLoops() const;
BRIDGED_INLINE void setNeedBreakInfiniteLoops(bool value) const;
BRIDGED_INLINE bool getNeedCompleteLifetimes() const;
BRIDGED_INLINE void setNeedCompleteLifetimes(bool value) const;
// Access SIL module data structures
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);
BRIDGED_INLINE SwiftInt getNumVTables() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedVTable getVTable(SwiftInt index) 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);
// Passmanager housekeeping
BRIDGED_INLINE bool continueWithNextSubpassRun(OptionalBridgedInstruction inst) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedContext initializeNestedPassContext(BridgedFunction newFunction) const;
BRIDGED_INLINE void deinitializedNestedPassContext() const;
BRIDGED_INLINE void
addFunctionToPassManagerWorklist(BridgedFunction newFunction,
BridgedFunction oldFunction) const;
// Options
enum class AssertConfiguration {
Debug = 0,
Release = 1,
Unchecked = 2
};
BRIDGED_INLINE bool useAggressiveReg2MemForCodeSize() const;
BRIDGED_INLINE bool enableStackProtection() const;
BRIDGED_INLINE bool enableMergeableTraps() const;
BRIDGED_INLINE bool hasFeature(BridgedFeature feature) const;
BRIDGED_INLINE bool shouldRemoveCondFail(BridgedStringRef message, BridgedStringRef function) const;
BRIDGED_INLINE bool enableMoveInoutStackProtection() const;
BRIDGED_INLINE AssertConfiguration getAssertConfiguration() const;
bool enableSimplificationFor(BridgedInstruction inst) const;
BRIDGED_INLINE bool enableWMORequiredDiagnostics() const;
BRIDGED_INLINE bool noAllocations() const;
// Temporary for AddressableParameters Bootstrapping.
BRIDGED_INLINE bool enableAddressDependencies() const;
// Closure specializer
SWIFT_IMPORT_UNSAFE BridgedFunction createSpecializedFunctionDeclaration(BridgedStringRef specializedName,
const BridgedParameterInfo * _Nullable specializedBridgedParams,
SwiftInt paramCount,
const BridgedResultInfo *_Nullable specializedBridgedResults,
SwiftInt resultCount,
BridgedFunction bridgedOriginal,
BridgedASTType::FunctionTypeRepresentation representation,
bool makeBare,
bool preserveGenericSignature) const;
bool completeLifetime(BridgedValue value) const;
};
bool BeginApply_canInline(BridgedInstruction beginApply);
enum class BridgedDynamicCastResult {
willSucceed,
maySucceed,
willFail
};
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedCanType sourceTy, BridgedCanType destTy,
BridgedFunction function,
bool sourceTypeIsExact);
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedInstruction inst);
//===----------------------------------------------------------------------===//
// Pass registration
//===----------------------------------------------------------------------===//
struct BridgedFunctionPassCtxt {
BridgedFunction function;
BridgedContext passContext;
} ;
struct BridgedInstructionPassCtxt {
BridgedInstruction instruction;
BridgedContext passContext;
};
typedef void (* _Nonnull BridgedModulePassRunFn)(BridgedContext);
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);
void registerFunctionTestThunk(SwiftNativeFunctionTestThunk);
void registerFunctionTest(BridgedStringRef, void *_Nonnull nativeSwiftContext);
#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