From c96e0afbf1060dc719356b8c82601c45ad688110 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 7 Nov 2022 23:02:21 +0000 Subject: Begin work on implementing the new `map` internals --- src/check_expr.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 9e48fd8ad..043b98173 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1364,7 +1364,6 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type); bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type); if (key || value) { - poly->Map.entry_type = nullptr; poly->Map.internal_type = nullptr; poly->Map.lookup_result_type = nullptr; init_map_internal_types(poly); -- cgit v1.2.3 From 810a1eee41cc8e047759c8934af70d6e68113082 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 8 Nov 2022 11:13:46 +0000 Subject: Remove the need for `type->Map.internal_type` and replace with the definition of `runtime.Raw_Map` --- src/check_expr.cpp | 1 - src/check_type.cpp | 24 ++---------------------- src/checker.cpp | 11 +++++++---- src/llvm_backend_debug.cpp | 3 ++- src/llvm_backend_general.cpp | 20 ++------------------ src/llvm_backend_utility.cpp | 17 +++++++---------- src/types.cpp | 2 +- 7 files changed, 21 insertions(+), 57 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 043b98173..c2753e979 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1364,7 +1364,6 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type); bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type); if (key || value) { - poly->Map.internal_type = nullptr; poly->Map.lookup_result_type = nullptr; init_map_internal_types(poly); return true; diff --git a/src/check_type.cpp b/src/check_type.cpp index 39344fb2c..5d7f8d7b5 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2198,34 +2198,14 @@ void map_cell_size_and_len(Type *type, i64 *size_, i64 *len_) { void init_map_internal_types(Type *type) { GB_ASSERT(type->kind == Type_Map); GB_ASSERT(t_allocator != nullptr); - if (type->Map.internal_type != nullptr) return; + if (type->Map.lookup_result_type != nullptr) return; Type *key = type->Map.key; Type *value = type->Map.value; GB_ASSERT(key != nullptr); GB_ASSERT(value != nullptr); - Type *generated_struct_type = alloc_type_struct(); - - /* - struct { - data: uintptr, - size: uintptr, - allocator: runtime.Allocator, - } - */ - Scope *s = create_scope(nullptr, builtin_pkg->scope); - - auto fields = slice_make(permanent_allocator(), 3); - fields[0] = alloc_entity_field(s, make_token_ident(str_lit("data")), t_uintptr, false, 0, EntityState_Resolved); - fields[1] = alloc_entity_field(s, make_token_ident(str_lit("size")), t_uintptr, false, 1, EntityState_Resolved); - fields[2] = alloc_entity_field(s, make_token_ident(str_lit("allocator")), t_allocator, false, 2, EntityState_Resolved); - - generated_struct_type->Struct.fields = fields; - type_set_offsets(generated_struct_type); - - type->Map.internal_type = generated_struct_type; - type->Map.lookup_result_type = make_optional_ok_type(value); + type->Map.lookup_result_type = make_optional_ok_type(value); } void add_map_key_type_dependencies(CheckerContext *ctx, Type *key) { diff --git a/src/checker.cpp b/src/checker.cpp index d5d2c6026..fa3ef245b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1933,7 +1933,8 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { init_map_internal_types(bt); add_type_info_type_internal(c, bt->Map.key); add_type_info_type_internal(c, bt->Map.value); - add_type_info_type_internal(c, bt->Map.internal_type); + add_type_info_type_internal(c, t_uintptr); // hash value + add_type_info_type_internal(c, t_allocator); break; case Type_Tuple: @@ -2155,7 +2156,8 @@ void add_min_dep_type_info(Checker *c, Type *t) { init_map_internal_types(bt); add_min_dep_type_info(c, bt->Map.key); add_min_dep_type_info(c, bt->Map.value); - add_min_dep_type_info(c, bt->Map.internal_type); + add_min_dep_type_info(c, t_uintptr); // hash value + add_min_dep_type_info(c, t_allocator); break; case Type_Tuple: @@ -2845,9 +2847,10 @@ void init_core_map_type(Checker *c) { if (t_map_info != nullptr) { return; } - t_map_info = find_core_type(c, str_lit("Map_Info")); - t_map_cell_info = find_core_type(c, str_lit("Map_Cell_Info")); init_mem_allocator(c); + t_map_info = find_core_type(c, str_lit("Map_Info")); + t_map_cell_info = find_core_type(c, str_lit("Map_Cell_Info")); + t_raw_map = find_core_type(c, str_lit("Raw_Map")); } void init_preload(Checker *c) { diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 8a98b7f39..e69424929 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -671,7 +671,8 @@ void lb_debug_complete_types(lbModule *m) { break; case Type_Map: - bt = bt->Map.internal_type; + GB_ASSERT(t_raw_map != nullptr); + bt = base_type(t_raw_map); /*fallthrough*/ case Type_Struct: if (file == nullptr) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 69b1fce20..ffc7a1496 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1931,24 +1931,8 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_Map: init_map_internal_types(type); - { - Type *internal_type = type->Map.internal_type; - GB_ASSERT(internal_type->kind == Type_Struct); - - m->internal_type_level -= 1; - defer (m->internal_type_level += 1); - - unsigned field_count = cast(unsigned)(internal_type->Struct.fields.count); - GB_ASSERT(field_count == 3); - - LLVMTypeRef fields[3] = { - lb_type(m, t_uintptr), // data - lb_type(m, t_uintptr), // len - lb_type(m, t_allocator), // allocator - }; - - return LLVMStructTypeInContext(ctx, fields, field_count, false); - } + GB_ASSERT(t_raw_map != nullptr); + return lb_type_internal(m, t_raw_map); case Type_Struct: { diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index cbe690155..f4d17c7a2 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -990,15 +990,13 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { } } else if (is_type_map(t)) { init_map_internal_types(t); - Type *itp = alloc_type_pointer(t->Map.internal_type); + Type *itp = alloc_type_pointer(t_raw_map); s = lb_emit_transmute(p, s, itp); - Type *gst = t->Map.internal_type; - GB_ASSERT(gst->kind == Type_Struct); switch (index) { - case 0: result_type = get_struct_field_type(gst, 0); break; - case 1: result_type = get_struct_field_type(gst, 1); break; - case 2: result_type = get_struct_field_type(gst, 2); break; + case 0: result_type = get_struct_field_type(t_raw_map, 0); break; + case 1: result_type = get_struct_field_type(t_raw_map, 1); break; + case 2: result_type = get_struct_field_type(t_raw_map, 2); break; } } else if (is_type_array(t)) { return lb_emit_array_epi(p, s, index); @@ -1131,11 +1129,10 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { case Type_Map: { init_map_internal_types(t); - Type *gst = t->Map.internal_type; switch (index) { - case 0: result_type = get_struct_field_type(gst, 0); break; - case 1: result_type = get_struct_field_type(gst, 1); break; - case 2: result_type = get_struct_field_type(gst, 2); break; + case 0: result_type = get_struct_field_type(t_raw_map, 0); break; + case 1: result_type = get_struct_field_type(t_raw_map, 1); break; + case 2: result_type = get_struct_field_type(t_raw_map, 2); break; } } break; diff --git a/src/types.cpp b/src/types.cpp index 220d1a6ab..9b2fd30d4 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -226,7 +226,6 @@ struct TypeProc { TYPE_KIND(Map, struct { \ Type *key; \ Type *value; \ - Type *internal_type; \ Type *lookup_result_type; \ }) \ TYPE_KIND(Struct, TypeStruct) \ @@ -686,6 +685,7 @@ gb_global Type *t_source_code_location_ptr = nullptr; gb_global Type *t_map_info = nullptr; gb_global Type *t_map_cell_info = nullptr; +gb_global Type *t_raw_map = nullptr; gb_global Type *t_equal_proc = nullptr; -- cgit v1.2.3 From a71daee545f5425aae971c0e00d7064fe53d64c7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 8 Nov 2022 14:58:05 +0000 Subject: Allow for `-use-static-map-calls` which generates a get procedure per `map`; add `runtime.map_get` --- core/runtime/dynamic_map_internal.odin | 104 ++++++++++++++++++-- src/build_settings.cpp | 2 + src/check_expr.cpp | 15 ++- src/checker.cpp | 4 + src/llvm_backend.cpp | 172 ++++++++++++++++++++++++++++++--- src/llvm_backend.hpp | 1 + src/llvm_backend_general.cpp | 1 + src/llvm_backend_stmt.cpp | 26 +++-- src/llvm_backend_utility.cpp | 4 +- src/main.cpp | 6 ++ src/types.cpp | 1 + 11 files changed, 302 insertions(+), 34 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index 7e453b4b8..b9b10dd40 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -137,6 +137,47 @@ map_cell_index_dynamic_const :: proc "contextless" (base: uintptr, #no_alias inf return base + (cell_index * size_of_cell) + (data_index * size_of_type) } +// We always round the capacity to a power of two so this becomes [16]Foo, which +// works out to [4]Cell(Foo). +// +// The following compile-time procedure indexes such a [N]Cell(T) structure as +// if it were a flat array accounting for the internal padding introduced by the +// Cell structure. +map_cell_index_static :: #force_inline proc "contextless" (cells: [^]Map_Cell($T), index: uintptr) -> ^T #no_bounds_check { + N :: size_of(Map_Cell(T){}.data) / size_of(T) when size_of(T) > 0 else 1 + + #assert(N <= MAP_CACHE_LINE_SIZE) + + // No padding case, can treat as a regular array of []T. + when size_of(Map_Cell(T)) == size_of([N]T) { + return &([^]T)(cells)[index] + } + + // Likely case, N is a power of two because T is a power of two. + when (N & (N - 1)) == 0 { + // Compute the integer log 2 of N, this is the shift amount to index the + // correct cell. Odin's intrinsics.count_leading_zeros does not produce a + // constant, hence this approach. We only need to check up to N = 64. + SHIFT :: 1 when N < 2 else + 2 when N < 4 else + 3 when N < 8 else + 4 when N < 16 else + 5 when N < 32 else 6 + #assert(SHIFT <= MAP_CACHE_LINE_LOG2) + // Unique case, no need to index data here since only one element. + when N == 1 { + return &cells[index >> SHIFT].data[0] + } else { + return &cells[index >> SHIFT].data[index & (N - 1)] + } + } + + // Least likely (and worst case), we pay for a division operation but we + // assume the compiler does not actually generate a division. N will be in the + // range [1, CACHE_LINE_SIZE) and not a power of two. + return &cells[index / N].data[index % N] +} + // len() for map map_len :: #force_inline proc "contextless" (m: Raw_Map) -> int { return m.len @@ -721,27 +762,72 @@ map_clear_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #n } +map_kvh_data_static :: #force_inline proc "contextless" (m: $T/map[$K]$V) -> ([^]Map_Cell(K), [^]Map_Cell(V), [^]Map_Hash) { + H :: Map_Hash + capacity := uintptr(cap(m)) + ks := ([^]Map_Cell(K))(map_data(transmute(Raw_Map)m)) + vs := ([^]Map_Cell(V))(map_cell_index_static(ks, capacity)) + hs := ([^]Map_Cell(H))(map_cell_index_static(vs, capacity)) + return ks, vs, ([^]Map_Hash)(hs) +} + + +map_get :: proc "contextless" (m: $T/map[$K]$V, key: K) -> (stored_key: K, stored_value: V, ok: bool) { + rm := transmute(Raw_Map)m + if rm.len == 0 { + return + } + info := intrinsics.type_map_info(T) + key := key + + h := info.key_hasher(&key, 0) + pos := map_desired_position(rm, h) + distance := uintptr(0) + mask := (uintptr(1) << map_log2_cap(rm)) - 1 + ks, vs, hs := map_kvh_data_static(m) + for { + element_hash := hs[pos] + if map_hash_is_empty(element_hash) { + return + } else if distance > map_probe_distance(rm, element_hash, pos) { + return + } else if element_hash == h { + element_key := map_cell_index_static(ks, pos) + if info.key_equal(&key, rawptr(element_key)) { + element_value := map_cell_index_static(vs, pos) + stored_key = (^K)(element_key)^ + stored_value = (^V)(element_value)^ + ok = true + return + } + + } + pos = (pos + 1) & mask + distance += 1 + } +} + __dynamic_map_get :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, key: rawptr) -> (ptr: rawptr) { if m.len == 0 { return nil } h := info.key_hasher(key, 0) - p := map_desired_position(m, h) - d := uintptr(0) - c := (uintptr(1) << map_log2_cap(m)) - 1 + pos := map_desired_position(m, h) + distance := uintptr(0) + mask := (uintptr(1) << map_log2_cap(m)) - 1 ks, vs, hs, _, _ := map_kvh_data_dynamic(m, info) for { - element_hash := hs[p] + element_hash := hs[pos] if map_hash_is_empty(element_hash) { return nil - } else if d > map_probe_distance(m, element_hash, p) { + } else if distance > map_probe_distance(m, element_hash, pos) { return nil - } else if element_hash == h && info.key_equal(key, rawptr(map_cell_index_dynamic(ks, info.ks, p))) { - return rawptr(map_cell_index_dynamic(vs, info.vs, p)) + } else if element_hash == h && info.key_equal(key, rawptr(map_cell_index_dynamic(ks, info.ks, pos))) { + return rawptr(map_cell_index_dynamic(vs, info.vs, pos)) } - p = (p + 1) & c - d += 1 + pos = (pos + 1) & mask + distance += 1 } } diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 8067d1d01..1cd2899c4 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -307,6 +307,8 @@ struct BuildContext { bool disallow_rtti; + bool use_static_map_calls; + RelocMode reloc_mode; bool disable_red_zone; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c2753e979..045b22ca2 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3244,7 +3244,12 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint check_assignment(c, x, yt->Map.key, str_lit("map 'not_in'")); } - add_package_dependency(c, "runtime", "__dynamic_map_get"); + if (build_context.use_static_map_calls) { + add_package_dependency(c, "runtime", "map_desired_position"); + add_package_dependency(c, "runtime", "map_probe_distance"); + } else { + add_package_dependency(c, "runtime", "__dynamic_map_get"); + } } else if (is_type_bit_set(rhs_type)) { Type *yt = base_type(rhs_type); @@ -8992,8 +8997,14 @@ ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_h o->type = t->Map.value; o->expr = node; - add_package_dependency(c, "runtime", "__dynamic_map_get"); + add_package_dependency(c, "runtime", "__dynamic_map_set"); + if (build_context.use_static_map_calls) { + add_package_dependency(c, "runtime", "map_desired_position"); + add_package_dependency(c, "runtime", "map_probe_distance"); + } else { + add_package_dependency(c, "runtime", "__dynamic_map_get"); + } return Expr_Expr; } diff --git a/src/checker.cpp b/src/checker.cpp index 75a6da6fa..d48b37b26 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -926,6 +926,10 @@ void init_universal(void) { Type *hasher_args[2] = {t_rawptr, t_uintptr}; t_hasher_proc = alloc_type_proc_from_types(hasher_args, 2, t_uintptr, false, ProcCC_Contextless); + + Type *map_get_args[2] = {/*map*/t_rawptr, /*key*/t_rawptr}; + t_map_get_proc = alloc_type_proc_from_types(map_get_args, 2, t_rawptr, false, ProcCC_Contextless); + } // Constants diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 629daf1c9..2b95c5b2f 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -157,8 +157,8 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) { static u32 proc_index = 0; - char buf[16] = {}; - isize n = gb_snprintf(buf, 16, "__$equal%u", ++proc_index); + char buf[32] = {}; + isize n = gb_snprintf(buf, 32, "__$equal%u", ++proc_index); char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); String proc_name = make_string_c(str); @@ -280,8 +280,8 @@ lbValue lb_simple_compare_hash(lbProcedure *p, Type *type, lbValue data, lbValue i64 sz = type_size_of(type); if (1 <= sz && sz <= 16) { - char name[20] = {}; - gb_snprintf(name, 20, "default_hasher%d", cast(i32)sz); + char name[32] = {}; + gb_snprintf(name, 32, "default_hasher%d", cast(i32)sz); auto args = array_make(permanent_allocator(), 2); args[0] = data; @@ -310,8 +310,8 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { static u32 proc_index = 0; - char buf[16] = {}; - isize n = gb_snprintf(buf, 16, "__$hasher%u", ++proc_index); + char buf[32] = {}; + isize n = gb_snprintf(buf, 32, "__$hasher%u", ++proc_index); char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); String proc_name = make_string_c(str); @@ -454,6 +454,141 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { } +lbValue lb_get_map_get_proc_for_type(lbModule *m, Type *type) { + GB_ASSERT(build_context.use_static_map_calls); + type = base_type(type); + GB_ASSERT(type->kind == Type_Map); + + + lbProcedure **found = map_get(&m->map_get_procs, type); + if (found) { + GB_ASSERT(*found != nullptr); + return {(*found)->value, (*found)->type}; + } + static u32 proc_index = 0; + + char buf[32] = {}; + isize n = gb_snprintf(buf, 32, "__$map_get%u", ++proc_index); + char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); + String proc_name = make_string_c(str); + + lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_get_proc); + map_set(&m->map_get_procs, type, p); + lb_begin_procedure_body(p); + defer (lb_end_procedure_body(p)); + + LLVMValueRef x = LLVMGetParam(p->value, 0); + LLVMValueRef y = LLVMGetParam(p->value, 1); + lbValue map_ptr = {x, t_rawptr}; + lbValue key_ptr = {y, t_rawptr}; + + LLVMAttributeRef nonnull_attr = lb_create_enum_attribute(m->ctx, "nonnull"); + LLVMAttributeRef noalias_attr = lb_create_enum_attribute(m->ctx, "noalias"); + LLVMAddAttributeAtIndex(p->value, 1+0, nonnull_attr); + LLVMAddAttributeAtIndex(p->value, 1+0, noalias_attr); + LLVMAddAttributeAtIndex(p->value, 1+1, nonnull_attr); + LLVMAddAttributeAtIndex(p->value, 1+1, noalias_attr); + + map_ptr = lb_emit_conv(p, map_ptr, t_raw_map_ptr); + lbValue map = lb_emit_load(p, map_ptr); + + key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key)); + lbValue key = lb_emit_load(p, key_ptr); + + lbValue h = lb_gen_map_key_hash(p, key, type->Map.key, nullptr); + lbAddr pos = lb_add_local_generated(p, t_uintptr, false); + lbAddr distance = lb_add_local_generated(p, t_uintptr, true); + lbValue capacity = lb_map_cap(p, map); + lbValue mask = lb_emit_conv(p, lb_emit_arith(p, Token_Sub, capacity, lb_const_int(m, t_int, 1), t_int), t_uintptr); + + { + auto args = array_make(heap_allocator(), 2); + args[0] = map; + args[1] = h; + lb_addr_store(p, pos, lb_emit_runtime_call(p, "map_desired_position", args)); + } + lbValue zero_uintptr = lb_const_int(m, t_uintptr, 0); + lbValue one_uintptr = lb_const_int(m, t_uintptr, 1); + + lbValue ks = lb_map_data_uintptr(p, map); + lbValue vs = lb_map_cell_index_static(p, type->Map.key, ks, capacity); + lbValue hs = lb_map_cell_index_static(p, type->Map.value, vs, capacity); + + ks = lb_emit_conv(p, ks, alloc_type_pointer(type->Map.key)); + vs = lb_emit_conv(p, vs, alloc_type_pointer(type->Map.value)); + hs = lb_emit_conv(p, hs, alloc_type_pointer(t_uintptr)); + + // lbValue res = + // LLVMBuildRet(p->builder, res.value); + + lbBlock *loop = lb_create_block(p, "loop"); + lbBlock *probe_block = lb_create_block(p, "probe"); + lbBlock *increment_block = lb_create_block(p, "increment"); + lbBlock *hash_compare_block = lb_create_block(p, "hash_compare"); + lbBlock *key_compare_block = lb_create_block(p, "key_compare"); + lbBlock *value_block = lb_create_block(p, "value"); + lbBlock *nil_block = lb_create_block(p, "nil"); + + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbValue element_hash = lb_emit_load(p, lb_emit_ptr_offset(p, hs, lb_addr_load(p, pos))); + { + // if element_hash == 0 { return nil } + lb_emit_if(p, lb_emit_comp(p, Token_CmpEq, element_hash, zero_uintptr), nil_block, probe_block); + } + + lb_start_block(p, probe_block); + { + auto args = array_make(heap_allocator(), 3); + args[0] = map; + args[1] = element_hash; + args[2] = lb_addr_load(p, pos); + lbValue probe_distance = lb_emit_runtime_call(p, "map_probe_distance", args); + lbValue cond = lb_emit_comp(p, Token_Gt, lb_addr_load(p, distance), probe_distance); + lb_emit_if(p, cond, nil_block, hash_compare_block); + } + + lb_start_block(p, hash_compare_block); + { + lb_emit_if(p, lb_emit_comp(p, Token_CmpEq, element_hash, h), key_compare_block, increment_block); + } + + lb_start_block(p, key_compare_block); + { + lbValue element_key = lb_map_cell_index_static(p, type->Map.key, ks, lb_addr_load(p, pos)); + element_key = lb_emit_conv(p, element_key, ks.type); + lbValue cond = lb_emit_comp(p, Token_CmpEq, lb_emit_load(p, element_key), key); + lb_emit_if(p, cond, value_block, increment_block); + } + + lb_start_block(p, value_block); + { + lbValue element_value = lb_map_cell_index_static(p, type->Map.value, vs, lb_addr_load(p, pos)); + element_value = lb_emit_conv(p, element_value, t_rawptr); + LLVMBuildRet(p->builder, element_value.value); + } + + lb_start_block(p, increment_block); + { + lbValue pp = lb_addr_load(p, pos); + pp = lb_emit_arith(p, Token_Add, pp, one_uintptr, t_uintptr); + pp = lb_emit_arith(p, Token_And, pp, mask, t_uintptr); + lb_addr_store(p, pos, pp); + lb_emit_increment(p, distance.addr); + } + lb_emit_jump(p, loop); + + lb_start_block(p, nil_block); + { + lbValue res = lb_const_nil(m, t_rawptr); + LLVMBuildRet(p->builder, res.value); + } + + + return {p->value, p->type}; +} + lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) { lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, expr); if (found) { @@ -626,16 +761,27 @@ lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map, lbVa Type *map_type = base_type(map.type); GB_ASSERT(map_type->kind == Type_Map); + lbValue ptr = {}; + lbValue key_ptr = lb_address_from_load_or_generate_local(p, key); key_ptr = lb_emit_conv(p, key_ptr, t_rawptr); - auto args = array_make(permanent_allocator(), 3); - args[0] = lb_emit_transmute(p, map, t_raw_map); - args[1] = lb_gen_map_info_ptr(p->module, map_type); - args[2] = key_ptr; + if (build_context.use_static_map_calls) { + lbValue map_get_proc = lb_get_map_get_proc_for_type(p->module, map_type); - lbValue ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args); + auto args = array_make(permanent_allocator(), 2); + args[0] = lb_address_from_load_or_generate_local(p, map); + args[1] = key_ptr; + ptr = lb_emit_call(p, map_get_proc, args); + } else { + auto args = array_make(permanent_allocator(), 3); + args[0] = lb_emit_transmute(p, map, t_raw_map); + args[1] = lb_gen_map_info_ptr(p->module, map_type); + args[2] = key_ptr; + + ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args); + } return lb_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value)); } @@ -1206,6 +1352,10 @@ WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) { lbProcedure *p = m->hasher_procs.entries[i].value; lb_run_function_pass_manager(default_function_pass_manager, p); } + for_array(i, m->map_get_procs.entries) { + lbProcedure *p = m->map_get_procs.entries[i].value; + lb_run_function_pass_manager(default_function_pass_manager, p); + } return 0; } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 6c7c2e392..f9fe6cff0 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -144,6 +144,7 @@ struct lbModule { PtrMap equal_procs; PtrMap hasher_procs; + PtrMap map_get_procs; u32 nested_type_name_guid; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index e1a926255..859542fb5 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -67,6 +67,7 @@ void lb_init_module(lbModule *m, Checker *c) { map_init(&m->function_type_map, a); map_init(&m->equal_procs, a); map_init(&m->hasher_procs, a); + map_init(&m->map_get_procs, a); array_init(&m->procedures_to_generate, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); map_init(&m->debug_values, a); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 3e4846f02..6b83068ce 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -371,24 +371,30 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu } lbValue lb_map_cell_index_static(lbProcedure *p, Type *type, lbValue cells_ptr, lbValue index) { - i64 size, N; - i64 sz = type_size_of(type); - map_cell_size_and_len(type, &size, &N); + i64 size, len; + i64 elem_sz = type_size_of(type); + map_cell_size_and_len(type, &size, &len); - index = lb_emit_conv(p, index, t_uint); + index = lb_emit_conv(p, index, t_uintptr); - if (size == N*sz) { + if (size == len*elem_sz) { lbValue elems_ptr = lb_emit_conv(p, cells_ptr, alloc_type_pointer(type)); return lb_emit_ptr_offset(p, elems_ptr, index); } // TOOD(bill): N power of two optimization to use >> and & - lbValue N_const = lb_const_int(p->module, index.type, N); - lbValue cell_index = lb_emit_arith(p, Token_Quo, index, N_const, index.type); - lbValue data_index = lb_emit_arith(p, Token_Mod, index, N_const, index.type); - lbValue cell = lb_emit_ptr_offset(p, cells_ptr, cell_index); - lbValue elems_ptr = lb_emit_conv(p, cell, alloc_type_pointer(type)); + lbValue size_const = lb_const_int(p->module, t_uintptr, size); + lbValue len_const = lb_const_int(p->module, t_uintptr, len); + lbValue cell_index = lb_emit_arith(p, Token_Quo, index, len_const, t_uintptr); + lbValue data_index = lb_emit_arith(p, Token_Mod, index, len_const, t_uintptr); + + lbValue elems_ptr = lb_emit_conv(p, cells_ptr, t_uintptr); + lbValue cell_offset = lb_emit_arith(p, Token_Mul, size_const, cell_index, t_uintptr); + elems_ptr = lb_emit_arith(p, Token_Add, elems_ptr, cell_offset, t_uintptr); + + elems_ptr = lb_emit_conv(p, elems_ptr, alloc_type_pointer(type)); + return lb_emit_ptr_offset(p, elems_ptr, data_index); } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index a3493f864..6d69021ce 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1440,7 +1440,7 @@ lbValue lb_map_len(lbProcedure *p, lbValue value) { } lbValue lb_map_cap(lbProcedure *p, lbValue value) { - GB_ASSERT(is_type_map(value.type)); + GB_ASSERT_MSG(is_type_map(value.type) || are_types_identical(value.type, t_raw_map), "%s", type_to_string(value.type)); lbValue zero = lb_const_int(p->module, t_uintptr, 0); lbValue one = lb_const_int(p->module, t_uintptr, 1); @@ -1454,7 +1454,7 @@ lbValue lb_map_cap(lbProcedure *p, lbValue value) { } lbValue lb_map_data_uintptr(lbProcedure *p, lbValue value) { - GB_ASSERT(is_type_map(value.type)); + GB_ASSERT(is_type_map(value.type) || are_types_identical(value.type, t_raw_map)); lbValue data = lb_emit_struct_ev(p, value, 0); u64 mask_value = 0; if (build_context.word_size == 4) { diff --git a/src/main.cpp b/src/main.cpp index b75137613..3b0a599db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -638,6 +638,7 @@ enum BuildFlagKind { BuildFlag_StrictStyleInitOnly, BuildFlag_ForeignErrorProcedures, BuildFlag_DisallowRTTI, + BuildFlag_UseStaticMapCalls, BuildFlag_Compact, BuildFlag_GlobalDefinitions, @@ -814,6 +815,8 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_DisallowRTTI, str_lit("disallow-rtti"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_UseStaticMapCalls, str_lit("use-static-map-calls"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_Compact, str_lit("compact"), BuildFlagParam_None, Command_query); add_flag(&build_flags, BuildFlag_GlobalDefinitions, str_lit("global-definitions"), BuildFlagParam_None, Command_query); @@ -1414,6 +1417,9 @@ bool parse_build_flags(Array args) { case BuildFlag_DisallowRTTI: build_context.disallow_rtti = true; break; + case BuildFlag_UseStaticMapCalls: + build_context.use_static_map_calls = true; + break; case BuildFlag_DefaultToNilAllocator: build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true; break; diff --git a/src/types.cpp b/src/types.cpp index ab82e87b8..74b192010 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -693,6 +693,7 @@ gb_global Type *t_raw_map_ptr = nullptr; gb_global Type *t_equal_proc = nullptr; gb_global Type *t_hasher_proc = nullptr; +gb_global Type *t_map_get_proc = nullptr; gb_global Type *t_objc_object = nullptr; gb_global Type *t_objc_selector = nullptr; -- cgit v1.2.3 From 16fc96101049ef884401ab6182ea860390abd6a9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 11 Nov 2022 14:45:22 +0000 Subject: Begin work on map static set --- core/runtime/dynamic_map_internal.odin | 4 +- src/check_expr.cpp | 52 +++++++---- src/checker.cpp | 9 +- src/llvm_backend.cpp | 162 ++++++++++++++++++++++++++++++--- src/llvm_backend.hpp | 3 +- src/llvm_backend_const.cpp | 17 +++- src/llvm_backend_expr.cpp | 2 +- src/llvm_backend_general.cpp | 3 +- src/llvm_backend_utility.cpp | 7 ++ src/types.cpp | 1 + 10 files changed, 218 insertions(+), 42 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index 65f883c7c..9721340f6 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -696,9 +696,7 @@ __dynamic_map_check_grow :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: } // IMPORTANT: USED WITHIN THE COMPILER -__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr { - hash := info.key_hasher(key, 0) - +__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, hash: Map_Hash, key, value: rawptr, loc := #caller_location) -> rawptr { if found := __dynamic_map_get(m, info, hash, key); found != nil { intrinsics.mem_copy_non_overlapping(found, value, info.vs.size_of_type) return found diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 045b22ca2..c58aac609 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -285,6 +285,37 @@ void error_operand_no_value(Operand *o) { } } +void add_map_get_dependencies(CheckerContext *c) { + if (build_context.use_static_map_calls) { + add_package_dependency(c, "runtime", "map_desired_position"); + add_package_dependency(c, "runtime", "map_probe_distance"); + } else { + add_package_dependency(c, "runtime", "__dynamic_map_get"); + } +} + +void add_map_set_dependencies(CheckerContext *c) { + init_core_source_code_location(c->checker); + + if (t_map_set_proc == nullptr) { + Type *map_set_args[5] = {/*map*/t_rawptr, /*hash*/t_uintptr, /*key*/t_rawptr, /*value*/t_rawptr, /*#caller_location*/t_source_code_location}; + t_map_set_proc = alloc_type_proc_from_types(map_set_args, gb_count_of(map_set_args), t_rawptr, false, ProcCC_Odin); + } + + if (build_context.use_static_map_calls) { + add_package_dependency(c, "runtime", "__dynamic_map_check_grow"); + add_package_dependency(c, "runtime", "map_insert_hash_dynamic"); + } else { + add_package_dependency(c, "runtime", "__dynamic_map_set"); + } +} + +void add_map_reserve_dependencies(CheckerContext *c) { + init_core_source_code_location(c->checker); + add_package_dependency(c, "runtime", "__dynamic_map_reserve"); +} + + void check_scope_decls(CheckerContext *c, Slice const &nodes, isize reserve_size) { Scope *s = c->scope; @@ -3244,12 +3275,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint check_assignment(c, x, yt->Map.key, str_lit("map 'not_in'")); } - if (build_context.use_static_map_calls) { - add_package_dependency(c, "runtime", "map_desired_position"); - add_package_dependency(c, "runtime", "map_probe_distance"); - } else { - add_package_dependency(c, "runtime", "__dynamic_map_get"); - } + add_map_get_dependencies(c); } else if (is_type_bit_set(rhs_type)) { Type *yt = base_type(rhs_type); @@ -8560,8 +8586,8 @@ ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type * if (build_context.no_dynamic_literals && cl->elems.count) { error(node, "Compound literals of dynamic types have been disabled"); } else { - add_package_dependency(c, "runtime", "__dynamic_map_reserve"); - add_package_dependency(c, "runtime", "__dynamic_map_set"); + add_map_reserve_dependencies(c); + add_map_set_dependencies(c); } break; } @@ -8997,14 +9023,8 @@ ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_h o->type = t->Map.value; o->expr = node; - - add_package_dependency(c, "runtime", "__dynamic_map_set"); - if (build_context.use_static_map_calls) { - add_package_dependency(c, "runtime", "map_desired_position"); - add_package_dependency(c, "runtime", "map_probe_distance"); - } else { - add_package_dependency(c, "runtime", "__dynamic_map_get"); - } + add_map_get_dependencies(c); + add_map_set_dependencies(c); return Expr_Expr; } diff --git a/src/checker.cpp b/src/checker.cpp index 0c23f2627..4d1ef4614 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -922,14 +922,13 @@ void init_universal(void) { { Type *equal_args[2] = {t_rawptr, t_rawptr}; - t_equal_proc = alloc_type_proc_from_types(equal_args, 2, t_bool, false, ProcCC_Contextless); + t_equal_proc = alloc_type_proc_from_types(equal_args, gb_count_of(equal_args), t_bool, false, ProcCC_Contextless); Type *hasher_args[2] = {t_rawptr, t_uintptr}; - t_hasher_proc = alloc_type_proc_from_types(hasher_args, 2, t_uintptr, false, ProcCC_Contextless); + t_hasher_proc = alloc_type_proc_from_types(hasher_args, gb_count_of(hasher_args), t_uintptr, false, ProcCC_Contextless); Type *map_get_args[3] = {/*map*/t_rawptr, /*hash*/t_uintptr, /*key*/t_rawptr}; - t_map_get_proc = alloc_type_proc_from_types(map_get_args, 3, t_rawptr, false, ProcCC_Contextless); - + t_map_get_proc = alloc_type_proc_from_types(map_get_args, gb_count_of(map_get_args), t_rawptr, false, ProcCC_Contextless); } // Constants @@ -2844,7 +2843,7 @@ void init_core_source_code_location(Checker *c) { return; } t_source_code_location = find_core_type(c, str_lit("Source_Code_Location")); - t_source_code_location_ptr = alloc_type_pointer(t_allocator); + t_source_code_location_ptr = alloc_type_pointer(t_source_code_location); } void init_core_map_type(Checker *c) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 5306ed35e..4c34a56e9 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -484,7 +484,7 @@ lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { static u32 proc_index = 0; char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$map_get_%u", ++proc_index); + isize n = gb_snprintf(buf, 32, "__$map_get-%u", ++proc_index); char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); String proc_name = make_string_c(str); @@ -613,6 +613,129 @@ lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { return {p->value, p->type}; } +void lb_debug_print(lbProcedure *p, String const &str) { + auto args = array_make(heap_allocator(), 1); + args[0] = lb_const_string(p->module, str); + lb_emit_runtime_call(p, "print_string", args); +} + +lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) { + GB_ASSERT(build_context.use_static_map_calls); + type = base_type(type); + GB_ASSERT(type->kind == Type_Map); + + + lbProcedure **found = map_get(&m->map_set_procs, type); + if (found) { + GB_ASSERT(*found != nullptr); + return {(*found)->value, (*found)->type}; + } + static u32 proc_index = 0; + + char buf[32] = {}; + isize n = gb_snprintf(buf, 32, "__$map_set-%u", ++proc_index); + char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); + String proc_name = make_string_c(str); + + lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_set_proc); + map_set(&m->map_set_procs, type, p); + lb_begin_procedure_body(p); + defer (lb_end_procedure_body(p)); + + lb_add_attribute_to_proc(m, p->value, "nounwind"); + lb_add_attribute_to_proc(m, p->value, "noinline"); + + lbValue map_ptr = {LLVMGetParam(p->value, 0), t_rawptr}; + lbValue hash = {LLVMGetParam(p->value, 1), t_uintptr}; + lbValue key_ptr = {LLVMGetParam(p->value, 2), t_rawptr}; + lbValue value_ptr = {LLVMGetParam(p->value, 3), t_rawptr}; + lbValue location_ptr = {LLVMGetParam(p->value, 4), t_source_code_location_ptr}; + + map_ptr = lb_emit_conv(p, map_ptr, alloc_type_pointer(type)); + key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key)); + + lb_add_proc_attribute_at_index(p, 1+0, "nonnull"); + lb_add_proc_attribute_at_index(p, 1+0, "noalias"); + + lb_add_proc_attribute_at_index(p, 1+2, "nonnull"); + if (!are_types_identical(type->Map.key, type->Map.value)) { + lb_add_proc_attribute_at_index(p, 1+2, "noalias"); + } + lb_add_proc_attribute_at_index(p, 1+2, "readonly"); + + lb_add_proc_attribute_at_index(p, 1+3, "nonnull"); + if (!are_types_identical(type->Map.key, type->Map.value)) { + lb_add_proc_attribute_at_index(p, 1+3, "noalias"); + } + lb_add_proc_attribute_at_index(p, 1+3, "readonly"); + + lb_add_proc_attribute_at_index(p, 1+4, "nonnull"); + lb_add_proc_attribute_at_index(p, 1+4, "noalias"); + lb_add_proc_attribute_at_index(p, 1+4, "readonly"); + + //// + lbValue found_ptr = {}; + { + lbValue map_get_proc = lb_map_get_proc_for_type(m, type); + + auto args = array_make(permanent_allocator(), 3); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = hash; + args[2] = key_ptr; + + found_ptr = lb_emit_call(p, map_get_proc, args); + } + + + lbBlock *found_block = lb_create_block(p, "found"); + lbBlock *check_grow_block = lb_create_block(p, "check-grow"); + lbBlock *grow_fail_block = lb_create_block(p, "grow-fail"); + lbBlock *insert_block = lb_create_block(p, "insert"); + + lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, found_ptr), found_block, check_grow_block); + lb_start_block(p, found_block); + { + lb_mem_copy_non_overlapping(p, found_ptr, value_ptr, lb_const_int(m, t_int, type_size_of(type->Map.value))); + LLVMBuildRet(p->builder, lb_emit_conv(p, found_ptr, t_rawptr).value); + } + lb_start_block(p, check_grow_block); + + + lbValue map_info = lb_gen_map_info_ptr(p->module, type); + + { + auto args = array_make(permanent_allocator(), 3); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = map_info; + args[2] = lb_emit_load(p, location_ptr); + lbValue grow_err = lb_emit_runtime_call(p, "__dynamic_map_check_grow", args); + + lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, grow_err), grow_fail_block, insert_block); + + lb_start_block(p, grow_fail_block); + LLVMBuildRet(p->builder, LLVMConstNull(lb_type(m, t_rawptr))); + } + + lb_start_block(p, insert_block); + { + auto args = array_make(permanent_allocator(), 5); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = map_info; + args[2] = hash; + args[3] = lb_emit_conv(p, key_ptr, t_uintptr); + args[4] = lb_emit_conv(p, value_ptr, t_uintptr); + + lbValue result = lb_emit_runtime_call(p, "map_insert_hash_dynamic", args); + + lb_emit_increment(p, lb_map_len_ptr(p, map_ptr)); + + LLVMBuildRet(p->builder, lb_emit_conv(p, result, t_rawptr).value); + } + + return {p->value, p->type}; +} + + lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) { lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, expr); if (found) { @@ -810,8 +933,8 @@ lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, return lb_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value)); } -void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, Type *map_type, - lbValue const &map_key, lbValue const &map_value, Ast *node) { +void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_ptr, Type *map_type, + lbValue const &map_key, lbValue const &map_value, Ast *node) { map_type = base_type(map_type); GB_ASSERT(map_type->kind == Type_Map); @@ -821,14 +944,27 @@ void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, lbValue v = lb_emit_conv(p, map_value, map_type->Map.value); lbValue value_ptr = lb_address_from_load_or_generate_local(p, v); - auto args = array_make(permanent_allocator(), 6); - args[0] = lb_emit_conv(p, map_ptr, t_raw_map_ptr); - args[1] = lb_gen_map_info_ptr(p->module, map_type); - args[2] = hash; - args[3] = lb_emit_conv(p, key_ptr, t_rawptr); - args[4] = lb_emit_conv(p, value_ptr, t_rawptr); - args[5] = lb_emit_source_code_location_as_global(p, node); - lb_emit_runtime_call(p, "__dynamic_map_set", args); + if (build_context.use_static_map_calls) { + lbValue map_set_proc = lb_map_set_proc_for_type(p->module, map_type); + + auto args = array_make(permanent_allocator(), 5); + args[0] = lb_emit_conv(p, map_ptr, t_rawptr); + args[1] = hash; + args[2] = lb_emit_conv(p, key_ptr, t_rawptr); + args[3] = lb_emit_conv(p, value_ptr, t_rawptr); + args[4] = lb_emit_source_code_location_as_global(p, node); + + lb_emit_call(p, map_set_proc, args); + } else { + auto args = array_make(permanent_allocator(), 6); + args[0] = lb_emit_conv(p, map_ptr, t_raw_map_ptr); + args[1] = lb_gen_map_info_ptr(p->module, map_type); + args[2] = hash; + args[3] = lb_emit_conv(p, key_ptr, t_rawptr); + args[4] = lb_emit_conv(p, value_ptr, t_rawptr); + args[5] = lb_emit_source_code_location_as_global(p, node); + lb_emit_runtime_call(p, "__dynamic_map_set", args); + } } void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) { @@ -1386,6 +1522,10 @@ WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) { lbProcedure *p = m->map_get_procs.entries[i].value; lb_run_function_pass_manager(default_function_pass_manager, p); } + for_array(i, m->map_set_procs.entries) { + lbProcedure *p = m->map_set_procs.entries[i].value; + lb_run_function_pass_manager(default_function_pass_manager, p); + } return 0; } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index c4333e949..9074de42a 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -145,6 +145,7 @@ struct lbModule { PtrMap equal_procs; PtrMap hasher_procs; PtrMap map_get_procs; + PtrMap map_set_procs; u32 nested_type_name_guid; @@ -451,7 +452,7 @@ lbValue lb_gen_map_cell_info_ptr(lbModule *m, Type *type); lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type); lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, lbValue const &key); -void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, Type *map_type, lbValue const &map_key, lbValue const &map_value, Ast *node); +void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_ptr, Type *map_type, lbValue const &map_key, lbValue const &map_value, Ast *node); void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos); lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e); diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index a8b66a0ea..dff5298c5 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -283,19 +283,28 @@ lbValue lb_emit_source_code_location_const(lbProcedure *p, Ast *node) { return lb_emit_source_code_location_const(p, proc_name, pos); } -lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) { + +lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, String const &procedure, TokenPos const &pos) { lbValue loc = lb_emit_source_code_location_const(p, procedure, pos); lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr); lb_make_global_private_const(addr); - return lb_addr_load(p, addr); + return addr.addr; } -lbValue lb_emit_source_code_location_as_global(lbProcedure *p, Ast *node) { +lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, Ast *node) { lbValue loc = lb_emit_source_code_location_const(p, node); lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr); lb_make_global_private_const(addr); - return lb_addr_load(p, addr); + return addr.addr; +} + +lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) { + return lb_emit_load(p, lb_emit_source_code_location_as_global_ptr(p, procedure, pos)); +} + +lbValue lb_emit_source_code_location_as_global(lbProcedure *p, Ast *node) { + return lb_emit_load(p, lb_emit_source_code_location_as_global_ptr(p, node)); } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index aee87242c..e58c84c9c 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4139,7 +4139,7 @@ lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { lbValue key = lb_build_expr(p, fv->field); lbValue value = lb_build_expr(p, fv->value); - lb_insert_dynamic_map_key_and_value(p, v.addr, type, key, value, elem); + lb_internal_dynamic_map_set(p, v.addr, type, key, value, elem); } break; } diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index a0e4d80ba..f36dc1842 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -68,6 +68,7 @@ void lb_init_module(lbModule *m, Checker *c) { map_init(&m->equal_procs, a); map_init(&m->hasher_procs, a); map_init(&m->map_get_procs, a); + map_init(&m->map_set_procs, a); array_init(&m->procedures_to_generate, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); map_init(&m->debug_values, a); @@ -727,7 +728,7 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { return; } else if (addr.kind == lbAddr_Map) { - lb_insert_dynamic_map_key_and_value(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt); + lb_internal_dynamic_map_set(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt); return; } else if (addr.kind == lbAddr_Context) { lbAddr old_addr = lb_find_or_generate_context_ptr(p); diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 30c531d71..101b9dbfb 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1438,6 +1438,13 @@ lbValue lb_map_len(lbProcedure *p, lbValue value) { lbValue len = lb_emit_struct_ev(p, value, 1); return lb_emit_conv(p, len, t_int); } +lbValue lb_map_len_ptr(lbProcedure *p, lbValue map_ptr) { + Type *type = map_ptr.type; + GB_ASSERT(is_type_pointer(type)); + type = type_deref(type); + GB_ASSERT_MSG(is_type_map(type) || are_types_identical(type, t_raw_map), "%s", type_to_string(type)); + return lb_emit_struct_ep(p, map_ptr, 1); +} lbValue lb_map_cap(lbProcedure *p, lbValue value) { GB_ASSERT_MSG(is_type_map(value.type) || are_types_identical(value.type, t_raw_map), "%s", type_to_string(value.type)); diff --git a/src/types.cpp b/src/types.cpp index 74b192010..47007491d 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -694,6 +694,7 @@ gb_global Type *t_raw_map_ptr = nullptr; gb_global Type *t_equal_proc = nullptr; gb_global Type *t_hasher_proc = nullptr; gb_global Type *t_map_get_proc = nullptr; +gb_global Type *t_map_set_proc = nullptr; gb_global Type *t_objc_object = nullptr; gb_global Type *t_objc_selector = nullptr; -- cgit v1.2.3 From a705a2e38bee035d6800999ba6eddd82792594f7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 13 Nov 2022 22:55:32 +0000 Subject: Minor improvement to multi return value reducing stack usage --- src/check_expr.cpp | 3 +++ src/check_stmt.cpp | 4 ++++ src/checker.hpp | 1 + src/llvm_backend_general.cpp | 24 ++++++++++++++---------- src/llvm_backend_opt.cpp | 35 ++++++++++++++++++++++++++++++++++- src/llvm_backend_proc.cpp | 42 ++++++++++++++++++++++++++++++++++-------- 6 files changed, 90 insertions(+), 19 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c58aac609..c819267fd 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6739,6 +6739,9 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr if (initial_entity != nullptr && initial_entity->kind == Entity_Procedure) { if (initial_entity->Procedure.deferred_procedure.entity != nullptr) { call->viral_state_flags |= ViralStateFlag_ContainsDeferredProcedure; + if (c->decl != nullptr) { + c->decl->defer_use_count += 1; + } } } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 9cacb4a35..8271ca451 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2014,6 +2014,10 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { if (is_ast_decl(ds->stmt)) { error(ds->token, "You cannot defer a declaration"); } else { + if (ctx->decl != nullptr) { + ctx->decl->defer_use_count += 1; + } + bool out_in_defer = ctx->in_defer; ctx->in_defer = true; check_stmt(ctx, ds->stmt, 0); diff --git a/src/checker.hpp b/src/checker.hpp index badcd93d5..ded4a0ad6 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -158,6 +158,7 @@ struct DeclInfo { bool is_using; bool where_clauses_evaluated; bool proc_checked; + isize defer_use_count; CommentGroup *comment; CommentGroup *docs; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index f36dc1842..6f2253d01 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -936,23 +936,27 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { LLVMValueRef src_ptr_original = LLVMGetOperand(value.value, 0); LLVMValueRef src_ptr = LLVMBuildPointerCast(p->builder, src_ptr_original, LLVMTypeOf(dst_ptr), ""); - LLVMBuildMemMove(p->builder, - dst_ptr, lb_try_get_alignment(dst_ptr, 1), - src_ptr, lb_try_get_alignment(src_ptr_original, 1), - LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); + if (dst_ptr != src_ptr && dst_ptr != src_ptr_original) { + LLVMBuildMemMove(p->builder, + dst_ptr, lb_try_get_alignment(dst_ptr, 1), + src_ptr, lb_try_get_alignment(src_ptr_original, 1), + LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); + } return; } else if (LLVMIsConstant(value.value)) { lbAddr addr = lb_add_global_generated(p->module, value.type, value, nullptr); lb_make_global_private_const(addr); LLVMValueRef dst_ptr = ptr.value; - LLVMValueRef src_ptr = addr.addr.value; - src_ptr = LLVMBuildPointerCast(p->builder, src_ptr, LLVMTypeOf(dst_ptr), ""); + LLVMValueRef src_ptr_original = addr.addr.value; + LLVMValueRef src_ptr = LLVMBuildPointerCast(p->builder, src_ptr_original, LLVMTypeOf(dst_ptr), ""); - LLVMBuildMemMove(p->builder, - dst_ptr, lb_try_get_alignment(dst_ptr, 1), - src_ptr, lb_try_get_alignment(src_ptr, 1), - LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); + if (dst_ptr != src_ptr && dst_ptr != src_ptr_original) { + LLVMBuildMemMove(p->builder, + dst_ptr, lb_try_get_alignment(dst_ptr, 1), + src_ptr, lb_try_get_alignment(src_ptr, 1), + LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); + } return; } } diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index e2f51b868..ba5a41871 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -267,6 +267,8 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa **************************************************************************/ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { + LLVMTypeRef llvm_void = LLVMVoidTypeInContext(p->module->ctx); + isize removal_count = 0; isize pass_count = 0; isize const max_pass_count = 10; @@ -322,7 +324,7 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { case LLVMOr: case LLVMXor: case LLVMAlloca: - case LLVMLoad: + case LLVMLoad: // TODO: should LLVMLoad be removed? case LLVMGetElementPtr: case LLVMTrunc: case LLVMZExt: @@ -347,6 +349,37 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { LLVMInstructionEraseFromParent(curr_instr); was_dead_instructions = true; break; + + case LLVMCall: + if (LLVMTypeOf(curr_instr) == llvm_void) { + LLVMValueRef the_proc = LLVMGetCalledValue(curr_instr); + unsigned id = LLVMGetIntrinsicID(the_proc); + if (id != 0) { + size_t text_len = 0; + char const *text = LLVMIntrinsicGetName(id, &text_len); + String name = make_string(cast(u8 const *)text, cast(isize)text_len); + if (name == "llvm.memmove" || name == "llvm.memcpy") { + LLVMValueRef dst = LLVMGetOperand(curr_instr, 0); + LLVMValueRef src = LLVMGetOperand(curr_instr, 1); + LLVMValueRef sz = LLVMGetOperand(curr_instr, 2); + if ((dst == src) || (LLVMIsConstant(sz) && LLVMConstIntGetZExtValue(sz) == 0)) { + removal_count += 1; + LLVMInstructionEraseFromParent(curr_instr); + was_dead_instructions = true; + break; + } + } else if (name == "llvm.memset") { + LLVMValueRef sz = LLVMGetOperand(curr_instr, 2); + if (LLVMIsConstant(sz) && LLVMConstIntGetZExtValue(sz) == 0) { + removal_count += 1; + LLVMInstructionEraseFromParent(curr_instr); + was_dead_instructions = true; + break; + } + } + } + } + break; } } } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index eaff6edc0..2e508a939 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -9,9 +9,15 @@ LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* a } void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) { + if (dst.value == src.value) { + return; + } dst = lb_emit_conv(p, dst, t_rawptr); src = lb_emit_conv(p, src, t_rawptr); len = lb_emit_conv(p, len, t_int); + if (dst.value == src.value) { + return; + } char const *name = "llvm.memmove"; if (LLVMIsConstant(len.value)) { @@ -38,9 +44,16 @@ void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue l void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) { + if (dst.value == src.value) { + return; + } dst = lb_emit_conv(p, dst, t_rawptr); src = lb_emit_conv(p, src, t_rawptr); len = lb_emit_conv(p, len, t_int); + if (dst.value == src.value) { + return; + } + char const *name = "llvm.memcpy"; if (LLVMIsConstant(len.value)) { @@ -580,18 +593,31 @@ void lb_begin_procedure_body(lbProcedure *p) { if (e->token.string != "") { GB_ASSERT(!is_blank_ident(e->token)); - // NOTE(bill): Don't even bother trying to optimize this with the return ptr value - // This will violate the defer rules if you do: - // foo :: proc() -> (x, y: T) { - // defer x = ... // defer is executed after the `defer` - // return // the values returned should be zeroed - // } - lbAddr res = lb_add_local(p, e->type, e); + lbAddr res = {}; + if (p->return_ptr.addr.value != nullptr && + p->entity != nullptr && + p->entity->decl_info != nullptr && + p->entity->decl_info->defer_use_count == 0) { + lbValue val = lb_emit_struct_ep(p, p->return_ptr.addr, cast(i32)i); + + lb_add_entity(p->module, e, val); + lb_add_debug_local_variable(p, val.value, e->type, e->token); + + // NOTE(bill): no need to zero initialize due to caller will zero return value + res = lb_addr(val); + } else { + // NOTE(bill): Don't even bother trying to optimize this with the return ptr value + // This will violate the defer rules if you do: + // foo :: proc() -> (x, y: T) { + // defer x = ... // defer is executed after the `defer` + // return // the values returned should be zeroed + // } + res = lb_add_local(p, e->type, e); + } if (e->Variable.param_value.kind != ParameterValue_Invalid) { lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos); lb_addr_store(p, res, c); } - } } -- cgit v1.2.3 From 25bec19b1f91cac47544ec434b825bd2b9727a39 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 13 Nov 2022 23:56:05 +0000 Subject: Revert "Minor improvement to multi return value reducing stack usage" --- src/check_expr.cpp | 3 --- src/check_stmt.cpp | 4 ---- src/checker.hpp | 1 - src/llvm_backend_general.cpp | 24 ++++++++++-------------- src/llvm_backend_opt.cpp | 35 +---------------------------------- src/llvm_backend_proc.cpp | 44 +++++++++----------------------------------- 6 files changed, 20 insertions(+), 91 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c819267fd..c58aac609 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6739,9 +6739,6 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr if (initial_entity != nullptr && initial_entity->kind == Entity_Procedure) { if (initial_entity->Procedure.deferred_procedure.entity != nullptr) { call->viral_state_flags |= ViralStateFlag_ContainsDeferredProcedure; - if (c->decl != nullptr) { - c->decl->defer_use_count += 1; - } } } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 8271ca451..9cacb4a35 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2014,10 +2014,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { if (is_ast_decl(ds->stmt)) { error(ds->token, "You cannot defer a declaration"); } else { - if (ctx->decl != nullptr) { - ctx->decl->defer_use_count += 1; - } - bool out_in_defer = ctx->in_defer; ctx->in_defer = true; check_stmt(ctx, ds->stmt, 0); diff --git a/src/checker.hpp b/src/checker.hpp index ded4a0ad6..badcd93d5 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -158,7 +158,6 @@ struct DeclInfo { bool is_using; bool where_clauses_evaluated; bool proc_checked; - isize defer_use_count; CommentGroup *comment; CommentGroup *docs; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 6f2253d01..f36dc1842 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -936,27 +936,23 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { LLVMValueRef src_ptr_original = LLVMGetOperand(value.value, 0); LLVMValueRef src_ptr = LLVMBuildPointerCast(p->builder, src_ptr_original, LLVMTypeOf(dst_ptr), ""); - if (dst_ptr != src_ptr && dst_ptr != src_ptr_original) { - LLVMBuildMemMove(p->builder, - dst_ptr, lb_try_get_alignment(dst_ptr, 1), - src_ptr, lb_try_get_alignment(src_ptr_original, 1), - LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); - } + LLVMBuildMemMove(p->builder, + dst_ptr, lb_try_get_alignment(dst_ptr, 1), + src_ptr, lb_try_get_alignment(src_ptr_original, 1), + LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); return; } else if (LLVMIsConstant(value.value)) { lbAddr addr = lb_add_global_generated(p->module, value.type, value, nullptr); lb_make_global_private_const(addr); LLVMValueRef dst_ptr = ptr.value; - LLVMValueRef src_ptr_original = addr.addr.value; - LLVMValueRef src_ptr = LLVMBuildPointerCast(p->builder, src_ptr_original, LLVMTypeOf(dst_ptr), ""); + LLVMValueRef src_ptr = addr.addr.value; + src_ptr = LLVMBuildPointerCast(p->builder, src_ptr, LLVMTypeOf(dst_ptr), ""); - if (dst_ptr != src_ptr && dst_ptr != src_ptr_original) { - LLVMBuildMemMove(p->builder, - dst_ptr, lb_try_get_alignment(dst_ptr, 1), - src_ptr, lb_try_get_alignment(src_ptr, 1), - LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); - } + LLVMBuildMemMove(p->builder, + dst_ptr, lb_try_get_alignment(dst_ptr, 1), + src_ptr, lb_try_get_alignment(src_ptr, 1), + LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); return; } } diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index ba5a41871..e2f51b868 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -267,8 +267,6 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa **************************************************************************/ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { - LLVMTypeRef llvm_void = LLVMVoidTypeInContext(p->module->ctx); - isize removal_count = 0; isize pass_count = 0; isize const max_pass_count = 10; @@ -324,7 +322,7 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { case LLVMOr: case LLVMXor: case LLVMAlloca: - case LLVMLoad: // TODO: should LLVMLoad be removed? + case LLVMLoad: case LLVMGetElementPtr: case LLVMTrunc: case LLVMZExt: @@ -349,37 +347,6 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { LLVMInstructionEraseFromParent(curr_instr); was_dead_instructions = true; break; - - case LLVMCall: - if (LLVMTypeOf(curr_instr) == llvm_void) { - LLVMValueRef the_proc = LLVMGetCalledValue(curr_instr); - unsigned id = LLVMGetIntrinsicID(the_proc); - if (id != 0) { - size_t text_len = 0; - char const *text = LLVMIntrinsicGetName(id, &text_len); - String name = make_string(cast(u8 const *)text, cast(isize)text_len); - if (name == "llvm.memmove" || name == "llvm.memcpy") { - LLVMValueRef dst = LLVMGetOperand(curr_instr, 0); - LLVMValueRef src = LLVMGetOperand(curr_instr, 1); - LLVMValueRef sz = LLVMGetOperand(curr_instr, 2); - if ((dst == src) || (LLVMIsConstant(sz) && LLVMConstIntGetZExtValue(sz) == 0)) { - removal_count += 1; - LLVMInstructionEraseFromParent(curr_instr); - was_dead_instructions = true; - break; - } - } else if (name == "llvm.memset") { - LLVMValueRef sz = LLVMGetOperand(curr_instr, 2); - if (LLVMIsConstant(sz) && LLVMConstIntGetZExtValue(sz) == 0) { - removal_count += 1; - LLVMInstructionEraseFromParent(curr_instr); - was_dead_instructions = true; - break; - } - } - } - } - break; } } } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 510479440..7c83125ca 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -9,15 +9,9 @@ LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* a } void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) { - if (dst.value == src.value) { - return; - } dst = lb_emit_conv(p, dst, t_rawptr); src = lb_emit_conv(p, src, t_rawptr); len = lb_emit_conv(p, len, t_int); - if (dst.value == src.value) { - return; - } char const *name = "llvm.memmove"; if (LLVMIsConstant(len.value)) { @@ -44,16 +38,9 @@ void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue l void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) { - if (dst.value == src.value) { - return; - } dst = lb_emit_conv(p, dst, t_rawptr); src = lb_emit_conv(p, src, t_rawptr); len = lb_emit_conv(p, len, t_int); - if (dst.value == src.value) { - return; - } - char const *name = "llvm.memcpy"; if (LLVMIsConstant(len.value)) { @@ -593,32 +580,19 @@ void lb_begin_procedure_body(lbProcedure *p) { if (e->token.string != "") { GB_ASSERT(!is_blank_ident(e->token)); - lbAddr res = {}; - if (p->return_ptr.addr.value != nullptr && - p->entity != nullptr && - p->entity->decl_info != nullptr && - p->entity->decl_info->defer_use_count == 0) { - lbValue val = lb_emit_struct_ep(p, p->return_ptr.addr, cast(i32)i); - val = lb_emit_conv(p, val, alloc_type_pointer(e->type)); - - lb_add_entity(p->module, e, val); - lb_add_debug_local_variable(p, val.value, e->type, e->token); - - // NOTE(bill): no need to zero initialize due to caller will zero return value - res = lb_addr(val); - } else { - // NOTE(bill): Don't even bother trying to optimize this with the return ptr value - // This will violate the defer rules if you do: - // foo :: proc() -> (x, y: T) { - // defer x = ... // defer is executed after the `defer` - // return // the values returned should be zeroed - // } - res = lb_add_local(p, e->type, e); - } + // NOTE(bill): Don't even bother trying to optimize this with the return ptr value + // This will violate the defer rules if you do: + // foo :: proc() -> (x, y: T) { + // defer x = ... // defer is executed after the `defer` + // return // the values returned should be zeroed + // } + // NOTE(bill): REALLY, don't even bother. + lbAddr res = lb_add_local(p, e->type, e); if (e->Variable.param_value.kind != ParameterValue_Invalid) { lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos); lb_addr_store(p, res, c); } + } } -- cgit v1.2.3