Skip to content

Commit d18f9b2

Browse files
committed
ext/standard/array.c: Optimize min/max functions for int/float
1 parent 20128a6 commit d18f9b2

File tree

3 files changed

+230
-8
lines changed

3 files changed

+230
-8
lines changed

ext/standard/array.c

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,11 +1237,53 @@ PHP_FUNCTION(min)
12371237
uint32_t i;
12381238

12391239
min = &args[0];
1240+
zend_long min_lval;
1241+
double min_dval;
12401242

1241-
for (i = 1; i < argc; i++) {
1242-
is_smaller_function(&result, &args[i], min);
1243-
if (Z_TYPE(result) == IS_TRUE) {
1244-
min = &args[i];
1243+
if (Z_TYPE_P(min) == IS_LONG) {
1244+
min_lval = Z_LVAL_P(min);
1245+
1246+
for (i = 1; i < argc; i++) {
1247+
if (EXPECTED(Z_TYPE(args[i]) == IS_LONG)) {
1248+
if (min_lval > Z_LVAL(args[i])) {
1249+
min_lval = Z_LVAL(args[i]);
1250+
min = &args[i];
1251+
}
1252+
} else if (Z_TYPE(args[i]) == IS_DOUBLE) {
1253+
min_dval = (double) min_lval;
1254+
goto double_compare;
1255+
} else {
1256+
goto generic_compare;
1257+
}
1258+
}
1259+
1260+
RETURN_LONG(min_lval);
1261+
} else if (Z_TYPE_P(min) == IS_DOUBLE) {
1262+
min_dval = Z_DVAL_P(min);
1263+
1264+
for (i = 1; i < argc; i++) {
1265+
if (EXPECTED(Z_TYPE(args[i]) == IS_DOUBLE)) {
1266+
double_compare:
1267+
if (min_dval > Z_DVAL(args[i])) {
1268+
min_dval = Z_DVAL(args[i]);
1269+
min = &args[i];
1270+
}
1271+
} else if (Z_TYPE(args[i]) == IS_LONG) {
1272+
if (min_dval > (double)Z_LVAL(args[i])) {
1273+
min_dval = (double)Z_LVAL(args[i]);
1274+
min = &args[i];
1275+
}
1276+
} else {
1277+
goto generic_compare;
1278+
}
1279+
}
1280+
} else {
1281+
for (i = 1; i < argc; i++) {
1282+
generic_compare:
1283+
is_smaller_function(&result, &args[i], min);
1284+
if (Z_TYPE(result) == IS_TRUE) {
1285+
min = &args[i];
1286+
}
12451287
}
12461288
}
12471289

@@ -1283,11 +1325,53 @@ PHP_FUNCTION(max)
12831325
uint32_t i;
12841326

12851327
max = &args[0];
1328+
zend_long max_lval;
1329+
double max_dval;
12861330

1287-
for (i = 1; i < argc; i++) {
1288-
is_smaller_or_equal_function(&result, &args[i], max);
1289-
if (Z_TYPE(result) == IS_FALSE) {
1290-
max = &args[i];
1331+
if (Z_TYPE_P(max) == IS_LONG) {
1332+
max_lval = Z_LVAL_P(max);
1333+
1334+
for (i = 1; i < argc; i++) {
1335+
if (EXPECTED(Z_TYPE(args[i]) == IS_LONG)) {
1336+
if (max_lval < Z_LVAL(args[i])) {
1337+
max_lval = Z_LVAL(args[i]);
1338+
max = &args[i];
1339+
}
1340+
} else if (Z_TYPE(args[i]) == IS_DOUBLE) {
1341+
max_dval = (double) max_lval;
1342+
goto double_compare;
1343+
} else {
1344+
goto generic_compare;
1345+
}
1346+
}
1347+
1348+
RETURN_LONG(max_lval);
1349+
} else if (Z_TYPE_P(max) == IS_DOUBLE) {
1350+
max_dval = Z_DVAL_P(max);
1351+
1352+
for (i = 1; i < argc; i++) {
1353+
if (EXPECTED(Z_TYPE(args[i]) == IS_DOUBLE)) {
1354+
double_compare:
1355+
if (max_dval < Z_DVAL(args[i])) {
1356+
max_dval = Z_DVAL(args[i]);
1357+
max = &args[i];
1358+
}
1359+
} else if (Z_TYPE(args[i]) == IS_LONG) {
1360+
if (max_dval < (double)Z_LVAL(args[i])) {
1361+
max_dval = (double)Z_LVAL(args[i]);
1362+
max = &args[i];
1363+
}
1364+
} else {
1365+
goto generic_compare;
1366+
}
1367+
}
1368+
} else {
1369+
for (i = 1; i < argc; i++) {
1370+
generic_compare:
1371+
is_smaller_or_equal_function(&result, &args[i], max);
1372+
if (Z_TYPE(result) == IS_FALSE) {
1373+
max = &args[i];
1374+
}
12911375
}
12921376
}
12931377

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Check max() optimisation for int and float types
3+
--FILE--
4+
<?php
5+
6+
echo "Start as int optimisation:\n";
7+
var_dump(max([
8+
10, 5, 3, 2
9+
]));
10+
var_dump(max([
11+
2, 3, 5, 10
12+
]));
13+
var_dump(max([
14+
10, 5, 3.5, 2
15+
]));
16+
var_dump(max([
17+
2, 3.5, 5, 10
18+
]));
19+
var_dump(max([
20+
10, 5, "3", 2
21+
]));
22+
var_dump(max([
23+
2, "3", 5, 10
24+
]));
25+
var_dump(max([
26+
2, 3, "15", 10
27+
]));
28+
29+
echo "Start as float optimisation:\n";
30+
var_dump(max([
31+
10.5, 5.5, 3.5, 2.5
32+
]));
33+
var_dump(max([
34+
2.5, 3.5, 5.5, 10.5
35+
]));
36+
var_dump(max([
37+
10.5, 5.5, 3, 2.5
38+
]));
39+
var_dump(max([
40+
2.5, 3, 5.5, 10.5
41+
]));
42+
var_dump(max([
43+
10.5, 5.5, "3.5", 2.5
44+
]));
45+
var_dump(max([
46+
2.5, "3.5", 5.5, 10.5
47+
]));
48+
var_dump(max([
49+
2.5, 3.5, "15.5", 10.5
50+
]));
51+
52+
?>
53+
--EXPECT--
54+
Start as int optimisation:
55+
int(10)
56+
int(10)
57+
int(10)
58+
int(10)
59+
int(10)
60+
int(10)
61+
string(2) "15"
62+
Start as float optimisation:
63+
float(10.5)
64+
float(10.5)
65+
float(10.5)
66+
float(10.5)
67+
float(10.5)
68+
float(10.5)
69+
string(4) "15.5"
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Check min() optimisation for int and float types
3+
--FILE--
4+
<?php
5+
6+
echo "Start as int optimisation:\n";
7+
var_dump(min([
8+
10, 5, 3, 2
9+
]));
10+
var_dump(min([
11+
2, 3, 5, 10
12+
]));
13+
var_dump(min([
14+
10, 5, 3.5, 2
15+
]));
16+
var_dump(min([
17+
2, 3.5, 5, 10
18+
]));
19+
var_dump(min([
20+
10, 5, "3", 2
21+
]));
22+
var_dump(min([
23+
2, "3", 5, 10
24+
]));
25+
var_dump(min([
26+
2, 3, "1", 10
27+
]));
28+
29+
echo "Start as float optimisation:\n";
30+
var_dump(min([
31+
10.5, 5.5, 3.5, 2.5
32+
]));
33+
var_dump(min([
34+
2.5, 3.5, 5.5, 10.5
35+
]));
36+
var_dump(min([
37+
10.5, 5.5, 3, 2.5
38+
]));
39+
var_dump(min([
40+
2.5, 3, 5.5, 10.5
41+
]));
42+
var_dump(min([
43+
10.5, 5.5, "3.5", 2.5
44+
]));
45+
var_dump(min([
46+
2.5, "3.5", 5.5, 10.5
47+
]));
48+
var_dump(min([
49+
2.5, 3.5, "1.5", 10.5
50+
]));
51+
52+
?>
53+
--EXPECT--
54+
Start as int optimisation:
55+
int(2)
56+
int(2)
57+
int(2)
58+
int(2)
59+
int(2)
60+
int(2)
61+
string(1) "1"
62+
Start as float optimisation:
63+
float(2.5)
64+
float(2.5)
65+
float(2.5)
66+
float(2.5)
67+
float(2.5)
68+
float(2.5)
69+
string(3) "1.5"

0 commit comments

Comments
 (0)