Skip to content

Commit 7f91bfc

Browse files
committed
ir: fix updating temps for forward refs
1 parent 2faf5c0 commit 7f91bfc

File tree

2 files changed

+82
-78
lines changed

2 files changed

+82
-78
lines changed

ir/context.c2

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
561561

562562
const char* name = c.pool.idx2str(s.name);
563563
bool print = false;
564+
//print = true;
564565

565566
//c.dump_function(c.tmp_info, name);
566567
// causes crash
@@ -679,7 +680,6 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
679680
}
680681

681682
s.f.info = fi2;
682-
// TODO use Ref.StackSlot that doesn't change (= not temp)
683683
c.tmp_info.clear();
684684
c.block_order.clear();
685685

@@ -690,6 +690,7 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
690690
c.create_ssa(id, fi2, name, print);
691691

692692
if (print) c.print_function(id, fi2, "after create SSA");
693+
693694
if (c.inserter.needsFixup()) {
694695
c.fixup_function(fi2);
695696
if (print) c.print_function(id, fi2, "after fixup");
@@ -700,7 +701,7 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
700701
if (print) c.print_function(id, fi2, "after eliminate copies");
701702

702703
c.removeNone(fi2);
703-
if (print) c.print_function(id, fi2, "remove none");
704+
if (print) c.print_function(id, fi2, "after remove none");
704705
}
705706

