@@ -8,6 +8,7 @@ typedef struct
88{
99 AstExpr * * location ;
1010 size_t stmt_index ;
11+ AstStmt * stmt ;
1112} CseOccurrence ;
1213
1314typedef struct
@@ -32,15 +33,15 @@ static void optimize_block(AstBlock *block);
3233static void optimize_statement_children (AstStmt * stmt );
3334static void collect_block_candidates (AstBlock * block , CseEntryList * entries );
3435static void collect_statement_candidates (AstStmt * stmt , size_t stmt_index , CseEntryList * entries );
35- static void collect_expr_candidates (AstExpr * * expr_ptr , size_t stmt_index , CseEntryList * entries );
36+ static void collect_expr_candidates (AstExpr * * expr_ptr , size_t stmt_index , AstStmt * owner , CseEntryList * entries );
3637static int expr_is_constant (const AstExpr * expr );
3738static int expr_is_candidate (const AstExpr * expr );
3839static char * expr_make_key (const AstExpr * expr );
39- static void register_candidate (CseEntryList * entries , AstExpr * * expr_ptr , size_t stmt_index );
40+ static void register_candidate (CseEntryList * entries , AstExpr * * expr_ptr , size_t stmt_index , AstStmt * owner );
4041static CseEntry * find_entry (CseEntryList * entries , const char * key );
4142static void ensure_entry_capacity (CseEntryList * list , size_t needed );
4243static void ensure_occ_capacity (CseEntry * entry , size_t needed );
43- static void add_occurrence (CseEntry * entry , AstExpr * * location , size_t stmt_index );
44+ static void add_occurrence (CseEntry * entry , AstExpr * * location , size_t stmt_index , AstStmt * stmt );
4445static void apply_cse (AstBlock * block , CseEntryList * entries );
4546static void insert_statement (AstStmtList * list , size_t index , AstStmt * stmt );
4647static AstExpr * make_temp_identifier (const char * name , TypeKind type );
@@ -49,6 +50,7 @@ static void free_entries(CseEntryList *entries);
4950static char * dup_string (const char * value );
5051static void * xmalloc (size_t size );
5152static int compare_entries_by_index (const void * lhs , const void * rhs );
53+ static int occurrence_survives_dce (const CseOccurrence * occ );
5254
5355void optimize_program (AstProgram * program )
5456{
@@ -138,20 +140,20 @@ static void collect_statement_candidates(AstStmt *stmt, size_t stmt_index, CseEn
138140 case STMT_DECL :
139141 if (!stmt -> data .decl .is_array && stmt -> data .decl .init )
140142 {
141- collect_expr_candidates (& stmt -> data .decl .init , stmt_index , entries );
143+ collect_expr_candidates (& stmt -> data .decl .init , stmt_index , stmt , entries );
142144 }
143145 break ;
144146 case STMT_ASSIGN :
145- collect_expr_candidates (& stmt -> data .assign .value , stmt_index , entries );
147+ collect_expr_candidates (& stmt -> data .assign .value , stmt_index , stmt , entries );
146148 break ;
147149 case STMT_ARRAY_ASSIGN :
148- collect_expr_candidates (& stmt -> data .array_assign .value , stmt_index , entries );
150+ collect_expr_candidates (& stmt -> data .array_assign .value , stmt_index , stmt , entries );
149151 break ;
150152 case STMT_EXPR :
151153 case STMT_RETURN :
152154 if (stmt -> data .expr )
153155 {
154- collect_expr_candidates (& stmt -> data .expr , stmt_index , entries );
156+ collect_expr_candidates (& stmt -> data .expr , stmt_index , stmt , entries );
155157 }
156158 break ;
157159 case STMT_WHILE :
@@ -164,7 +166,7 @@ static void collect_statement_candidates(AstStmt *stmt, size_t stmt_index, CseEn
164166 }
165167}
166168
167- static void collect_expr_candidates (AstExpr * * expr_ptr , size_t stmt_index , CseEntryList * entries )
169+ static void collect_expr_candidates (AstExpr * * expr_ptr , size_t stmt_index , AstStmt * owner , CseEntryList * entries )
168170{
169171 if (!expr_ptr || !* expr_ptr )
170172 {
@@ -176,35 +178,35 @@ static void collect_expr_candidates(AstExpr **expr_ptr, size_t stmt_index, CseEn
176178 switch (expr -> kind )
177179 {
178180 case EXPR_BINARY :
179- collect_expr_candidates (& expr -> data .binary .left , stmt_index , entries );
180- collect_expr_candidates (& expr -> data .binary .right , stmt_index , entries );
181+ collect_expr_candidates (& expr -> data .binary .left , stmt_index , owner , entries );
182+ collect_expr_candidates (& expr -> data .binary .right , stmt_index , owner , entries );
181183 break ;
182184 case EXPR_UNARY :
183- collect_expr_candidates (& expr -> data .unary .operand , stmt_index , entries );
185+ collect_expr_candidates (& expr -> data .unary .operand , stmt_index , owner , entries );
184186 break ;
185187 case EXPR_CALL :
186188 for (size_t i = 0 ; i < expr -> data .call .args .count ; ++ i )
187189 {
188- collect_expr_candidates (& expr -> data .call .args .items [i ], stmt_index , entries );
190+ collect_expr_candidates (& expr -> data .call .args .items [i ], stmt_index , owner , entries );
189191 }
190192 break ;
191193 case EXPR_ARRAY_LITERAL :
192194 for (size_t i = 0 ; i < expr -> data .array_literal .elements .count ; ++ i )
193195 {
194- collect_expr_candidates (& expr -> data .array_literal .elements .items [i ], stmt_index , entries );
196+ collect_expr_candidates (& expr -> data .array_literal .elements .items [i ], stmt_index , owner , entries );
195197 }
196198 break ;
197199 case EXPR_SUBSCRIPT :
198- collect_expr_candidates (& expr -> data .subscript .array , stmt_index , entries );
199- collect_expr_candidates (& expr -> data .subscript .index , stmt_index , entries );
200+ collect_expr_candidates (& expr -> data .subscript .array , stmt_index , owner , entries );
201+ collect_expr_candidates (& expr -> data .subscript .index , stmt_index , owner , entries );
200202 break ;
201203 default :
202204 break ;
203205 }
204206
205207 if (expr_is_candidate (expr ))
206208 {
207- register_candidate (entries , expr_ptr , stmt_index );
209+ register_candidate (entries , expr_ptr , stmt_index , owner );
208210 }
209211}
210212
@@ -244,7 +246,7 @@ static int expr_is_candidate(const AstExpr *expr)
244246 return expr_is_constant (expr );
245247}
246248
247- static void register_candidate (CseEntryList * entries , AstExpr * * expr_ptr , size_t stmt_index )
249+ static void register_candidate (CseEntryList * entries , AstExpr * * expr_ptr , size_t stmt_index , AstStmt * owner )
248250{
249251 if (!entries || !expr_ptr || !* expr_ptr )
250252 {
@@ -273,7 +275,7 @@ static void register_candidate(CseEntryList *entries, AstExpr **expr_ptr, size_t
273275 entry -> first_stmt_index = stmt_index ;
274276 }
275277 }
276- add_occurrence (entry , expr_ptr , stmt_index );
278+ add_occurrence (entry , expr_ptr , stmt_index , owner );
277279}
278280
279281static CseEntry * find_entry (CseEntryList * entries , const char * key )
@@ -342,7 +344,7 @@ static void ensure_occ_capacity(CseEntry *entry, size_t needed)
342344 entry -> occurrence_capacity = new_capacity ;
343345}
344346
345- static void add_occurrence (CseEntry * entry , AstExpr * * location , size_t stmt_index )
347+ static void add_occurrence (CseEntry * entry , AstExpr * * location , size_t stmt_index , AstStmt * stmt )
346348{
347349 if (!entry )
348350 {
@@ -351,6 +353,7 @@ static void add_occurrence(CseEntry *entry, AstExpr **location, size_t stmt_inde
351353 ensure_occ_capacity (entry , entry -> occurrence_count + 1 );
352354 entry -> occurrences [entry -> occurrence_count ].location = location ;
353355 entry -> occurrences [entry -> occurrence_count ].stmt_index = stmt_index ;
356+ entry -> occurrences [entry -> occurrence_count ].stmt = stmt ;
354357 entry -> occurrence_count ++ ;
355358}
356359
@@ -411,7 +414,21 @@ static void apply_cse(AstBlock *block, CseEntryList *entries)
411414 }
412415 }
413416
417+ int has_live_use = 0 ;
418+ for (size_t j = 0 ; j < entry -> occurrence_count ; ++ j )
419+ {
420+ if (occurrence_survives_dce (& entry -> occurrences [j ]))
421+ {
422+ has_live_use = 1 ;
423+ break ;
424+ }
425+ }
426+
414427 AstStmt * decl = ast_stmt_make_decl (entry -> type , dup_string (temp_name ), init_expr );
428+ if (has_live_use )
429+ {
430+ decl -> data .decl .is_used = 1 ; /* mark as live so DCE keeps this temp */
431+ }
415432 insert_statement (& block -> statements , entry -> first_stmt_index + inserted , decl );
416433 inserted ++ ;
417434 free (temp_name );
@@ -520,6 +537,19 @@ static int compare_entries_by_index(const void *lhs, const void *rhs)
520537 return 0 ;
521538}
522539
540+ static int occurrence_survives_dce (const CseOccurrence * occ )
541+ {
542+ if (!occ || !occ -> stmt )
543+ {
544+ return 1 ;
545+ }
546+ if (occ -> stmt -> kind != STMT_DECL )
547+ {
548+ return 1 ;
549+ }
550+ return occ -> stmt -> data .decl .is_used != 0 ;
551+ }
552+
523553static char * expr_make_key (const AstExpr * expr )
524554{
525555 if (!expr )
@@ -531,9 +561,12 @@ static char *expr_make_key(const AstExpr *expr)
531561 {
532562 case EXPR_INT_LITERAL :
533563 // Include type information in the key to distinguish between int and char literals
534- if (expr -> type == TYPE_CHAR ) {
564+ if (expr -> type == TYPE_CHAR )
565+ {
535566 snprintf (buffer , sizeof (buffer ), "C:%lld" , expr -> data .int_value );
536- } else {
567+ }
568+ else
569+ {
537570 snprintf (buffer , sizeof (buffer ), "I:%lld" , expr -> data .int_value );
538571 }
539572 return dup_string (buffer );
0 commit comments