@@ -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?
312252fn 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+
391388fn 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