Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: opcache JIT optimization >=2 [Windows cli] #18136

Open
nono303 opened this issue Mar 24, 2025 · 3 comments
Open

Bug: opcache JIT optimization >=2 [Windows cli] #18136

nono303 opened this issue Mar 24, 2025 · 3 comments

Comments

@nono303
Copy link
Contributor

nono303 commented Mar 24, 2025

Hi,
I'm facing a strange bug on a "simple" distance calculation (addition in a loop) with PHP cli & opcache JIT enabled.
with opcache.enable_cli = 1 and opcache.jit >= 1252 (optimization level between 2 and 5) at some time in the loop the addition (+=) give erratic results.

  • Only appears when using the phpGPX components.
    I've extracted the distance calculation function for standalone & callback tests with same data without any issue.
    So, might be related to namespace, object type or whatever...
  • The bug doesn't affect PHP cgi: tested with the same script, same data same php.ini... configuration without any issue.
  • I'm running on Windows, self-compiled PHP 8.4.5 TS vs17 x64

Here are "ready to test" files to reproduce it (like on linux)
⏩ Results:

opcache.enable_cli:0
  standalone: 9063.663059466
  phpGPX    : 9063.6630584286

opcache.enable_cli:1    opcache.jit:disable
  standalone: 9063.663059466
  phpGPX    : 9063.6630584286
opcache.enable_cli:1    opcache.jit:1251
  standalone: 9063.663059466
  phpGPX    : 9063.6630584286
opcache.enable_cli:1    opcache.jit:1252
  standalone: 9063.663059466
  phpGPX    : 1.369121694286
opcache.enable_cli:1    opcache.jit:1253
  standalone: 9063.663059466
  phpGPX    : 1.7499852968769
opcache.enable_cli:1    opcache.jit:1254
  standalone: 9063.663059466
  phpGPX    : 1.7499852968769
opcache.enable_cli:1    opcache.jit:1255
  standalone: 9063.663059466
  phpGPX    : 1.7499852968769

Adding a debug line to DistanceCalculator.php

diff --git "a/src/phpGPX/Helpers/DistanceCalculator.php" "b/src/phpGPX/Helpers/DistanceCalculator.php"
index 5a2a51b..d2df82e 100644
--- "a/src/phpGPX/Helpers/DistanceCalculator.php"
+++ "b/src/phpGPX/Helpers/DistanceCalculator.php"
@@ -77,6 +77,8 @@ class DistanceCalculator
 			else {
 				$distance += $curPoint->difference;
 				$lastConsideredPoint = $curPoint;
+				if($p >= 120 && $p <= 130)
+					echo "it:".$p." last:".$ld." cur:".$distance." add:".$curPoint->difference.PHP_EOL;
 			}
 
 			$curPoint->distance = $distance;

results, failing @ iteration 128:

opcache.enable_cli:1 opcache.jit:1254
it:120 last:565.12951886607 cur:568.91636386652 add:3.7868450004519
it:121 last:568.91636386652 cur:574.28152730666 add:5.3651634401381
it:122 last:574.28152730666 cur:578.88597767002 add:4.604450363368
it:123 last:578.88597767002 cur:583.43520379413 add:4.5492261241002
it:124 last:583.43520379413 cur:587.74462875461 add:4.3094249604809
it:125 last:587.74462875461 cur:594.67011966358 add:6.9254909089751
it:126 last:594.67011966358 cur:598.5481926842 add:3.8780730206198
it:127 last:598.5481926842 cur:601.6696032882 add:3.1214106039962
it:128 last:0.51993194404748 cur:2.8028430036349 add:2.2829110595874
it:129 last:0.51993220497079 cur:5.3492195083835 add:4.8292873034127
it:130 last:0.51993241619443 cur:4.6919392250549 add:4.1720068088605

opcache.enable_cli:0
it:120 last:565.12951886607 cur:568.91636386652 add:3.7868450004519
it:121 last:568.91636386652 cur:574.28152730666 add:5.3651634401381
it:122 last:574.28152730666 cur:578.88597767002 add:4.604450363368
it:123 last:578.88597767002 cur:583.43520379413 add:4.5492261241002
it:124 last:583.43520379413 cur:587.74462875461 add:4.3094249604809
it:125 last:587.74462875461 cur:594.67011966358 add:6.9254909089751
it:126 last:594.67011966358 cur:598.5481926842 add:3.8780730206198
it:127 last:598.5481926842 cur:601.6696032882 add:3.1214106039962
it:128 last:601.6696032882 cur:603.95251434778 add:2.2829110595874
it:129 last:603.95251434778 cur:608.7818016512 add:4.8292873034127
it:130 last:608.7818016512 cur:612.95380846006 add:4.1720068088605

Available to perform further tests and provide details if needed

PHP Version

PHP 8.4.5 TS vs17 x64

Operating System

Windows 11 x64

@nielsdos
Copy link
Member

I get an assertion failure on 8.4.5 on Windows+JIT (when built in debug mode):
Assertion failed: _blocks[use] == b || use_insn->op == IR_PARAM, file ext\opcache\jit\ir\ir_gcm.c, line 948
On PHP-8.4 git HEAD I no longer get the assertion failure but I do get the wrong result on Windows+JIT.
I'll have a look a bit later

@nielsdos
Copy link
Member

nielsdos commented Mar 24, 2025

Reduced to a standalone reproducer:

<?php
namespace Foo;

function diff($point1, $point2)
{
	$a = deg2rad($point1); // Prefixing these with \ also makes the issue go away
	$b = deg2rad($point2);
	return $a - $b;
}

function getRawDistance()
{
	$distance = 0;
	for ($p = 0; $p < 200; $p++) {
		// Needs to be a namespaced call_user_func call to reproduce the issue (i.e. adding \ at front makes the issue go away)
		$distance += call_user_func('Foo\diff', 0, $p);
	}

	return $distance;
}

var_dump(getRawDistance());

@nielsdos
Copy link
Member

nielsdos commented Mar 24, 2025

The above reproducer outputs float(-3.473205211468716) but it should output float(-347.3205211468715). Can only reproduce it on Windows, not on Linux. Run with -d opcache.jit=tracing. Not sure where to start looking and I don't have a capstone package on Windows to look at the disassembly... cc @dstogov
EDIT: it's as if instead of addition to $distance, it assigns to $distance. The result of $distance is always equal to the result of the last call to Foo\diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants