Merge branch 'main' into mpokhylets/isolated-deinit

This commit is contained in:
Konrad `ktoso` Malawski
2024-09-02 23:16:17 +09:00
committed by GitHub
207 changed files with 3850 additions and 2417 deletions

View File

@@ -543,10 +543,37 @@ public:
RangeIterationHelpers::MapFunctor());
}
void visitUsers(llvm::function_ref<void(SILInstruction *, LifetimeEnding)>
visitor) const {
for (auto &pair : users) {
visitor(pair.first, pair.second);
}
}
void print(llvm::raw_ostream &OS) const;
void dump() const;
};
/// Recording liveness boundary at some level of detail; see concrete subclasses
/// PrunedLivenessBoundary and PrunedLivenessBlockBoundary.
struct AnyPrunedLivenessBoundary {
virtual ~AnyPrunedLivenessBoundary() {}
/// Targets whose single predecessor has at least one non-boundary successor.
SmallVector<SILBasicBlock *, 8> boundaryEdges;
friend class SSAPrunedLiveness;
friend class MultiDefPrunedLiveness;
private:
virtual void findBoundaryInSSADefBlock(SILNode *ssaDef,
const PrunedLiveness &liveness) = 0;
virtual void
findBoundaryInMultiDefBlock(SILBasicBlock *block, bool isLiveOut,
const MultiDefPrunedLiveness &liveness) = 0;
virtual void findBoundaryInNonDefBlock(SILBasicBlock *block,
const PrunedLiveness &liveness) = 0;
};
/// Record the last use points and CFG edges that form the boundary of
/// PrunedLiveness.
///
@@ -558,9 +585,8 @@ public:
/// Each boundary edge is identified by its target block. The source of the edge
/// is the target block's single predecessor which must have at least one other
/// non-boundary successor.
struct PrunedLivenessBoundary {
struct PrunedLivenessBoundary : AnyPrunedLivenessBoundary {
SmallVector<SILInstruction *, 8> lastUsers;
SmallVector<SILBasicBlock *, 8> boundaryEdges;
SmallVector<SILNode *, 1> deadDefs;
void clear() {
@@ -579,6 +605,39 @@ struct PrunedLivenessBoundary {
void print(llvm::raw_ostream &OS) const;
void dump() const;
private:
void findBoundaryInSSADefBlock(SILNode *ssaDef,
const PrunedLiveness &liveness) override;
void
findBoundaryInMultiDefBlock(SILBasicBlock *block, bool isLiveOut,
const MultiDefPrunedLiveness &liveness) override;
void findBoundaryInNonDefBlock(SILBasicBlock *block,
const PrunedLiveness &liveness) override;
};
/// Record the blocks which either contain last use points or are boundary edge
/// targets.
///
/// Enables clients only interested in block-level details to avoid expensive
/// and for-them wasteful instruction list iteration.
struct PrunedLivenessBlockBoundary : AnyPrunedLivenessBoundary {
/// Blocks containing last users or dead defs.
SmallVector<SILBasicBlock *, 8> endBlocks;
void clear() {
endBlocks.clear();
boundaryEdges.clear();
}
private:
void findBoundaryInSSADefBlock(SILNode *ssaDef,
const PrunedLiveness &liveness) override;
void
findBoundaryInMultiDefBlock(SILBasicBlock *block, bool isLiveOut,
const MultiDefPrunedLiveness &liveness) override;
void findBoundaryInNonDefBlock(SILBasicBlock *block,
const PrunedLiveness &liveness) override;
};
/// PrunedLiveness with information about defs for computing the live range
@@ -689,7 +748,7 @@ public:
/// The computed boundary will completely post-dominate, including dead end
/// paths. The client should query DeadEndBlocks to ignore those dead end
/// paths.
void computeBoundary(PrunedLivenessBoundary &boundary) const;
void computeBoundary(AnyPrunedLivenessBoundary &boundary) const;
/// Compute the boundary from a backward CFG traversal from a known set of
/// jointly post-dominating blocks. Avoids the need to record an ordered list
@@ -765,7 +824,7 @@ public:
/// SSA implementation of computeBoundary.
void findBoundariesInBlock(SILBasicBlock *block, bool isLiveOut,
PrunedLivenessBoundary &boundary) const;
AnyPrunedLivenessBoundary &boundary) const;
/// Compute liveness for a single SSA definition. The lifetime-ending uses are
/// also recorded--destroy_value or end_borrow.
@@ -853,9 +912,9 @@ public:
/// Multi-Def implementation of computeBoundary.
void findBoundariesInBlock(SILBasicBlock *block, bool isLiveOut,
PrunedLivenessBoundary &boundary) const;
AnyPrunedLivenessBoundary &boundary) const;
/// Compute liveness for a all currently initialized definitions. The
/// Compute liveness for all currently initialized definitions. The
/// lifetime-ending uses are also recorded--destroy_value or
/// end_borrow. However destroy_values might not jointly-post dominate if
/// dead-end blocks are present.
@@ -872,6 +931,9 @@ public:
/// also lack scope-ending instructions, so the liveness of their nested uses
/// may be ignored.
LiveRangeSummary computeSimple();
friend struct PrunedLivenessBoundary;
friend struct PrunedLivenessBlockBoundary;
};
//===----------------------------------------------------------------------===//

