We found that in a special condition, the input callee Samples is null for findExternalInlineCandidate, which caused an ICE.
In some rare cases, call instruction could be changed after being pushed into inline candidate queue, this is because earlier inlining may expose constant propagation which can change indirect call to direct call. When this happens, we may fail to find matching function samples for the candidate later(for example if the profile is stale), even if a match was found when the candidate was enqueued.
See this reduced program:
file1.c:
int bar(int x); int(*foo())() { return bar; }; void func() { int (*fptr)(int); fptr = foo(); a += (*fptr)(10); }
file2.c:
int bar(int x) { return x + 1;}
The two CALL: foo and (*ptr) are pushed into the queue at the beginning, say foo is hotter and popped first for inlining. During the inlining of foo, it performs the constant propagation for the function pointer bar and then changed (*ptr) to a direct call bar(..). Note that at this time, (*ptr)/bar is still in the queue, later while it's popped out for inlining, it use the a different target name(bar) to look for the callee samples. At the same time, if the profile is stale and the new function is different from the old function in the profile, then this led the return of the null callee sample.
typo: Replayed