Skip to content

Commit a8695c2

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 a8695c2

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

src/opt-sccp.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
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+
* The implementation is designed to work within shecc's constraints,
17+
* avoiding dynamic memory allocation and complex data structures.
18+
*/
19+
20+
/* Simple constant propagation within basic blocks */
21+
bool simple_sccp(func_t *func)
22+
{
23+
if (!func || !func->bbs)
24+
return false;
25+
26+
bool changed = false;
27+
28+
/* Iterate through basic blocks */
29+
for (basic_block_t *bb = func->bbs; bb; bb = bb->rpo_next) {
30+
/* Process instructions in the block */
31+
for (insn_t *insn = bb->insn_list.head; insn; insn = insn->next) {
32+
/* Skip if no destination */
33+
if (!insn->rd)
34+
continue;
35+
36+
/* Handle simple constant propagation */
37+
switch (insn->opcode) {
38+
case OP_assign:
39+
/* Propagate constants through assignments */
40+
if (insn->rs1 && insn->rs1->is_const && !insn->rd->is_const) {
41+
insn->rd->is_const = true;
42+
insn->rd->init_val = insn->rs1->init_val;
43+
insn->opcode = OP_load_constant;
44+
insn->rs1 = NULL;
45+
changed = true;
46+
}
47+
break;
48+
49+
case OP_add:
50+
case OP_sub:
51+
case OP_mul:
52+
/* Fold binary operations with constants */
53+
if (insn->rs1 && insn->rs1->is_const && insn->rs2 &&
54+
insn->rs2->is_const &&
55+
!insn->rd->is_global) { /* Don't modify globals */
56+
int result = 0;
57+
int l = insn->rs1->init_val;
58+
int r = insn->rs2->init_val;
59+
60+
switch (insn->opcode) {
61+
case OP_add:
62+
result = l + r;
63+
break;
64+
case OP_sub:
65+
result = l - r;
66+
break;
67+
case OP_mul:
68+
result = l * r;
69+
break;
70+
default:
71+
continue;
72+
}
73+
74+
/* Convert to constant load */
75+
insn->opcode = OP_load_constant;
76+
insn->rd->is_const = true;
77+
insn->rd->init_val = result;
78+
insn->rs1 = NULL;
79+
insn->rs2 = NULL;
80+
changed = true;
81+
}
82+
break;
83+
84+
case OP_eq:
85+
case OP_neq:
86+
case OP_lt:
87+
case OP_leq:
88+
case OP_gt:
89+
case OP_geq:
90+
/* Fold comparison operations */
91+
if (insn->rs1 && insn->rs1->is_const && insn->rs2 &&
92+
insn->rs2->is_const &&
93+
!insn->rd->is_global) { /* Don't modify globals */
94+
int result = 0;
95+
int l = insn->rs1->init_val;
96+
int r = insn->rs2->init_val;
97+
98+
switch (insn->opcode) {
99+
case OP_eq:
100+
result = (l == r);
101+
break;
102+
case OP_neq:
103+
result = (l != r);
104+
break;
105+
case OP_lt:
106+
result = (l < r);
107+
break;
108+
case OP_leq:
109+
result = (l <= r);
110+
break;
111+
case OP_gt:
112+
result = (l > r);
113+
break;
114+
case OP_geq:
115+
result = (l >= r);
116+
break;
117+
default:
118+
continue;
119+
}
120+
121+
/* Convert to constant load */
122+
insn->opcode = OP_load_constant;
123+
insn->rd->is_const = true;
124+
insn->rd->init_val = result;
125+
insn->rs1 = NULL;
126+
insn->rs2 = NULL;
127+
changed = true;
128+
}
129+
break;
130+
131+
default:
132+
/* Other opcodes - no optimization */
133+
break;
134+
}
135+
}
136+
137+
/* Simple constant branch folding */
138+
insn_t *last = bb->insn_list.tail;
139+
if (last && last->opcode == OP_branch) {
140+
if (last->rs1 && last->rs1->is_const) {
141+
/* Convert to unconditional jump */
142+
last->opcode = OP_jump;
143+
144+
if (last->rs1->init_val != 0) {
145+
/* Take then branch */
146+
bb->else_ = NULL;
147+
} else {
148+
/* Take else branch */
149+
bb->then_ = bb->else_;
150+
bb->else_ = NULL;
151+
}
152+
153+
last->rs1 = NULL;
154+
changed = true;
155+
}
156+
}
157+
}
158+
159+
return changed;
160+
}

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)