View File

@@ -60,9 +60,8 @@ struct SubstitutionMapWithLocalArchetypes {
// Map the local archetype to an interface type in the new generic
// signature.
MapLocalArchetypesOutOfContext mapOutOfContext(BaseGenericSig,
CapturedEnvs);
auto interfaceTy = mapOutOfContext(local);
auto interfaceTy = mapLocalArchetypesOutOfContext(
local, BaseGenericSig, CapturedEnvs);
// Map this interface type into the new generic environment to get
// a primary archetype.

View File

@@ -56,7 +56,8 @@ enum IsThunk_t {
IsNotThunk,
IsThunk,
IsReabstractionThunk,
IsSignatureOptimizedThunk
IsSignatureOptimizedThunk,
IsBackDeployedThunk,
};
enum IsDynamicallyReplaceable_t {
IsNotDynamic,
@@ -368,7 +369,7 @@ private:
///
/// The inliner uses this information to avoid inlining (non-trivial)
/// functions into the thunk.
unsigned Thunk : 2;
unsigned Thunk : 3;
/// The scope in which the parent class can be subclassed, if this is a method
/// which is contained in the vtable of that class.
@@ -486,6 +487,7 @@ private:
break;
case IsThunk:
case IsReabstractionThunk:
case IsBackDeployedThunk:
thunkCanHaveSubclassScope = false;
break;
}

View File

@@ -722,8 +722,8 @@ public:
/// Run the given function for each local archetype this instruction
/// defines, passing the value that should be used to record the
/// dependency.
void forEachDefinedLocalArchetype(
llvm::function_ref<void(CanLocalArchetypeType archetype,
void forEachDefinedLocalEnvironment(
llvm::function_ref<void(GenericEnvironment *genericEnv,
SILValue typeDependency)> function) const;
bool definesLocalArchetypes() const;
@@ -8194,8 +8194,8 @@ class OpenPackElementInst final
public:
/// Call the given function for each element archetype that this
/// instruction opens.
void forEachDefinedLocalArchetype(
llvm::function_ref<void(CanLocalArchetypeType, SILValue)> fn) const;
void forEachDefinedLocalEnvironment(
llvm::function_ref<void(GenericEnvironment *, SILValue)> fn) const;
GenericEnvironment *getOpenedGenericEnvironment() const {
return Env;

View File

@@ -343,7 +343,7 @@ private:
/// projections, shared between all functions in the module.
std::unique_ptr<IndexTrieNode> indexTrieRoot;
/// A mapping from root local archetypes to the instructions which define
/// A mapping from local generic environments to the instructions which define
/// them.
///
/// The value is either a SingleValueInstruction or a PlaceholderValue,
@@ -351,10 +351,10 @@ private:
/// deserializing SIL, where local archetypes can be forward referenced.
///
/// In theory we wouldn't need to have the SILFunction in the key, because
/// local archetypes \em should be unique across the module. But currently
/// local environments should be unique across the module. But currently
/// in some rare cases SILGen re-uses the same local archetype for multiple
/// functions.
using LocalArchetypeKey = std::pair<LocalArchetypeType *, SILFunction *>;
using LocalArchetypeKey = std::pair<GenericEnvironment *, SILFunction *>;
llvm::DenseMap<LocalArchetypeKey, SILValue> RootLocalArchetypeDefs;
/// The number of PlaceholderValues in RootLocalArchetypeDefs.
@@ -451,6 +451,27 @@ public:
hasAccessMarkerHandler = true;
}
/// Returns the instruction which defines the given local generic environment,
/// e.g. an open_existential_addr.
///
/// In case the generic environment is not defined yet (e.g. during parsing or
/// deserialization), a PlaceholderValue is returned. This should not be the
/// case outside of parsing or deserialization.
SILValue getLocalGenericEnvironmentDef(GenericEnvironment *genericEnv,
SILFunction *inFunction);
/// Returns the instruction which defines the given local generic environment,
/// e.g. an open_existential_addr.
///
/// In contrast to getLocalGenericEnvironmentDef, it is required that all local
/// generic environments are resolved.
SingleValueInstruction *
getLocalGenericEnvironmentDefInst(GenericEnvironment *genericEnv,
SILFunction *inFunction) {
return dyn_cast<SingleValueInstruction>(
getLocalGenericEnvironmentDef(genericEnv, inFunction));
}
/// Returns the instruction which defines the given root local archetype,
/// e.g. an open_existential_addr.
///