[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. /// The Program Expression Graph (PEG) of CFL analysis
template <typename EdgeTypeT> class WeightedBidirectionalGraph { class CFLGraph {
public:
typedef std::size_t Node;
private: private:
const static Node StartNode = Node(0); typedef Value *Node;
struct Edge { struct Edge {
EdgeTypeT Weight; StratifiedAttrs Attr;
EdgeType Type;
Node Other; 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 { // Gets the inverse of a given EdgeType.
return Weight == E.Weight && Other == E.Other; 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 { static Node nodeDeref(const NodeMap::value_type &P) { return P.first; }
std::vector<Edge> Edges; typedef std::pointer_to_unary_function<const NodeMap::value_type &, Node>
}; NodeDerefFun;
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]; }
public: public:
/// \brief Iterator for edges. Because this graph is bidirected, we don't typedef EdgeList::const_iterator const_edge_iterator;
/// allow modification of the edges using this iterator. Additionally, the typedef mapped_iterator<NodeMap::const_iterator, NodeDerefFun>
/// iterator becomes invalid if you add edges to or from the node you're const_node_iterator;
/// 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) {}
EdgeIterator(NodeImpl &Impl) : Current(Impl.begin()) {} CFLGraph() = default;
CFLGraph(CFLGraph &&) = default;
CFLGraph &operator=(CFLGraph &&) = default;
EdgeIterator &operator++() { void addNode(Node N) { getOrCreateNode(N); }
++Current;
return *this; 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) { iterator_range<const_edge_iterator> edgesFor(Node N) const {
EdgeIterator Copy(Current); auto Edges = getNode(N);
operator++(); assert(Edges != nullptr);
return Copy; return make_range(Edges->begin(), Edges->end());
} }
std::tuple<EdgeTypeT, Node> &operator*() { iterator_range<const_node_iterator> nodes() const {
Store = std::make_tuple(Current->Weight, Current->Other); return make_range<const_node_iterator>(
return Store; map_iterator(NodeImpls.begin(), NodeDerefFun(nodeDeref)),
} map_iterator(NodeImpls.end(), NodeDerefFun(nodeDeref)));
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()));
} }
bool empty() const { return NodeImpls.empty(); } bool empty() const { return NodeImpls.empty(); }
std::size_t size() const { return NodeImpls.size(); } 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. /// Given a Value, potentially return which StratifiedAttr it maps to.
static Optional<StratifiedAttr> valueToAttr(Value *Val); 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*. /// Gets edges of the given Instruction*, writing them to the SmallVector*.
static void argsToEdges(CFLAAResult &, Instruction *, SmallVectorImpl<Edge> &, static void argsToEdges(CFLAAResult &, Instruction *, SmallVectorImpl<Edge> &,
const TargetLibraryInfo &); const TargetLibraryInfo &);
@ -685,7 +626,7 @@ static Level directionOfEdgeType(EdgeType);
/// Builds the graph needed for constructing the StratifiedSets for the /// Builds the graph needed for constructing the StratifiedSets for the
/// given function /// given function
static void buildGraphFrom(CFLAAResult &, Function *, static void buildGraphFrom(CFLAAResult &, Function *,
SmallVectorImpl<Value *> &, NodeMapT &, GraphT &, SmallVectorImpl<Value *> &, CFLGraph &,
const TargetLibraryInfo &); const TargetLibraryInfo &);
/// Gets the edges of a ConstantExpr as if it was an Instruction. This function /// 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` /// addInstructionToGraph would add both the `load` and `getelementptr`
/// instructions to the graph appropriately. /// instructions to the graph appropriately.
static void addInstructionToGraph(CFLAAResult &, Instruction &, static void addInstructionToGraph(CFLAAResult &, Instruction &,
SmallVectorImpl<Value *> &, NodeMapT &, SmallVectorImpl<Value *> &, CFLGraph &,
GraphT &, const TargetLibraryInfo &); const TargetLibraryInfo &);
/// Determines whether it would be pointless to add the given Value to our sets. /// Determines whether it would be pointless to add the given Value to our sets.
static bool canSkipAddingToSets(Value *Val); static bool canSkipAddingToSets(Value *Val);
@ -777,18 +718,6 @@ static StratifiedAttr argNumberToAttr(unsigned ArgNum) {
return 1 << (ArgNum + AttrFirstArgIndex); 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, static void argsToEdges(CFLAAResult &Analysis, Instruction *Inst,
SmallVectorImpl<Edge> &Output, SmallVectorImpl<Edge> &Output,
const TargetLibraryInfo &TLI) { const TargetLibraryInfo &TLI) {
@ -851,18 +780,8 @@ static void constexprToEdges(CFLAAResult &Analysis,
static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst, static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
SmallVectorImpl<Value *> &ReturnedValues, SmallVectorImpl<Value *> &ReturnedValues,
NodeMapT &Map, GraphT &Graph, CFLGraph &Graph,
const TargetLibraryInfo &TLI) { 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 // We don't want the edges of most "return" instructions, but we *do* want
// to know what can be returned. // to know what can be returned.
if (isa<ReturnInst>(&Inst)) if (isa<ReturnInst>(&Inst))
@ -880,17 +799,12 @@ static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
auto MaybeVal = getTargetValue(&Inst); auto MaybeVal = getTargetValue(&Inst);
assert(MaybeVal.hasValue()); assert(MaybeVal.hasValue());
auto *Target = *MaybeVal; auto *Target = *MaybeVal;
findOrInsertNode(Target); Graph.addNode(Target);
return; return;
} }
auto addEdgeToGraph = [&](const Edge &E) { auto addEdgeToGraph = [&Graph](const Edge &E) {
auto To = findOrInsertNode(E.To); Graph.addEdge(E.From, E.To, E.Weight, E.AdditionalAttrs);
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));
}; };
SmallVector<ConstantExpr *, 4> ConstantExprs; SmallVector<ConstantExpr *, 4> ConstantExprs;
@ -911,13 +825,12 @@ static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
static void buildGraphFrom(CFLAAResult &Analysis, Function *Fn, static void buildGraphFrom(CFLAAResult &Analysis, Function *Fn,
SmallVectorImpl<Value *> &ReturnedValues, SmallVectorImpl<Value *> &ReturnedValues,
NodeMapT &Map, GraphT &Graph, CFLGraph &Graph, const TargetLibraryInfo &TLI) {
const TargetLibraryInfo &TLI) {
// (N.B. We may remove graph construction entirely, because it doesn't really // (N.B. We may remove graph construction entirely, because it doesn't really
// buy us much.) // buy us much.)
for (auto &Bb : Fn->getBasicBlockList()) for (auto &Bb : Fn->getBasicBlockList())
for (auto &Inst : Bb.getInstList()) for (auto &Inst : Bb.getInstList())
addInstructionToGraph(Analysis, Inst, ReturnedValues, Map, Graph, TLI); addInstructionToGraph(Analysis, Inst, ReturnedValues, Graph, TLI);
} }
static bool canSkipAddingToSets(Value *Val) { static bool canSkipAddingToSets(Value *Val) {
@ -943,48 +856,31 @@ static bool canSkipAddingToSets(Value *Val) {
// Builds the graph + StratifiedSets for a function. // Builds the graph + StratifiedSets for a function.
CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) { CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
NodeMapT Map; CFLGraph Graph;
GraphT Graph;
SmallVector<Value *, 4> ReturnedValues; SmallVector<Value *, 4> ReturnedValues;
buildGraphFrom(*this, Fn, ReturnedValues, Map, Graph, TLI); buildGraphFrom(*this, Fn, ReturnedValues, 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;
};
StratifiedSetsBuilder<Value *> Builder; StratifiedSetsBuilder<Value *> Builder;
SmallVector<GraphT::Node, 16> Worklist; SmallVector<Value *, 16> Worklist;
SmallPtrSet<Value *, 16> Globals; SmallPtrSet<Value *, 16> Globals;
for (auto &Pair : Map) {
Worklist.clear();
auto *Value = Pair.first; for (auto Node : Graph.nodes())
Builder.add(Value); Worklist.push_back(Node);
auto InitialNode = Pair.second;
Worklist.push_back(InitialNode);
while (!Worklist.empty()) { while (!Worklist.empty()) {
auto Node = Worklist.pop_back_val(); auto *CurValue = Worklist.pop_back_val();
auto *CurValue = findValueOrDie(Node); Builder.add(CurValue);
if (canSkipAddingToSets(CurValue)) if (canSkipAddingToSets(CurValue))
continue; continue;
if (isa<GlobalValue>(CurValue)) if (isa<GlobalValue>(CurValue))
Globals.insert(CurValue); Globals.insert(CurValue);
for (const auto &EdgeTuple : Graph.edgesFor(Node)) { for (const auto &Edge : Graph.edgesFor(CurValue)) {
auto Weight = std::get<0>(EdgeTuple); auto Label = Edge.Type;
auto Label = Weight.first; auto *OtherValue = Edge.Other;
auto &OtherNode = std::get<1>(EdgeTuple);
auto *OtherValue = findValueOrDie(OtherNode);
if (canSkipAddingToSets(OtherValue)) if (canSkipAddingToSets(OtherValue))
continue; continue;
@ -1004,13 +900,12 @@ CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
break; break;
} }
auto Aliasing = Weight.second; auto Aliasing = Edge.Attr;
Builder.noteAttributes(CurValue, Aliasing); Builder.noteAttributes(CurValue, Aliasing);
Builder.noteAttributes(OtherValue, Aliasing); Builder.noteAttributes(OtherValue, Aliasing);
if (Added) if (Added)
Worklist.push_back(OtherNode); Worklist.push_back(OtherValue);
}
} }
} }