<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [SPGO] Crash when the sample profile loader promotes an indirect call"
   href="https://bugs.llvm.org/show_bug.cgi?id=34383">34383</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[SPGO] Crash when the sample profile loader promotes an indirect call
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>rob.lougher@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Compiling the following program and profile results in a crash:

========== test.c ================
float foo(int i) { return 5; }

int bar(int (*f)(int)) {
  return (*f)(5);
}
==================================

====== prof.txt ======
bar:1:1
 1: foo:1
======================

$ clang -O2 -fprofile-sample-use=prof.txt test.c

#0 0x0000000003facc75 llvm::sys::PrintStackTrace(llvm::raw_ostream&)
/llvm/lib/Support/Unix/Signals.inc:398:0
#1 0x0000000003facd08 PrintStackTraceSignalHandler(void*)
/llvm/lib/Support/Unix/Signals.inc:462:0
#2 0x0000000003faaf4f llvm::sys::RunSignalHandlers()
/llvm/lib/Support/Signals.cpp:49:0
#3 0x0000000003fac4ea SignalHandler(int)
/llvm/lib/Support/Unix/Signals.inc:252:0
#4 0x00007f34458a9390 __restore_rt
(/lib/x86_64-linux-gnu/libpthread.so.0+0x11390)
#5 0x0000000001eeecfe llvm::Instruction::getParent()
/llvm/include/llvm/IR/Instruction.h:67:0
#6 0x0000000003ffca3f llvm::InlineFunction(llvm::CallSite,
llvm::InlineFunctionInfo&, llvm::AAResults*, bool)
/llvm/lib/Transforms/Utils/InlineFunction.cpp:1460:0
#7 0x00000000039d471d (anonymous
namespace)::SampleProfileLoader::inlineHotFunctions(llvm::Function&,
llvm::DenseSet<unsigned long, llvm::DenseMapInfo<unsigned long> >&)
/llvm/lib/Transforms/IPO/SampleProfile.cpp:748:0
#8 0x00000000039d762a (anonymous
namespace)::SampleProfileLoader::emitAnnotations(llvm::Function&)
/llvm/lib/Transforms/IPO/SampleProfile.cpp:1362:0
#9 0x00000000039d8731 (anonymous
namespace)::SampleProfileLoader::runOnFunction(llvm::Function&,
llvm::AnalysisManager<llvm::Module>*) /llvm/lib/Transforms/IPO/SampleProfil
e.cpp:1500:0
...

The problem occurs within the sample profile loader.  When it sees an indirect
call it tries to promote it using the call targets from the sample data. This
involves creating a direct and an indirect call path guarded with a target
check.  After promoting the call it then inlines the direct function call in
order to apply the sample.

According to the sample profile the indirect call target was the function
foo().  The call is promoted as follows:

== Basic Block Before ==

entry:
  %call = call i32 %f(i32 5), !dbg !9
  ret i32 %call, !dbg !10


== Basic Blocks After ==

entry:
  %0 = bitcast i32 (i32)* %f to i8*, !dbg !9
  %1 = icmp eq i8* %0, bitcast (float (i32)* @foo to i8*), !dbg !9
  br i1 %1, label %if.true.direct_targ, label %if.false.orig_indirect, !dbg !9,
!prof !10

if.true.direct_targ:                              ; preds = %entry
  %2 = call float @foo(i32 5), !dbg !9
  %3 = bitcast float %2 to i32
  br label %if.end.icp, !dbg !9

if.false.orig_indirect:                           ; preds = %entry
  %call = call i32 %f(i32 5), !dbg !9
  br label %if.end.icp, !dbg !9

if.end.icp:                                       ; preds =
%if.false.orig_indirect, %if.true.direct_targ
  %4 = phi i32 [ %call, %if.false.orig_indirect ], [ %3, %if.true.direct_targ ]
  ret i32 %4, !dbg !11
==========================

Note the direct call path (if.true.direct_targ) has a direct call to foo().

What causes the crash is the mismatch in return types between the indirect call
and foo().  Normally, the utility function that promoted the call
(promoteIndirectCall) returns a reference to the direct call instruction. 
However, the return type mismatch has caused a cast to be inserted from
float->int, and promoteIndirectCall() instead returns a reference to the cast.

A later change in r294205 modified the code so that any pointer casts were
skipped (via stripPointerCasts).  However, in this case we have a non-pointer
cast which is not skipped, and we end up trying to inline a cast instruction...

So how did we end up with a return type mismatch?  The example was manually
constructed from scratch after investigating a real-life crash.  It could
theoretically occur due to profile corruption or use of an out-of-date profile.
 However, in this case, the crash occured in the following circumstances:

1) a source line contained two calls (one indirect and one direct)
2) the sampled binary was compiled with -g only (i.e. without
-fdebug-info-for-profiling)
3) "by luck" the sample didn't capture any targets for the indirect call, only
for the direct call.

As the program was compiled without -fdebug-info-for-profiling no
discriminators were present.  This meant the sample for the direct call matched
when the sample loader looked for the indirect call targets, resulting in a
wrong function being found.

A less than ideal fix for the problem would be to abandon inlining of the
function if after skipping pointer casts we did not have a call instruction. 
This is less than ideal because we would still have promoted the indirect call
to a wrong function.  However, it is benign as the target guard means the
indirect path will always be taken.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>