@@ -51,6 +51,126 @@ static char *dup_string(const char *value);
5151static void * xmalloc (size_t size );
5252static int compare_entries_by_index (const void * lhs , const void * rhs );
5353static int occurrence_survives_dce (const CseOccurrence * occ );
54+
55+ static int expr_is_constant_bool (const AstExpr * expr , int * out_value )
56+ {
57+ if (!expr )
58+ return 0 ;
59+
60+ switch (expr -> kind )
61+ {
62+ case EXPR_BOOL_LITERAL :
63+ * out_value = expr -> data .bool_value ? 1 : 0 ;
64+ return 1 ;
65+
66+ case EXPR_INT_LITERAL :
67+ * out_value = (expr -> data .int_value != 0 );
68+ return 1 ;
69+
70+ case EXPR_FLOAT_LITERAL :
71+ * out_value = (expr -> data .float_value != 0.0 );
72+ return 1 ;
73+
74+ case EXPR_UNARY :
75+ if (expr -> data .unary .op == UN_OP_NOT )
76+ {
77+ int v ;
78+ if (!expr_is_constant_bool (expr -> data .unary .operand , & v ))
79+ return 0 ;
80+ * out_value = !v ;
81+ return 1 ;
82+ }
83+ return expr_is_constant_bool (expr -> data .unary .operand , out_value );
84+
85+ case EXPR_BINARY :
86+ {
87+ int l , r ;
88+ if (!expr_is_constant_bool (expr -> data .binary .left , & l ))
89+ return 0 ;
90+ if (!expr_is_constant_bool (expr -> data .binary .right , & r ))
91+ return 0 ;
92+
93+ switch (expr -> data .binary .op )
94+ {
95+ case BIN_OP_AND :
96+ * out_value = l && r ;
97+ return 1 ;
98+ case BIN_OP_OR :
99+ * out_value = l || r ;
100+ return 1 ;
101+ case BIN_OP_EQ :
102+ * out_value = (l == r );
103+ return 1 ;
104+ case BIN_OP_NEQ :
105+ * out_value = (l != r );
106+ return 1 ;
107+ default :
108+ return 0 ;
109+ }
110+ }
111+
112+ default :
113+ return 0 ;
114+ }
115+ }
116+
117+ static void optimize_if_constants (AstBlock * block )
118+ {
119+ if (!block )
120+ return ;
121+
122+ for (size_t i = 0 ; i < block -> statements .count ;)
123+ {
124+ AstStmt * stmt = block -> statements .items [i ];
125+ if (!stmt )
126+ {
127+ i ++ ;
128+ continue ;
129+ }
130+
131+ if (stmt -> kind == STMT_IF )
132+ {
133+ int cond ;
134+ if (expr_is_constant_bool (stmt -> data .if_stmt .condition , & cond ))
135+ {
136+ AstStmt * replacement = NULL ;
137+
138+ if (cond )
139+ {
140+ replacement = stmt -> data .if_stmt .then_branch ;
141+ stmt -> data .if_stmt .then_branch = NULL ;
142+ }
143+ else
144+ {
145+ replacement = stmt -> data .if_stmt .else_branch ;
146+ stmt -> data .if_stmt .else_branch = NULL ;
147+ }
148+
149+ ast_expr_list_destroy (NULL );
150+ {
151+ }
152+ free (stmt -> data .if_stmt .condition );
153+ free (stmt );
154+
155+ if (replacement )
156+ {
157+ block -> statements .items [i ] = replacement ;
158+ continue ;
159+ }
160+ else
161+ {
162+ memmove (& block -> statements .items [i ],
163+ & block -> statements .items [i + 1 ],
164+ (block -> statements .count - i - 1 ) * sizeof (AstStmt * ));
165+ block -> statements .count -- ;
166+ continue ;
167+ }
168+ }
169+ }
170+
171+ i ++ ;
172+ }
173+ }
54174static void eliminate_unreachable (AstStmtList * list );
55175
56176void optimize_program (AstProgram * program )
@@ -81,6 +201,8 @@ static void optimize_block(AstBlock *block)
81201 return ;
82202 }
83203
204+ optimize_if_constants (block );
205+
84206 CseEntryList entries = {0 };
85207 collect_block_candidates (block , & entries );
86208 apply_cse (block , & entries );
@@ -113,6 +235,11 @@ static void optimize_statement_children(AstStmt *stmt)
113235 optimize_statement_children (stmt -> data .for_stmt .body );
114236 optimize_statement_children (stmt -> data .for_stmt .post );
115237 break ;
238+ case STMT_IF :
239+ optimize_statement_children (stmt -> data .if_stmt .then_branch );
240+ if (stmt -> data .if_stmt .else_branch )
241+ optimize_statement_children (stmt -> data .if_stmt .else_branch );
242+ break ;
116243 default :
117244 break ;
118245 }
@@ -160,9 +287,9 @@ static void collect_statement_candidates(AstStmt *stmt, size_t stmt_index, CseEn
160287 break ;
161288 case STMT_WHILE :
162289 case STMT_FOR :
163- /* Loop conditions must be evaluated every iteration, so skip them. */
164290 break ;
165291 case STMT_BLOCK :
292+ case STMT_IF :
166293 default :
167294 break ;
168295 }
@@ -429,7 +556,7 @@ static void apply_cse(AstBlock *block, CseEntryList *entries)
429556 AstStmt * decl = ast_stmt_make_decl (entry -> type , dup_string (temp_name ), init_expr );
430557 if (has_live_use )
431558 {
432- decl -> data .decl .is_used = 1 ; /* mark as live so DCE keeps this temp */
559+ decl -> data .decl .is_used = 1 ;
433560 }
434561 insert_statement (& block -> statements , entry -> first_stmt_index + inserted , decl );
435562 inserted ++ ;
@@ -562,7 +689,6 @@ static char *expr_make_key(const AstExpr *expr)
562689 switch (expr -> kind )
563690 {
564691 case EXPR_INT_LITERAL :
565- // Include type information in the key to distinguish between int and char literals
566692 if (expr -> type == TYPE_CHAR )
567693 {
568694 snprintf (buffer , sizeof (buffer ), "C:%lld" , expr -> data .int_value );
@@ -610,7 +736,6 @@ static char *expr_make_key(const AstExpr *expr)
610736 return dup_string ("<unsupported>" );
611737 }
612738}
613-
614739static void eliminate_unreachable (AstStmtList * list )
615740{
616741 if (!list )
0 commit comments