<div dir="ltr">+some debug info cabal folks who might have more detail to help/add/look at (no doubt Tim can find some of these folks in the Hallowed Halls of his employer ;) ) <br><br><div class="gmail_quote"><div dir="ltr">On Mon, Jul 9, 2018 at 10:42 PM Mikael Holmén via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
I wrote<br>
<br>
  <a href="https://bugs.llvm.org/show_bug.cgi?id=38114" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_bug.cgi?id=38114</a><br>
<br>
about this.<br>
<br>
Regards,<br>
Mikael<br>
<br>
On 07/09/2018 10:21 AM, Mikael Holmén via llvm-commits wrote:<br>
> Hi Tim,<br>
> <br>
> I found a case which started going wrong with this patch. I don't know <br>
> if it's the patch itself that is the problem or if it's just exposing <br>
> somethng already existing.<br>
> <br>
> With<br>
> <br>
>   opt -S -o - foo.ll -argpromotion -instcombine<br>
> <br>
> I get<br>
> <br>
> DISubprogram attached to more than one function<br>
> !1 = distinct !DISubprogram(name: "func_27", scope: !2, file: !2, line: <br>
> 251, type: !3, isLocal: true, isDefinition: true, scopeLine: 252, <br>
> isOptimized: false, unit: !5)<br>
> i64 ()* @func_27<br>
> LLVM ERROR: Broken module found, compilation aborted!<br>
> <br>
> If I add -print-before-all -print-after-all -print-module-scope I get <br>
> this as the last printouts:<br>
> <br>
> *** IR Dump Before Module Verifier *** (function: func_27)<br>
> ; ModuleID = 'foo.ll'<br>
> source_filename = "foo.ll"<br>
> <br>
> @g_280 = external global i32<br>
> <br>
> define i32 @func_1() {<br>
> bb1:<br>
>    %l_55.115 = alloca i32*, align 8<br>
>    %_tmp555 = load i32*, i32** %l_55.115, align 8<br>
>    %0 = call i64 @func_27()<br>
>    ret i32 undef<br>
> }<br>
> <br>
> define internal i64 @func_27() !dbg !1 {<br>
>    store i32* @g_280, i32** undef, align 8<br>
>    ret i64 undef<br>
> }<br>
> <br>
> define i16 @func_28() {<br>
>    %_tmp5791 = call i32 @func_1()<br>
>    ret i16 undef<br>
> }<br>
> <br>
> !<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{}<br>
> !llvm.module.flags = !{!0}<br>
> <br>
> !0 = !{i32 2, !"Debug Info Version", i32 3}<br>
> !1 = distinct !DISubprogram(name: "func_27", scope: !2, file: !2, line: <br>
> 251, type: !3, isLocal: true, isDefinition: true, scopeLine: 252, <br>
> isOptimized: false, unit: !5)<br>
> !2 = !DIFile(filename: "foo.c", directory: "/bar")<br>
> !3 = !DISubroutineType(types: !4)<br>
> !4 = !{}<br>
> !5 = distinct !DICompileUnit(language: DW_LANG_C, file: !2, producer: <br>
> "My compiler", isOptimized: false, runtimeVersion: 0, emissionKind: <br>
> LineTablesOnly)<br>
> DISubprogram attached to more than one function<br>
> !1 = distinct !DISubprogram(name: "func_27", scope: !2, file: !2, line: <br>
> 251, type: !3, isLocal: true, isDefinition: true, scopeLine: 252, <br>
> isOptimized: false, unit: !5)<br>
> i64 ()* @func_27<br>
> *** IR Dump After Module Verifier *** (function: func_27)<br>
> ; ModuleID = 'foo.ll'<br>
> source_filename = "foo.ll"<br>
> <br>
> @g_280 = external global i32<br>
> <br>
> define i32 @func_1() {<br>
> bb1:<br>
>    %l_55.115 = alloca i32*, align 8<br>
>    %_tmp555 = load i32*, i32** %l_55.115, align 8<br>
>    %0 = call i64 @func_27()<br>
>    ret i32 undef<br>
> }<br>
> <br>
> define internal i64 @func_27() !dbg !1 {<br>
>    store i32* @g_280, i32** undef, align 8<br>
>    ret i64 undef<br>
> }<br>
> <br>
> define i16 @func_28() {<br>
>    %_tmp5791 = call i32 @func_1()<br>
>    ret i16 undef<br>
> }<br>
> <br>
> !<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{}<br>
> !llvm.module.flags = !{!0}<br>
> <br>
> !0 = !{i32 2, !"Debug Info Version", i32 3}<br>
> !1 = distinct !DISubprogram(name: "func_27", scope: !2, file: !2, line: <br>
> 251, type: !3, isLocal: true, isDefinition: true, scopeLine: 252, <br>
> isOptimized: false, unit: !5)<br>
> !2 = !DIFile(filename: "foo.c", directory: "/bar")<br>
> !3 = !DISubroutineType(types: !4)<br>
> !4 = !{}<br>
> !5 = distinct !DICompileUnit(language: DW_LANG_C, file: !2, producer: <br>
> "My compiler", isOptimized: false, runtimeVersion: 0, emissionKind: <br>
> LineTablesOnly)<br>
> LLVM ERROR: Broken module found, compilation aborted!<br>
> <br>
> As far as I can see in the printouts !1 is only used on func_27 and <br>
> still it complains.<br>
> <br>
> func27 was changed during argpromotion:<br>
> <br>
> ARG PROMOTION:  Promoting to:<br>
> declare !dbg !0 internal i64 @func_27(i32*)<br>
> <br>
> From:<br>
> define internal i64 @func_27(i32* %p1, i32* %p2) {<br>
>    store i32* %p1, i32** undef<br>
>    store i32* @g_280, i32** undef<br>
>    ret i64 undef<br>
> }<br>
> <br>
> so I'm not sure if the old func_27 is still hanging around in some way?<br>
> <br>
> Should I write a PR on this or do you understand what's going on?<br>
> <br>
> Regards,<br>
> Mikael<br>
> <br>
> On 07/06/2018 10:04 AM, Tim Northover via llvm-commits wrote:<br>
>> Author: tnorthover<br>
>> Date: Fri Jul  6 01:04:47 2018<br>
>> New Revision: 336419<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=336419&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=336419&view=rev</a><br>
>> Log:<br>
>> CallGraphSCCPass: iterate over all functions.<br>
>><br>
>> Previously we only iterated over functions reachable from the set of<br>
>> external functions in the module. But since some of the passes under<br>
>> this (notably the always-inliner and coroutine lowerer) are required for<br>
>> correctness, they need to run over everything.<br>
>><br>
>> This just adds an extra layer of iteration over the CallGraph to keep<br>
>> track of which functions we've already visited and get the next batch of<br>
>> SCCs.<br>
>><br>
>> Should fix PR38029.<br>
>><br>
>> Modified:<br>
>>      llvm/trunk/include/llvm/ADT/SCCIterator.h<br>
>>      llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp<br>
>>      llvm/trunk/test/Transforms/Inline/always-inline.ll<br>
>><br>
>> Modified: llvm/trunk/include/llvm/ADT/SCCIterator.h<br>
>> URL: <br>
>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SCCIterator.h?rev=336419&r1=336418&r2=336419&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SCCIterator.h?rev=336419&r1=336418&r2=336419&view=diff</a> <br>
>><br>
>> ============================================================================== <br>
>><br>
>> --- llvm/trunk/include/llvm/ADT/SCCIterator.h (original)<br>
>> +++ llvm/trunk/include/llvm/ADT/SCCIterator.h Fri Jul  6 01:04:47 2018<br>
>> @@ -90,6 +90,7 @@ class scc_iterator : public iterator_fac<br>
>>     /// Compute the next SCC using the DFS traversal.<br>
>>     void GetNextSCC();<br>
>> +public:<br>
>>     scc_iterator(NodeRef entryN) : visitNum(0) {<br>
>>       DFSVisitOne(entryN);<br>
>>       GetNextSCC();<br>
>> @@ -98,12 +99,6 @@ class scc_iterator : public iterator_fac<br>
>>     /// End is when the DFS stack is empty.<br>
>>     scc_iterator() = default;<br>
>> -public:<br>
>> -  static scc_iterator begin(const GraphT &G) {<br>
>> -    return scc_iterator(GT::getEntryNode(G));<br>
>> -  }<br>
>> -  static scc_iterator end(const GraphT &) { return scc_iterator(); }<br>
>> -<br>
>>     /// Direct loop termination test which is more efficient than<br>
>>     /// comparison with \c end().<br>
>>     bool isAtEnd() const {<br>
>> @@ -222,16 +217,25 @@ bool scc_iterator<GraphT, GT>::hasLoop()<br>
>>       return false;<br>
>>     }<br>
>> -/// Construct the begin iterator for a deduced graph type T.<br>
>> +/// Construct the begin iterator for a deduced graph type T, starting <br>
>> from its<br>
>> +/// entry node.<br>
>>   template <class T> scc_iterator<T> scc_begin(const T &G) {<br>
>> -  return scc_iterator<T>::begin(G);<br>
>> +  return scc_iterator<T>(GraphTraits<T>::getEntryNode(G));<br>
>>   }<br>
>> -/// Construct the end iterator for a deduced graph type T.<br>
>> +/// Construct the begin iterator for a graph type T, starting from <br>
>> the specified<br>
>> +/// node.<br>
>> +template <class T, class U = GraphTraits<T>><br>
>> +scc_iterator<T, U> scc_begin(typename U::NodeRef N) {<br>
>> +  return scc_iterator<T>(N);<br>
>> +}<br>
>> +<br>
>> +  /// Construct the end iterator for a deduced graph type T.<br>
>>   template <class T> scc_iterator<T> scc_end(const T &G) {<br>
>> -  return scc_iterator<T>::end(G);<br>
>> +  return scc_iterator<T>();<br>
>>   }<br>
>> +<br>
>>   } // end namespace llvm<br>
>>   #endif // LLVM_ADT_SCCITERATOR_H<br>
>><br>
>> Modified: llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp<br>
>> URL: <br>
>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp?rev=336419&r1=336418&r2=336419&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp?rev=336419&r1=336418&r2=336419&view=diff</a> <br>
>><br>
>> ============================================================================== <br>
>><br>
>> --- llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp (original)<br>
>> +++ llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp Fri Jul  6 01:04:47 2018<br>
>> @@ -17,6 +17,7 @@<br>
>>   #include "llvm/Analysis/CallGraphSCCPass.h"<br>
>>   #include "llvm/ADT/DenseMap.h"<br>
>> +#include "llvm/ADT/DenseSet.h"<br>
>>   #include "llvm/ADT/SCCIterator.h"<br>
>>   #include "llvm/ADT/Statistic.h"<br>
>>   #include "llvm/Analysis/CallGraph.h"<br>
>> @@ -63,6 +64,10 @@ public:<br>
>>     /// whether any of the passes modifies the module, and if so, <br>
>> return true.<br>
>>     bool runOnModule(Module &M) override;<br>
>> +  /// Execute all of the passes scheduled for execution on a given <br>
>> SCC. Return<br>
>> +  /// true if any passes modify the module.<br>
>> +  bool runOnSCC(CallGraphSCC &SCC, CallGraph &CG);<br>
>> +<br>
>>     using ModulePass::doInitialization;<br>
>>     using ModulePass::doFinalization;<br>
>> @@ -448,51 +453,78 @@ bool CGPassManager::RunAllPassesOnSCC(Ca<br>
>>   bool CGPassManager::runOnModule(Module &M) {<br>
>>     CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();<br>
>>     bool Changed = doInitialization(CG);<br>
>> -<br>
>> -  // Walk the callgraph in bottom-up SCC order.<br>
>> -  scc_iterator<CallGraph*> CGI = scc_begin(&CG);<br>
>> -  CallGraphSCC CurSCC(CG, &CGI);<br>
>> -  while (!CGI.isAtEnd()) {<br>
>> -    // Copy the current SCC and increment past it so that the pass <br>
>> can hack<br>
>> -    // on the SCC if it wants to without invalidating our iterator.<br>
>> -    const std::vector<CallGraphNode *> &NodeVec = *CGI;<br>
>> -    CurSCC.initialize(NodeVec);<br>
>> -    ++CGI;<br>
>> -<br>
>> -    // At the top level, we run all the passes in this pass manager <br>
>> on the<br>
>> -    // functions in this SCC.  However, we support iterative <br>
>> compilation in the<br>
>> -    // case where a function pass devirtualizes a call to a <br>
>> function.  For<br>
>> -    // example, it is very common for a function pass (often GVN or <br>
>> instcombine)<br>
>> -    // to eliminate the addressing that feeds into a call.  With that <br>
>> improved<br>
>> -    // information, we would like the call to be an inline candidate, <br>
>> infer<br>
>> -    // mod-ref information etc.<br>
>> -    //<br>
>> -    // Because of this, we allow iteration up to a specified <br>
>> iteration count.<br>
>> -    // This only happens in the case of a devirtualized call, so we <br>
>> only burn<br>
>> -    // compile time in the case that we're making progress.  We also <br>
>> have a hard<br>
>> -    // iteration count limit in case there is crazy code.<br>
>> -    unsigned Iteration = 0;<br>
>> -    bool DevirtualizedCall = false;<br>
>> -    do {<br>
>> -      LLVM_DEBUG(if (Iteration) dbgs()<br>
>> -                 << "  SCCPASSMGR: Re-visiting SCC, iteration #" << <br>
>> Iteration<br>
>> -                 << '\n');<br>
>> -      DevirtualizedCall = false;<br>
>> -      Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall);<br>
>> -    } while (Iteration++ < MaxIterations && DevirtualizedCall);<br>
>> -<br>
>> -    if (DevirtualizedCall)<br>
>> -      LLVM_DEBUG(dbgs() << "  CGSCCPASSMGR: Stopped iteration after "<br>
>> -                        << Iteration<br>
>> -                        << " times, due to -max-cg-scc-iterations\n");<br>
>> +  DenseSet<const Function *> Visited;<br>
>> -    MaxSCCIterations.updateMax(Iteration);<br>
>> +  CallGraph::iterator INext;<br>
>> +  for (auto I = CG.begin(), E = CG.end(); I != E;) {<br>
>> +    // Walk the callgraph in bottom-up SCC order.<br>
>> +    auto CGI = scc_begin<CallGraph *>(I->second.get());<br>
>> +<br>
>> +    CallGraphSCC CurSCC(CG, &CGI);<br>
>> +    while (!CGI.isAtEnd()) {<br>
>> +      const std::vector<CallGraphNode *> &NodeVec = *CGI;<br>
>> +<br>
>> +      // Record that we've seen this set of functions so we don't run <br>
>> the pass<br>
>> +      // twice.<br>
>> +      for (auto *Elt : NodeVec)<br>
>> +        Visited.insert(Elt->getFunction());<br>
>> +<br>
>> +      // Copy the current SCC and increment past it so that the pass <br>
>> can hack<br>
>> +      // on the SCC if it wants to without invalidating our iterator.<br>
>> +      CurSCC.initialize(NodeVec);<br>
>> +      ++CGI;<br>
>> +<br>
>> +      // If we've got all functions reachable from our chosen initial <br>
>> node,<br>
>> +      // calculate the next node we need to search from now before <br>
>> parts of the<br>
>> +      // graph are invalidated.<br>
>> +      if (CGI.isAtEnd()) {<br>
>> +        do<br>
>> +          ++I;<br>
>> +        while (I != E && Visited.count(I->first));<br>
>> +      }<br>
>> +<br>
>> +      Changed |= runOnSCC(CurSCC, CG);<br>
>> +    }<br>
>>     }<br>
>> +<br>
>>     Changed |= doFinalization(CG);<br>
>>     return Changed;<br>
>>   }<br>
>> +bool CGPassManager::runOnSCC(CallGraphSCC &CurSCC, CallGraph &CG) {<br>
>> +  bool Changed = false;<br>
>> +<br>
>> +  // At the top level, we run all the passes in this pass manager on the<br>
>> +  // functions in this SCC.  However, we support iterative <br>
>> compilation in the<br>
>> +  // case where a function pass devirtualizes a call to a function.  For<br>
>> +  // example, it is very common for a function pass (often GVN or <br>
>> instcombine)<br>
>> +  // to eliminate the addressing that feeds into a call.  With that <br>
>> improved<br>
>> +  // information, we would like the call to be an inline candidate, <br>
>> infer<br>
>> +  // mod-ref information etc.<br>
>> +  //<br>
>> +  // Because of this, we allow iteration up to a specified iteration <br>
>> count.<br>
>> +  // This only happens in the case of a devirtualized call, so we <br>
>> only burn<br>
>> +  // compile time in the case that we're making progress.  We also <br>
>> have a hard<br>
>> +  // iteration count limit in case there is crazy code.<br>
>> +  unsigned Iteration = 0;<br>
>> +  bool DevirtualizedCall = false;<br>
>> +  do {<br>
>> +    LLVM_DEBUG(if (Iteration) dbgs()<br>
>> +               << "  SCCPASSMGR: Re-visiting SCC, iteration #" << <br>
>> Iteration<br>
>> +               << '\n');<br>
>> +    DevirtualizedCall = false;<br>
>> +    Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall);<br>
>> +  } while (Iteration++ < MaxIterations && DevirtualizedCall);<br>
>> +<br>
>> +  if (DevirtualizedCall)<br>
>> +    LLVM_DEBUG(dbgs() << "  CGSCCPASSMGR: Stopped iteration after " <br>
>> << Iteration<br>
>> +                      << " times, due to -max-cg-scc-iterations\n");<br>
>> +<br>
>> +  MaxSCCIterations.updateMax(Iteration);<br>
>> +  return Changed;<br>
>> +}<br>
>> +<br>
>>   /// Initialize CG<br>
>>   bool CGPassManager::doInitialization(CallGraph &CG) {<br>
>>     bool Changed = false;<br>
>><br>
>> Modified: llvm/trunk/test/Transforms/Inline/always-inline.ll<br>
>> URL: <br>
>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/always-inline.ll?rev=336419&r1=336418&r2=336419&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/always-inline.ll?rev=336419&r1=336418&r2=336419&view=diff</a> <br>
>><br>
>> ============================================================================== <br>
>><br>
>> --- llvm/trunk/test/Transforms/Inline/always-inline.ll (original)<br>
>> +++ llvm/trunk/test/Transforms/Inline/always-inline.ll Fri Jul  6 <br>
>> 01:04:47 2018<br>
>> @@ -316,3 +316,10 @@ define void @outer14() {<br>
>>     call void @inner14()<br>
>>     ret void<br>
>>   }<br>
>> +<br>
>> +define internal i32 @outer15() {<br>
>> +; CHECK-LABEL: @outer15<br>
>> +; CHECK: ret i32 1<br>
>> +  %res = call i32 @inner1()<br>
>> +  ret i32 %res<br>
>> +}<br>
>><br>
>><br>
>> _______________________________________________<br>
>> llvm-commits mailing list<br>
>> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
>><br>
> <br>
> <br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
> <br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>