diff options
author | Jan Voung <jvoung@chromium.org> | 2013-03-28 16:56:41 -0700 |
---|---|---|
committer | Jan Voung <jvoung@chromium.org> | 2013-03-28 16:56:41 -0700 |
commit | 946417b9fe7da9334c76182f28020ff4f46e11f8 (patch) | |
tree | 7fb6f266cec32158396e074aba7195848f652cd2 | |
parent | 37a28705d4dfdda8ecbb9aca9bc10a6fd6d80582 (diff) |
Add a pass to strip bitcode metadata.
This only works on instruction attachments for now. Since it is a
ModulePass we can add something to strip NamedMetadata
based on a whitelist, if we want to retain some of that.
It does not touch debug metadata, and leaves -strip-debug to handle that.
BUG= https://code.google.com/p/nativeclient/issues/detail?id=3348
Review URL: https://codereview.chromium.org/12844027
-rw-r--r-- | include/llvm/InitializePasses.h | 1 | ||||
-rw-r--r-- | include/llvm/Transforms/NaCl.h | 1 | ||||
-rw-r--r-- | lib/Transforms/NaCl/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Transforms/NaCl/StripMetadata.cpp | 77 | ||||
-rw-r--r-- | test/Transforms/NaCl/strip-branchweight-metadata.ll | 29 | ||||
-rw-r--r-- | test/Transforms/NaCl/strip-meta-leaves-debug.ll | 34 | ||||
-rw-r--r-- | test/Transforms/NaCl/strip-tbaa-metadata.ll | 36 | ||||
-rw-r--r-- | tools/opt/opt.cpp | 1 |
8 files changed, 180 insertions, 0 deletions
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index d03a51fd70..236fe2ff87 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -288,6 +288,7 @@ void initializeNaClCcRewritePass(PassRegistry&); void initializePNaClABIVerifyModulePass(PassRegistry&); void initializePNaClABIVerifyFunctionsPass(PassRegistry&); void initializeResolveAliasesPass(PassRegistry&); +void initializeStripMetadataPass(PassRegistry&); // @LOCALMOD-END } diff --git a/include/llvm/Transforms/NaCl.h b/include/llvm/Transforms/NaCl.h index 6782f6581f..58166bbf22 100644 --- a/include/llvm/Transforms/NaCl.h +++ b/include/llvm/Transforms/NaCl.h @@ -24,6 +24,7 @@ ModulePass *createExpandTlsConstantExprPass(); ModulePass *createExpandVarArgsPass(); ModulePass *createGlobalCleanupPass(); ModulePass *createResolveAliasesPass(); +ModulePass *createStripMetadataPass(); } diff --git a/lib/Transforms/NaCl/CMakeLists.txt b/lib/Transforms/NaCl/CMakeLists.txt index 4e33abc1a7..1ca8e3d59e 100644 --- a/lib/Transforms/NaCl/CMakeLists.txt +++ b/lib/Transforms/NaCl/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_library(LLVMTransformsNaCl ExpandTlsConstantExpr.cpp ExpandVarArgs.cpp GlobalCleanup.cpp + StripMetadata.cpp ) add_dependencies(LLVMTransformsNaCl intrinsics_gen) diff --git a/lib/Transforms/NaCl/StripMetadata.cpp b/lib/Transforms/NaCl/StripMetadata.cpp new file mode 100644 index 0000000000..a7d2e7eb68 --- /dev/null +++ b/lib/Transforms/NaCl/StripMetadata.cpp @@ -0,0 +1,77 @@ +//===- StripMetadata.cpp - Strip non-stable non-debug metadata ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The StripMetadata transformation strips instruction attachment +// metadata, such as !tbaa and !prof metadata. +// TODO: Strip NamedMetadata too. +// +// It does not strip debug metadata. Debug metadata is used by debug +// intrinsic functions and calls to those intrinsic functions. Use the +// -strip-debug or -strip pass to strip that instead. +// +// The goal of this pass is to reduce bitcode ABI surface area. +// We don't know yet which kind of metadata is considered stable. +//===----------------------------------------------------------------------===// + +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/NaCl.h" + +using namespace llvm; + +namespace { + class StripMetadata : public ModulePass { + public: + static char ID; + explicit StripMetadata() : ModulePass(ID) { + initializeStripMetadataPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnModule(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + } + }; +} + +char StripMetadata::ID = 0; +INITIALIZE_PASS(StripMetadata, "strip-metadata", + "Strip all non-stable non-debug metadata from a module.", + false, false) + +ModulePass *llvm::createStripMetadataPass() { + return new StripMetadata(); +} + +static bool DoStripMetadata(Module &M) { + bool Changed = false; + + for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { + for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) { + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; + ++BI) { + SmallVector<std::pair<unsigned, MDNode *>, 8> InstMeta; + // Let the debug metadata be stripped by the -strip-debug pass. + BI->getAllMetadataOtherThanDebugLoc(InstMeta); + for (size_t i = 0; i < InstMeta.size(); ++i) { + BI->setMetadata(InstMeta[i].first, NULL); + Changed = true; + } + } + } + } + + return Changed; +} + +bool StripMetadata::runOnModule(Module &M) { + return DoStripMetadata(M); +} diff --git a/test/Transforms/NaCl/strip-branchweight-metadata.ll b/test/Transforms/NaCl/strip-branchweight-metadata.ll new file mode 100644 index 0000000000..61d3a6d5af --- /dev/null +++ b/test/Transforms/NaCl/strip-branchweight-metadata.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -strip-metadata %s | FileCheck %s + +; Test that !prof metadata is removed from branches +; CHECK: @foo +; CHECK-NOT: !prof +define i32 @foo(i32 %c) { + switch i32 %c, label %3 [ + i32 5, label %4 + i32 0, label %1 + i32 4, label %2 + ], !prof !0 + +; <label>:1 ; preds = %0 + br label %4 + +; <label>:2 ; preds = %0 + br label %4 + +; <label>:3 ; preds = %0 + br label %4 + +; <label>:4 ; preds = %0, %3, %2, %1 + %.0 = phi i32 [ -1, %1 ], [ 99, %2 ], [ 1, %3 ], [ 0, %0 ] + ret i32 %.0 +} + +; CHECK: ret i32 %.0 +; CHECK-NOT: !0 = +!0 = metadata !{metadata !"branch_weights", i32 4, i32 256, i32 8, i32 4} diff --git a/test/Transforms/NaCl/strip-meta-leaves-debug.ll b/test/Transforms/NaCl/strip-meta-leaves-debug.ll new file mode 100644 index 0000000000..a49b4dd1c3 --- /dev/null +++ b/test/Transforms/NaCl/strip-meta-leaves-debug.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -strip-metadata %s | FileCheck %s +; RUN: opt -S -strip-metadata -strip-debug %s | FileCheck %s --check-prefix=NODEBUG + +define i32 @foo(i32 %c) { +; CHECK: @foo +; CHECK-NEXT: call void @llvm.dbg{{.*}}, !dbg +; CHECK-NEXT: ret{{.*}}, !dbg +; NODEBUG: @foo +; NODEBUG-NOT: !dbg + tail call void @llvm.dbg.value(metadata !{i32 %c}, i64 0, metadata !9), !dbg !10 + ret i32 %c, !dbg !11 +} + +; CHECK: @llvm.dbg.value +; NODEBUG: ret i32 +; NODEBUG-NOT: @llvm.dbg.value +declare void @llvm.dbg.value(metadata, i64, metadata) #1 + +; CHECK: !llvm.dbg.cu +; CHECK: !0 = +!llvm.dbg.cu = !{!0} + +!0 = metadata !{i32 786449, i32 0, i32 12, metadata !"test.c", metadata !"/tmp", metadata !"clang version 3.3 (trunk 176732) (llvm/trunk 176733)", i1 true, i1 true, metadata !"", i32 0, metadata !1, metadata !1, metadata !2, metadata !1, metadata !""} ; [ DW_TAG_compile_unit ] [/tmp/test.c] [DW_LANG_C99] +!1 = metadata !{i32 0} +!2 = metadata !{metadata !3} +!3 = metadata !{i32 786478, i32 0, metadata !4, metadata !"foo", metadata !"foo", metadata !"", metadata !4, i32 1, metadata !5, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 (i32)* @foo, null, null, metadata !8, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!4 = metadata !{i32 786473, metadata !"test.c", metadata !"/tmp", null} ; [ DW_TAG_file_type ] +!5 = metadata !{i32 786453, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !6, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!6 = metadata !{metadata !7, metadata !7} +!7 = metadata !{i32 786468, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!8 = metadata !{metadata !9} +!9 = metadata !{i32 786689, metadata !3, metadata !"c", metadata !4, i32 16777217, metadata !7, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [c] [line 1] +!10 = metadata !{i32 1, i32 0, metadata !3, null} +!11 = metadata !{i32 2, i32 0, metadata !3, null} diff --git a/test/Transforms/NaCl/strip-tbaa-metadata.ll b/test/Transforms/NaCl/strip-tbaa-metadata.ll new file mode 100644 index 0000000000..c555af6712 --- /dev/null +++ b/test/Transforms/NaCl/strip-tbaa-metadata.ll @@ -0,0 +1,36 @@ +; RUN: opt -S -strip-metadata %s | FileCheck %s + +; Test that !tbaa is removed from loads/stores. +; CHECK: @foo +; CHECK-NOT: !tbaa +define double @foo(i32* nocapture %ptr1, double* nocapture %ptr2) nounwind readonly { + store i32 99999, i32* %ptr1, align 1, !tbaa !0 + %1 = load double* %ptr2, align 8, !tbaa !3 + ret double %1 +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +; Test that !tbaa is removed from calls. +; CHECK: @bar +; CHECK-NOT: !tbaa +define void @bar(i8* nocapture %p, i8* nocapture %q, + i8* nocapture %s) nounwind { + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, + i64 16, i32 1, i1 false), !tbaa !4 + store i8 2, i8* %s, align 1, !tbaa !5 + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %q, i8* %p, + i64 16, i32 1, i1 false), !tbaa !4 +; CHECK ret void + ret void +} + +; Test that the metadata nodes aren't left over. +; CHECK-NOT: !0 = + +!0 = metadata !{metadata !"int", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA"} +!3 = metadata !{metadata !"double", metadata !1} +!4 = metadata !{metadata !"A", metadata !1} +!5 = metadata !{metadata !"B", metadata !1} diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index c682768164..106da562c6 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -585,6 +585,7 @@ int main(int argc, char **argv) { initializeExpandVarArgsPass(Registry); initializeGlobalCleanupPass(Registry); initializeResolveAliasesPass(Registry); + initializeStripMetadataPass(Registry); // @LOCALMOD-END cl::ParseCommandLineOptions(argc, argv, |