[LCG] Minor cleanup to the LCG walk over a function, NFC.

This just hoists the check for declarations up a layer which allows
various sets used in the walk to be smaller. Also moves the relevant
comments to match, and catches a few other cleanups in this code.

llvm-svn: 289163
This commit is contained in:
Chandler Carruth 2016-12-09 00:46:44 +00:00
parent 7a1e5bbe4e
commit 86f0bdf832
2 changed files with 33 additions and 22 deletions

View File

@ -953,6 +953,13 @@ public:
/// useful to code doing updates or otherwise wanting to walk the IR in the
/// same patterns as when we build the call graph.
/// Recursively visits the defined functions whose address is reachable from
/// every constant in the \p Worklist.
///
/// Doesn't recurse through any constants already in the \p Visited set, and
/// updates that set with every constant visited.
///
/// For each defined function, calls \p Callback with that function.
template <typename CallbackT>
static void visitReferences(SmallVectorImpl<Constant *> &Worklist,
SmallPtrSetImpl<Constant *> &Visited,
@ -961,7 +968,8 @@ public:
Constant *C = Worklist.pop_back_val();
if (Function *F = dyn_cast<Function>(C)) {
Callback(*F);
if (!F->isDeclaration())
Callback(*F);
continue;
}
@ -969,10 +977,10 @@ public:
if (Visited.insert(cast<Constant>(Op)).second)
Worklist.push_back(cast<Constant>(Op));
}
///@}
}
///@}
private:
typedef SmallVectorImpl<Node *>::reverse_iterator node_stack_iterator;
typedef iterator_range<node_stack_iterator> node_stack_range;

View File

@ -11,6 +11,7 @@
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instructions.h"
@ -25,21 +26,11 @@ using namespace llvm;
static void addEdge(SmallVectorImpl<LazyCallGraph::Edge> &Edges,
DenseMap<Function *, int> &EdgeIndexMap, Function &F,
LazyCallGraph::Edge::Kind EK) {
// Note that we consider *any* function with a definition to be a viable
// edge. Even if the function's definition is subject to replacement by
// some other module (say, a weak definition) there may still be
// optimizations which essentially speculate based on the definition and
// a way to check that the specific definition is in fact the one being
// used. For example, this could be done by moving the weak definition to
// a strong (internal) definition and making the weak definition be an
// alias. Then a test of the address of the weak function against the new
// strong definition's address would be an effective way to determine the
// safety of optimizing a direct call edge.
if (!F.isDeclaration() &&
EdgeIndexMap.insert({&F, Edges.size()}).second) {
DEBUG(dbgs() << " Added callable function: " << F.getName() << "\n");
Edges.emplace_back(LazyCallGraph::Edge(F, EK));
}
if (!EdgeIndexMap.insert({&F, Edges.size()}).second)
return;
DEBUG(dbgs() << " Added callable function: " << F.getName() << "\n");
Edges.emplace_back(LazyCallGraph::Edge(F, EK));
}
LazyCallGraph::Node::Node(LazyCallGraph &G, Function &F)
@ -56,14 +47,26 @@ LazyCallGraph::Node::Node(LazyCallGraph &G, Function &F)
// are trivially added, but to accumulate the latter we walk the instructions
// and add every operand which is a constant to the worklist to process
// afterward.
//
// Note that we consider *any* function with a definition to be a viable
// edge. Even if the function's definition is subject to replacement by
// some other module (say, a weak definition) there may still be
// optimizations which essentially speculate based on the definition and
// a way to check that the specific definition is in fact the one being
// used. For example, this could be done by moving the weak definition to
// a strong (internal) definition and making the weak definition be an
// alias. Then a test of the address of the weak function against the new
// strong definition's address would be an effective way to determine the
// safety of optimizing a direct call edge.
for (BasicBlock &BB : F)
for (Instruction &I : BB) {
if (auto CS = CallSite(&I))
if (Function *Callee = CS.getCalledFunction())
if (Callees.insert(Callee).second) {
Visited.insert(Callee);
addEdge(Edges, EdgeIndexMap, *Callee, LazyCallGraph::Edge::Call);
}
if (!Callee->isDeclaration())
if (Callees.insert(Callee).second) {
Visited.insert(Callee);
addEdge(Edges, EdgeIndexMap, *Callee, LazyCallGraph::Edge::Call);
}
for (Value *Op : I.operand_values())
if (Constant *C = dyn_cast<Constant>(Op))