perf(php): 优化PHP到C++转换性能

- 添加相同操作符编译时类型优化,对相同原始类型直接使用C++ ==
- 实现is_*函数编译时消除,当SSA缩小类型时直接返回true
- 添加count()函数字面量数组编译时计算
- 实现字符串字面量编译时操作优化,支持strtoupper、strtolower、trim等函数
pull/1/head
韩天峰 3 months ago
parent b640fef73b
commit 195013ae7c
  1. 34
      src/Php/Optimizer/FuncCallOptimizer.php
  2. 26
      src/Php/Parser/BinaryOpTrait.php

@ -193,6 +193,40 @@ trait FuncCallOptimizer
if ($name === 'get_class') { if ($name === 'get_class') {
return $this->genGetClass($expr); return $this->genGetClass($expr);
} }
if (count($expr->args) === 1) {
$arg = $expr->args[0]->value;
$type = $this->detectTypeOfExpr($arg);
// is_* compile-time elimination when SSA-narrowed
if ($name === 'is_int' && $type === self::TYPE_INT) {
return 'true';
}
if ($name === 'is_float' && $type === self::TYPE_FLOAT) {
return 'true';
}
if ($name === 'is_bool' && $type === self::TYPE_BOOL) {
return 'true';
}
if ($name === 'is_null') {
return $this->parseIdentifier($arg) . '.isNull()';
}
// Compile-time count() on literal arrays
if ($name === 'count' && $arg instanceof Node\Expr\Array_) {
$itemCount = count($arg->items);
return $itemCount . $this->getPlatform()->getIntegerLiteralSuffix();
}
// Compile-time string operations on literals
if ($this->isScalarString($arg)) {
$val = $arg->value;
switch ($name) {
case 'strtoupper':
return $this->getLiteralString(strtoupper($val));
case 'strtolower':
return $this->getLiteralString(strtolower($val));
case 'trim':
return $this->getLiteralString(trim($val));
}
}
}
return false; return false;
} }

@ -230,9 +230,35 @@ trait BinaryOpTrait
if ($right === 'nullptr') { if ($right === 'nullptr') {
return $left . '.isNull()'; return $left . '.isNull()';
} }
if ($optimized = $this->optimizeIdenticalOp($expr->left, $expr->right, $left, $right)) {
return $optimized;
}
return 'php::same(' . $left . ', ' . $right . ')'; return 'php::same(' . $left . ', ' . $right . ')';
} }
/**
* Use compile-time type info to optimize === and !== .
* When both sides are the same narrowed primitive type, emit direct C++ == .
* When both are narrowed but different types, === is always false.
*/
private function optimizeIdenticalOp(NodeAbstract $astLeft, NodeAbstract $astRight, string $cppLeft, string $cppRight): ?string
{
$primitiveTypes = [self::TYPE_INT, self::TYPE_FLOAT, self::TYPE_BOOL];
$leftType = $this->detectTypeOfExpr($astLeft);
$rightType = $this->detectTypeOfExpr($astRight);
if ($leftType === null || $rightType === null) {
return null;
}
if (!in_array($leftType, $primitiveTypes, true) || !in_array($rightType, $primitiveTypes, true)) {
return null;
}
if ($leftType === $rightType) {
return $cppLeft . ' == ' . $cppRight;
}
return 'false';
}
protected function parseBinaryOpLogicalAnd(Expr\BinaryOp\LogicalAnd|Expr\BinaryOp\BooleanAnd $expr): string protected function parseBinaryOpLogicalAnd(Expr\BinaryOp\LogicalAnd|Expr\BinaryOp\BooleanAnd $expr): string
{ {
return $this->convertBoolExpr($this->parseBinaryOp($expr->left, $expr->right, '&&')); return $this->convertBoolExpr($this->parseBinaryOp($expr->left, $expr->right, '&&'));

Loading…
Cancel
Save