mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This allows one to place types like PointerIntPair and value types that wrap a pointer into the pointer set. I am making this change before I use this data structure in TransferNonSendable and using ARC to validate that I haven't broken anything.
253 lines
10 KiB
C++
253 lines
10 KiB
C++
//===--- ARCRegionState.h ---------------------------------------*- C++ -*-===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_ARCREGIONSTATE_H
|
|
#define SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_ARCREGIONSTATE_H
|
|
|
|
#include "GlobalLoopARCSequenceDataflow.h"
|
|
#include "swift/Basic/NullablePtr.h"
|
|
|
|
namespace swift {
|
|
|
|
class LoopRegion;
|
|
class LoopRegionFunctionInfo;
|
|
class AliasAnalysis;
|
|
class RCIdentityFunctionInfo;
|
|
|
|
/// Per-Region state.
|
|
class ARCRegionState {
|
|
public:
|
|
// TODO: These are relatively expensive, find something else to use here.
|
|
using TopDownMapTy = SmallBlotMapVector<SILValue, TopDownRefCountState, 4>;
|
|
using BottomUpMapTy = SmallBlotMapVector<SILValue, BottomUpRefCountState, 4>;
|
|
|
|
private:
|
|
/// The region that this ARCRegionState summarizes information for.
|
|
///
|
|
/// The only time that the pointer is null is during initialization. Using
|
|
/// NullablePtr is just a convenient way to make sure that we assert if we
|
|
/// attempt to use Region during initialization before the pointer is set.
|
|
NullablePtr<LoopRegion> Region;
|
|
|
|
/// The top-down traversal uses this to record information known about a
|
|
/// pointer at the bottom of each block.
|
|
TopDownMapTy PtrToTopDownState;
|
|
|
|
/// The bottom-up traversal uses this to record information known about a
|
|
/// pointer at the top of each block.
|
|
BottomUpMapTy PtrToBottomUpState;
|
|
|
|
/// Is this a region from which we can leak ARC values?
|
|
///
|
|
/// If we know that the program has entered a state from which it is
|
|
/// guaranteed to terminate soon, in our model we allow for all memory to be
|
|
/// leaked since the operating system will soon reclaim the memory. We take
|
|
/// advantage of this to ignore control flow.
|
|
bool AllowsLeaks;
|
|
|
|
/// A list of instructions contained in this region that can either use or
|
|
/// decrement reference counts.
|
|
///
|
|
/// This is flow insensitive since we just add all of the potential
|
|
/// users/decrements in subregions without caring if there is only one along a
|
|
/// path. This is for simplicity in the first iteration.
|
|
///
|
|
/// TODO: This needs a better name.
|
|
llvm::SmallVector<SILInstruction *, 4> SummarizedInterestingInsts;
|
|
|
|
public:
|
|
ARCRegionState(LoopRegion *R, bool AllowsLeaks);
|
|
|
|
/// Is this Region from which we can leak memory safely?
|
|
bool allowsLeaks() const { return AllowsLeaks; }
|
|
|
|
/// Return the region associated with this ARCRegionState.
|
|
///
|
|
/// Even though Region is a NullablePtr, it is only null during
|
|
/// initialization. This method should not be called then.
|
|
const LoopRegion *getRegion() const { return Region.get(); }
|
|
LoopRegion *getRegion() { return Region.get(); }
|
|
|
|
/// Top Down Iterators
|
|
using topdown_iterator = TopDownMapTy::iterator;
|
|
using topdown_const_iterator = TopDownMapTy::const_iterator;
|
|
topdown_iterator topdown_begin() { return PtrToTopDownState.begin(); }
|
|
topdown_iterator topdown_end() { return PtrToTopDownState.end(); }
|
|
topdown_const_iterator topdown_begin() const {
|
|
return PtrToTopDownState.begin();
|
|
}
|
|
topdown_const_iterator topdown_end() const { return PtrToTopDownState.end(); }
|
|
iterator_range<topdown_iterator> getTopDownStates() {
|
|
return make_range(topdown_begin(), topdown_end());
|
|
}
|
|
|
|
/// Bottom up iteration.
|
|
using bottomup_iterator = BottomUpMapTy::iterator;
|
|
using bottomup_const_iterator = BottomUpMapTy::const_iterator;
|
|
bottomup_iterator bottomup_begin() { return PtrToBottomUpState.begin(); }
|
|
bottomup_iterator bottomup_end() { return PtrToBottomUpState.end(); }
|
|
bottomup_const_iterator bottomup_begin() const {
|
|
return PtrToBottomUpState.begin();
|
|
}
|
|
bottomup_const_iterator bottomup_end() const {
|
|
return PtrToBottomUpState.end();
|
|
}
|
|
iterator_range<bottomup_iterator> getBottomupStates() {
|
|
return make_range(bottomup_begin(), bottomup_end());
|
|
}
|
|
|
|
/// Attempt to find the PtrState object describing the top down state for
|
|
/// pointer Arg. Return a new initialized PtrState describing the top down
|
|
/// state for Arg if we do not find one.
|
|
TopDownRefCountState &getTopDownRefCountState(SILValue Ptr) {
|
|
return PtrToTopDownState[Ptr];
|
|
}
|
|
|
|
/// Attempt to find the PtrState object describing the bottom up state for
|
|
/// pointer Arg. Return a new initialized PtrState describing the bottom up
|
|
/// state for Arg if we do not find one.
|
|
BottomUpRefCountState &getBottomUpRefCountState(SILValue Ptr) {
|
|
return PtrToBottomUpState[Ptr];
|
|
}
|
|
|
|
/// Blot \p Ptr.
|
|
void clearBottomUpRefCountState(SILValue Ptr) {
|
|
PtrToBottomUpState.erase(Ptr);
|
|
}
|
|
|
|
/// Blot \p Ptr.
|
|
void clearTopDownRefCountState(SILValue Ptr) { PtrToTopDownState.erase(Ptr); }
|
|
|
|
void clearTopDownState() { PtrToTopDownState.clear(); }
|
|
void clearBottomUpState() { PtrToBottomUpState.clear(); }
|
|
|
|
/// Clear both the bottom up *AND* top down state.
|
|
void clear() {
|
|
clearTopDownState();
|
|
clearBottomUpState();
|
|
}
|
|
|
|
using const_reverse_summarizedinterestinginsts_iterator =
|
|
decltype(SummarizedInterestingInsts)::const_reverse_iterator;
|
|
const_reverse_summarizedinterestinginsts_iterator
|
|
summarizedinterestinginsts_rbegin() const {
|
|
return SummarizedInterestingInsts.rbegin();
|
|
}
|
|
const_reverse_summarizedinterestinginsts_iterator
|
|
summarizedinterestinginsts_rend() const {
|
|
return SummarizedInterestingInsts.rend();
|
|
}
|
|
|
|
using const_summarizedinterestinginsts_iterator =
|
|
decltype(SummarizedInterestingInsts)::const_iterator;
|
|
const_summarizedinterestinginsts_iterator
|
|
summarizedinterestinginsts_begin() const {
|
|
return SummarizedInterestingInsts.begin();
|
|
}
|
|
const_summarizedinterestinginsts_iterator
|
|
summarizedinterestinginsts_end() const {
|
|
return SummarizedInterestingInsts.end();
|
|
}
|
|
iterator_range<const_summarizedinterestinginsts_iterator>
|
|
getSummarizedInterestingInsts() const {
|
|
return {summarizedinterestinginsts_begin(),
|
|
summarizedinterestinginsts_end()};
|
|
}
|
|
|
|
/// Merge in the state of the successor basic block. This is currently a stub.
|
|
void mergeSuccBottomUp(ARCRegionState &SuccRegion);
|
|
|
|
/// Initialize this Region with the state of the successor basic block. This
|
|
/// is
|
|
/// called on a basic block's state and then any other successors states are
|
|
/// merged in. This is currently a stub.
|
|
void initSuccBottomUp(ARCRegionState &SuccRegion);
|
|
|
|
/// Merge in the state of the predecessor basic block. This is currently a
|
|
/// stub.
|
|
void mergePredTopDown(ARCRegionState &PredRegion);
|
|
|
|
/// Initialize the state for this Region with the state of its predecessor
|
|
/// Region. Used to create an initial state before we merge in other
|
|
/// predecessors. This is currently a stub.
|
|
void initPredTopDown(ARCRegionState &PredRegion);
|
|
|
|
/// If this region is a block, process all instructions top down. Otherwise,
|
|
/// apply the summarized top down information to the merged top down
|
|
/// state. Returns true if nested retains were detected while visiting
|
|
/// instructions. Returns false otherwise.
|
|
bool processTopDown(
|
|
AliasAnalysis *AA, RCIdentityFunctionInfo *RCIA,
|
|
LoopRegionFunctionInfo *LRFI,
|
|
llvm::DenseSet<SILInstruction *> &UnmatchedRefCountInsts,
|
|
BlotMapVector<SILInstruction *, TopDownRefCountState> &DecToIncStateMap,
|
|
llvm::DenseMap<const LoopRegion *, ARCRegionState *> &LoopRegionState,
|
|
ImmutablePointerSetFactory<SILInstruction *> &SetFactory);
|
|
|
|
/// If this region is a block, process all instructions bottom up. Otherwise,
|
|
/// apply the summarized bottom up information to the merged bottom up
|
|
/// state. Returns true if nested releases were detected while visiting
|
|
/// instructions. Returns false otherwise.
|
|
bool processBottomUp(
|
|
AliasAnalysis *AA, RCIdentityFunctionInfo *RCIA,
|
|
EpilogueARCFunctionInfo *EAFI, LoopRegionFunctionInfo *LRFI,
|
|
bool FreezeOwnedArgEpilogueReleases,
|
|
llvm::DenseSet<SILInstruction *> &UnmatchedRefCountInsts,
|
|
BlotMapVector<SILInstruction *, BottomUpRefCountState> &IncToDecStateMap,
|
|
llvm::DenseMap<const LoopRegion *, ARCRegionState *> &RegionStateInfo,
|
|
ImmutablePointerSetFactory<SILInstruction *> &SetFactory);
|
|
|
|
void summarizeBlock(SILBasicBlock *BB);
|
|
|
|
void summarize(
|
|
LoopRegionFunctionInfo *LRFI,
|
|
llvm::DenseMap<const LoopRegion *, ARCRegionState *> &RegionStateInfo);
|
|
|
|
/// Add \p I to the interesting instruction list of this region if it is a
|
|
/// block. We assume that I is an instruction in the block.
|
|
void addInterestingInst(SILInstruction *I);
|
|
|
|
/// Remove \p I from the interesting instruction list of this region if it is
|
|
/// a block. We assume that I is an instruction in the block.
|
|
void removeInterestingInst(SILInstruction *I);
|
|
|
|
private:
|
|
bool processBlockBottomUp(
|
|
const LoopRegion *R, AliasAnalysis *AA, RCIdentityFunctionInfo *RCIA,
|
|
EpilogueARCFunctionInfo *EAFI, LoopRegionFunctionInfo *LRFI,
|
|
bool FreezeOwnedArgEpilogueReleases,
|
|
BlotMapVector<SILInstruction *, BottomUpRefCountState> &IncToDecStateMap,
|
|
ImmutablePointerSetFactory<SILInstruction *> &SetFactory);
|
|
bool processLoopBottomUp(
|
|
const LoopRegion *R, AliasAnalysis *AA, LoopRegionFunctionInfo *LRFI,
|
|
RCIdentityFunctionInfo *RCIA,
|
|
llvm::DenseMap<const LoopRegion *, ARCRegionState *> &RegionStateInfo,
|
|
llvm::DenseSet<SILInstruction *> &UnmatchedRefCountInsts);
|
|
|
|
bool processBlockTopDown(
|
|
SILBasicBlock &BB, AliasAnalysis *AA, RCIdentityFunctionInfo *RCIA,
|
|
BlotMapVector<SILInstruction *, TopDownRefCountState> &DecToIncStateMap,
|
|
ImmutablePointerSetFactory<SILInstruction *> &SetFactory);
|
|
bool processLoopTopDown(
|
|
const LoopRegion *R, ARCRegionState *State, AliasAnalysis *AA,
|
|
LoopRegionFunctionInfo *LRFI, RCIdentityFunctionInfo *RCIA,
|
|
llvm::DenseSet<SILInstruction *> &UnmatchedRefCountInsts);
|
|
|
|
void summarizeLoop(
|
|
const LoopRegion *R, LoopRegionFunctionInfo *LRFI,
|
|
llvm::DenseMap<const LoopRegion *, ARCRegionState *> &RegionStateInfo);
|
|
};
|
|
|
|
} // end swift namespace
|
|
|
|
#endif
|