mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
ALso renamed the header ReferenceCountState.h => RefCountState.h since it matches the name of the class now. Swift SVN r26587
217 lines
7.5 KiB
C++
217 lines
7.5 KiB
C++
//===--- RefCountState.cpp ------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "sil-global-arc-opts"
|
|
#include "RefCountState.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
using namespace swift;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Lattice State Merging
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
static inline BottomUpRefCountState::LatticeState
|
|
MergeBottomUpLatticeStates(BottomUpRefCountState::LatticeState L1,
|
|
BottomUpRefCountState::LatticeState L2) {
|
|
using LatticeState = BottomUpRefCountState::LatticeState;
|
|
// If both states equal, return the first.
|
|
if (L1 == L2)
|
|
return L1;
|
|
|
|
// If either are none, return None.
|
|
if (L1 == LatticeState::None || L2 == LatticeState::None)
|
|
return LatticeState::None;
|
|
|
|
// Canonicalize.
|
|
if (unsigned(L1) > unsigned(L2))
|
|
std::swap(L1, L2);
|
|
|
|
// Choose the side further along in the sequence.
|
|
if ((L1 == LatticeState::Decremented || L1 == LatticeState::MightBeUsed) ||
|
|
(L2 == LatticeState::MightBeUsed ||
|
|
L2 == LatticeState::MightBeDecremented))
|
|
return L2;
|
|
|
|
// Otherwise, we don't know what happened, be conservative and return none.
|
|
return LatticeState::None;
|
|
}
|
|
|
|
static inline TopDownRefCountState::LatticeState
|
|
MergeTopDownLatticeStates(TopDownRefCountState::LatticeState L1,
|
|
TopDownRefCountState::LatticeState L2) {
|
|
using LatticeState = TopDownRefCountState::LatticeState;
|
|
// If both states equal, return the first.
|
|
if (L1 == L2)
|
|
return L1;
|
|
|
|
// If either are none, return None.
|
|
if (L1 == LatticeState::None || L2 == LatticeState::None)
|
|
return LatticeState::None;
|
|
|
|
// Canonicalize.
|
|
if (unsigned(L1) > unsigned(L2))
|
|
std::swap(L1, L2);
|
|
|
|
// Choose the side further along in the sequence.
|
|
if ((L1 == LatticeState::Incremented ||
|
|
L1 == LatticeState::MightBeDecremented) ||
|
|
(L2 == LatticeState::MightBeDecremented ||
|
|
L2 == LatticeState::MightBeUsed))
|
|
return L2;
|
|
|
|
// Otherwise, we don't know what happened, return none.
|
|
return LatticeState::None;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Reference Count State Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool TopDownRefCountState::merge(const TopDownRefCountState &Other) {
|
|
auto NewState = MergeTopDownLatticeStates(LatState, Other.LatState);
|
|
DEBUG(llvm::dbgs() << " Performing TopDown Merge.\n");
|
|
DEBUG(llvm::dbgs() << " Left: " << LatState << "; Right: "
|
|
<< Other.LatState << "; Result: " << NewState << "\n");
|
|
DEBUG(llvm::dbgs() << " V: ";
|
|
if (hasValue())
|
|
getValue()->dump();
|
|
else
|
|
llvm::dbgs() << "\n";
|
|
llvm::dbgs() << " OtherV: ";
|
|
if (Other.hasValue())
|
|
Other.getValue()->dump();
|
|
else
|
|
llvm::dbgs() << "\n");
|
|
|
|
LatState = NewState;
|
|
KnownSafe &= Other.KnownSafe;
|
|
|
|
// If we're doing a merge on a path that's previously seen a partial merge,
|
|
// conservatively drop the sequence, to avoid doing partial RR elimination. If
|
|
// the branch predicates for the two merge differ, mixing them is unsafe since
|
|
// they are not control dependent.
|
|
//
|
|
// TODO: Add support for determining control dependence.
|
|
if (LatState == TopDownRefCountState::LatticeState::None) {
|
|
clear();
|
|
DEBUG(llvm::dbgs() << " Found LatticeState::None. "
|
|
"Clearing State!\n");
|
|
return false;
|
|
}
|
|
|
|
// We should never have an argument path merge with a non-argument path.
|
|
if (Argument.isNull() != Other.Argument.isNull()) {
|
|
clear();
|
|
DEBUG(llvm::dbgs() << " Can not merge Argument with "
|
|
"Non-Argument path... Bailing!\n");
|
|
return false;
|
|
}
|
|
|
|
Increments.insert(Other.Increments.begin(), Other.Increments.end());
|
|
|
|
Partial |= Other.Partial;
|
|
Partial |= InsertPts.size() != Other.InsertPts.size();
|
|
for (auto *SI : Other.InsertPts)
|
|
Partial |= InsertPts.insert(SI).second;
|
|
|
|
DEBUG(llvm::dbgs() << " Partial: " << (Partial ? "yes" : "no")
|
|
<< "\n");
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BottomUpRefCountState::merge(const BottomUpRefCountState &Other) {
|
|
|
|
auto NewState = MergeBottomUpLatticeStates(LatState, Other.LatState);
|
|
DEBUG(llvm::dbgs() << " Performing BottomUp Merge.\n");
|
|
DEBUG(llvm::dbgs() << " Left: " << LatState << "; Right: "
|
|
<< Other.LatState << "; Result: " << NewState << "\n");
|
|
DEBUG(llvm::dbgs() << " V: ";
|
|
if (hasValue())
|
|
getValue()->dump();
|
|
else
|
|
llvm::dbgs() << "\n";
|
|
llvm::dbgs() << " OtherV: ";
|
|
if (Other.hasValue())
|
|
Other.getValue()->dump();
|
|
else
|
|
llvm::dbgs() << "\n");
|
|
|
|
LatState = NewState;
|
|
KnownSafe &= Other.KnownSafe;
|
|
|
|
// If we're doing a merge on a path that's previously seen a partial merge,
|
|
// conservatively drop the sequence, to avoid doing partial RR elimination. If
|
|
// the branch predicates for the two merge differ, mixing them is unsafe since
|
|
// they are not control dependent.
|
|
//
|
|
// TODO: Add support for working around control dependence issues.
|
|
if (LatState == BottomUpRefCountState::LatticeState::None) {
|
|
DEBUG(llvm::dbgs() << " Found LatticeState::None. "
|
|
"Clearing State!\n");
|
|
clear();
|
|
return false;
|
|
}
|
|
|
|
// Merge previously seen instructions.
|
|
Decrements.insert(Other.Decrements.begin(), Other.Decrements.end());
|
|
|
|
Partial |= Other.Partial;
|
|
Partial |= InsertPts.size() != Other.InsertPts.size();
|
|
for (auto *SI : Other.InsertPts)
|
|
Partial |= InsertPts.insert(SI).second;
|
|
|
|
DEBUG(llvm::dbgs() << " Partial: " << (Partial ? "yes" : "no")
|
|
<< "\n");
|
|
return true;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Printing Utilities
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace llvm {
|
|
|
|
raw_ostream &operator<<(raw_ostream &OS,
|
|
BottomUpRefCountState::LatticeState S) {
|
|
using LatticeState = BottomUpRefCountState::LatticeState;
|
|
switch (S) {
|
|
case LatticeState::None:
|
|
return OS << "None";
|
|
case LatticeState::Decremented:
|
|
return OS << "Decremented";
|
|
case LatticeState::MightBeUsed:
|
|
return OS << "MightBeUsed";
|
|
case LatticeState::MightBeDecremented:
|
|
return OS << "MightBeDecremented";
|
|
}
|
|
}
|
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
|
|
TopDownRefCountState::LatticeState S) {
|
|
using LatticeState = TopDownRefCountState::LatticeState;
|
|
switch (S) {
|
|
case LatticeState::None:
|
|
return OS << "None";
|
|
case LatticeState::Incremented:
|
|
return OS << "Incremented";
|
|
case LatticeState::MightBeUsed:
|
|
return OS << "MightBeUsed";
|
|
case LatticeState::MightBeDecremented:
|
|
return OS << "MightBeDecremented";
|
|
}
|
|
}
|
|
|
|
} // end namespace llvm
|
|
|