706707
fn bool empty_block(const Block* b, const InstrList* instructions) {

ir/ssa.c2

Lines changed: 79 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ fn void Context.create_ssa(Context* c, SymbolId id, FunctionInfo* fi, const char
152152
c.active_blocks.reset(num_blocks);
153153

154154
if (print) c.print_function(id, fi, "after collector.fill");
155-
//if (num_blocks == 1) return;
156155
//c.collector.dump();
157156
//c.revlist.dump();
158157

@@ -179,7 +178,7 @@ fn void Context.create_ssa(Context* c, SymbolId id, FunctionInfo* fi, const char
179178
// Note: block 0 will usually never have reads, but can have after optimizations with loops
180179
for (u32 i = 0; i < num_blocks; i++) {
181180
u32 blk_id = i;
182-
c.active_blocks.set(i);
181+
// Note: dont add start block as active, since it might provide write itself (in loops)
183182
const BlockIndex* bi = c.collector.getBlock(blk_id);
184183
for (u32 j = bi.rd_start; j < bi.rd_start + bi.rd_count; j++) {
185184
ReadSlotAccess* ra = &c.collector.reads[j];
@@ -200,9 +199,6 @@ fn void Context.create_ssa(Context* c, SymbolId id, FunctionInfo* fi, const char
200199
}
201200
}
202201

203-
// if getcount != 0:
204-
// TODO also add 'write' (if not already), so that next calls dont redo the same work
205-
206202
// Note: results.getCount() can be 0 if only passing variable to calls
207203
if (results.getCount()) {
208204
Ref ref;
@@ -251,62 +247,6 @@ fn void Context.create_ssa(Context* c, SymbolId id, FunctionInfo* fi, const char
251247
//c.inserter.dump();
252248
}
253249

254-
fn void Context.eliminateCopies(Context* c, FunctionInfo* fi) {
255-
// do copy eliminination. Try 1 pass (if possible)
256-
// otherwise mark in prev run and apply here
257-
c.copies.clear();
258-
259-
// Note: the filling could be done in previous loop already!
260-
Instr* all = fi.instructions.get(0);
261-
for (u32 i=0; i<fi.instructions.getCount(); i++) {
262-
Instr* instr = &all[i];
263-
if (instr.isCopy()) {
264-
c.copies.add(i, instr.args[0]);
265-
// TODO also check if args is already in list for nested copies
266-
instr.clear();
267-
} else {
268-
if (instr.isPhi()) {
269-
PhiClause* clauses = fi.phis.get(instr.phi_clauses.start);
270-
for (u32 j=0; j<instr.phi_clauses.count; j++) {
271-
Ref* r = &clauses[j].ref;
272-
if (r.isTemp()) {
273-
Ref* copy = c.copies.find(r.value);
274-
if (copy) *r = *copy;
275-
}
276-
}
277-
} else {
278-
Ref* r = &instr.args[0];
279-
if (r.isTemp()) {
280-
Ref* copy = c.copies.find(r.value);
281-
if (copy) instr.args[0] = *copy;
282-
}
283-
r = &instr.args[1];
284-
if (r.isTemp()) {
285-
Ref* copy = c.copies.find(r.value);
286-
if (copy) instr.args[1] = *copy;
287-
} else if (r.isRefList()) { // can only occur on args[1]
288-
Ref* refs = fi.refs.get(r.value);
289-
u32 idx = 0;
290-
while (1) {
291-
Ref* r2 = &refs[idx];
292-
if (r2.isTemp()) {
293-
Ref* copy = c.copies.find(r2.value);
294-
if (copy) refs[idx] = *copy;
295-
}
296-
if (!r2.isValid()) break;
297-
idx++;
298-
}
299-
}
300-
}
301-
}
302-
}
303-
}
304-
305-
fn void Context.removeNone(Context* c, FunctionInfo* fi) {
306-
c.inserter.clear();
307-
c.fixup_function(fi);
308-
}
309-
310250
// TODO pas Optimizer? (with Context, FunctionInfo, other?)
311251
// TODO dont pass info as separate arg, but combine with Context?
312252
fn Ref Context.checkPredBlock(Context* c, BlockId blk_id, u16 slot, u32 indent, FunctionInfo* fi) {
@@ -334,6 +274,7 @@ fn Ref Context.checkPredBlock(Context* c, BlockId blk_id, u16 slot, u32 indent,
334274
PhiCache results.init();
335275
for (u32 j = revs.start; j < rev_end; j++) {
336276
u32 rev_blk = c.revlist.getRev(j);
277+
// TODO do check block itself, but not more (for loops)
337278
if (!c.active_blocks.get(rev_blk)) {
338279
Ref ref2 = c.checkPredBlock(rev_blk, slot, indent+1, fi);
339280
if (ref2.isValid()) {
@@ -388,6 +329,62 @@ fn Ref Context.checkPredBlock(Context* c, BlockId blk_id, u16 slot, u32 indent,
388329
return ref;
389330
}
390331

332+
fn void Context.eliminateCopies(Context* c, FunctionInfo* fi) {
333+
// do copy eliminination. Try 1 pass (if possible)
334+
// otherwise mark in prev run and apply here
335+
c.copies.clear();
336+
337+
// Note: the filling could be done in previous loop already!
338+
Instr* all = fi.instructions.get(0);
339+
for (u32 i=0; i<fi.instructions.getCount(); i++) {
340+
Instr* instr = &all[i];
341+
if (instr.isCopy()) {
342+
c.copies.add(i, instr.args[0]);
343+
// TODO also check if args is already in list for nested copies
344+
instr.clear();
345+
} else {
346+
if (instr.isPhi()) {
347+
PhiClause* clauses = fi.phis.get(instr.phi_clauses.start);
348+
for (u32 j=0; j<instr.phi_clauses.count; j++) {
349+
Ref* r = &clauses[j].ref;
350+
if (r.isTemp()) {
351+
Ref* copy = c.copies.find(r.value);
352+
if (copy) *r = *copy;
353+
}
354+
}
355+
} else {
356+
Ref* r = &instr.args[0];
357+
if (r.isTemp()) {
358+
Ref* copy = c.copies.find(r.value);
359+
if (copy) instr.args[0] = *copy;
360+
}
361+
r = &instr.args[1];
362+
if (r.isTemp()) {
363+
Ref* copy = c.copies.find(r.value);
364+
if (copy) instr.args[1] = *copy;
365+
} else if (r.isRefList()) { // can only occur on args[1]
366+
Ref* refs = fi.refs.get(r.value);
367+
u32 idx = 0;
368+
while (1) {
369+
Ref* r2 = &refs[idx];
370+
if (r2.isTemp()) {
371+
Ref* copy = c.copies.find(r2.value);
372+
if (copy) refs[idx] = *copy;
373+
}
374+
if (!r2.isValid()) break;
375+
idx++;
376+
}
377+
}
378+
}
379+
}
380+
}
381+
}
382+
383+
fn void Context.removeNone(Context* c, FunctionInfo* fi) {
384+
c.inserter.clear();
385+
c.fixup_function(fi);
386+
}
387+
391388
fn void Context.fixup_function(Context* c, FunctionInfo* fi) {
392389
// only change instructions!, not blocks (except to update instr start+count)
393390
u32 old_icount = fi.instructions.getCount();
@@ -398,7 +395,7 @@ fn void Context.fixup_function(Context* c, FunctionInfo* fi) {
398395

399396
const Instr* i_old = fi.instructions.get(0);
400397
u32 blk_count = fi.blocks.getCount();
401-
// TODO similar code in Context.finalizeFunction, try to share
398+
// 1st step: insert new instructions, remove None instructions
402399
u32 new_index = 0;
403400
for (u32 i=0; i<blk_count; i++) {
404401
Block* b = fi.blocks.get(i);
@@ -421,8 +418,26 @@ fn void Context.fixup_function(Context* c, FunctionInfo* fi) {
421418
is.copy(&i_old[j]);
422419
c.conversion.set(j, new_index);
423420

424-
// update TEMP refs (do afterwards to include forward and backward)
425-
// can also do outside loop (inside better for cache)
421+
new_index++;
422+
}
423+
b.instr.start = new_start;
424+
b.instr.count = new_index - new_start;
425+
}
426+
427+
i_new.swap(&fi.instructions);
428+
i_new.free();
429+
c.inserter.clear();
430+
431+
// 2nd step: update all temps (needed after first loop for forwards refs)
432+
Instr* instrs = fi.instructions.get(0);
433+
for (u32 i=0; i<blk_count; i++) {
434+
Block* b = fi.blocks.get(i);
435+
u32 i_start = b.instr.start;
436+
u32 i_count = b.instr.count;
437+
//stdio.printf(" B[%d] %d - %d\n", i, i_start, i_start+i_count-1);
438+
for (u32 j=i_start; j<i_start+i_count; j++) {
439+
Instr* is = &instrs[j];
440+
426441
if (is.isPhi()) {
427442
PhiClause* clauses = fi.phis.get(is.phi_clauses.start);
428443
for (u32 p=0; p<is.phi_clauses.count; p++) {
@@ -445,19 +460,7 @@ fn void Context.fixup_function(Context* c, FunctionInfo* fi) {
445460
}
446461
}
447462
}
448-
new_index++;
449463
}
450-
b.instr.start = new_start;
451-
b.instr.count = new_index - new_start;
452-
}
453-
// update refs used inside Phi instructions
454-
for (u32 i=0; i<fi.phis.getCount(); i++) {
455-
PhiClause* pc = fi.phis.get(i);
456-
if (pc.ref.isTemp()) pc.ref.value = c.conversion.get(pc.ref.value);
457464
}
458-
459-
i_new.swap(&fi.instructions);
460-
i_new.free();
461-
c.inserter.clear();
462465
}
463466

0 commit comments

Comments
 (0)