Skip to content

Commit 9ecf518

Browse files
committed
Add Sparse Conditional Constant Propagation optimization
Implement basic SCCP optimization pass that performs: - Constant propagation through assignments - Constant folding for arithmetic operations (+, -, *) - Constant folding for comparison operations (==, \!=, <, <=, >, >=) - Branch folding when conditions are compile-time constants - Dead code elimination through unreachable branch removal
1 parent ff96476 commit 9ecf518

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

src/opt-sccp.c

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* shecc - Self-Hosting and Educational C Compiler.
3+
*
4+
* shecc is freely redistributable under the BSD 2 clause license. See the
5+
* file "LICENSE" for information on usage and redistribution of this file.
6+
*/
7+
8+
/* SCCP (Sparse Conditional Constant Propagation) Optimization Pass
9+
*
10+
* This optimization pass performs:
11+
* - Constant propagation through assignments
12+
* - Constant folding for arithmetic and comparison operations
13+
* - Branch folding when conditions are compile-time constants
14+
* - Dead code elimination through unreachable branch removal
15+
*/
16+
17+
/* Simple constant propagation within basic blocks */
18+
bool simple_sccp(func_t *func)
19+
{
20+
if (!func || !func->bbs)
21+
return false;
22+
23+
bool changed = false;
24+
25+
/* Iterate through basic blocks */
26+
for (basic_block_t *bb = func->bbs; bb; bb = bb->rpo_next) {
27+
/* Process instructions in the block */
28+
for (insn_t *insn = bb->insn_list.head; insn; insn = insn->next) {
29+
/* Skip if no destination */
30+
if (!insn->rd)
31+
continue;
32+
33+
/* Handle simple constant propagation */
34+
switch (insn->opcode) {
35+
case OP_assign:
36+
/* Propagate constants through assignments */
37+
if (insn->rs1 && insn->rs1->is_const && !insn->rd->is_const) {
38+
insn->rd->is_const = true;
39+
insn->rd->init_val = insn->rs1->init_val;
40+
insn->opcode = OP_load_constant;
41+
insn->rs1 = NULL;
42+
changed = true;
43+
}
44+
break;
45+
46+
case OP_add:
47+
case OP_sub:
48+
case OP_mul:
49+
/* Fold binary operations with constants */
50+
if (insn->rs1 && insn->rs1->is_const && insn->rs2 &&
51+
insn->rs2->is_const &&
52+
!insn->rd->is_global) { /* Don't modify globals */
53+
int result = 0;
54+
int l = insn->rs1->init_val, r = insn->rs2->init_val;
55+
56+
switch (insn->opcode) {
57+
case OP_add:
58+
result = l + r;
59+
break;
60+
case OP_sub:
61+
result = l - r;
62+
break;
63+
case OP_mul:
64+
result = l * r;
65+
break;
66+
default:
67+
continue;
68+
}
69+
70+
/* Convert to constant load */
71+
insn->opcode = OP_load_constant;
72+
insn->rd->is_const = true;
73+
insn->rd->init_val = result;
74+
insn->rs1 = NULL;
75+
insn->rs2 = NULL;
76+
changed = true;
77+
}
78+
break;
79+
80+
case OP_eq:
81+
case OP_neq:
82+
case OP_lt:
83+
case OP_leq:
84+
case OP_gt:
85+
case OP_geq:
86+
/* Fold comparison operations */
87+
if (insn->rs1 && insn->rs1->is_const && insn->rs2 &&
88+
insn->rs2->is_const &&
89+
!insn->rd->is_global) { /* Don't modify globals */
90+
int result = 0;
91+
int l = insn->rs1->init_val;
92+
int r = insn->rs2->init_val;
93+
94+
switch (insn->opcode) {
95+
case OP_eq:
96+
result = (l == r);
97+
break;
98+
case OP_neq:
99+
result = (l != r);
100+
break;
101+
case OP_lt:
102+
result = (l < r);
103+
break;
104+
case OP_leq:
105+
result = (l <= r);
106+
break;
107+
case OP_gt:
108+
result = (l > r);
109+
break;
110+
case OP_geq:
111+
result = (l >= r);
112+
break;
113+
default:
114+
continue;
115+
}
116+
117+
/* Convert to constant load */
118+
insn->opcode = OP_load_constant;
119+
insn->rd->is_const = true;
120+
insn->rd->init_val = result;
121+
insn->rs1 = NULL;
122+
insn->rs2 = NULL;
123+
changed = true;
124+
}
125+
break;
126+
127+
default:
128+
/* Other opcodes - no optimization */
129+
break;
130+
}
131+
}
132+
133+
/* Simple constant branch folding */
134+
insn_t *last = bb->insn_list.tail;
135+
if (last && last->opcode == OP_branch) {
136+
if (last->rs1 && last->rs1->is_const) {
137+
/* Convert to unconditional jump */
138+
last->opcode = OP_jump;
139+
140+
if (last->rs1->init_val != 0) {
141+
/* Take then branch */
142+
bb->else_ = NULL;
143+
} else {
144+
/* Take else branch */
145+
bb->then_ = bb->else_;
146+
bb->else_ = NULL;
147+
}
148+
149+
last->rs1 = NULL;
150+
changed = true;
151+
}
152+
}
153+
}
154+
155+
return changed;
156+
}

src/ssa.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "defs.h"
1212
#include "globals.c"
1313

14+
/* SCCP (Sparse Conditional Constant Propagation) optimization */
15+
#include "opt-sccp.c"
16+
1417
/* cfront does not accept structure as an argument, pass pointer */
1518
void bb_forward_traversal(bb_traversal_args_t *args)
1619
{
@@ -1886,6 +1889,11 @@ void optimize(void)
18861889

18871890
use_chain_build();
18881891

1892+
/* Run simple SCCP optimization first */
1893+
for (func_t *func = FUNC_LIST.head; func; func = func->next) {
1894+
simple_sccp(func);
1895+
}
1896+
18891897
for (func_t *func = FUNC_LIST.head; func; func = func->next) {
18901898
/* basic block level (control flow) optimizations */
18911899

0 commit comments

Comments
 (0)