<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 16, 2014 at 3:23 PM, Duncan P. N. Exon Smith <span dir="ltr"><<a href="mailto:dexonsmith@apple.com" target="_blank">dexonsmith@apple.com</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: dexonsmith<br>
Date: Tue Dec 16 17:23:41 2014<br>
New Revision: 224389<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=224389&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=224389&view=rev</a><br>
Log:<br>
Linker: Drop superseded subprograms<br>
<br>
When a function gets replaced by `ModuleLinker`, drop superseded<br>
subprograms.  This ensures that the "first" subprogram pointing at a<br>
function is the same one that `!dbg` references point at.<br>
<br>
This is a stop-gap fix for PR21910.  Notably, this fixes Release+Asserts<br>
bootstraps </blockquote><div><br>LTO bootstraps, specifically, yes? (not just a normal bootstrap)<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">that are currently asserting out in<br>
`LexicalScopes::initialize()` due to the explicit instantiations in<br>
`lib/IR/Dominators.cpp` eventually getting replaced by -argpromotion.<br>
<br>
Added:<br>
    llvm/trunk/test/Linker/Inputs/replaced-function-matches-first-subprogram.ll<br>
    llvm/trunk/test/Linker/replaced-function-matches-first-subprogram.ll<br>
Modified:<br>
    llvm/trunk/lib/Linker/LinkModules.cpp<br>
<br>
Modified: llvm/trunk/lib/Linker/LinkModules.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=224389&r1=224388&r2=224389&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=224389&r1=224388&r2=224389&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)<br>
+++ llvm/trunk/lib/Linker/LinkModules.cpp Tue Dec 16 17:23:41 2014<br>
@@ -19,6 +19,7 @@<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
 #include "llvm/IR/Constants.h"<br>
+#include "llvm/IR/DebugInfo.h"<br>
 #include "llvm/IR/DiagnosticInfo.h"<br>
 #include "llvm/IR/DiagnosticPrinter.h"<br>
 #include "llvm/IR/LLVMContext.h"<br>
@@ -416,6 +417,9 @@ class ModuleLinker {<br>
   // Vector of GlobalValues to lazily link in.<br>
   std::vector<GlobalValue *> LazilyLinkGlobalValues;<br>
<br>
+  /// Functions that have replaced other functions.<br>
+  SmallPtrSet<const Function *, 16> OverridingFunctions;<br>
+<br>
   Linker::DiagnosticHandlerFunction DiagnosticHandler;<br>
<br>
 public:<br>
@@ -494,6 +498,7 @@ private:<br>
   bool linkGlobalValueBody(GlobalValue &Src);<br>
<br>
   void linkNamedMDNodes();<br>
+  void stripReplacedSubprograms();<br>
 };<br>
 }<br>
<br>
@@ -1078,6 +1083,10 @@ bool ModuleLinker::linkGlobalValueProto(<br>
     }<br>
<br>
     NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV);<br>
+<br>
+    if (DGV && isa<Function>(DGV))<br>
+      if (auto *NewF = dyn_cast<Function>(NewGV))<br>
+        OverridingFunctions.insert(NewF);<br>
   }<br>
<br>
   NewGV->setUnnamedAddr(HasUnnamedAddr);<br>
@@ -1244,6 +1253,48 @@ void ModuleLinker::linkNamedMDNodes() {<br>
   }<br>
 }<br>
