Skip to content

Commit 91182f0

Browse files
committed
ir: dead-code-removal, move constants -> ast_utils/
* removes all unused instructions * since functions are not yet marked with no-side-effects, all calls are assumed to have side-effects * moved constants.c2 to ast_utils/ since AST depends on it
1 parent 54fe154 commit 91182f0

File tree

5 files changed

+106
-21
lines changed

5 files changed

+106
-21
lines changed
File renamed without changes.

ir/print.c2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const char* col_Attr = color.Bmagenta;
3232
const char* col_Unknown = color.Yellow;
3333
const char* col_Value = color.Magenta;
3434
const char* col_Register = color.Cyan;
35-
const char* col_Data = color.Bgreen;
35+
const char* col_Data = color.Bcyan;
3636
const char* col_Slot = color.Bcyan;
3737
const char* col_Temp = color.Bgreen;
3838
const char* col_Param = color.Cyan;

ir/ssa.c2

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -374,30 +374,69 @@ fn void Tools.eliminateCopies(Tools* t, FunctionInfo* fi) {
374374
}
375375
}
376376

377+
378+
fn void Tools.checkRef(Tools* t, Ref r) {
379+
if (r.isTemp()) t.usage.incr(r.value);
380+
}
381+
377382
fn void Tools.fillUsage(Tools* t, FunctionInfo* fi) {
378383
t.usage.clear(fi.instructions.getCount());
379384

380385
// Usage: counter both usage and if it has a result.
381386
// count 0 means: has no result, (of course) not used
382387
// count 1 means: has result, not used (could still have side effects)
383388
// count 2+ means: used
389+
384390
Instr* all = fi.instructions.get(0);
385391
for (u32 i=0; i<fi.instructions.getCount(); i++) {
386392
Instr* is = &all[i];
387393
if (is.hasResult()) t.usage.incr(i);
388-
if (is.isPhi()) {
394+
395+
switch (is.getKind()) {
396+
case Call:
397+
// TODO check if call with side effects.
398+
// TEMP do extra incr then so it will not be pruned (could be void, so incr twice)
399+
t.usage.incr(i);
400+
t.usage.incr(i);
401+
t.checkRef(is.args[0]);
402+
t.checkRef(is.args[1]);
403+
if (is.args[1].isRefList()) {
404+
const Ref* refs = fi.refs.get(is.args[1].value);
405+
u32 j = 0;
406+
while (refs[j].kind != RefKind.None) {
407+
t.checkRef(refs[j]);
408+
j++;
409+
}
410+
}
411+
break;
412+
case Switch:
413+
t.checkRef(is.args[0]);
414+
break;
415+
case Phi:
389416
PhiClause* clauses = fi.phis.get(is.phi_clauses.start);
390417
for (u32 p=0; p<is.phi_clauses.count; p++) {
391-
Ref* r = &clauses[p].ref;
392-
if (r.isTemp()) t.usage.incr(r.value);
418+
t.checkRef(clauses[p].ref);
393419
}
394-
} else {
395-
Ref* r = &is.args[0];
396-
if (r.isTemp()) t.usage.incr(r.value);
397-
r = &is.args[1];
398-
if (r.isTemp()) t.usage.incr(r.value);
420+
break;
421+
default:
422+
t.checkRef(is.args[0]);
423+
t.checkRef(is.args[1]);
424+
break;
399425
}
400426
}
427+
428+
//t.usage.dump();
429+
t.usage.fillQueue();
430+
431+
while (t.usage.hasWork()) {
432+
u32 i = t.usage.popHead();
433+
Instr* is = &all[i];
434+
Ref* r = &is.args[0];
435+
if (r.isTemp()) t.usage.decr(r.value);
436+
r = &is.args[1];
437+
if (r.isTemp()) t.usage.decr(r.value);
438+
is.clear();
439+
}
401440
}
402441

403442
#if 0

ir/usage_counter.c2

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,21 @@ public type Counter struct {
1010
u32 count;
1111
u32 capacity;
1212
u8* counts;
13+
u32 max_idx;
14+
15+
u32[64] work_queue; // TODO make re-sizeable
16+
u32 queue_head;
17+
u32 queue_count;
1318
}
1419

1520
public fn void Counter.init(Counter* c, u32 cap) {
1621
c.count = 0;
1722
c.capacity = 0;
1823
c.counts = nil;
1924
c.resize(cap);
25+
c.max_idx = 0;
26+
c.queue_head = 0;
27+
c.queue_count = 0;
2028
}
2129

2230
public fn void Counter.free(Counter* c) {
@@ -32,26 +40,61 @@ fn void Counter.resize(Counter* c, u32 cap) {
3240
public fn void Counter.clear(Counter* c, u32 cap) {
3341
if (cap > c.capacity) c.resize(cap);
3442
c.count = cap;
43+
// TODO could be costly
3544
memset(c.counts, 0, cap);
45+
c.max_idx = 0;
46+
c.queue_head = 0;
47+
c.queue_count = 0;
3648
}
3749

3850
public fn void Counter.incr(Counter* c, u32 idx) {
3951
//assert(c.counts[idx] != u8.max); // u8
4052
assert(c.counts[idx] != c2.max_u8);
4153
c.counts[idx]++;
54+
if (idx > c.max_idx) c.max_idx = idx;
4255
}
4356

44-
/*
45-
public fn bool Counter.decr(Counter* c, u32 idx) {
57+
public fn void Counter.decr(Counter* c, u32 idx) {
4658
c.counts[idx]--;
47-
return c.counts[idx] != 0;
59+
if (c.counts[idx] == 1) {
60+
// add to work_queue if not already in
61+
u32 pos = c.queue_head;
62+
for (u32 i=0; i<c.queue_count; i++) {
63+
if (c.work_queue[pos] == idx) return; // already in
64+
pos = (pos + 1) % elemsof(c.work_queue);
65+
}
66+
assert(c.queue_count != elemsof(c.work_queue));
67+
c.work_queue[pos] = idx;
68+
c.queue_count++;
69+
}
70+
}
71+
72+
public fn bool Counter.hasWork(const Counter* c) {
73+
return c.queue_count != 0;
74+
}
75+
76+
public fn void Counter.fillQueue(Counter* c) {
77+
u32 i = c.max_idx;
78+
while (i != c2.max_u32) {
79+
if (c.counts[i] == 1) {
80+
assert(c.queue_count != elemsof(c.work_queue));
81+
// fill linearly since it starts empty
82+
c.work_queue[c.queue_count++] = i;
83+
}
84+
i--;
85+
}
86+
}
87+
88+
public fn u32 Counter.popHead(Counter* c) {
89+
u32 idx = c.work_queue[c.queue_head];
90+
c.queue_head = (c.queue_head + 1) % elemsof(c.work_queue);
91+
c.queue_count--;
92+
return idx;
4893
}
49-
*/
5094

5195
public fn void Counter.dump(const Counter* c) @(unused) {
52-
stdio.printf("Usage counter (%d)\n", c.count);
53-
for (u32 i=0; i<c.count; i++) {
54-
stdio.printf(" [%3d] %d\n", i, c.counts[i]);
96+
for (u32 i=0; i<=c.max_idx; i++) {
97+
if (c.counts[i] != 0) stdio.printf(" [%3d] %d\n", i, c.counts[i]);
5598
}
5699
}
57100

recipe.txt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ set common
99
common/build_target.c2
1010
common/component.c2
1111
common/console.c2
12-
common/constants.c2
1312
common/diagnostics.c2
1413
common/file/reader.c2
1514
common/file/writer.c2
@@ -30,6 +29,7 @@ set ast
3029
ast_utils/attr.c2
3130
ast_utils/attr_table.c2
3231
ast_utils/color.c2
32+
ast_utils/constants.c2
3333
ast_utils/context.c2
3434
ast_utils/number_radix.c2
3535
ast_utils/src_loc.c2
@@ -135,7 +135,6 @@ set yaml
135135
end
136136

137137
set refs
138-
common/constants.c2
139138
common/linked_list.c2
140139
common/quicksort.c2
141140
common/utils.c2
@@ -313,6 +312,8 @@ executable c2tags
313312

314313
(refs)
315314

315+
ast_utils/constants.c2
316+
316317
tools/c2tags.c2
317318
end
318319

@@ -321,6 +322,8 @@ executable c2rename
321322
$backend c
322323
$config RadixTreeValue
323324

325+
ast_utils/constants.c2
326+
324327
common/file/reader.c2
325328
common/file/writer.c2
326329

@@ -343,9 +346,9 @@ executable tester
343346
# $config TesterDebug
344347

345348
ast_utils/color.c2
349+
ast_utils/constants.c2
346350
ast_utils/string_buffer.c2
347351

348-
common/constants.c2
349352
common/file/reader.c2
350353
common/file/writer.c2
351354
common/string_utils.c2
@@ -363,12 +366,12 @@ executable c2cat
363366
$backend c
364367

365368
ast_utils/color.c2
369+
ast_utils/constants.c2
366370
ast_utils/number_radix.c2
367371
ast_utils/src_loc.c2
368372
ast_utils/string_buffer.c2
369373
ast_utils/string_pool.c2
370374

371-
common/constants.c2
372375
common/file/reader.c2
373376
common/string_list.c2
374377
common/utf8.c2
@@ -392,12 +395,12 @@ executable c2loc
392395
$backend c
393396

394397
ast_utils/color.c2
398+
ast_utils/constants.c2
395399
ast_utils/src_loc.c2
396400
ast_utils/string_buffer.c2
397401
ast_utils/string_pool.c2
398402

399403
common/build_target.c2
400-
common/constants.c2
401404
common/file/reader.c2
402405
common/library_list.c2
403406
common/source_mgr.c2

0 commit comments

Comments
 (0)