[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