diff options
| author | gingerBill <bill@gingerbill.org> | 2020-12-08 15:43:57 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-12-08 15:43:57 +0000 |
| commit | d7a5767aa3497f9b4b6f0ced955ce31fb019ef80 (patch) | |
| tree | f5afd9187de1a01433b82a9cc27f5258cc6802ed /src/ir.cpp | |
| parent | 15bf57e4e193f8e5a545517210526fb7144048e8 (diff) | |
If `ir_type_requires_mem_zero` is stored with zero, don't store again with the `zeroinitializer`
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 192 |
1 files changed, 114 insertions, 78 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 34b64562f..f69b25494 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -901,7 +901,7 @@ Array<irValue *> *ir_value_referrers(irValue *v) { //////////////////////////////////////////////////////////////// void ir_module_add_value (irModule *m, Entity *e, irValue *v); -void ir_emit_zero_init (irProcedure *p, irValue *address, Ast *expr); +irValue *ir_emit_zero_init (irProcedure *p, irValue *address, Ast *expr); irValue *ir_emit_comment (irProcedure *p, String text); irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value, bool is_volatile=false); irValue *ir_emit_load (irProcedure *p, irValue *address, i64 custom_align=0); @@ -3091,6 +3091,85 @@ void ir_pop_debug_location(irModule *m) { irValue *ir_emit_runtime_call(irProcedure *proc, char const *name_, Array<irValue *> args, Ast *expr = nullptr, ProcInlining inlining = ProcInlining_none); irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, Ast *expr = nullptr, ProcInlining inlining = ProcInlining_none); +bool ir_type_requires_mem_zero(Type *t) { + t = core_type(t); + isize sz = type_size_of(t); + if (t->kind == Type_SimdVector) { + return false; + } + + if (!(gb_is_power_of_two(sz) && sz <= build_context.max_align)) { + return true; + } + + enum : i64 {LARGE_SIZE = 64}; + if (sz > LARGE_SIZE) { + return true; + } + + switch (t->kind) { + case Type_Union: + return true; + case Type_Struct: + if (t->Struct.is_raw_union) { + return true; + } + if (t->Struct.is_packed) { + return false; + } else { + i64 packed_sized = 0; + for_array(i, t->Struct.fields) { + Entity *f = t->Struct.fields[i]; + if (f->kind == Entity_Variable) { + packed_sized += type_size_of(f->type); + } + } + return sz != packed_sized; + } + break; + case Type_Tuple: + if (t->Tuple.is_packed) { + return false; + } else { + i64 packed_sized = 0; + for_array(i, t->Tuple.variables) { + Entity *f = t->Tuple.variables[i]; + if (f->kind == Entity_Variable) { + packed_sized += type_size_of(f->type); + } + } + return sz != packed_sized; + } + break; + + case Type_DynamicArray: + case Type_Map: + case Type_BitField: + return true; + case Type_Array: + return ir_type_requires_mem_zero(t->Array.elem); + case Type_EnumeratedArray: + return ir_type_requires_mem_zero(t->EnumeratedArray.elem); + } + return false; +} + +irValue *ir_call_mem_zero(irProcedure *p, irValue *address, Ast *expr = nullptr) { + Type *t = type_deref(ir_type(address)); + // TODO(bill): Is this a good idea? + auto args = array_make<irValue *>(ir_allocator(), 2); + args[0] = ir_emit_conv(p, address, t_rawptr); + args[1] = ir_const_int(type_size_of(t)); + AstPackage *pkg_runtime = get_core_package(p->module->info, str_lit("runtime")); + if (p->entity != nullptr) { + String name = p->entity->token.string; + if (p->entity->pkg != pkg_runtime && !(name == "mem_zero" || name == "memset")) { + ir_emit_comment(p, str_lit("ZeroInit")); + return ir_emit_package_call(p, "runtime", "mem_zero", args, expr); + } + } + return nullptr; +} irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value, bool is_volatile) { Type *a = type_deref(ir_type(address)); @@ -3108,6 +3187,35 @@ irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value, bool is if (!is_type_untyped(b)) { GB_ASSERT_MSG(are_types_identical(core_type(a), core_type(b)), "%s %s", type_to_string(a), type_to_string(b)); } + + + if (value->kind == irValue_Constant) { + ExactValue const &v = value->Constant.value; + irValue *res = nullptr; + switch (v.kind) { + case ExactValue_Invalid: + res = ir_call_mem_zero(p, address); + if (res) { + return res; + } + goto end; + + case ExactValue_Compound: + // NOTE(bill): This is to enforce the zeroing of the padding + if (ir_type_requires_mem_zero(a)) { + res = ir_call_mem_zero(p, address); + if (res == nullptr || v.value_compound == nullptr) { + goto end; + } + if (is_exact_value_zero(v)) { + return res; + } + } + goto end; + } + } + +end:; return ir_emit(p, ir_instr_store(p, address, value, is_volatile)); } irValue *ir_emit_load(irProcedure *p, irValue *address, i64 custom_align) { @@ -3162,91 +3270,19 @@ void ir_value_set_debug_location(irProcedure *proc, irValue *v) { } } -bool ir_type_requires_mem_zero(Type *t) { - t = core_type(t); - isize sz = type_size_of(t); - if (t->kind == Type_SimdVector) { - return false; - } - - if (!(gb_is_power_of_two(sz) && sz <= build_context.max_align)) { - return true; - } - - enum : i64 {LARGE_SIZE = 64}; - if (sz > LARGE_SIZE) { - return true; - } - - switch (t->kind) { - case Type_Union: - return true; - case Type_Struct: - if (t->Struct.is_raw_union) { - return true; - } - if (t->Struct.is_packed) { - return false; - } else { - i64 packed_sized = 0; - for_array(i, t->Struct.fields) { - Entity *f = t->Struct.fields[i]; - if (f->kind == Entity_Variable) { - packed_sized += type_size_of(f->type); - } - } - return sz != packed_sized; - } - break; - case Type_Tuple: - if (t->Tuple.is_packed) { - return false; - } else { - i64 packed_sized = 0; - for_array(i, t->Tuple.variables) { - Entity *f = t->Tuple.variables[i]; - if (f->kind == Entity_Variable) { - packed_sized += type_size_of(f->type); - } - } - return sz != packed_sized; - } - break; - - case Type_DynamicArray: - case Type_Map: - case Type_BitField: - return true; - case Type_Array: - return ir_type_requires_mem_zero(t->Array.elem); - case Type_EnumeratedArray: - return ir_type_requires_mem_zero(t->EnumeratedArray.elem); - } - return false; -} - -void ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) { +irValue *ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) { gbAllocator a = ir_allocator(); Type *t = type_deref(ir_type(address)); if (address) address->uses += 1; if (ir_type_requires_mem_zero(t)) { - // TODO(bill): Is this a good idea? - auto args = array_make<irValue *>(a, 2); - args[0] = ir_emit_conv(p, address, t_rawptr); - args[1] = ir_const_int(type_size_of(t)); - AstPackage *pkg_runtime = get_core_package(p->module->info, str_lit("runtime")); - if (p->entity != nullptr) { - String name = p->entity->token.string; - if (p->entity->pkg != pkg_runtime && !(name == "mem_zero" || name == "memset")) { - ir_emit_comment(p, str_lit("ZeroInit")); - irValue *v = ir_emit_package_call(p, "runtime", "mem_zero", args, expr); - return; - } + irValue *res = ir_call_mem_zero(p, address, expr); + if (res) { + return res; } } - ir_emit(p, ir_instr_zero_init(p, address)); + return ir_emit(p, ir_instr_zero_init(p, address)); } irValue *ir_emit_comment(irProcedure *p, String text) { |