freebsd-skq/contrib/llvm/lib/Support/DAGDeltaAlgorithm.cpp
ed b9a7e30aff Upgrade our Clang in base to r108428.
This commit merges the latest LLVM sources from the vendor space. It
also updates the build glue to match the new sources. Clang's version
number is changed to match LLVM's, which means /usr/include/clang/2.0
has been renamed to /usr/include/clang/2.8.

Obtained from:	projects/clangbsd
2010-07-20 17:16:57 +00:00

358 lines
13 KiB
C++

//===--- DAGDeltaAlgorithm.cpp - A DAG Minimization Algorithm --*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
//
// The algorithm we use attempts to exploit the dependency information by
// minimizing top-down. We start by constructing an initial root set R, and
// then iteratively:
//
// 1. Minimize the set R using the test predicate:
// P'(S) = P(S union pred*(S))
//
// 2. Extend R to R' = R union pred(R).
//
// until a fixed point is reached.
//
// The idea is that we want to quickly prune entire portions of the graph, so we
// try to find high-level nodes that can be eliminated with all of their
// dependents.
//
// FIXME: The current algorithm doesn't actually provide a strong guarantee
// about the minimality of the result. The problem is that after adding nodes to
// the required set, we no longer consider them for elimination. For strictly
// well formed predicates, this doesn't happen, but it commonly occurs in
// practice when there are unmodelled dependencies. I believe we can resolve
// this by allowing the required set to be minimized as well, but need more test
// cases first.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DAGDeltaAlgorithm.h"
#include "llvm/ADT/DeltaAlgorithm.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <map>
using namespace llvm;
namespace {
class DAGDeltaAlgorithmImpl {
friend class DeltaActiveSetHelper;
public:
typedef DAGDeltaAlgorithm::change_ty change_ty;
typedef DAGDeltaAlgorithm::changeset_ty changeset_ty;
typedef DAGDeltaAlgorithm::changesetlist_ty changesetlist_ty;
typedef DAGDeltaAlgorithm::edge_ty edge_ty;
private:
typedef std::vector<change_ty>::iterator pred_iterator_ty;
typedef std::vector<change_ty>::iterator succ_iterator_ty;
typedef std::set<change_ty>::iterator pred_closure_iterator_ty;
typedef std::set<change_ty>::iterator succ_closure_iterator_ty;
DAGDeltaAlgorithm &DDA;
const changeset_ty &Changes;
const std::vector<edge_ty> &Dependencies;
std::vector<change_ty> Roots;
/// Cache of failed test results. Successful test results are never cached
/// since we always reduce following a success. We maintain an independent
/// cache from that used by the individual delta passes because we may get
/// hits across multiple individual delta invocations.
mutable std::set<changeset_ty> FailedTestsCache;
// FIXME: Gross.
std::map<change_ty, std::vector<change_ty> > Predecessors;
std::map<change_ty, std::vector<change_ty> > Successors;
std::map<change_ty, std::set<change_ty> > PredClosure;
std::map<change_ty, std::set<change_ty> > SuccClosure;
private:
pred_iterator_ty pred_begin(change_ty Node) {
assert(Predecessors.count(Node) && "Invalid node!");
return Predecessors[Node].begin();
}
pred_iterator_ty pred_end(change_ty Node) {
assert(Predecessors.count(Node) && "Invalid node!");
return Predecessors[Node].end();
}
pred_closure_iterator_ty pred_closure_begin(change_ty Node) {
assert(PredClosure.count(Node) && "Invalid node!");
return PredClosure[Node].begin();
}
pred_closure_iterator_ty pred_closure_end(change_ty Node) {
assert(PredClosure.count(Node) && "Invalid node!");
return PredClosure[Node].end();
}
succ_iterator_ty succ_begin(change_ty Node) {
assert(Successors.count(Node) && "Invalid node!");
return Successors[Node].begin();
}
succ_iterator_ty succ_end(change_ty Node) {
assert(Successors.count(Node) && "Invalid node!");
return Successors[Node].end();
}
succ_closure_iterator_ty succ_closure_begin(change_ty Node) {
assert(SuccClosure.count(Node) && "Invalid node!");
return SuccClosure[Node].begin();
}
succ_closure_iterator_ty succ_closure_end(change_ty Node) {
assert(SuccClosure.count(Node) && "Invalid node!");
return SuccClosure[Node].end();
}
void UpdatedSearchState(const changeset_ty &Changes,
const changesetlist_ty &Sets,
const changeset_ty &Required) {
DDA.UpdatedSearchState(Changes, Sets, Required);
}
/// ExecuteOneTest - Execute a single test predicate on the change set \arg S.
bool ExecuteOneTest(const changeset_ty &S) {
// Check dependencies invariant.
DEBUG({
for (changeset_ty::const_iterator it = S.begin(),
ie = S.end(); it != ie; ++it)
for (succ_iterator_ty it2 = succ_begin(*it),
ie2 = succ_end(*it); it2 != ie2; ++it2)
assert(S.count(*it2) && "Attempt to run invalid changeset!");
});
return DDA.ExecuteOneTest(S);
}
public:
DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &_DDA,
const changeset_ty &_Changes,
const std::vector<edge_ty> &_Dependencies);
changeset_ty Run();
/// GetTestResult - Get the test result for the active set \arg Changes with
/// \arg Required changes from the cache, executing the test if necessary.
///
/// \param Changes - The set of active changes being minimized, which should
/// have their pred closure included in the test.
/// \param Required - The set of changes which have previously been
/// established to be required.
/// \return - The test result.
bool GetTestResult(const changeset_ty &Changes, const changeset_ty &Required);
};
/// Helper object for minimizing an active set of changes.
class DeltaActiveSetHelper : public DeltaAlgorithm {
DAGDeltaAlgorithmImpl &DDAI;
const changeset_ty &Required;
protected:
/// UpdatedSearchState - Callback used when the search state changes.
virtual void UpdatedSearchState(const changeset_ty &Changes,
const changesetlist_ty &Sets) {
DDAI.UpdatedSearchState(Changes, Sets, Required);
}
virtual bool ExecuteOneTest(const changeset_ty &S) {
return DDAI.GetTestResult(S, Required);
}
public:
DeltaActiveSetHelper(DAGDeltaAlgorithmImpl &_DDAI,
const changeset_ty &_Required)
: DDAI(_DDAI), Required(_Required) {}
};
}
DAGDeltaAlgorithmImpl::DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &_DDA,
const changeset_ty &_Changes,
const std::vector<edge_ty>
&_Dependencies)
: DDA(_DDA),
Changes(_Changes),
Dependencies(_Dependencies)
{
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it) {
Predecessors.insert(std::make_pair(*it, std::vector<change_ty>()));
Successors.insert(std::make_pair(*it, std::vector<change_ty>()));
}
for (std::vector<edge_ty>::const_iterator it = Dependencies.begin(),
ie = Dependencies.end(); it != ie; ++it) {
Predecessors[it->second].push_back(it->first);
Successors[it->first].push_back(it->second);
}
// Compute the roots.
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it)
if (succ_begin(*it) == succ_end(*it))
Roots.push_back(*it);
// Pre-compute the closure of the successor relation.
std::vector<change_ty> Worklist(Roots.begin(), Roots.end());
while (!Worklist.empty()) {
change_ty Change = Worklist.back();
Worklist.pop_back();
std::set<change_ty> &ChangeSuccs = SuccClosure[Change];
for (pred_iterator_ty it = pred_begin(Change),
ie = pred_end(Change); it != ie; ++it) {
SuccClosure[*it].insert(Change);
SuccClosure[*it].insert(ChangeSuccs.begin(), ChangeSuccs.end());
Worklist.push_back(*it);
}
}
// Invert to form the predecessor closure map.
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it)
PredClosure.insert(std::make_pair(*it, std::set<change_ty>()));
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it)
for (succ_closure_iterator_ty it2 = succ_closure_begin(*it),
ie2 = succ_closure_end(*it); it2 != ie2; ++it2)
PredClosure[*it2].insert(*it);
// Dump useful debug info.
DEBUG({
llvm::errs() << "-- DAGDeltaAlgorithmImpl --\n";
llvm::errs() << "Changes: [";
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it) {
if (it != Changes.begin()) llvm::errs() << ", ";
llvm::errs() << *it;
if (succ_begin(*it) != succ_end(*it)) {
llvm::errs() << "(";
for (succ_iterator_ty it2 = succ_begin(*it),
ie2 = succ_end(*it); it2 != ie2; ++it2) {
if (it2 != succ_begin(*it)) llvm::errs() << ", ";
llvm::errs() << "->" << *it2;
}
llvm::errs() << ")";
}
}
llvm::errs() << "]\n";
llvm::errs() << "Roots: [";
for (std::vector<change_ty>::const_iterator it = Roots.begin(),
ie = Roots.end(); it != ie; ++it) {
if (it != Roots.begin()) llvm::errs() << ", ";
llvm::errs() << *it;
}
llvm::errs() << "]\n";
llvm::errs() << "Predecessor Closure:\n";
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it) {
llvm::errs() << format(" %-4d: [", *it);
for (pred_closure_iterator_ty it2 = pred_closure_begin(*it),
ie2 = pred_closure_end(*it); it2 != ie2; ++it2) {
if (it2 != pred_closure_begin(*it)) llvm::errs() << ", ";
llvm::errs() << *it2;
}
llvm::errs() << "]\n";
}
llvm::errs() << "Successor Closure:\n";
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it) {
llvm::errs() << format(" %-4d: [", *it);
for (succ_closure_iterator_ty it2 = succ_closure_begin(*it),
ie2 = succ_closure_end(*it); it2 != ie2; ++it2) {
if (it2 != succ_closure_begin(*it)) llvm::errs() << ", ";
llvm::errs() << *it2;
}
llvm::errs() << "]\n";
}
llvm::errs() << "\n\n";
});
}
bool DAGDeltaAlgorithmImpl::GetTestResult(const changeset_ty &Changes,
const changeset_ty &Required) {
changeset_ty Extended(Required);
Extended.insert(Changes.begin(), Changes.end());
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it)
Extended.insert(pred_closure_begin(*it), pred_closure_end(*it));
if (FailedTestsCache.count(Extended))
return false;
bool Result = ExecuteOneTest(Extended);
if (!Result)
FailedTestsCache.insert(Extended);
return Result;
}
DAGDeltaAlgorithm::changeset_ty
DAGDeltaAlgorithmImpl::Run() {
// The current set of changes we are minimizing, starting at the roots.
changeset_ty CurrentSet(Roots.begin(), Roots.end());
// The set of required changes.
changeset_ty Required;
// Iterate until the active set of changes is empty. Convergence is guaranteed
// assuming input was a DAG.
//
// Invariant: CurrentSet intersect Required == {}
// Invariant: Required == (Required union succ*(Required))
while (!CurrentSet.empty()) {
DEBUG({
llvm::errs() << "DAG_DD - " << CurrentSet.size() << " active changes, "
<< Required.size() << " required changes\n";
});
// Minimize the current set of changes.
DeltaActiveSetHelper Helper(*this, Required);
changeset_ty CurrentMinSet = Helper.Run(CurrentSet);
// Update the set of required changes. Since
// CurrentMinSet subset CurrentSet
// and after the last iteration,
// succ(CurrentSet) subset Required
// then
// succ(CurrentMinSet) subset Required
// and our invariant on Required is maintained.
Required.insert(CurrentMinSet.begin(), CurrentMinSet.end());
// Replace the current set with the predecssors of the minimized set of
// active changes.
CurrentSet.clear();
for (changeset_ty::const_iterator it = CurrentMinSet.begin(),
ie = CurrentMinSet.end(); it != ie; ++it)
CurrentSet.insert(pred_begin(*it), pred_end(*it));
// FIXME: We could enforce CurrentSet intersect Required == {} here if we
// wanted to protect against cyclic graphs.
}
return Required;
}
DAGDeltaAlgorithm::changeset_ty
DAGDeltaAlgorithm::Run(const changeset_ty &Changes,
const std::vector<edge_ty> &Dependencies) {
return DAGDeltaAlgorithmImpl(*this, Changes, Dependencies).Run();
}