From 42f936742e00c81ffdb57870247fcec6d1449092 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Feb 2019 21:23:02 +0000 Subject: [PATCH] Add extra dead code elimination --- src/ir.cpp | 112 +++++++++++++++++++++++++++++++++++++++-------- src/ir_print.cpp | 19 ++++---- 2 files changed, 102 insertions(+), 29 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index c0bb6d462..aca3c3ce9 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1243,7 +1243,7 @@ irValue *ir_instr_phi(irProcedure *p, Array edges, Type *type) { i->Phi.type = type; for_array(j, edges) { - edges[j]->uses += 1; + if (edges[j]) edges[j]->uses += 1; } return v; } @@ -1287,7 +1287,7 @@ irValue *ir_instr_call(irProcedure *p, irValue *value, irValue *return_ptr, Arra if (value) value->uses += 1; if (return_ptr) return_ptr->uses += 1; for_array(i, args) { - args[i]->uses += 1; + if (args[i]) args[i]->uses += 1; } if (context_ptr) context_ptr->uses += 1; @@ -2776,8 +2776,8 @@ irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value, bool is value = ir_emit_conv(p, value, a); } - address->uses += 1; - value->uses += 1; + if (address) address->uses += 1; + if (value) value->uses += 1; Type *b = ir_type(value); @@ -2792,13 +2792,13 @@ irValue *ir_emit_load(irProcedure *p, irValue *address) { // if (is_type_boolean(t)) { // return ir_emit(p, ir_instr_load_bool(p, address)); // } - address->uses += 1; + if (address) address->uses += 1; return ir_emit(p, ir_instr_load(p, address)); } irValue *ir_emit_select(irProcedure *p, irValue *cond, irValue *t, irValue *f) { - cond->uses += 1; - t->uses += 1; - f->uses += 1; + if (cond) cond->uses += 1; + if (t) t->uses += 1; + if (f) f->uses += 1; return ir_emit(p, ir_instr_select(p, cond, t, f)); } @@ -2836,7 +2836,7 @@ void ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) { Type *t = type_deref(ir_type(address)); isize sz = type_size_of(t); - address->uses += 1; + if (address) address->uses += 1; if (!(gb_is_power_of_two(sz) && sz <= build_context.max_align)) { // TODO(bill): Is this a good idea? @@ -2879,13 +2879,12 @@ irValue *ir_copy_value_to_ptr(irProcedure *proc, irValue *val, Type *new_type, i ptr->Instr.Local.alignment = alignment; ir_emit_store(proc, ptr, val); - val->uses += 1; + if (val) val->uses += 1; return ptr; } irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type) { - data->uses += 1; return ir_emit(proc, ir_instr_conv(proc, irConv_bitcast, data, ir_type(data), type)); } @@ -2998,7 +2997,7 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array args, Pro Type *rt = reduce_tuple_to_single_type(results); if (pt->Proc.return_by_pointer) { irValue *return_ptr = nullptr; - if (use_return_ptr_hint) { + if (use_return_ptr_hint && p->return_ptr_hint_value != nullptr) { if (are_types_identical(type_deref(ir_type(p->return_ptr_hint_value)), rt)) { return_ptr = p->return_ptr_hint_value; p->return_ptr_hint_used = true; @@ -3147,6 +3146,8 @@ void ir_emit_return(irProcedure *proc, irValue *v) { ir_emit(proc, ir_instr_return(proc, v)); } + + if (v) v->uses += 1; } void ir_emit_jump(irProcedure *proc, irBlock *target_block) { @@ -3168,6 +3169,8 @@ void ir_emit_if(irProcedure *proc, irValue *cond, irBlock *true_block, irBlock * ir_add_edge(b, true_block); ir_add_edge(b, false_block); ir_start_block(proc, nullptr); + + if (cond) cond->uses += 1; } @@ -3201,7 +3204,6 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val_ptr, Type *map_ty ir_emit_store(proc, ir_emit_struct_ep(proc, h, 4), ir_const_uintptr(value_offset)); ir_emit_store(proc, ir_emit_struct_ep(proc, h, 5), ir_const_int(value_size)); - return ir_emit_load(proc, h); } @@ -9079,21 +9081,93 @@ void ir_begin_procedure_body(irProcedure *proc) { } -void ir_remove_dead_instr(irProcedure *proc) { +bool ir_remove_dead_instr(irProcedure *proc) { + isize elimination_count = 0; +retry: +#if 1 for_array(i, proc->blocks) { irBlock *b = proc->blocks[i]; b->index = cast(i32)i; - for (isize j = 0; j < b->instrs.count; j += 1) { + for (isize j = 0; j < b->instrs.count; /**/) { irValue *value = b->instrs[j]; GB_ASSERT_MSG(value->kind == irValue_Instr, "%.*s", LIT(proc->name)); irInstr *instr = &value->Instr; - if (instr->kind == irInstr_Load && value->uses == 0) { - gb_memmove(b->instrs.data+j, b->instrs.data+j+1, gb_size_of(irValue *)*(b->instrs.count-j-1)); - b->instrs.count -= 1; - continue; + if (value->uses == 0) { + switch (instr->kind) { + case irInstr_Load: + instr->Load.address->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_Local: + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_AtomicLoad: + instr->AtomicLoad.address->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_PtrOffset: + instr->PtrOffset.address->uses -= 1; + instr->PtrOffset.offset->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_ArrayElementPtr: + instr->ArrayElementPtr.address->uses -= 1; + instr->ArrayElementPtr.elem_index->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_StructElementPtr: + instr->StructElementPtr.address->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_StructExtractValue: + instr->StructExtractValue.address->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_UnionTagPtr: + instr->UnionTagPtr.address->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + case irInstr_UnionTagValue: + instr->UnionTagValue.address->uses -= 1; + array_ordered_remove(&b->instrs, j); + elimination_count += 1; + continue; + // case irInstr_Conv: + // // instr->Conv.value->uses -= 1; + // array_ordered_remove(&b->instrs, j); + // elimination_count += 1; + // continue; + // case irInstr_UnaryOp: + // // instr->UnaryOp.expr->uses -= 1; + // array_ordered_remove(&b->instrs, j); + // elimination_count += 1; + // continue; + // case irInstr_BinaryOp: + // // instr->BinaryOp.left->uses -= 1; + // // instr->BinaryOp.right->uses -= 1; + // array_ordered_remove(&b->instrs, j); + // elimination_count += 1; + // continue; + } } + j += 1; } } +#endif + if (elimination_count > 0) { + // gb_printf_err("Retry ir_remove_dead_instr, count: %td; %.*s\n", elimination_count, LIT(proc->name)); + elimination_count = 0; + goto retry; + } + return elimination_count > 0; } void ir_end_procedure_body(irProcedure *proc) { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 0cde805d8..a3fdc282b 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1780,19 +1780,18 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { bool return_by_pointer = proc_type->Proc.return_by_pointer; + isize param_index = 0; + ir_write_byte(f, '('); if (return_by_pointer) { GB_ASSERT(call->return_ptr != nullptr); ir_print_type(f, m, proc_type->Proc.results); ir_write_str_lit(f, "* "); ir_print_value(f, m, call->return_ptr, ir_type(call->return_ptr)); - if (call->args.count > 0) { - ir_write_str_lit(f, ", "); - } + param_index += 1; } - isize param_index = 0; if (call->args.count > 0) { TypeTuple *params = &proc_type->Proc.params->Tuple; if (proc_type->Proc.c_vararg) { @@ -1850,7 +1849,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { } } if (proc_type->Proc.calling_convention == ProcCC_Odin) { - if (param_index > 0 || return_by_pointer) ir_write_str_lit(f, ", "); + if (param_index > 0) ir_write_str_lit(f, ", "); ir_print_context_parameter_prefix(f, m); ir_print_value(f, m, call->context_ptr, t_context_ptr); @@ -1951,17 +1950,17 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { #endif ir_print_encoded_global(f, proc->name, ir_print_is_proc_global(m, proc)); + + isize param_index = 0; + ir_write_byte(f, '('); if (proc_type->return_by_pointer) { ir_print_type(f, m, reduce_tuple_to_single_type(proc_type->results)); ir_write_str_lit(f, "* sret noalias "); ir_write_str_lit(f, "%agg.result"); - if (param_count > 0) { - ir_write_string(f, str_lit(", ")); - } + param_index += 1; } - isize param_index = 0; if (param_count > 0) { TypeTuple *params = &proc_type->params->Tuple; for (isize i = 0; i < param_count; i++) { @@ -1992,7 +1991,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { } } if (proc_type->calling_convention == ProcCC_Odin) { - if (param_index > 0 || proc_type->return_by_pointer) ir_write_str_lit(f, ", "); + if (param_index > 0) ir_write_str_lit(f, ", "); ir_print_context_parameter_prefix(f, m); ir_write_str_lit(f, "%__.context_ptr");