[llvm-commits] [llvm] r165490 - in /llvm/trunk: include/llvm/DebugInfo.h lib/Transforms/IPO/DeadArgumentElimination.cpp lib/VMCore/DebugInfo.cpp test/Transforms/DeadArgElim/dbginfo.ll
Chandler Carruth
chandlerc at google.com
Tue Oct 9 01:38:43 PDT 2012
On Tue, Oct 9, 2012 at 1:13 AM, Alexey Samsonov <samsonov at google.com> wrote:
> Author: samsonov
> Date: Tue Oct 9 03:13:15 2012
> New Revision: 165490
>
> URL: http://llvm.org/viewvc/llvm-project?rev=165490&view=rev
> Log:
> Fix PR14016.
> DeadArgumentElimination pass can replace one LLVM function with another,
> invalidating a pointer stored in debug info metadata entry for this
> function.
> To fix this, we collect debug info descriptors for functions before
> running a DeadArgumentElimination pass and "patch" pointers in metadata
> nodes
> if we replace a function.
>
> Added:
> llvm/trunk/test/Transforms/DeadArgElim/dbginfo.ll
> Modified:
> llvm/trunk/include/llvm/DebugInfo.h
> llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
> llvm/trunk/lib/VMCore/DebugInfo.cpp
>
> Modified: llvm/trunk/include/llvm/DebugInfo.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo.h?rev=165490&r1=165489&r2=165490&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo.h Tue Oct 9 03:13:15 2012
> @@ -81,6 +81,7 @@
> GlobalVariable *getGlobalVariableField(unsigned Elt) const;
> Constant *getConstantField(unsigned Elt) const;
> Function *getFunctionField(unsigned Elt) const;
> + void replaceFunctionField(unsigned Elt, Function *F);
>
> public:
> explicit DIDescriptor() : DbgNode(0) {}
> @@ -562,6 +563,7 @@
> bool describes(const Function *F);
>
> Function *getFunction() const { return getFunctionField(16); }
> + void replaceFunction(Function *F) { replaceFunctionField(16, F); }
> DIArray getTemplateParams() const { return getFieldAs<DIArray>(17); }
> DISubprogram getFunctionDeclaration() const {
> return getFieldAs<DISubprogram>(18);
>
> Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=165490&r1=165489&r2=165490&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Tue Oct 9
> 03:13:15 2012
> @@ -21,7 +21,9 @@
> #include "llvm/Transforms/IPO.h"
> #include "llvm/CallingConv.h"
> #include "llvm/Constant.h"
> +#include "llvm/DebugInfo.h"
> #include "llvm/DerivedTypes.h"
> +#include "llvm/DIBuilder.h"
> #include "llvm/Instructions.h"
> #include "llvm/IntrinsicInst.h"
> #include "llvm/LLVMContext.h"
> @@ -121,6 +123,15 @@
>
> typedef SmallVector<RetOrArg, 5> UseVector;
>
> + // Map each LLVM function to corresponding metadata with debug info.
> If
> + // the function is replaced with another one, we should patch the
> pointer
> + // to LLVM function in metadata.
> + // As the code generation for module is finished (and DIBuilder is
> + // finalized) we assume that subprogram descriptors won't be changed,
> and
> + // they are stored in map for short duration anyway.
> + typedef std::map<Function*, DISubprogram> FunctionDIMap;
>
DenseMap or DenseSmallMap would likely be better here. You're not iterating
anywhere...
> + FunctionDIMap FunctionDIs;
> +
> protected:
> // DAH uses this to specify a different ID.
> explicit DAE(char &ID) : ModulePass(ID) {}
> @@ -141,6 +152,7 @@
> unsigned RetValNum = 0);
> Liveness SurveyUses(const Value *V, UseVector &MaybeLiveUses);
>
> + void CollectFunctionDIs(Module &M);
> void SurveyFunction(const Function &F);
> void MarkValue(const RetOrArg &RA, Liveness L,
> const UseVector &MaybeLiveUses);
> @@ -180,6 +192,31 @@
> ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); }
> ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); }
>
> +/// CollectFunctionDIs - Map each function in the module to its debug info
> +/// descriptor.
> +void DAE::CollectFunctionDIs(Module &M) {
> + FunctionDIs.clear();
> +
> + for (Module::named_metadata_iterator I = M.named_metadata_begin(),
> + E = M.named_metadata_end(); I != E; ++I) {
> + NamedMDNode &NMD = *I;
> + for (unsigned i = 0, n = NMD.getNumOperands(); i < n; ++i) {
> + MDNode *Node = NMD.getOperand(i);
> + if (DIDescriptor(Node).isCompileUnit()) {
> + DICompileUnit CU(Node);
> + const DIArray &SPs = CU.getSubprograms();
> + for (unsigned i = 0, n = SPs.getNumElements(); i < n; ++i) {
> + DISubprogram SP(SPs.getElement(i));
> + if (SP.Verify()) {
> + if (Function *F = SP.getFunction())
> + FunctionDIs[F] = SP;
> + }
> + }
> + }
> + }
> + }
>
This loop is terrifying! ;] A couple of changes here that are pretty common
steps to simplify loops in LLVM-land:
- Don't shadow loop variables in inner loops. You've shadowed both 'i' and
'n', so this happens to work, but a tiny typo would lead to disaster. ;]
- Use 'continue' and inverted conditions to reduce the indentation.
> +}
> +
> /// DeleteDeadVarargs - If this is an function that takes a ... list, and
> if
> /// llvm.vastart is never called, the varargs list is dead for the
> function.
> bool DAE::DeleteDeadVarargs(Function &Fn) {
> @@ -284,6 +321,11 @@
> I2->takeName(I);
> }
>
> + // Patch the pointer to LLVM function in debug info descriptor.
> + FunctionDIMap::iterator DI = FunctionDIs.find(&Fn);
> + if (DI != FunctionDIs.end())
> + DI->second.replaceFunction(NF);
> +
> // Finally, nuke the old function.
> Fn.eraseFromParent();
> return true;
> @@ -952,6 +994,11 @@
> BB->getInstList().erase(RI);
> }
>
> + // Patch the pointer to LLVM function in debug info descriptor.
> + FunctionDIMap::iterator DI = FunctionDIs.find(F);
> + if (DI != FunctionDIs.end())
> + DI->second.replaceFunction(NF);
> +
> // Now that the old function is dead, delete it.
> F->eraseFromParent();
>
> @@ -961,6 +1008,9 @@
> bool DAE::runOnModule(Module &M) {
> bool Changed = false;
>
> + // Collect debug info descriptors for functions.
> + CollectFunctionDIs(M);
> +
> // First pass: Do a simple check to see if any functions can have their
> "..."
> // removed. We can do this if they never call va_start. This loop
> cannot be
> // fused with the next loop, because deleting a function invalidates
>
> Modified: llvm/trunk/lib/VMCore/DebugInfo.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/DebugInfo.cpp?rev=165490&r1=165489&r2=165490&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/VMCore/DebugInfo.cpp (original)
> +++ llvm/trunk/lib/VMCore/DebugInfo.cpp Tue Oct 9 03:13:15 2012
> @@ -111,6 +111,16 @@
> return 0;
> }
>
> +void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) {
> + if (DbgNode == 0)
> + return;
> +
> + if (Elt < DbgNode->getNumOperands()) {
> + MDNode *Node = const_cast<MDNode*>(DbgNode);
> + Node->replaceOperandWith(Elt, F);
> + }
> +}
> +
> unsigned DIVariable::getNumAddrElements() const {
> if (getVersion() <= LLVMDebugVersion8)
> return DbgNode->getNumOperands()-6;
>
> Added: llvm/trunk/test/Transforms/DeadArgElim/dbginfo.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/dbginfo.ll?rev=165490&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/DeadArgElim/dbginfo.ll (added)
> +++ llvm/trunk/test/Transforms/DeadArgElim/dbginfo.ll Tue Oct 9 03:13:15
> 2012
> @@ -0,0 +1,64 @@
> +; RUN: opt %s -deadargelim -S | FileCheck %s
> +; PR14016
> +
> +; Check that debug info metadata for subprograms stores pointers to
> +; updated LLVM functions.
> +
> +target datalayout =
> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> +target triple = "x86_64-unknown-linux-gnu"
> +
> + at x = global i32 0, align 4
> +
> +define void @_Z3runv() uwtable {
> +entry:
> + call void @_ZN12_GLOBAL__N_18dead_argEPv(i8* null), !dbg !10
> + call void (...)* @_ZN12_GLOBAL__N_111dead_varargEz(), !dbg !12
> + ret void, !dbg !13
> +}
> +
> +; Argument will be deleted
> +define internal void @_ZN12_GLOBAL__N_18dead_argEPv(i8* %foo) nounwind
> uwtable {
> +entry:
> + %0 = load i32* @x, align 4, !dbg !14
> + %inc = add nsw i32 %0, 1, !dbg !14
> + store i32 %inc, i32* @x, align 4, !dbg !14
> + ret void, !dbg !16
> +}
> +
> +; Vararg will be deleted
> +define internal void @_ZN12_GLOBAL__N_111dead_varargEz(...) nounwind
> uwtable {
> +entry:
> + %0 = load i32* @x, align 4, !dbg !17
> + %inc = add nsw i32 %0, 1, !dbg !17
> + store i32 %inc, i32* @x, align 4, !dbg !17
> + ret void, !dbg !19
> +}
> +
> +!llvm.dbg.cu = !{!0}
> +
> +!0 = metadata !{i32 786449, i32 0, i32 4, metadata !"test.cc", metadata
> !"/home/samsonov/tmp/clang-di", metadata !"clang version 3.2 (trunk
> 165305)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1,
> metadata !3, metadata !1} ; [ DW_TAG_compile_unit ]
> [/home/samsonov/tmp/clang-di/test.cc] [DW_LANG_C_plus_plus]
> +!1 = metadata !{metadata !2}
> +!2 = metadata !{i32 0}
> +!3 = metadata !{metadata !4}
> +!4 = metadata !{metadata !5, metadata !8, metadata !9}
> +!5 = metadata !{i32 786478, i32 0, metadata !6, metadata !"run", metadata
> !"run", metadata !"", metadata !6, i32 8, metadata !7, i1 false, i1 true,
> i32 0, i32 0, null, i32 256, i1 false, void ()* @_Z3runv, null, null,
> metadata !1, i32 8} ; [ DW_TAG_subprogram ] [line 8] [def] [run]
> +!6 = metadata !{i32 786473, metadata !"test.cc", metadata
> !"/home/samsonov/tmp/clang-di", null} ; [ DW_TAG_file_type ]
> +!7 = metadata !{i32 786453, i32 0, metadata !"", i32 0, i32 0, i64 0, i64
> 0, i64 0, i32 0, null, metadata !2, i32 0, i32 0} ; [
> DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
> +!8 = metadata !{i32 786478, i32 0, metadata !6, metadata !"dead_vararg",
> metadata !"dead_vararg", metadata !"", metadata !6, i32 5, metadata !7, i1
> true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (...)*
> @_ZN12_GLOBAL__N_111dead_varargEz, null, null, metadata !1, i32 5} ; [
> DW_TAG_subprogram ] [line 5] [local] [def] [dead_vararg]
> +
> +; CHECK: metadata !"dead_vararg"{{.*}}void ()*
> @_ZN12_GLOBAL__N_111dead_varargEz
> +
> +!9 = metadata !{i32 786478, i32 0, metadata !6, metadata !"dead_arg",
> metadata !"dead_arg", metadata !"", metadata !6, i32 4, metadata !7, i1
> true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i8*)*
> @_ZN12_GLOBAL__N_18dead_argEPv, null, null, metadata !1, i32 4} ; [
> DW_TAG_subprogram ] [line 4] [local] [def] [dead_arg]
> +
> +; CHECK: metadata !"dead_arg"{{.*}}void ()* @_ZN12_GLOBAL__N_18dead_argEPv
> +
> +!10 = metadata !{i32 8, i32 14, metadata !11, null}
> +!11 = metadata !{i32 786443, metadata !5, i32 8, i32 12, metadata !6, i32
> 0} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc]
> +!12 = metadata !{i32 8, i32 27, metadata !11, null}
> +!13 = metadata !{i32 8, i32 42, metadata !11, null}
> +!14 = metadata !{i32 4, i32 28, metadata !15, null}
> +!15 = metadata !{i32 786443, metadata !9, i32 4, i32 26, metadata !6, i32
> 2} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc]
> +!16 = metadata !{i32 4, i32 33, metadata !15, null}
> +!17 = metadata !{i32 5, i32 25, metadata !18, null}
> +!18 = metadata !{i32 786443, metadata !8, i32 5, i32 23, metadata !6, i32
> 1} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc]
> +!19 = metadata !{i32 5, i32 30, metadata !18, null}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121009/4d8c09f4/attachment.html>
More information about the llvm-commits
mailing list