Skip to content

Incorrect arithmetic calculations when using JIT (2) #10271

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

Closed
GajowyJ opened this issue Jan 9, 2023 · 5 comments
Closed

Incorrect arithmetic calculations when using JIT (2) #10271

GajowyJ opened this issue Jan 9, 2023 · 5 comments

Comments

@GajowyJ
Copy link

GajowyJ commented Jan 9, 2023

Description

EDIT: The test to reproduce the issue is in the comment below: #10271 (comment)

This bug is the same as #10195. The previous ticket was closed because it has not been confirmed in 8.1.13 (by my mistake - zend extenstion not configured correctlyin php.ini). After repeating with the correct setting, the issue appeared.

Additional informations: tests showed that the value of $sol['xc'] and $sol['yc'] variables in line 6 and 7 below behave as they were both equal =1 (and in fact are not!).

1 function Tangential2XY($tang,$sol)
2 {
3	$x = $sol['X']['k']*$tang['KSI'] + $sol['X']['e']*$tang['ETA'] + $sol['X'][1];
4	$y = $sol['Y']['k']*$tang['KSI'] + $sol['Y']['e']*$tang['ETA'] + $sol['Y'][1];
5	printf("In;%.12f;%.12f;%.12f;%.12f;",$x,$y,$sol['xc'],$sol['yc']);
6	$x = $sol['xc']*($x+1);
7	$y = $sol['yc']*($y+1);
8	printf("Out;%.12f;%.12f\n",$x,$y);
9	return ['x'=>$x,'y'=>$y];
10 }

The above code produces when JIT enabled:
In;0.005909845561;0.003134992878;968.000000000000;548.000000000000;Out;1.005909845561;1.003134992878

...and when JIT disabled (correct values):
In;0.005909845561;0.003134992878;968.000000000000;548.000000000000;Out;973.720730502727;549.717976097410

It is important to mention that sometimes the same function works correctly, however it's not random - the problem appears exactly in the same place of code execution. From other hand skipping part of the unrelated code causes the problem appears in another place or doesn't appear at all.

PHP Version

PHP 8.1.13

Operating System

Windows 10

@hormus
Copy link

hormus commented Jan 9, 2023

it seems that it is not possible to make more expressions.

function test() {
$num = 0.005909845561;
$num = ($num) + (1);
if(2.0 > $num && $num > 1.0) {
echo 'ok' . PHP_EOL;
}
printf('%0.12F', $num);
// 973.720730503048
return (968.000000000000) * ($num);
}
ini_set('precision', -1);
ini_set('serialize_precision', -1);
var_dump(test());

?>

@GajowyJ
Copy link
Author

GajowyJ commented Jan 10, 2023

@hormus Is there any setting that can increase the number of expressions that can be executed? I am determined to help fix this bug as it undermines my calculations.

I tested behaviour when changing following configuration parameters, with no effect on result (eg. problem still exists):

opcache.jit_buffer_size (values tested: 256M,512M)
opcache.memory_consumption (128,256M,512M)
opcache.interned_strings_buffer (8,16)
opcache.max_accelerated_files (10000,40000)
opcache.save_comments (1,0)
opcache.dups_fix (0,1)
opcache.log_verbosity_level (1,4)

Changing configuration parameters of opcache.jit somehow eliminates the issue:
Values of opcache.jit for which the problem is absent:
1251
1205, 1215, 1225, 1235, 1245
1055
Values of opcache.jit for which the problem persits:
1252, 1253, 1254, 1255
1155

The function debug information when set opcache.opt_debug_level=1

Tangential2XY:
     ; (lines=56, args=2, vars=4, tmps=39)
     ; (after pass 1)
     ; G:\Mój dysk\Astro\Photometry\cords.inc:80-89
     ; return  [] RANGE[0..0]
