[llvm-dev] Higher level program analysis

preejackie via llvm-dev llvm-dev at lists.llvm.org
Fri Mar 29 09:02:51 PDT 2019


Hi Bekket, Please see the comment inline..

On 29/03/19 3:58 AM, Bekket McClane wrote:
> Hi,
>
> David:
> Good point, it will be interesting to see speculative compilation in 
> this context applying on devirtualization, with high level (type) 
> information if applicable.
>
>> On Mar 28, 2019, at 2:35 PM, preejackie <praveenvelliengiri at gmail.com 
>> <mailto:praveenvelliengiri at gmail.com>> wrote:
>>
>> Hi David & Bekket,
>>
>> Thanks your replies :)
>>
>> David, Indent here is: ORC v2 JIT APIs has initial(basic) support for 
>> concurrent compilation in background compile threads. This means we 
>> can speculatively compile functions before they are even referenced 
>> by the clients. In future, if the client refer some function and if 
>> that function is already compiled speculatively we can just return 
>> the address of function, if this is correctly done we can reduce the 
>> JIT compilation latencies. IMO, the possible candidates to 
>> speculate(functions) are those which will be executed next. We can 
>> use *program analysis and dynamic profiling* to find such functions.
>>
>> Three possible approaches are possible:
>>
>>  1. Based, on analysis from call graphs select functions to compile
>>     speculatively with less aggressive optimization flags in
>>     background dedicated compiler threads.
>>  2. Since it is a JIT, with the help of dynamic profiling we can find
>>     frequently executed functions and *re*compile them with more
>>     aggressive optimization in compile thread.
>>  3. With Profile-guide optimization results of previous executions,
>>     we can find function that are likely to compile next then
>>     *compile it with aggressive optimization. *[PGOs are app dependent]
>>
>> for cases 1,2: profile guide optimization results are not used. I 
>> hope these techniques collectively improve program execution time in 
>> long-time. Of course, program-based prediction is not equal to the 
>> accuracy of profile-based prediction, but in JIT it is useful to 
>> first compile function speculatively by using multiple threads.
>>
> I’m a little bit lost, from what I’m understanding, you’re arguing 
> that with the profiling data (collected from runtime), we can make 
> more precise prediction about callee candidates executed next. But in 
> the baseline(i.e. first-time execution) stage, these profile data 
> doesn’t exist, thus you want improve the prediction at that stage with 
> the help of some static analysis.
> Am I understanding correctly?

Not exactly, My thought is to make speculative compilation available for 
both non-PGO & PGO cases.

|--------------------------------------------------------------------------------------------|

   | llvm-IR   ----> ORC ----> Codegen + link ---> raw executable bits| 
        -----> Non-PGO case

    ORC uses program analysis information to guess functions to *compile 
*next.

|--------------------------------------------------------------------------------------------|


|--------------------------------------------------------------------------------------------------|

| llvm-IR    -----> ORC ----> Codegen + link -----> raw executable bits  
|    ----> PGO case.

   ORC uses the profile data to find functions to compile next + 
optimize hot functions aggressively.

|--------------------------------------------------------------------------------------------------| 


By this, we can't force JIT clients to use PGO, to get benefits of 
speculative compilation.

>> I have considered CFG as a higher level program representation, I 
>> maybe wrong here.
>>
>> For example:
>>
>> |void f2() {}
>> |
>>
>> |void f3() {}|
>>
>> |void  z(){|
>>
>> |if(/some condition/)
>> |
>>
>> | f2();f3();|
>>
>> |else
>> |
>>
>> |fn();|
>>
>> |}
>> |
>>
>> Follow the control flow of z and compute probability that one of the 
>> paths[entry to exit] within the z that lead to a call f2, if the call 
>> to f2 occurs in many paths, then the probability that it will execute 
>> next is high. It will require some control flow analysis.
>>
> Following my comment above, I think you have some misunderstandings on 
> the power of static analysis in LLVM: LLVM of course can eliminate 
> some trivial control flow structure like
> if(true) {
>  // do something
> }
> Or
> if(1 + 2 < 6)
> For these cases, you don’t even need to analyze the probability of 
> those branches, cause LLVM will just eliminate and optimize the entire 
> control structures.
>
> But other than that, it’s really hard for LLVM to evaluate the 
> probability of certain branches statically without help from (dynamic) 
> data like profiling data or certain programmer’s annotations like 
> __builtin_expect.
> The closest analysis I can come up with are probably LazyValueInfo and 
> ScalarEvolution. You can see if they fit your need.
>
Are you suggesting that static analysis is much inferior than profiling 
in finding "next executing function" ?  I'm stuck at deciding which one 
to prefer & implement during this summer project, Could you please help me?

Also if I choose to do PGO stuff with ORC, Can I able to use most of PGO 
code available for AOT with the JIT. Is there any downsides to it?


> Best,
> Bekket
>>
>> Challenges:
>>
>>  1.    To incorporate speculation in ORC v2.
>>  2.    Making speculative decisions faster, hence I decide to use
>>     simple heuristics.
>>
>> If you need more information / or feeling I'm missing something, 
>> Please leave a reply :)
>>
>> On 29/03/19 12:27 AM, David Greene wrote:
>>> Devirtualization is an example of predicting calls and is much more
>>> easily done on a higher-level representation.  It is simply easier to
>>> reason about certain things given information that is lost during
>>> translation to LLVM IR.  The MLIR project makes similar arguments.
>>>
>>> It would be helpful to know what's being attempted here.  I'm not sure
>>> what the (hardware?) branch predictor has to do with making decisions
>>> based compile-time information, unless some kind of PGO is being used.
>>> I could imagine something that takes branch probabilities and guesses
>>> the most likely path through a function, thus predicting certain calls
>>> will happen over others.
>>>
>>>                      -David
>>>
>>> Bekket McClane via llvm-dev<llvm-dev at lists.llvm.org>  writes:
>>>
>>>> Hi PreeJackie,
>>>>
>>>> I still have difficulties associating ‘higher level program analysis’ with the possible candidate functions that will be executed next.
>>>> Call graph will definitely be your tools(and actually it’s usually not considered ‘high level’), and function attributes might help. But AFAIC, there is little ‘high level’
>>>> language constructions that can help us determinate the possible functions executed next.
>>>> Maybe you can give us some examples?
>>>>
>>>> Best,
>>>> Bekket
>>>>
>>>>   On Mar 27, 2019, at 8:55 PM, preejackie via llvm-dev<llvm-dev at lists.llvm.org>  wrote:
>>>>
>>>>   Hi all,
>>>>
>>>>   I'm looking for some program analysis techniques which help me to find potential functions to execute next, from the current executing function. I want to
>>>>   decision based on compile time information. I consider LLVM IR is too low-level to make such analysis. So, I using call graph representation of module. I
>>>>   figured out the probability of function which execute next based on the branch predictor, Call instruction distance from the entry of function. I believe that
>>>>   many attributes can be derived from higher level program representation. Is there any similar work done like this? LLVM already support analysis for this?
>> -- 
>> Have a great day!
>> PreeJackie
>
-- 
Have a great day!
PreeJackie

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190329/a55f486d/attachment.html>


More information about the llvm-dev mailing list