<br>
+/// Drop DISubprograms that have been superseded.<br>
+///<br>
+/// FIXME: this creates an asymmetric result: we strip losing subprograms from<br>
+/// DstM, but leave losing subprograms in SrcM.  Instead we should also strip<br>
+/// losers from SrcM, but this requires extra plumbing in MapValue.<br>
+void ModuleLinker::stripReplacedSubprograms() {<br>
+  // Avoid quadratic runtime by returning early when there's nothing to do.<br>
+  if (OverridingFunctions.empty())<br>
+    return;<br>
+<br>
+  // Move the functions now, so the set gets cleared even on early returns.<br>
+  auto Functions = std::move(OverridingFunctions);<br>
+  OverridingFunctions.clear();<br>
+<br>
+  // Drop subprograms whose functions have been overridden by the new compile<br>
+  // unit.<br>
+  NamedMDNode *CompileUnits = DstM->getNamedMetadata("<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a>");<br>
+  if (!CompileUnits)<br>
+    return;<br>
+  for (unsigned I = 0, E = CompileUnits->getNumOperands(); I != E; ++I) {<br>
+    DICompileUnit CU(CompileUnits->getOperand(I));<br>
+    assert(CU && "Expected valid compile unit");<br>
+<br>
+    DITypedArray<DISubprogram> SPs(CU.getSubprograms());<br>
+    assert(SPs && "Expected valid subprogram array");<br>
+<br>
+    SmallVector<Metadata *, 16> NewSPs;<br>
+    NewSPs.reserve(SPs.getNumElements());<br>
+    for (unsigned S = 0, SE = SPs.getNumElements(); S != SE; ++S) {<br>
+      DISubprogram SP = SPs.getElement(S);<br>
+      if (SP && SP.getFunction() && Functions.count(SP.getFunction()))<br>
+        continue;<br>
+<br>
+      NewSPs.push_back(SP);<br>
+    }<br>
+<br>
+    // Redirect operand to the overriding subprogram.<br>
+    if (NewSPs.size() != SPs.getNumElements())<br>
+      CU.replaceSubprograms(DIArray(MDNode::get(DstM->getContext(), NewSPs)));<br>
+  }<br>
+}<br>
+<br>
 /// Merge the linker flags in Src into the Dest module.<br>
 bool ModuleLinker::linkModuleFlagsMetadata() {<br>
   // If the source module has no module flags, we are done.<br>
@@ -1509,6 +1560,9 @@ bool ModuleLinker::run() {<br>
     linkGlobalValueBody(Src);<br>
   }<br>
<br>
+  // Strip replaced subprograms before linking together compile units.<br>
+  stripReplacedSubprograms();<br>
+<br>
   // Remap all of the named MDNodes in Src into the DstM module. We do this<br>
   // after linking GlobalValues so that MDNodes that reference GlobalValues<br>
   // are properly remapped.<br>
<br>
Added: llvm/trunk/test/Linker/Inputs/replaced-function-matches-first-subprogram.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/replaced-function-matches-first-subprogram.ll?rev=224389&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/replaced-function-matches-first-subprogram.ll?rev=224389&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Linker/Inputs/replaced-function-matches-first-subprogram.ll (added)<br>
+++ llvm/trunk/test/Linker/Inputs/replaced-function-matches-first-subprogram.ll Tue Dec 16 17:23:41 2014<br>
@@ -0,0 +1,27 @@<br>
+%struct.Class = type { i8 }<br>
+<br>
+define weak_odr i32 @_ZN5ClassIiE3fooEv(%struct.Class* %this) align 2 {<br>
+entry:<br>
+  %this.addr = alloca %struct.Class*, align 8<br>
+  store %struct.Class* %this, %struct.Class** %this.addr, align 8<br>
+  %this1 = load %struct.Class** %this.addr<br>
+  ret i32 0, !dbg !12<br>
+}<br>
+<br>
+!<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!8, !9, !10}<br>
+!llvm.ident = !{!11}<br>
+<br>
+!0 = !{!"0x11\004\00clang version 3.6.0 (trunk 224193) (llvm/trunk 224197)\000\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d2/t2.cpp] [DW_LANG_C_plus_plus]<br>
+!1 = !{!"t2.cpp", !"/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d2"}<br>
+!2 = !{}<br>
+!3 = !{!4}<br>
+!4 = !{!"0x2e\00foo\00foo\00\002\000\001\000\000\00256\000\002", !5, !6, !7, null, i32 (%struct.Class*)* @_ZN5ClassIiE3fooEv, null, null, !2} ; [ DW_TAG_subprogram ] [line 2] [def] [foo]<br>
+!5 = !{!"../t.h", !"/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d2"}<br>
+!6 = !{!"0x29", !5}    ; [ DW_TAG_file_type ] [/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d2/../t.h]<br>
+!7 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]<br>
+!8 = !{i32 2, !"Dwarf Version", i32 2}<br>
+!9 = !{i32 2, !"Debug Info Version", i32 2}<br>
+!10 = !{i32 1, !"PIC Level", i32 2}<br>
+!11 = !{!"clang version 3.6.0 (trunk 224193) (llvm/trunk 224197)"}<br>
+!12 = !{i32 2, i32 15, !4, null}<br>
<br>
Added: llvm/trunk/test/Linker/replaced-function-matches-first-subprogram.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/replaced-function-matches-first-subprogram.ll?rev=224389&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/replaced-function-matches-first-subprogram.ll?rev=224389&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Linker/replaced-function-matches-first-subprogram.ll (added)<br>
+++ llvm/trunk/test/Linker/replaced-function-matches-first-subprogram.ll Tue Dec 16 17:23:41 2014<br>
@@ -0,0 +1,75 @@<br>
+; RUN: llvm-link %s %S/Inputs/replaced-function-matches-first-subprogram.ll -S | FileCheck %s<br>
+<br>
+; Generated from C++ source:<br>
+;<br>
+; // repro/t.h<br>
+; template <class T> struct Class {<br>
+;   int foo() { return 0; }<br>
+; };<br>
+; // repro/d1/t1.cpp<br>
+; #include "t.h"<br>
+; int foo() { return Class<int>().foo(); }<br>
+; // repro/d2/t2.cpp<br>
+; #include "t.h"<br>
+; template struct Class<int>;<br>
+<br>
+%struct.Class = type { i8 }<br>
+<br>
+define i32 @_Z3foov() {<br>
+entry:<br>
+  %tmp = alloca %struct.Class, align 1<br>
+  %call = call i32 @_ZN5ClassIiE3fooEv(%struct.Class* %tmp), !dbg !14<br>
+  ret i32 %call, !dbg !14<br>
+}<br>
+<br>
+; CHECK: define weak_odr i32 @_ZN5ClassIiE3fooEv(%struct.Class* %this){{.*}}{<br>
+; CHECK-NOT: }<br>
+; CHECK: !dbg ![[LOC:[0-9]+]]<br>
+define linkonce_odr i32 @_ZN5ClassIiE3fooEv(%struct.Class* %this) align 2 {<br>
+entry:<br>
+  %this.addr = alloca %struct.Class*, align 8<br>
+  store %struct.Class* %this, %struct.Class** %this.addr, align 8<br>
+  %this1 = load %struct.Class** %this.addr<br>
+  ret i32 0, !dbg !15<br>
+}<br>
+<br>
+; CHECK: !<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a> = !{![[CU1:[0-9]+]], ![[CU2:[0-9]+]]}<br>
+!<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!10, !11, !12}<br>
+!llvm.ident = !{!13}<br>
+<br>
+; Extract out the list of subprograms from each compile unit.<br>
+; CHECK-DAG: ![[CU1]] = !{!"0x11{{[^"]+}}", {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, ![[SPs1:[0-9]+]],<br>
+; CHECK-DAG: ![[CU2]] = !{!"0x11{{[^"]+}}", {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, ![[SPs2:[0-9]+]],<br>
+!0 = !{!"0x11\004\00clang version 3.6.0 (trunk 224193) (llvm/trunk 224197)\000\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d1/t1.cpp] [DW_LANG_C_plus_plus]<br>
+!1 = !{!"t1.cpp", !"/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d1"}<br>
+!2 = !{}<br>
+<br>
+; Extract out each compile unit's single subprogram.  The replaced subprogram<br>
+; should be dropped by the first compile unit.<br>
+; CHECK-DAG: ![[SPs1]] = !{![[SP1:[0-9]+]]}<br>
+; CHECK-DAG: ![[SPs2]] = !{![[SP2:[0-9]+]]}<br>
+!3 = !{!4, !7}<br>
+!4 = !{!"0x2e\00foo\00foo\00\002\000\001\000\000\00256\000\002", !1, !5, !6, null, i32 ()* @_Z3foov, null, null, !2} ; [ DW_TAG_subprogram ] [line 2] [def] [foo]<br>
+!5 = !{!"0x29", !1}    ; [ DW_TAG_file_type ] [/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d1/t1.cpp]<br>
+!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]<br>
+<br>
+; Extract out the file from the replaced subprogram.  Confirm that each<br>
+; subprogram is pointing at the correct function.<br>
+; CHECK-DAG: ![[SP1]] = !{!"0x2e{{[^"]+}}", {{.*}}, i32 ()* @_Z3foov,<br>
+; CHECK-DAG: ![[SP2]] = !{!"0x2e{{[^"]+}}", ![[FILE:[0-9]+]], {{.*}}, i32 (%struct.Class*)* @_ZN5ClassIiE3fooEv,<br>
+!7 = !{!"0x2e\00foo\00foo\00\002\000\001\000\000\00256\000\002", !8, !9, !6, null, i32 (%struct.Class*)* @_ZN5ClassIiE3fooEv, null, null, !2} ; [ DW_TAG_subprogram ] [line 2] [def] [foo]<br>
+<br>
+; The new subprogram should be pointing at the new directory.<br>
+; CHECK-DAG: ![[FILE]] = !{!"../t.h", !"/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d2"}<br>
+!8 = !{!"../t.h", !"/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d1"}<br>
+!9 = !{!"0x29", !8}    ; [ DW_TAG_file_type ] [/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d1/../t.h]<br>
+!10 = !{i32 2, !"Dwarf Version", i32 2}<br>
+!11 = !{i32 2, !"Debug Info Version", i32 2}<br>
+!12 = !{i32 1, !"PIC Level", i32 2}<br>
+!13 = !{!"clang version 3.6.0 (trunk 224193) (llvm/trunk 224197)"}<br>
+!14 = !{i32 2, i32 20, !4, null}<br>
+<br>
+; The same subprogram should be pointed to by inside the !dbg reference.<br>
+; CHECK: ![[LOC]] = !{i32 2, i32 15, ![[SP2]], null}<br>
+!15 = !{i32 2, i32 15, !7, null}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div></div>