30
30
#include "zend_inference.h"
31
31
#include "zend_dump.h"
32
32
33
- #ifndef ZEND_DEBUG_DFA
33
+ // #ifndef ZEND_DEBUG_DFA
34
34
# define ZEND_DEBUG_DFA ZEND_DEBUG
35
- #endif
35
+ // #endif
36
36
37
37
#if ZEND_DEBUG_DFA
38
38
# include "ssa_integrity.c"
@@ -1076,6 +1076,84 @@ static bool zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ss
1076
1076
return 0 ;
1077
1077
}
1078
1078
1079
+ static int zend_dfa_remove_only_free_uses (zend_op_array * op_array , zend_ssa * ssa )
1080
+ {
1081
+ int times_applied = 0 ;
1082
+ for (uint32_t i = 0 ; i < op_array -> last ; i ++ ) {
1083
+ zend_op * opline = op_array -> opcodes + i ;
1084
+ if (opline -> opcode != ZEND_FREE ) {
1085
+ continue ;
1086
+ }
1087
+ int op1_use = ssa -> ops [i ].op1_use ;
1088
+ /* Possible if it's unreachable. */
1089
+ if (op1_use < 0 ) {
1090
+ continue ;
1091
+ }
1092
+ int definition = ssa -> vars [op1_use ].definition ;
1093
+ if (definition < 0 ) {
1094
+ continue ;
1095
+ }
1096
+ zend_op * defining_opline = op_array -> opcodes + definition ;
1097
+ if (opline -> op1_type == IS_TMP_VAR ) {
1098
+ switch (defining_opline -> opcode ) {
1099
+ case ZEND_ASSIGN :
1100
+ case ZEND_ASSIGN_DIM :
1101
+ case ZEND_ASSIGN_OBJ :
1102
+ case ZEND_ASSIGN_STATIC_PROP :
1103
+ case ZEND_ASSIGN_OP :
1104
+ case ZEND_ASSIGN_DIM_OP :
1105
+ case ZEND_ASSIGN_OBJ_OP :
1106
+ case ZEND_ASSIGN_STATIC_PROP_OP :
1107
+ case ZEND_PRE_INC :
1108
+ case ZEND_PRE_DEC :
1109
+ case ZEND_PRE_INC_OBJ :
1110
+ case ZEND_PRE_DEC_OBJ :
1111
+ case ZEND_PRE_INC_STATIC_PROP :
1112
+ case ZEND_PRE_DEC_STATIC_PROP :
1113
+ break ;
1114
+ default :
1115
+ continue ;
1116
+ }
1117
+ } else if (opline -> op1_type == IS_VAR ) {
1118
+ switch (defining_opline -> opcode ) {
1119
+ case ZEND_FETCH_R :
1120
+ case ZEND_FETCH_STATIC_PROP_R :
1121
+ case ZEND_FETCH_DIM_R :
1122
+ case ZEND_FETCH_OBJ_R :
1123
+ case ZEND_NEW :
1124
+ case ZEND_FETCH_THIS :
1125
+ continue ;
1126
+ default :
1127
+ break ;
1128
+ }
1129
+ }
1130
+ int use ;
1131
+ bool all_free = true;
1132
+ int result_def = ssa -> ops [definition ].result_def ;
1133
+ if (result_def < 0 ) {
1134
+ continue ;
1135
+ }
1136
+ FOREACH_USE (ssa -> vars + result_def , use ) {
1137
+ if (op_array -> opcodes [use ].opcode != ZEND_FREE ) {
1138
+ all_free = false;
1139
+ break ;
1140
+ }
1141
+ } FOREACH_USE_END ();
1142
+ if (all_free ) {
1143
+ FOREACH_USE (ssa -> vars + result_def , use ) {
1144
+ MAKE_NOP (op_array -> opcodes + use );
1145
+ ssa -> ops [use ].op1_use_chain = -1 ;
1146
+ ssa -> ops [use ].op1_use = -1 ;
1147
+ } FOREACH_USE_END ();
1148
+ defining_opline -> result_type = IS_UNUSED ;
1149
+ zend_ssa_remove_uses_of_var (ssa , result_def );
1150
+ zend_ssa_remove_result_def (ssa , ssa -> ops + definition );
1151
+ times_applied ++ ;
1152
+ }
1153
+ }
1154
+ return times_applied ;
1155
+ }
1156
+
1079
1157
void zend_dfa_optimize_op_array (zend_op_array * op_array , zend_optimizer_ctx * ctx , zend_ssa * ssa , zend_call_info * * call_map )
1080
1158
{
1081
1159
if (ctx -> debug_level & ZEND_DUMP_BEFORE_DFA_PASS ) {
@@ -1094,6 +1172,10 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
1094
1172
ssa_verify_integrity (op_array , ssa , "before dfa" );
1095
1173
#endif
1096
1174
1175
+ if (zend_dfa_remove_only_free_uses (op_array , ssa )) {
1176
+ remove_nops = 1 ;
1177
+ }
1178
+
1097
1179
if (ZEND_OPTIMIZER_PASS_8 & ctx -> optimization_level ) {
1098
1180
if (sccp_optimize_op_array (ctx , op_array , ssa , call_map )) {
1099
1181
remove_nops = 1 ;
0 commit comments