rfc:jit-ir

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
rfc:jit-ir [2023/09/20 09:36] – created dmitryrfc:jit-ir [2023/10/24 09:43] (current) – Updated "Implemenetation" section dmitry
Line 1: Line 1:
 ====== PHP RFC: A new JIT implementation based on IR Framework ====== ====== PHP RFC: A new JIT implementation based on IR Framework ======
-  * Version: 0.9+  * Version: 1.0
   * Date: 2023-09-20   * Date: 2023-09-20
   * Author: Dmitry Stogov, dmitry@php.net   * Author: Dmitry Stogov, dmitry@php.net
-  * Status: Draft (or Under Discussion or Accepted or Declined)+  * Status: Accepted
   * First Published at: http://wiki.php.net/rfc/php-ir   * First Published at: http://wiki.php.net/rfc/php-ir
  
 ===== Introduction ===== ===== Introduction =====
-The first version of JIT for PHP was released in PHP-8.0 (https://wiki.php.net/rfc/jit). That time we took a quite simple approach. We are generating native code directly from Zend VM bytecode. This approach allowed to deliver JIT in a quite short time, but it also made significant limitation in possible optimizations. Smart optimizations require more formal and detailed **Intermediate Representation** (IR). The later introduction of AArch64 JIT back-end in PHP-8.1, made the maintenance of JIT a bit more complex, because now we often had to update assembler code in two back-ends.+The first version of JIT for PHP was released in PHP-8.0 (https://wiki.php.net/rfc/jit). That time we took a quite simple approach. We are generating native code directly from Zend VM byte code. This approach allowed to deliver JIT in a quite short time, but it also created significant limitations in possible optimizations. Smart optimizations require more formal and detailed **Intermediate Representation** (IR). The introduction of the AArch64 JIT back-end in PHP-8.1, made the maintenance of JIT a bit more complex, because now we often have to update assembler code in two back-ends.
    
-A smarter JIT compiler with some Intermediate Representation was planned for a long time. The real work was started in January 2022. +A smarter JIT compiler with some Intermediate Representation was planned a long time. The real work was started in January 2022. 
-This proposal is the result of that 1.75 years work.+This proposal is the result of these 1.75 years of work.
    
 ===== Proposal ===== ===== Proposal =====
-I propose a new JIT implementation that is based on a separately developed [[https://github.com/dstogov/ir|IR Framework]]  +I propose a new JIT implementation that is based on a separately developed [[https://github.com/dstogov/ir|IR Framework]].
  
 Instead of separate back-ends that generated x86 and AArch64 code, now we have a single back-end that constructs IR. Instead of separate back-ends that generated x86 and AArch64 code, now we have a single back-end that constructs IR.
-Then this IR is passed to the Framework that performs machine independent optimisations, register allocation, scheduling and native code generation. The new back-end doesn't have to care about many old low-level details, e.g. register assignment, different calling conventions, etc. On the other hand, sometimes the construction of IR may be more complex because all the dependencies must be consistently reflected, but this helps to find many errors during formal IR verification. 
  
-New JIT implementation will affect only a few core PHP developers who are involved in the JIT development or maintenance. +This IR is passed to the framework that performsmachine independent optimizationsregister allocation, scheduling, and native code generationThe new back-end doesn'have to care about many old low-level details, e.g.: register assignment, different calling conventions, etc.
-JIT is a self-containing subsystem and the changes in the implementation details (even big changes) don't affect others. +
-You may see that the proposed [[https://github.com/php/php-src/pull/12079|patch]] almost doesn't make changes outside **ext/opcache/jit**it also very carefully adds new IR related code into **zend_jit.c** and **zend_jit_trace.c** keeping the ability to work with old and new back-ends. At the current state the PR doesn'remove the sources of the old JIT implementation. It's possible to switch to the old implementation by configuring PHP with **--disable-opcache-jit-ir**.+
  
-JIT is a quite complex subsystem. It can come without bugs, but I hope everything will be fixed. The early we merge this, the more time we have until the release.+On the other handsometimes the construction of IR may be more complex because all the dependencies must be consistently reflected. This helps to find many errors during formal IR verification.
  
-The main goal of separate IR Framework development is the collaboration with other compiler experts (sharing expertise, contribution, etc). The necessary part of the IR Framework is embedded into php source tree anyway, so this won't introduce any new external dependencies.+The new JIT implementation will affect only a few core PHP developers who are involved in the JIT development or maintenance.
  
-I won'explain the internals of the IR Framework here. I'll publish a related presentation soon. The preview is already shared with some of the core PHP developers     +JIT is a self-contained subsystem, and the changes in the implementation details (even big changes) don'affect others. 
 + 
 +The proposed [[https://github.com/php/php-src/pull/12079|patch]] makes few changes outside **ext/opcache/jit**. It also very carefully adds new IR related code into **zend_jit.c** and **zend_jit_trace.c**, keeping the ability to work with old and new back-ends. 
 + 
 +At the current state the PR doesn't remove the sources of the old JIT implementation. It is possible to switch to the old implementation by configuring PHP with **--disable-opcache-jit-ir**. 
 + 
 +JIT is a quite complex subsystem. Its first implementation will likely have bugs, but I am confident that these can be addressed. We have more time to fix potential issues, the sooner this proposal passes, and the patch is merged. 
 + 
 +The main goal of a separate IR Framework development is the collaboration with other compiler experts (sharing expertise, contribution, etc.). I'm doing my best to make the IR project interesting outside the PHP world and involve others. In case of success, this will reduce the PHP "bus-factor". 
 + 
 +The necessary part of the IR Framework is embedded into the PHP source tree, and won't introduce any new external dependencies. 
 + 
 +The details of the IR framework are complex. This [[https://www.researchgate.net/publication/374470404_IR_JIT_Framework_a_base_for_the_next_generation_JIT_for_PHP|presentation]] explains design ideas and makes overview of the most important implementaion details.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
-There is no any BC breaks.+ 
 +There are no BC breaks in regard to user land PHP code.
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
 +
 next (master branch) next (master branch)
  
Line 37: Line 48:
  
 ==== Performance ==== ==== Performance ====
-In the current state the new PHP JIT implements exactly the same set of PHP related features and optimizations as the old one. 
-Anyway, because of IR Framework optimizations and smarter Register Allocator, new JIT produces a bit faster (5-10%) and smaller code. 
-This is visible on **bench.php** and **micro_bench.php**. Speed of the real-life applications is not affected. 
  
-Compilation speed of Tracing JIT is almost the same, function JIT compilation speed shows up to 4 times slowdown (tested on Wordpress). +The current new PHP JIT implements exactly the same set of PHP related features and optimizations as the old one. 
-Anyway, this is quite good result for an Optimizing JIT compiler. In my tests PHP with new JIT may produce ~15MB of native code per second.   + 
 +Because the IR Framework provides more optimizations and has a smarter Register Allocator, the JIT produces a bit faster (5-10%) and smaller code. 
 + 
 +This is visible with **bench.php** and **micro_bench.php**. The speed of the real-life applications is not affected. 
 + 
 +The compilation speed of the Tracing JIT is almost the same. The compilation speed of the Function JIT is up to 4 times slower (tested on Wordpress). 
 + 
 +This is quite good result for an Optimizing JIT compiler. In my testsPHP with the new JIT may produce ~15MB of native code per second.   
  
 ==== Zend VM ==== ==== Zend VM ====
-On JIT supported platforms (x86, x86_64, AArch64) HYBRID VM interpreter starts to save and restore all the persistent CPU registers at **execute_ex()** prologue and epilogue. This allows elimination of the similar save/restore code in each JIT-ed function or trace. CLANG and MSVC builds that use CALL VM are not affected+ 
 +On JIT supported platforms (x86, x86_64, AArch64), the HYBRID VM interpreter starts to save and restore all the persistent CPU registers at **execute_ex()** prologue and epilogue. 
 + 
 +This allows elimination of the similar save/restore code in each JIT-ed function or trace. CLANG and MSVC builds that use CALL VM are not impacted
  
 ==== To Opcache ==== ==== To Opcache ====
-JIT is implemented as a part of opcache, so the PR changes the build process for opcache+ 
-Nothing else is affected.+JIT is implemented as a part of Opcache, so the PR changes the build process for Opcache
 +No other changes are present.
  
 ==== php.ini Defaults ==== ==== php.ini Defaults ====
-The PR doesn'introduce new php.ini detectives or change any default values. + 
-It adds few new IR related JIT debugging capabilities that may be enabled through **opcache.jit_debug** directive bits.+The PR does not introduce new php.ini detectives or changes any default values. 
 + 
 +It adds few new IR related JIT debugging capabilities that may be enabled through **opcache.jit_debug** directive bits:
  
   * 0x01000000 - print the initial IR graph right after construction    * 0x01000000 - print the initial IR graph right after construction 
-  * 0x02000000 - print the final IR graph right before code emmision+  * 0x02000000 - print the final IR graph right before code emission
   * 0x04000000 - print Control Flow Graph   * 0x04000000 - print Control Flow Graph
   * 0x08000000 - print information about Live Ranges and Allocated Registers   * 0x08000000 - print information about Live Ranges and Allocated Registers
   * 0x10000000 - print IR graph after Sparse Conditional Constants Propagation pass   * 0x10000000 - print IR graph after Sparse Conditional Constants Propagation pass
-  * 0x20000000 - print IR graph after Global Code Motion and linearisation pass+  * 0x20000000 - print IR graph after Global Code Motion and linearization pass
   * 0x40000000 - print IR graph after Register Allocation pass   * 0x40000000 - print IR graph after Register Allocation pass
-  * 0x80000000 - anotate IR graph with information about CFG, Regisers and Code Generation rules+  * 0x80000000 - annotate IR graph with information about CFG, Registers and Code Generation rules
  
 ==== To SAPIs ==== ==== To SAPIs ====
 +
 SAPIs are not affected. SAPIs are not affected.
  
 ==== To Existing Extensions ==== ==== To Existing Extensions ====
 +
 PHP extensions are not affected. PHP extensions are not affected.
    
 ==== New Constants ==== ==== New Constants ====
 +
 There are no new constants. There are no new constants.
  
 ===== Open Issues ===== ===== Open Issues =====
-Should we keep the old implementation of the JIT for a while?+ 
 +Should we keep the old implementation of the JIT for a while, or change the patch to replace it straight away?
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
-JIT is developed as a self-contained feature and it doesn't affect anything else directly.+ 
 +JIT is developed as a self-contained featureand doesn't affect anything else directly.
  
 ===== Future Scope ===== ===== Future Scope =====
-Usage of IR opens the door for more powerful optimizations. Part of them are going to be PHP independent (e.g. planned introduction of new loop optimization passes, improvement in LOAD/STORE motion and redundancy, improvement in code generator). The other part is PHP specific (e.g. we now may extend CPU register usage for more instructions). It'also possible to support new JIT tagets (e.g. RISCV) almost independently from PHP.+ 
 +The usage of IR opens the door for more powerful optimizations. Some of these are going to be PHP independent (e.g.): the planned 
 +introduction of new loop optimization passes, improvement in LOAD/STORE motion and redundancy, improvements to the code generator. 
 + 
 +The other part is PHP specific (for example, we can extend CPU register usage for more instructions). 
 + 
 +It is also possible to support new JIT targets (e.g. RISCV)almost independently of PHP
 + 
 +Finally, we may try to completely avoid the manual IR construction in JIT. We may introduce a single formal specification for VM instructions in a C-like language, convert it to IR and then use partial evaluation to generate VM and JIT handlers (similar to Truffle)
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
-Merge the new JIT implementation into PHP master?+ 
 +Voting opened 2023-10-06 and closes 2023-10-19. 
 + 
 +<doodle title="Merge the new JIT implementation into PHP master?" auth="user" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle> 
 + 
 + 
 +Secondary vote: Should we keep the old JIT implementation for a while or remove it right after merge? 
 + 
 +Note, that old implementation is not going to be tested (by CI) and we can't guarantee its work anyway. 
 + 
 +<doodle title="Remove the old JIT implementation right after merging the new one?" auth="user" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle> 
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
 +
   - https://github.com/php/php-src/pull/12079   - https://github.com/php/php-src/pull/12079
-  - All CI tests (including nightly workflow) were passed: https://github.com/dstogov/php-src/actions/runs/6123676012/job/16638279521 +  - All CI tests (including nightly workflow) passed: https://github.com/dstogov/php-src/actions/runs/6123676012/job/16638279521 
  
 ===== Implementation ===== ===== Implementation =====
-After the project is implemented, this section should contain  + 
-  the version(s) it was merged into +   - merged into master via 25cb2a40d640b64f8881a894f2247d46a781ef75 
-  a link to the git commit(s) +   old JIT implementation is removed via be275433d936e41d95b2fd656464bcc4d7138b76
-  - a link to the PHP manual entry for the feature +
-  - a link to the language specification section (if any)+
  
 ===== References ===== ===== References =====
-https://github.com/dstogov/ir 
  
-===== Rejected Features ===== +https://github.com/dstogov/ir
-Keep this updated with features that were discussed on the mail lists.+
  
rfc/jit-ir.1695202597.txt.gz · Last modified: 2023/09/20 09:36 by dmitry