[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
Alexey Samsonov
samsonov at google.com
Tue Oct 9 03:37:31 PDT 2012
r165498.
On Tue, Oct 9, 2012 at 12:38 PM, Chandler Carruth <chandlerc at google.com>wrote:
> 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
>>
>
>
--
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121009/e9f5a5a4/attachment.html>
More information about the llvm-commits
mailing list