@@ -431,6 +431,53 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
431431 case ZEND_CASE :
432432 case ZEND_CASE_STRICT :
433433 case ZEND_COPY_TMP :
434+ /* Check for printf optimization from `zend_compile_func_printf()`
435+ * where the result of `printf()` is actually unused and remove the
436+ * superflous COPY_TMP, STRLEN and FREE opcodes:
437+ * T1 = COPY_TMP T0
438+ * ECHO T0
439+ * T2 = STRLEN T1
440+ * FREE T2
441+ */
442+ if (opline -> op1_type == IS_TMP_VAR &&
443+ opline + 1 < end && (opline + 1 )-> opcode == ZEND_ECHO &&
444+ opline + 2 < end && (opline + 2 )-> opcode == ZEND_STRLEN &&
445+ opline + 3 < end && (opline + 3 )-> opcode == ZEND_FREE ) {
446+
447+ zend_op * echo_op = opline + 1 ;
448+ zend_op * strlen_op = opline + 2 ;
449+ zend_op * free_op = opline + 3 ;
450+
451+ /* Verify the pattern:
452+ * - ECHO uses the same source as COPY_TMP
453+ * - STRLEN uses the result of COPY_TMP
454+ * - FREE uses the result of STRLEN
455+ */
456+ if (echo_op -> op1_type == IS_TMP_VAR &&
457+ echo_op -> op1 .var == opline -> op1 .var &&
458+ strlen_op -> op1_type == IS_TMP_VAR &&
459+ strlen_op -> op1 .var == opline -> result .var &&
460+ free_op -> op1_type == IS_TMP_VAR &&
461+ free_op -> op1 .var == strlen_op -> result .var ) {
462+
463+ /* Remove COPY_TMP, STRLEN, and FREE */
464+ MAKE_NOP (opline );
465+ MAKE_NOP (strlen_op );
466+ MAKE_NOP (free_op );
467+
468+ /* Update source tracking */
469+ if (opline -> result_type == IS_TMP_VAR ) {
470+ VAR_SOURCE (opline -> result ) = NULL ;
471+ }
472+ if (strlen_op -> result_type == IS_TMP_VAR ) {
473+ VAR_SOURCE (strlen_op -> result ) = NULL ;
474+ }
475+
476+ ++ (* opt_count );
477+ break ;
478+ }
479+ }
480+
434481 if (opline -> op1_type & (IS_TMP_VAR |IS_VAR )) {
435482 /* Variable will be deleted later by FREE, so we can't optimize it */
436483 Tsource [VAR_NUM (opline -> op1 .var )] = NULL ;
@@ -538,7 +585,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
538585 }
539586 }
540587 break ;
541-
588+
542589 case ZEND_BOOL :
543590 case ZEND_BOOL_NOT :
544591 optimize_bool :
0 commit comments