From 195013ae7c4914c84a0249a98dadfaf92d8286f8 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Fri, 5 Jun 2026 13:16:20 +0800 Subject: [PATCH] =?UTF-8?q?perf(php):=20=E4=BC=98=E5=8C=96PHP=E5=88=B0C++?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加相同操作符编译时类型优化,对相同原始类型直接使用C++ == - 实现is_*函数编译时消除,当SSA缩小类型时直接返回true - 添加count()函数字面量数组编译时计算 - 实现字符串字面量编译时操作优化,支持strtoupper、strtolower、trim等函数 --- src/Php/Optimizer/FuncCallOptimizer.php | 34 +++++++++++++++++++++++++ src/Php/Parser/BinaryOpTrait.php | 26 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/Php/Optimizer/FuncCallOptimizer.php b/src/Php/Optimizer/FuncCallOptimizer.php index 84ae9ae3..70471000 100644 --- a/src/Php/Optimizer/FuncCallOptimizer.php +++ b/src/Php/Optimizer/FuncCallOptimizer.php @@ -193,6 +193,40 @@ trait FuncCallOptimizer if ($name === 'get_class') { 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; } diff --git a/src/Php/Parser/BinaryOpTrait.php b/src/Php/Parser/BinaryOpTrait.php index 00dbe061..0ff4147c 100644 --- a/src/Php/Parser/BinaryOpTrait.php +++ b/src/Php/Parser/BinaryOpTrait.php @@ -230,9 +230,35 @@ trait BinaryOpTrait if ($right === 'nullptr') { return $left . '.isNull()'; } + if ($optimized = $this->optimizeIdenticalOp($expr->left, $expr->right, $left, $right)) { + return $optimized; + } 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 { return $this->convertBoolExpr($this->parseBinaryOp($expr->left, $expr->right, '&&'));