0000 CV0($tang) = RECV 1
0001 CV1($sol) = RECV 2
0002 T4 = FETCH_DIM_R CV1($sol) string("X")
0003 T5 = FETCH_DIM_R T4 string("k")
0004 T6 = FETCH_DIM_R CV0($tang) string("KSI")
0005 T7 = MUL T5 T6
0006 T8 = FETCH_DIM_R CV1($sol) string("X")
0007 T9 = FETCH_DIM_R T8 string("e")
0008 T10 = FETCH_DIM_R CV0($tang) string("ETA")
0009 T11 = MUL T9 T10
0010 T12 = ADD T7 T11
0011 T13 = FETCH_DIM_R CV1($sol) string("X")
0012 T14 = FETCH_DIM_R T13 int(1)
0013 T15 = ADD T12 T14
0014 ASSIGN CV2($x) T15
0015 T17 = FETCH_DIM_R CV1($sol) string("Y")
0016 T18 = FETCH_DIM_R T17 string("k")
0017 T19 = FETCH_DIM_R CV0($tang) string("KSI")
0018 T20 = MUL T18 T19
0019 T21 = FETCH_DIM_R CV1($sol) string("Y")
0020 T22 = FETCH_DIM_R T21 string("e")
0021 T23 = FETCH_DIM_R CV0($tang) string("ETA")
0022 T24 = MUL T22 T23
0023 T25 = ADD T20 T24
0024 T26 = FETCH_DIM_R CV1($sol) string("Y")
0025 T27 = FETCH_DIM_R T26 int(1)
0026 T28 = ADD T25 T27
0027 ASSIGN CV3($y) T28
0028 INIT_FCALL 5 160 string("printf")
0029 SEND_VAL string("In;%.12f;%.12f;%.12f;%.12f;") 1
0030 SEND_VAR CV2($x) 2
0031 SEND_VAR CV3($y) 3
0032 T30 = FETCH_DIM_R CV1($sol) string("xc")
0033 SEND_VAL T30 4
0034 T31 = FETCH_DIM_R CV1($sol) string("yc")
0035 SEND_VAL T31 5
0036 DO_ICALL
0037 T33 = FETCH_DIM_R CV1($sol) string("xc")
0038 T34 = ADD CV2($x) int(1)
0039 T35 = MUL T33 T34
0040 ASSIGN CV2($x) T35
0041 T37 = FETCH_DIM_R CV1($sol) string("yc")
0042 T38 = ADD CV3($y) int(1)
0043 T39 = MUL T37 T38
0044 ASSIGN CV3($y) T39
0045 INIT_FCALL 3 128 string("printf")
0046 SEND_VAL string("Out;%.12f;%.12f") 1
0047 SEND_VAR CV2($x) 2
0048 SEND_VAR CV3($y) 3
0049 DO_ICALL
0050 T42 = INIT_ARRAY 2 CV2($x) string("x")
0051 T42 = ADD_ARRAY_ELEMENT CV3($y) string("y")
0052 VERIFY_RETURN_TYPE T42
0053 RETURN T42
0054 VERIFY_RETURN_TYPE
0055 RETURN null

@GajowyJ
Copy link
Author

GajowyJ commented Jan 10, 2023

Here is a code that reproduces the issue:

<?php
$tang['KSI']=-9.1751656444142E-5;
$tang['ETA']=8.5076090069491E-5;

$sol['X']['k']=-222.45470924306;
$sol['X']['e']=-8.1787760034414;
$sol['X'][1]=-0.020231298698539;

$sol['Y']['k']=-14.400586941152;
$sol['Y']['e']=392.95090925357;
$sol['Y'][1]=-0.035664413413272;

$sol['xc']=968;
$sol['yc']=548;

for( $p=0; $p<1000; $p++ )
{
	print($p.': ');
	Tangential2XY($tang,$sol);
}

function Tangential2XY(array $tang, array $sol) : array
{
	$x = $sol['X']['k']*$tang['KSI'] + $sol['X']['e']*$tang['ETA'] + $sol['X'][1];
	$y = $sol['Y']['k']*$tang['KSI'] + $sol['Y']['e']*$tang['ETA'] + $sol['Y'][1];
	printf("In;%.12f;%.12f;%.12f;%.12f;",$x,$y,$sol['xc'],$sol['yc']);
	$x = $sol['xc']*($x+1);
	$y = $sol['yc']*($y+1);
	printf("Out;%.12f;%.12f\n",$x,$y);
	if( $x<100 )
		exit("Mamy to!\n");
	return ['x'=>$x,'y'=>$y];
}
?>

The output is:

0: In;-0.000516528926;-0.000912408759;968.000000000000;548.000000000000;Out;967.500000000004;547.500000000009
...
62: In;-0.000516528926;-0.000912408759;968.000000000000;548.000000000000;Out;967.500000000004;547.500000000009
63: In;-0.000516528926;-0.000912408759;968.000000000000;548.000000000000;Out;967.500000000004;547.500000000009
64: In;-0.000516528926;-0.000912408759;968.000000000000;548.000000000000;Out;0.999483471074;0.999087591241
Mamy to!

So the problem came with 65th execution of the function.
Small change in the code, change var type of $sol['xc'] and $sol['yc'] to float:

$sol['xc']=968.0;
$sol['yc']=548.0;

eliminates the problem.

@cmb69
Copy link
Member

cmb69 commented Jan 10, 2023

I can repro that also on current master.

@dstogov
Copy link
Member

dstogov commented Jan 16, 2023

I confirm this and will work on a fix.
The problem is somehow related to register allocation in tracing JIT.

dstogov added a commit that referenced this issue Jan 16, 2023
* PHP-8.1:
  Fix GH-10271: Incorrect arithmetic calculations when using JIT
dstogov added a commit that referenced this issue Jan 16, 2023
* PHP-8.2:
  Fix GH-10271: Incorrect arithmetic calculations when using JIT
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

5 participants