Daniele Cono D'Elia edited case-study.tex  over 8 years ago

Commit id: f1c338c52b1bca74be1a85283a8fa6407852e80d

deletions | additions      

       

The source code of McVM is publicly available~\cite{mcvm}; after porting it from the LLVM legacy JIT to MCJIT, we have extended it with the following components to enable the optimization of \feval\ instructions:  \begin{enumerate}  \item An analysis pass to identify optimization opportunities for \feval\ instructions in the IIRrepresentation  of a function \item An extension for the IIR compiler to track the correspondence between IIR and IR objects at \feval\ sites  \item An inserter component to insert OSR points in the IR for IIR locations annotated during the analysis pass  \item An optimizer module triggered at OSR points, which in turn is made of: 

The analysis pass is also able to determine whether the value of the argument can change across two executions of the same \feval\ instruction, thus discriminating when a run-time guard must be inserted during the run-time optimization phase. Compared to the OSR-based approach by Lameed and Hendren, our solution is cheaper because the types for the other arguments do not need to be cached or guarded: as we will see later on, the type inference engine will compute the most accurate yet sound type information in the analysis of the optimized IIR where direct calls are used.  When the IIR compiler processes an annotated \feval\ instruction, it will store stores  in the metadata of the function version being compiled a copy of its the current  variable map (i.e., a map between IIR and IR objects), thecurrent  {\tt llvm::BasicBlock*} created for the call \feval\  and the {\tt llvm::Value*} object corresponding to the first argument for the \feval. The last two objects are used by the inserter component as source label and profiling value {\tt val} argument  for inserting an open OSR point, with the copy of the variable map being passed (along with other information) as {\tt extra} field. point.  The open-OSR stub will in turn invoke the callback optimizer component we are about to describe in the next subsection. present.  \subsection{Generating Optimized Code}  The core of our optimization pipeline is thecallback  optimizer component, module  that is responsible for generating optimized code for the current function $f$ usingprofiling (i.e.,  the object containing run-time value of  the first argument for \feval) \feval  and contextual information passed from the open-OSR stub. As a first step, the optimizer will process the profiling object inspects {\tt val}  to resolve the target of the call - which we call $g$ - and check whether a previously compiled optimized function is available from the code cache. If not, a new function $f_{opt}$ is generated by cloning the IIR representation $f^{IIR}$ of $f$ into $f^{IIR}_{opt}$ and replacing all the \feval\ calls in the same group of the instrumented one with direct calls to $g$.  As a next step, the optimizer asks the IIR compiler to analyze $f^{IIR}_{opt}$ and generate optimized LLVM IR $f^{IR}_{opt}$, also making a copy of the variable map between IIR and IR objects when compiling the direct call corresponding to the \feval\ instruction that triggered the OSR.