Skip to content

Commit

Permalink
SILOptimizer: use the BasicBlockFlag utility in ValueLifetimeAnalysis
Browse files Browse the repository at this point in the history
  • Loading branch information
eeckstein committed Jan 21, 2021
1 parent 763bfed commit 3e8612b
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 23 deletions.
16 changes: 10 additions & 6 deletions include/swift/SILOptimizer/Utils/ValueLifetime.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/Basic/STLExtras.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILBitfield.h"
#include "swift/SILOptimizer/Utils/InstOptUtils.h"

namespace swift {
Expand All @@ -34,7 +35,10 @@ class ValueLifetimeAnalysis {
PointerUnion<SILInstruction *, SILArgument *> defValue;

/// The set of blocks where the value is live.
llvm::SmallSetVector<SILBasicBlock *, 16> liveBlocks;
llvm::SmallVector<SILBasicBlock *, 16> liveBlocks;

/// True for blocks which are in liveBlocks.
BasicBlockFlag inLiveBlocks;

/// The set of instructions where the value is used, or the users-list
/// provided with the constructor.
Expand Down Expand Up @@ -66,7 +70,7 @@ class ValueLifetimeAnalysis {
/// iterators.
template <typename RangeTy>
ValueLifetimeAnalysis(SILArgument *def, const RangeTy &useRange)
: defValue(def), userSet() {
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
for (SILInstruction *use : useRange)
userSet.insert(use);
propagateLiveness();
Expand All @@ -75,7 +79,7 @@ class ValueLifetimeAnalysis {
ValueLifetimeAnalysis(
SILArgument *def,
llvm::iterator_range<ValueBaseUseIterator> useRange)
: defValue(def), userSet() {
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
for (Operand *use : useRange)
userSet.insert(use->getUser());
propagateLiveness();
Expand All @@ -84,7 +88,7 @@ class ValueLifetimeAnalysis {
template <typename RangeTy>
ValueLifetimeAnalysis(
SILInstruction *def, const RangeTy &useRange)
: defValue(def), userSet() {
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
for (SILInstruction *use : useRange)
userSet.insert(use);
propagateLiveness();
Expand All @@ -93,7 +97,7 @@ class ValueLifetimeAnalysis {
ValueLifetimeAnalysis(
SILInstruction *def,
llvm::iterator_range<ValueBaseUseIterator> useRange)
: defValue(def), userSet() {
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
for (Operand *use : useRange)
userSet.insert(use->getUser());
propagateLiveness();
Expand Down Expand Up @@ -144,7 +148,7 @@ class ValueLifetimeAnalysis {

/// Returns true if the value is alive at the begin of block \p bb.
bool isAliveAtBeginOfBlock(SILBasicBlock *bb) {
return liveBlocks.count(bb) &&
return inLiveBlocks.get(bb) &&
(hasUsersBeforeDef || bb != getDefValueParentBlock());
}

Expand Down
4 changes: 2 additions & 2 deletions lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ void ArrayInfo::getLastDestroys(
// copy_values, using ValueLifetimeAnalysis. The frontier is a list of
// instructions that mark the exits of the flow of control from the
// \c destroys.
ValueLifetimeAnalysis lifetimeAnalysis =
ValueLifetimeAnalysis(arrayValue->getDefiningInstruction(), destroys);
ValueLifetimeAnalysis lifetimeAnalysis(arrayValue->getDefiningInstruction(),
destroys);
ValueLifetimeAnalysis::Frontier frontier;
lifetimeAnalysis.computeFrontier(frontier,
ValueLifetimeAnalysis::DontModifyCFG);
Expand Down
3 changes: 1 addition & 2 deletions lib/SILOptimizer/Mandatory/OSLogOptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -881,8 +881,7 @@ getEndPointsOfDataDependentChain(SILValue value, SILFunction *fun,
SILInstruction *valueDefinition = value->getDefiningInstruction();
SILInstruction *def =
valueDefinition ? valueDefinition : &(value->getParentBlock()->front());
ValueLifetimeAnalysis lifetimeAnalysis =
ValueLifetimeAnalysis(def, transitiveUsers);
ValueLifetimeAnalysis lifetimeAnalysis(def, transitiveUsers);
ValueLifetimeAnalysis::Frontier frontier;
bool hasCriticlEdges = lifetimeAnalysis.computeFrontier(
frontier, ValueLifetimeAnalysis::DontModifyCFG);
Expand Down
28 changes: 15 additions & 13 deletions lib/SILOptimizer/Utils/ValueLifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,14 @@ void ValueLifetimeAnalysis::propagateLiveness() {
// Compute the def block only if we have a SILInstruction. If we have a
// SILArgument, this will be nullptr.
auto *defBB = getDefValueParentBlock();
SmallVector<SILBasicBlock *, 64> worklist;
int numUsersBeforeDef = 0;

// Find the initial set of blocks where the value is live, because
// it is used in those blocks.
for (SILInstruction *user : userSet) {
SILBasicBlock *userBlock = user->getParent();
if (liveBlocks.insert(userBlock))
worklist.push_back(userBlock);
if (!inLiveBlocks.testAndSet(userBlock))
liveBlocks.push_back(userBlock);

// A user in the defBB could potentially be located before the defValue. If
// we had a SILArgument, defBB will be nullptr, so we should always have
Expand All @@ -62,8 +61,9 @@ void ValueLifetimeAnalysis::propagateLiveness() {

// Now propagate liveness backwards until we hit the block that defines the
// value.
while (!worklist.empty()) {
auto *bb = worklist.pop_back_val();
unsigned workIdx = 0;
while (workIdx < liveBlocks.size()) {
auto *bb = liveBlocks[workIdx++];

// Don't go beyond the definition.
if (bb == defBB && !hasUsersBeforeDef)
Expand All @@ -72,8 +72,8 @@ void ValueLifetimeAnalysis::propagateLiveness() {
for (auto *predBB : bb->getPredecessorBlocks()) {
// If it's already in the set, then we've already queued and/or
// processed the predecessors.
if (liveBlocks.insert(predBB))
worklist.push_back(predBB);
if (!inLiveBlocks.testAndSet(predBB))
liveBlocks.push_back(predBB);
}
}
}
Expand Down Expand Up @@ -186,7 +186,8 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
}
}
// Handle "exit" edges from the lifetime region.
llvm::SmallPtrSet<SILBasicBlock *, 16> unhandledFrontierBlocks;
BasicBlockSet unhandledFrontierBlocks(getFunction());
bool unhandledFrontierBlocksFound = false;
for (SILBasicBlock *frontierBB : frontierBlocks) {
assert(mode != UsersMustPostDomDef);
bool needSplit = false;
Expand All @@ -201,12 +202,13 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
if (needSplit) {
// We need to split the critical edge to create a frontier instruction.
unhandledFrontierBlocks.insert(frontierBB);
unhandledFrontierBlocksFound = true;
} else {
// The first instruction of the exit-block is part of the frontier.
frontier.push_back(&*frontierBB->begin());
}
}
if (unhandledFrontierBlocks.size() == 0) {
if (!unhandledFrontierBlocksFound) {
return true;
}

Expand All @@ -222,7 +224,7 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
succBlocks.push_back(succ);

for (unsigned i = 0, e = succBlocks.size(); i != e; ++i) {
if (unhandledFrontierBlocks.count(succBlocks[i])) {
if (unhandledFrontierBlocks.contains(succBlocks[i])) {
assert((isCriticalEdge(term, i) || userSet.count(term)) &&
"actually not a critical edge?");
noCriticalEdges = false;
Expand All @@ -244,7 +246,7 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *inst) {
SILBasicBlock *bb = inst->getParent();
// Check if the value is not live anywhere in inst's block.
if (!liveBlocks.count(bb))
if (!inLiveBlocks.get(bb))
return false;
for (const SILSuccessor &succ : bb->getSuccessors()) {
// If the value is live at the beginning of any successor block it is also
Expand Down Expand Up @@ -288,7 +290,7 @@ blockContainsDeallocRef(SILBasicBlock *bb,
}

bool ValueLifetimeAnalysis::containsDeallocRef(const FrontierImpl &frontier) {
SmallPtrSet<SILBasicBlock *, 8> frontierBlocks;
BasicBlockSet frontierBlocks(getFunction());
// Search in live blocks where the value is not alive until the end of the
// block, i.e. the live range is terminated by a frontier instruction.
for (SILInstruction *frontierInst : frontier) {
Expand All @@ -300,7 +302,7 @@ bool ValueLifetimeAnalysis::containsDeallocRef(const FrontierImpl &frontier) {
// Search in all other live blocks where the value is alive until the end of
// the block.
for (SILBasicBlock *bb : liveBlocks) {
if (frontierBlocks.count(bb) == 0) {
if (frontierBlocks.contains(bb) == 0) {
if (blockContainsDeallocRef(bb, defValue, bb->getTerminator()))
return true;
}
Expand Down

0 comments on commit 3e8612b

Please sign in to comment.