[CFLAA] Refactor to remove redundant maps. NFC.

Patch by Jia Chen.

Differential Revision: http://reviews.llvm.org/D21233

llvm-svn: 272578
This commit is contained in:
George Burgess IV 2016-06-13 19:21:18 +00:00
parent 582b9ce36e
commit dc96febc37
1 changed files with 103 additions and 208 deletions

View File

@ -512,141 +512,85 @@ public:
}
};
/// Set building requires a weighted bidirectional graph.
template <typename EdgeTypeT> class WeightedBidirectionalGraph {
public:
typedef std::size_t Node;
/// The Program Expression Graph (PEG) of CFL analysis
class CFLGraph {
private:
const static Node StartNode = Node(0);
typedef Value *Node;
struct Edge {
EdgeTypeT Weight;
StratifiedAttrs Attr;
EdgeType Type;
Node Other;
};
Edge(const EdgeTypeT &W, const Node &N) : Weight(W), Other(N) {}
typedef std::vector<Edge> EdgeList;
typedef DenseMap<Node, EdgeList> NodeMap;
NodeMap NodeImpls;
bool operator==(const Edge &E) const {
return Weight == E.Weight && Other == E.Other;
// Gets the inverse of a given EdgeType.
static EdgeType flipWeight(EdgeType Initial) {
switch (Initial) {
case EdgeType::Assign:
return EdgeType::Assign;
case EdgeType::Dereference:
return EdgeType::Reference;
case EdgeType::Reference:
return EdgeType::Dereference;
}
llvm_unreachable("Incomplete coverage of EdgeType enum");
}
bool operator!=(const Edge &E) const { return !operator==(E); }
};
const EdgeList *getNode(Node N) const {
auto Itr = NodeImpls.find(N);
if (Itr == NodeImpls.end())
return nullptr;
return &Itr->second;
}
EdgeList &getOrCreateNode(Node N) { return NodeImpls[N]; }
struct NodeImpl {
std::vector<Edge> Edges;
};
std::vector<NodeImpl> NodeImpls;
bool inbounds(Node NodeIndex) const { return NodeIndex < NodeImpls.size(); }
const NodeImpl &getNode(Node N) const { return NodeImpls[N]; }
NodeImpl &getNode(Node N) { return NodeImpls[N]; }
static Node nodeDeref(const NodeMap::value_type &P) { return P.first; }
typedef std::pointer_to_unary_function<const NodeMap::value_type &, Node>
NodeDerefFun;
public:
/// \brief Iterator for edges. Because this graph is bidirected, we don't
/// allow modification of the edges using this iterator. Additionally, the
/// iterator becomes invalid if you add edges to or from the node you're
/// getting the edges of.
struct EdgeIterator : public std::iterator<std::forward_iterator_tag,
std::tuple<EdgeTypeT, Node *>> {
EdgeIterator(const typename std::vector<Edge>::const_iterator &Iter)
: Current(Iter) {}
typedef EdgeList::const_iterator const_edge_iterator;
typedef mapped_iterator<NodeMap::const_iterator, NodeDerefFun>
const_node_iterator;
EdgeIterator(NodeImpl &Impl) : Current(Impl.begin()) {}
CFLGraph() = default;
CFLGraph(CFLGraph &&) = default;
CFLGraph &operator=(CFLGraph &&) = default;
EdgeIterator &operator++() {
++Current;
return *this;
void addNode(Node N) { getOrCreateNode(N); }
void addEdge(Node From, Node To, EdgeType Type,
StratifiedAttrs Attr = StratifiedAttrs()) {
// We can't getOrCreateNode() twice in a row here since the second call may
// invalidate the reference returned from the first call
getOrCreateNode(From);
auto &ToEdges = getOrCreateNode(To);
auto &FromEdges = getOrCreateNode(From);
FromEdges.push_back(Edge{Attr, Type, To});
ToEdges.push_back(Edge{Attr, flipWeight(Type), From});
}
EdgeIterator operator++(int) {
EdgeIterator Copy(Current);
operator++();
return Copy;
iterator_range<const_edge_iterator> edgesFor(Node N) const {
auto Edges = getNode(N);
assert(Edges != nullptr);
return make_range(Edges->begin(), Edges->end());
}
std::tuple<EdgeTypeT, Node> &operator*() {
Store = std::make_tuple(Current->Weight, Current->Other);
return Store;
}
bool operator==(const EdgeIterator &Other) const {
return Current == Other.Current;
}
bool operator!=(const EdgeIterator &Other) const {
return !operator==(Other);
}
private:
typename std::vector<Edge>::const_iterator Current;
std::tuple<EdgeTypeT, Node> Store;
};
/// Wrapper for EdgeIterator with begin()/end() calls.
struct EdgeIterable {
EdgeIterable(const std::vector<Edge> &Edges)
: BeginIter(Edges.begin()), EndIter(Edges.end()) {}
EdgeIterator begin() { return EdgeIterator(BeginIter); }
EdgeIterator end() { return EdgeIterator(EndIter); }
private:
typename std::vector<Edge>::const_iterator BeginIter;
typename std::vector<Edge>::const_iterator EndIter;
};
// ----- Actual graph-related things ----- //
WeightedBidirectionalGraph() {}
WeightedBidirectionalGraph(WeightedBidirectionalGraph<EdgeTypeT> &&Other)
: NodeImpls(std::move(Other.NodeImpls)) {}
WeightedBidirectionalGraph<EdgeTypeT> &
operator=(WeightedBidirectionalGraph<EdgeTypeT> &&Other) {
NodeImpls = std::move(Other.NodeImpls);
return *this;
}
Node addNode() {
auto Index = NodeImpls.size();
auto NewNode = Node(Index);
NodeImpls.push_back(NodeImpl());
return NewNode;
}
void addEdge(Node From, Node To, const EdgeTypeT &Weight,
const EdgeTypeT &ReverseWeight) {
assert(inbounds(From));
assert(inbounds(To));
auto &FromNode = getNode(From);
auto &ToNode = getNode(To);
FromNode.Edges.push_back(Edge(Weight, To));
ToNode.Edges.push_back(Edge(ReverseWeight, From));
}
iterator_range<EdgeIterator> edgesFor(const Node &N) const {
const auto &Node = getNode(N);
return make_range(EdgeIterator(Node.Edges.begin()),
EdgeIterator(Node.Edges.end()));
iterator_range<const_node_iterator> nodes() const {
return make_range<const_node_iterator>(
map_iterator(NodeImpls.begin(), NodeDerefFun(nodeDeref)),
map_iterator(NodeImpls.end(), NodeDerefFun(nodeDeref)));
}
bool empty() const { return NodeImpls.empty(); }
std::size_t size() const { return NodeImpls.size(); }
/// Gets an arbitrary node in the graph as a starting point for traversal.
Node getEntryNode() {
assert(inbounds(StartNode));
return StartNode;
}
};
typedef WeightedBidirectionalGraph<std::pair<EdgeType, StratifiedAttrs>> GraphT;
typedef DenseMap<Value *, GraphT::Node> NodeMapT;
}
//===----------------------------------------------------------------------===//
@ -667,9 +611,6 @@ static StratifiedAttr argNumberToAttr(unsigned ArgNum);
/// Given a Value, potentially return which StratifiedAttr it maps to.
static Optional<StratifiedAttr> valueToAttr(Value *Val);
/// Gets the inverse of a given EdgeType.
static EdgeType flipWeight(EdgeType Initial);
/// Gets edges of the given Instruction*, writing them to the SmallVector*.
static void argsToEdges(CFLAAResult &, Instruction *, SmallVectorImpl<Edge> &,
const TargetLibraryInfo &);
@ -685,7 +626,7 @@ static Level directionOfEdgeType(EdgeType);
/// Builds the graph needed for constructing the StratifiedSets for the
/// given function
static void buildGraphFrom(CFLAAResult &, Function *,
SmallVectorImpl<Value *> &, NodeMapT &, GraphT &,
SmallVectorImpl<Value *> &, CFLGraph &,
const TargetLibraryInfo &);
/// Gets the edges of a ConstantExpr as if it was an Instruction. This function
@ -702,8 +643,8 @@ static void constexprToEdges(CFLAAResult &, ConstantExpr &,
/// addInstructionToGraph would add both the `load` and `getelementptr`
/// instructions to the graph appropriately.
static void addInstructionToGraph(CFLAAResult &, Instruction &,
SmallVectorImpl<Value *> &, NodeMapT &,
GraphT &, const TargetLibraryInfo &);
SmallVectorImpl<Value *> &, CFLGraph &,
const TargetLibraryInfo &);
/// Determines whether it would be pointless to add the given Value to our sets.
static bool canSkipAddingToSets(Value *Val);
@ -777,18 +718,6 @@ static StratifiedAttr argNumberToAttr(unsigned ArgNum) {
return 1 << (ArgNum + AttrFirstArgIndex);
}
static EdgeType flipWeight(EdgeType Initial) {
switch (Initial) {
case EdgeType::Assign:
return EdgeType::Assign;
case EdgeType::Dereference:
return EdgeType::Reference;
case EdgeType::Reference:
return EdgeType::Dereference;
}
llvm_unreachable("Incomplete coverage of EdgeType enum");
}
static void argsToEdges(CFLAAResult &Analysis, Instruction *Inst,
SmallVectorImpl<Edge> &Output,
const TargetLibraryInfo &TLI) {
@ -851,18 +780,8 @@ static void constexprToEdges(CFLAAResult &Analysis,
static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
SmallVectorImpl<Value *> &ReturnedValues,
NodeMapT &Map, GraphT &Graph,
CFLGraph &Graph,
const TargetLibraryInfo &TLI) {
const auto findOrInsertNode = [&Map, &Graph](Value *Val) {
auto Pair = Map.insert(std::make_pair(Val, GraphT::Node()));
auto &Iter = Pair.first;
if (Pair.second) {
auto NewNode = Graph.addNode();
Iter->second = NewNode;
}
return Iter->second;
};
// We don't want the edges of most "return" instructions, but we *do* want
// to know what can be returned.
if (isa<ReturnInst>(&Inst))
@ -880,17 +799,12 @@ static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
auto MaybeVal = getTargetValue(&Inst);
assert(MaybeVal.hasValue());
auto *Target = *MaybeVal;
findOrInsertNode(Target);
Graph.addNode(Target);
return;
}
auto addEdgeToGraph = [&](const Edge &E) {
auto To = findOrInsertNode(E.To);
auto From = findOrInsertNode(E.From);
auto FlippedWeight = flipWeight(E.Weight);
auto Attrs = E.AdditionalAttrs;
Graph.addEdge(From, To, std::make_pair(E.Weight, Attrs),
std::make_pair(FlippedWeight, Attrs));
auto addEdgeToGraph = [&Graph](const Edge &E) {
Graph.addEdge(E.From, E.To, E.Weight, E.AdditionalAttrs);
};
SmallVector<ConstantExpr *, 4> ConstantExprs;
@ -911,13 +825,12 @@ static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
static void buildGraphFrom(CFLAAResult &Analysis, Function *Fn,
SmallVectorImpl<Value *> &ReturnedValues,
NodeMapT &Map, GraphT &Graph,
const TargetLibraryInfo &TLI) {
CFLGraph &Graph, const TargetLibraryInfo &TLI) {
// (N.B. We may remove graph construction entirely, because it doesn't really
// buy us much.)
for (auto &Bb : Fn->getBasicBlockList())
for (auto &Inst : Bb.getInstList())
addInstructionToGraph(Analysis, Inst, ReturnedValues, Map, Graph, TLI);
addInstructionToGraph(Analysis, Inst, ReturnedValues, Graph, TLI);
}
static bool canSkipAddingToSets(Value *Val) {
@ -943,48 +856,31 @@ static bool canSkipAddingToSets(Value *Val) {
// Builds the graph + StratifiedSets for a function.
CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
NodeMapT Map;
GraphT Graph;
CFLGraph Graph;
SmallVector<Value *, 4> ReturnedValues;
buildGraphFrom(*this, Fn, ReturnedValues, Map, Graph, TLI);
DenseMap<GraphT::Node, Value *> NodeValueMap;
NodeValueMap.reserve(Map.size());
for (const auto &Pair : Map)
NodeValueMap.insert(std::make_pair(Pair.second, Pair.first));
const auto findValueOrDie = [&NodeValueMap](GraphT::Node Node) {
auto ValIter = NodeValueMap.find(Node);
assert(ValIter != NodeValueMap.end());
return ValIter->second;
};
buildGraphFrom(*this, Fn, ReturnedValues, Graph, TLI);
StratifiedSetsBuilder<Value *> Builder;
SmallVector<GraphT::Node, 16> Worklist;
SmallVector<Value *, 16> Worklist;
SmallPtrSet<Value *, 16> Globals;
for (auto &Pair : Map) {
Worklist.clear();
auto *Value = Pair.first;
Builder.add(Value);
auto InitialNode = Pair.second;
Worklist.push_back(InitialNode);
for (auto Node : Graph.nodes())
Worklist.push_back(Node);
while (!Worklist.empty()) {
auto Node = Worklist.pop_back_val();
auto *CurValue = findValueOrDie(Node);
auto *CurValue = Worklist.pop_back_val();
Builder.add(CurValue);
if (canSkipAddingToSets(CurValue))
continue;
if (isa<GlobalValue>(CurValue))
Globals.insert(CurValue);
for (const auto &EdgeTuple : Graph.edgesFor(Node)) {
auto Weight = std::get<0>(EdgeTuple);
auto Label = Weight.first;
auto &OtherNode = std::get<1>(EdgeTuple);
auto *OtherValue = findValueOrDie(OtherNode);
for (const auto &Edge : Graph.edgesFor(CurValue)) {
auto Label = Edge.Type;
auto *OtherValue = Edge.Other;
if (canSkipAddingToSets(OtherValue))
continue;
@ -1004,13 +900,12 @@ CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
break;
}
auto Aliasing = Weight.second;
auto Aliasing = Edge.Attr;
Builder.noteAttributes(CurValue, Aliasing);
Builder.noteAttributes(OtherValue, Aliasing);
if (Added)
Worklist.push_back(OtherNode);
}
Worklist.push_back(OtherValue);
}
}