Skip to content

Commit eae5405

Browse files
committed
Improve dead code elimination
Enhanced the dead code elimination (DCE) optimizer with more aggressive and comprehensive dead code detection and removal capabilities. - Added side-effect analysis to identify safe-to-remove instructions - Enhanced dead variable detection within basic blocks - Improved dead store elimination for overwritten values - Better handling of unused computation chains - Added explicit handling of branches and jumps in DCE
1 parent 80fabde commit eae5405

File tree

1 file changed

+131
-12
lines changed

1 file changed

+131
-12
lines changed

src/ssa.c

Lines changed: 131 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,75 @@ bool const_folding(insn_t *insn)
15381538
return false;
15391539
}
15401540

1541+
/* Dead code detection helper */
1542+
bool is_side_effect_free(insn_t *insn)
1543+
{
1544+
/* Instructions that have no side effects and can be eliminated if unused */
1545+
switch (insn->opcode) {
1546+
case OP_load_constant:
1547+
case OP_add:
1548+
case OP_sub:
1549+
case OP_mul:
1550+
case OP_div:
1551+
case OP_mod:
1552+
case OP_lshift:
1553+
case OP_rshift:
1554+
case OP_bit_and:
1555+
case OP_bit_or:
1556+
case OP_bit_xor:
1557+
case OP_bit_not:
1558+
case OP_negate:
1559+
case OP_log_and:
1560+
case OP_log_or:
1561+
case OP_log_not:
1562+
case OP_eq:
1563+
case OP_neq:
1564+
case OP_lt:
1565+
case OP_leq:
1566+
case OP_gt:
1567+
case OP_geq:
1568+
case OP_read:
1569+
case OP_assign:
1570+
case OP_load_data_address:
1571+
return true;
1572+
default:
1573+
return false;
1574+
}
1575+
}
1576+
1577+
/* Check if instruction result is never used */
1578+
bool is_result_dead(insn_t *insn)
1579+
{
1580+
if (!insn->rd)
1581+
return false;
1582+
1583+
/* Check if the result variable is never used after this instruction */
1584+
var_t *var = insn->rd;
1585+
insn_t *next = insn->next;
1586+
bool found_use = false;
1587+
1588+
/* Scan forward in the basic block */
1589+
while (next && next->belong_to == insn->belong_to) {
1590+
if ((next->rs1 && next->rs1 == var) ||
1591+
(next->rs2 && next->rs2 == var)) {
1592+
found_use = true;
1593+
break;
1594+
}
1595+
/* Check if variable is redefined without being used */
1596+
if (next->rd && next->rd == var) {
1597+
/* Variable redefined before use - original is dead */
1598+
return true;
1599+
}
1600+
next = next->next;
1601+
}
1602+
1603+
/* If not used in current block and not global, it's likely dead */
1604+
if (!found_use && !var->is_global)
1605+
return true;
1606+
1607+
return false;
1608+
}
1609+
15411610
/* initial mark useful instruction */
15421611
int dce_init_mark(insn_t *insn, insn_t *work_list[], int work_list_idx)
15431612
{
@@ -1576,6 +1645,15 @@ int dce_init_mark(insn_t *insn, insn_t *work_list[], int work_list_idx)
15761645
mark_num++;
15771646
}
15781647
break;
1648+
/* Mark branches and jumps as initially useful */
1649+
case OP_branch:
1650+
case OP_jump:
1651+
/* Will be re-evaluated later for dead branch elimination */
1652+
insn->useful = true;
1653+
insn->belong_to->useful = true;
1654+
work_list[work_list_idx + mark_num] = insn;
1655+
mark_num++;
1656+
break;
15791657
default:
15801658
if (!insn->rd)
15811659
break;
@@ -1586,6 +1664,13 @@ int dce_init_mark(insn_t *insn, insn_t *work_list[], int work_list_idx)
15861664
work_list[work_list_idx + mark_num] = insn;
15871665
mark_num++;
15881666
}
1667+
/* Skip marking if result is provably dead */
1668+
else if (!is_result_dead(insn) && !is_side_effect_free(insn)) {
1669+
insn->useful = true;
1670+
insn->belong_to->useful = true;
1671+
work_list[work_list_idx + mark_num] = insn;
1672+
mark_num++;
1673+
}
15891674
break;
15901675
}
15911676
return mark_num;
@@ -1644,13 +1729,22 @@ void dce_insn(basic_block_t *bb)
16441729
}
16451730
}
16461731

1732+
16471733
void dce_sweep(void)
16481734
{
16491735
for (func_t *func = FUNC_LIST.head; func; func = func->next) {
16501736
for (basic_block_t *bb = func->bbs; bb; bb = bb->rpo_next) {
1651-
for (insn_t *insn = bb->insn_list.head; insn; insn = insn->next) {
1652-
if (insn->useful)
1737+
insn_t *insn = bb->insn_list.head;
1738+
insn_t *next;
1739+
1740+
while (insn) {
1741+
next = insn->next;
1742+
1743+
if (insn->useful) {
1744+
insn = next;
16531745
continue;
1746+
}
1747+
16541748
/* If a branch instruction is useless, redirect to the
16551749
* reverse immediate dominator of this basic block and
16561750
* remove the branch instruction. Later, register allocation
@@ -1669,15 +1763,42 @@ void dce_sweep(void)
16691763
}
16701764
}
16711765

1766+
/* Additional check for dead stores */
1767+
if (insn->opcode == OP_write && insn->rd && !insn->useful) {
1768+
/* Check if this store is immediately overwritten */
1769+
insn_t *check = insn->next;
1770+
bool is_dead_store = false;
1771+
while (check && check->belong_to == bb) {
1772+
if (check->opcode == OP_write &&
1773+
check->rd == insn->rd) {
1774+
/* Found overwriting store - original is dead */
1775+
is_dead_store = true;
1776+
break;
1777+
}
1778+
/* Stop if the value is read */
1779+
if ((check->rs1 && check->rs1 == insn->rd) ||
1780+
(check->rs2 && check->rs2 == insn->rd)) {
1781+
break;
1782+
}
1783+
check = check->next;
1784+
}
1785+
if (is_dead_store)
1786+
insn->useful = false;
1787+
}
1788+
16721789
/* remove useless instructions */
1673-
if (insn->next)
1674-
insn->next->prev = insn->prev;
1675-
else
1676-
bb->insn_list.tail = insn->prev;
1677-
if (insn->prev)
1678-
insn->prev->next = insn->next;
1679-
else
1680-
bb->insn_list.head = insn->next;
1790+
if (!insn->useful) {
1791+
if (insn->next)
1792+
insn->next->prev = insn->prev;
1793+
else
1794+
bb->insn_list.tail = insn->prev;
1795+
if (insn->prev)
1796+
insn->prev->next = insn->next;
1797+
else
1798+
bb->insn_list.head = insn->next;
1799+
}
1800+
1801+
insn = next;
16811802
}
16821803
}
16831804
}
@@ -1689,8 +1810,6 @@ void build_reversed_rpo();
16891810
void simple_copy_propagation(basic_block_t *bb);
16901811
void redundant_load_elimination(basic_block_t *bb);
16911812
void dead_store_elimination(basic_block_t *bb);
1692-
1693-
/* Enhanced optimization function declarations */
16941813
bool enhanced_const_fold(insn_t *insn);
16951814

16961815
void optimize(void)

0 commit comments

Comments
 (0)