blob: df139e9b7dcba2eae169b731ef4cc7e84b5ddd59 [file] [log] [blame]
//===--- ARCBBState.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_ARCBBSTATE_H
#define SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_ARCBBSTATE_H
#include "GlobalARCSequenceDataflow.h"
namespace swift {
/// \brief Per-BasicBlock state.
class ARCSequenceDataflowEvaluator::ARCBBState {
public:
using TopDownMapTy = SmallBlotMapVector<SILValue, TopDownRefCountState, 4>;
using BottomUpMapTy = SmallBlotMapVector<SILValue, BottomUpRefCountState, 4>;
private:
/// The basic block that this bbstate corresponds to.
SILBasicBlock *BB;
/// 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 BB that is a trap?
bool IsTrapBB;
public:
ARCBBState() : BB() {}
ARCBBState(SILBasicBlock *BB) : BB(BB) {}
void init(SILBasicBlock *NewBB, bool NewIsTrapBB) {
assert(NewBB && "Cannot set NewBB to a nullptr.");
BB = NewBB;
IsTrapBB = NewIsTrapBB;
}
/// Is this BB a BB that fits the canonical form of a trap?
///
/// The canonical form of a trap is:
///
/// builtin "int_trap"() : $()
/// unreachable
///
/// This cannot have any uses of reference counted values since the frontend
/// just leaks at that point.
bool isTrapBB() const { return IsTrapBB; }
/// 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.blot(Ptr);
}
/// Blot \p Ptr.
void clearTopDownRefCountState(SILValue Ptr) { PtrToTopDownState.blot(Ptr); }
void clearTopDownState() { PtrToTopDownState.clear(); }
void clearBottomUpState() { PtrToBottomUpState.clear(); }
/// Clear both the bottom up *AND* top down state.
void clear() {
clearTopDownState();
clearBottomUpState();
}
/// Returns a reference to the basic block that we are tracking.
SILBasicBlock &getBB() const { return *BB; }
/// Merge in the state of the successor basic block. This is currently a stub.
void mergeSuccBottomUp(ARCBBState &SuccBB);
/// Initialize this BB 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(ARCBBState &SuccBB);
/// Merge in the state of the predecessor basic block. This is currently a
/// stub.
void mergePredTopDown(ARCBBState &PredBB);
/// Initialize the state for this BB with the state of its predecessor
/// BB. Used to create an initial state before we merge in other
/// predecessors. This is currently a stub.
void initPredTopDown(ARCBBState &PredBB);
};
class ARCSequenceDataflowEvaluator::ARCBBStateInfoHandle {
friend ARCSequenceDataflowEvaluator::ARCBBStateInfo;
SILBasicBlock *BB;
ARCBBState &BBState;
NullablePtr<llvm::SmallPtrSet<SILBasicBlock *, 4>> BackedgeMap;
unsigned ID;
ARCBBStateInfoHandle(SILBasicBlock *BB, unsigned ID, ARCBBState &BBState)
: BB(BB), BBState(BBState), BackedgeMap(), ID(ID) {}
ARCBBStateInfoHandle(SILBasicBlock *BB, unsigned ID, ARCBBState &BBState,
llvm::SmallPtrSet<SILBasicBlock *, 4> &BackedgeMap)
: BB(BB), BBState(BBState), BackedgeMap(&BackedgeMap), ID(ID) {}
public:
ARCBBStateInfoHandle(const ARCBBStateInfoHandle &) = default;
ARCBBStateInfoHandle(ARCBBStateInfoHandle &&) = default;
;
~ARCBBStateInfoHandle() = default;
SILBasicBlock *getBB() const { return BB; }
unsigned getID() const { return ID; }
ARCBBState &getState() { return BBState; }
bool isBackedge(SILBasicBlock *BB) const {
if (BackedgeMap.isNull())
return false;
return BackedgeMap.get()->count(BB);
}
};
class ARCSequenceDataflowEvaluator::ARCBBStateInfo {
/// A map from BB -> BBID. A BB's BBID is its RPOT number.
llvm::DenseMap<SILBasicBlock *, unsigned> BBToBBIDMap;
/// Map from a BBID to BB's bottom up dataflow state. Meant to be used in
/// conjunction with BBToBBIDMap.
std::vector<ARCBBState> BBIDToBottomUpBBStateMap;
/// Map from a BBID to BB's top down dataflow state. Meant to be used in
/// conjunction with BBToBBIDMap.
std::vector<ARCBBState> BBIDToTopDownBBStateMap;
/// A map mapping the head to a tail of a backedge. We only compute this once
/// in the lifetime of this class.
llvm::DenseMap<SILBasicBlock *, llvm::SmallPtrSet<SILBasicBlock *, 4>>
BackedgeMap;
public:
ARCBBStateInfo(SILFunction *F, PostOrderAnalysis *POTA,
ProgramTerminationFunctionInfo *PTFI);
llvm::Optional<ARCBBStateInfoHandle> getBottomUpBBHandle(SILBasicBlock *BB);
llvm::Optional<ARCBBStateInfoHandle> getTopDownBBHandle(SILBasicBlock *BB);
void clear();
private:
llvm::Optional<unsigned> getBBID(SILBasicBlock *BB) const;
};
} // end swift namespace
#endif