[PATCH] [llvm-extract] Add -dag option.
Michael Spencer
bigcheesegs at gmail.com
Thu May 22 16:26:06 PDT 2014
Hi chandlerc,
The -dag option informs llvm-extract to keep all global values that were
explicitly listed and that are reachable from those listed. This is useful for
extracting sub-graphs of a program.
http://reviews.llvm.org/D3884
Files:
tools/llvm-extract/llvm-extract.cpp
Index: tools/llvm-extract/llvm-extract.cpp
===================================================================
--- tools/llvm-extract/llvm-extract.cpp
+++ tools/llvm-extract/llvm-extract.cpp
@@ -14,6 +14,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRPrintingPasses.h"
@@ -90,6 +91,63 @@
OutputAssembly("S",
cl::desc("Write output as LLVM assembly"), cl::Hidden);
+static cl::opt<bool>
+ExtractDAG("dag", cl::desc("Extract all globals and functions referenced by "
+ "the selected global values."));
+
+SmallPtrSet<Constant *, 8> SeenConstants;
+
+void MarkUsed(Constant *C, SetVector<GlobalValue *> &GVs);
+
+/// \brief Mark the specific global value as used, and recursively mark anything
+/// that it uses as also used.
+void MarkUsed(GlobalValue *G, SetVector<GlobalValue *> &GVs) {
+ // If the global is already in the set, no need to reprocess it.
+ if (!GVs.insert(G))
+ return;
+
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G)) {
+ // If this is a global variable, we must make sure to add any global values
+ // referenced by the initializer to the alive set.
+ if (GV->hasInitializer())
+ MarkUsed(GV->getInitializer(), GVs);
+ } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) {
+ // The target of a global alias is needed.
+ MarkUsed(GA->getAliasee(), GVs);
+ } else {
+ // Otherwise this must be a function object. We have to scan the body of
+ // the function looking for constants and global values which are used as
+ // operands. Any operands of these types must be processed to ensure that
+ // any globals used will be marked as needed.
+ Function *F = cast<Function>(G);
+
+ if (F->hasPrefixData())
+ MarkUsed(F->getPrefixData(), GVs);
+
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
+ for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
+ for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(*U))
+ MarkUsed(GV, GVs);
+ else if (Constant *C = dyn_cast<Constant>(*U))
+ MarkUsed(C, GVs);
+ }
+}
+
+void MarkUsed(Constant *C, SetVector<GlobalValue *> &GVs) {
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
+ return MarkUsed(GV, GVs);
+
+ // Loop over all of the operands of the constant, adding any globals they
+ // use to the list of needed globals.
+ for (User::op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I) {
+ // If we've already processed this constant there's no need to do it again.
+ Constant *Op = dyn_cast<Constant>(*I);
+ if (Op && SeenConstants.insert(Op))
+ MarkUsed(Op, GVs);
+ }
+}
+
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
@@ -213,6 +271,23 @@
}
}
+ // Add all referenced GVs.
+ if (ExtractDAG) {
+ SetVector<GlobalValue *> NewGVs;
+ for (size_t i = 0; i < GVs.size(); ++i) {
+ GlobalValue *GV = GVs[i];
+ if (GV->isMaterializable()) {
+ std::string ErrInfo;
+ if (GV->Materialize(&ErrInfo)) {
+ errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
+ return 1;
+ }
+ }
+ MarkUsed(GV, NewGVs);
+ }
+ GVs = NewGVs;
+ }
+
// Materialize requisite global values.
if (!DeleteFn)
for (size_t i = 0, e = GVs.size(); i != e; ++i) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3884.9722.patch
Type: text/x-patch
Size: 3629 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140522/e967f1c3/attachment.bin>
More information about the llvm-commits
mailing list