Browse Source

Simplify simple compare hasher code

gingerBill 4 years ago
parent
commit
9e13416312
2 changed files with 150 additions and 186 deletions
  1. 74 88
      src/ir.cpp
  2. 76 98
      src/llvm_backend.cpp

+ 74 - 88
src/ir.cpp

@@ -4965,6 +4965,32 @@ irValue *ir_get_equal_proc_for_type(irModule *m, Type *type) {
 }
 }
 
 
 
 
+irValue *ir_simple_compare_hash(irProcedure *p, Type *type, irValue *data, irValue *seed) {
+	GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type));
+
+	i64 sz = type_size_of(type);
+	char const *name = nullptr;
+	switch (sz) {
+	case 1:  name = "default_hasher1";  break;
+	case 2:  name = "default_hasher2";  break;
+	case 4:  name = "default_hasher4";  break;
+	case 8:  name = "default_hasher8";  break;
+	case 16: name = "default_hasher16"; break;
+	}
+	if (name != nullptr) {
+		auto args = array_make<irValue *>(permanent_allocator(), 2);
+		args[0] = data;
+		args[1] = seed;
+		return ir_emit_runtime_call(p, name, args);
+	}
+
+	auto args = array_make<irValue *>(permanent_allocator(), 3);
+	args[0] = data;
+	args[1] = seed;
+	args[2] = ir_const_int(type_size_of(type));
+	return ir_emit_runtime_call(p, "default_hasher_n", args);
+}
+
 irValue *ir_get_hasher_proc_for_type(irModule *m, Type *type) {
 irValue *ir_get_hasher_proc_for_type(irModule *m, Type *type) {
 	Type *original_type = type;
 	Type *original_type = type;
 	type = core_type(type);
 	type = core_type(type);
@@ -4998,100 +5024,78 @@ irValue *ir_get_hasher_proc_for_type(irModule *m, Type *type) {
 	proc->is_startup = true;
 	proc->is_startup = true;
 	proc->ignore_dead_instr = true;
 	proc->ignore_dead_instr = true;
 	ir_begin_procedure_body(proc);
 	ir_begin_procedure_body(proc);
+	defer (ir_end_procedure_body(proc));
+
 	// ir_start_block(proc, proc->decl_block);
 	// ir_start_block(proc, proc->decl_block);
 	GB_ASSERT(proc->curr_block != nullptr);
 	GB_ASSERT(proc->curr_block != nullptr);
 
 
 	irValue *data = proc->params[0];
 	irValue *data = proc->params[0];
 	irValue *seed = proc->params[1];
 	irValue *seed = proc->params[1];
 
 
+	if (is_type_simple_compare(type)) {
+		irValue *res = ir_simple_compare_hash(proc, type, data, seed);
+		ir_emit(proc, ir_instr_return(proc, res));
+		return p;
+	}
+
 	if (type->kind == Type_Struct) {
 	if (type->kind == Type_Struct) {
 		type_set_offsets(type);
 		type_set_offsets(type);
-		if (is_type_simple_compare(type)) {
-			i64 sz = type_size_of(type);
-			auto args = array_make<irValue *>(permanent_allocator(), 3);
-			args[0] = data;
-			args[1] = seed;
-			args[2] = ir_const_int(sz);
-			irValue *res = ir_emit_runtime_call(proc, "default_hasher_n", args);
-			ir_emit(proc, ir_instr_return(proc, res));
-		} else {
-			data = ir_emit_conv(proc, data, t_u8_ptr);
+		data = ir_emit_conv(proc, data, t_u8_ptr);
 
 
-			auto args = array_make<irValue *>(permanent_allocator(), 2);
-			for_array(i, type->Struct.fields) {
-				i64 offset = type->Struct.offsets[i];
-				Entity *field = type->Struct.fields[i];
-				irValue *field_hasher = ir_get_hasher_proc_for_type(m, field->type);
-				irValue *ptr = ir_emit_ptr_offset(proc, data, ir_const_uintptr(offset));
+		auto args = array_make<irValue *>(permanent_allocator(), 2);
+		for_array(i, type->Struct.fields) {
+			i64 offset = type->Struct.offsets[i];
+			Entity *field = type->Struct.fields[i];
+			irValue *field_hasher = ir_get_hasher_proc_for_type(m, field->type);
+			irValue *ptr = ir_emit_ptr_offset(proc, data, ir_const_uintptr(offset));
 
 
-				args[0] = ptr;
-				args[1] = seed;
-				seed = ir_emit_call(proc, field_hasher, args);
-			}
-			ir_emit(proc, ir_instr_return(proc, seed));
+			args[0] = ptr;
+			args[1] = seed;
+			seed = ir_emit_call(proc, field_hasher, args);
 		}
 		}
+		ir_emit(proc, ir_instr_return(proc, seed));
 	} else if (type->kind == Type_Array) {
 	} else if (type->kind == Type_Array) {
-		if (is_type_simple_compare(type)) {
-			i64 sz = type_size_of(type);
-			auto args = array_make<irValue *>(permanent_allocator(), 3);
-			args[0] = data;
-			args[1] = seed;
-			args[2] = ir_const_int(sz);
-			irValue *res = ir_emit_runtime_call(proc, "default_hasher_n", args);
-			ir_emit(proc, ir_instr_return(proc, res));
-		} else {
-			irValue *pres = ir_add_local_generated(proc, t_uintptr, false);
-			ir_emit_store(proc, pres, seed);
+		irValue *pres = ir_add_local_generated(proc, t_uintptr, false);
+		ir_emit_store(proc, pres, seed);
 
 
-			auto args = array_make<irValue *>(permanent_allocator(), 2);
-			irValue *elem_hasher = ir_get_hasher_proc_for_type(m, type->Array.elem);
+		auto args = array_make<irValue *>(permanent_allocator(), 2);
+		irValue *elem_hasher = ir_get_hasher_proc_for_type(m, type->Array.elem);
 
 
-			auto loop_data = ir_loop_start(proc, type->Array.count, t_i32);
+		auto loop_data = ir_loop_start(proc, type->Array.count, t_i32);
 
 
-			data = ir_emit_conv(proc, data, pt);
+		data = ir_emit_conv(proc, data, pt);
 
 
-			irValue *ptr = ir_emit_array_ep(proc, data, loop_data.idx);
-			args[0] = ptr;
-			args[1] = ir_emit_load(proc, pres);
-			irValue *new_seed = ir_emit_call(proc, elem_hasher, args);
-			ir_emit_store(proc, pres, new_seed);
+		irValue *ptr = ir_emit_array_ep(proc, data, loop_data.idx);
+		args[0] = ptr;
+		args[1] = ir_emit_load(proc, pres);
+		irValue *new_seed = ir_emit_call(proc, elem_hasher, args);
+		ir_emit_store(proc, pres, new_seed);
 
 
-			ir_loop_end(proc, loop_data);
+		ir_loop_end(proc, loop_data);
 
 
-			irValue *res = ir_emit_load(proc, pres);
-			ir_emit(proc, ir_instr_return(proc, res));
-		}
+		irValue *res = ir_emit_load(proc, pres);
+		ir_emit(proc, ir_instr_return(proc, res));
 	} else if (type->kind == Type_EnumeratedArray) {
 	} else if (type->kind == Type_EnumeratedArray) {
-		if (is_type_simple_compare(type)) {
-			i64 sz = type_size_of(type);
-			auto args = array_make<irValue *>(permanent_allocator(), 3);
-			args[0] = data;
-			args[1] = seed;
-			args[2] = ir_const_int(sz);
-			irValue *res = ir_emit_runtime_call(proc, "default_hasher_n", args);
-			ir_emit(proc, ir_instr_return(proc, res));
-		} else {
-			irValue *pres = ir_add_local_generated(proc, t_uintptr, false);
-			ir_emit_store(proc, pres, seed);
+		irValue *pres = ir_add_local_generated(proc, t_uintptr, false);
+		ir_emit_store(proc, pres, seed);
 
 
-			auto args = array_make<irValue *>(permanent_allocator(), 2);
-			irValue *elem_hasher = ir_get_hasher_proc_for_type(m, type->Array.elem);
+		auto args = array_make<irValue *>(permanent_allocator(), 2);
+		irValue *elem_hasher = ir_get_hasher_proc_for_type(m, type->Array.elem);
 
 
-			auto loop_data = ir_loop_start(proc, type->Array.count, t_i32);
+		auto loop_data = ir_loop_start(proc, type->Array.count, t_i32);
 
 
-			data = ir_emit_conv(proc, data, pt);
+		data = ir_emit_conv(proc, data, pt);
 
 
-			irValue *ptr = ir_emit_array_ep(proc, data, loop_data.idx);
-			args[0] = ptr;
-			args[1] = ir_emit_load(proc, pres);
-			irValue *new_seed = ir_emit_call(proc, elem_hasher, args);
-			ir_emit_store(proc, pres, new_seed);
+		irValue *ptr = ir_emit_array_ep(proc, data, loop_data.idx);
+		args[0] = ptr;
+		args[1] = ir_emit_load(proc, pres);
+		irValue *new_seed = ir_emit_call(proc, elem_hasher, args);
+		ir_emit_store(proc, pres, new_seed);
 
 
-			ir_loop_end(proc, loop_data);
+		ir_loop_end(proc, loop_data);
 
 
-			irValue *res = ir_emit_load(proc, pres);
-			ir_emit(proc, ir_instr_return(proc, res));
-		}
+		irValue *res = ir_emit_load(proc, pres);
+		ir_emit(proc, ir_instr_return(proc, res));
 	} else if (is_type_cstring(type)) {
 	} else if (is_type_cstring(type)) {
 		auto args = array_make<irValue *>(permanent_allocator(), 2);
 		auto args = array_make<irValue *>(permanent_allocator(), 2);
 		args[0] = data;
 		args[0] = data;
@@ -5105,25 +5109,7 @@ irValue *ir_get_hasher_proc_for_type(irModule *m, Type *type) {
 		irValue *res = ir_emit_runtime_call(proc, "default_hasher_string", args);
 		irValue *res = ir_emit_runtime_call(proc, "default_hasher_string", args);
 		ir_emit(proc, ir_instr_return(proc, res));
 		ir_emit(proc, ir_instr_return(proc, res));
 	} else {
 	} else {
-		GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type));
-
-		i64 sz = type_size_of(type);
-		char const *name = nullptr;
-		switch (sz) {
-		case 1:  name = "default_hasher1";  break;
-		case 2:  name = "default_hasher2";  break;
-		case 4:  name = "default_hasher4";  break;
-		case 8:  name = "default_hasher8";  break;
-		case 16: name = "default_hasher16"; break;
-		default: GB_PANIC("unhandled hasher for key type: %s", type_to_string(type));
-		}
-		GB_ASSERT(name != nullptr);
-
-		auto args = array_make<irValue *>(permanent_allocator(), 2);
-		args[0] = data;
-		args[1] = seed;
-		irValue *res = ir_emit_runtime_call(proc, name, args);
-		ir_emit(proc, ir_instr_return(proc, res));
+		GB_PANIC("Unhandled type for hasher: %s", type_to_string(type));
 	}
 	}
 
 
 
 

+ 76 - 98
src/llvm_backend.cpp

@@ -9249,6 +9249,32 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
 	return {compare_proc->value, compare_proc->type};
 	return {compare_proc->value, compare_proc->type};
 }
 }
 
 
+lbValue lb_simple_compare_hash(lbProcedure *p, Type *type, lbValue data, lbValue seed) {
+	GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type));
+
+	i64 sz = type_size_of(type);
+	char const *name = nullptr;
+	switch (sz) {
+	case 1:  name = "default_hasher1";  break;
+	case 2:  name = "default_hasher2";  break;
+	case 4:  name = "default_hasher4";  break;
+	case 8:  name = "default_hasher8";  break;
+	case 16: name = "default_hasher16"; break;
+	}
+	if (name != nullptr) {
+		auto args = array_make<lbValue>(permanent_allocator(), 2);
+		args[0] = data;
+		args[1] = seed;
+		return lb_emit_runtime_call(p, name, args);
+	}
+
+	auto args = array_make<lbValue>(permanent_allocator(), 3);
+	args[0] = data;
+	args[1] = seed;
+	args[2] = lb_const_int(p->module, t_int, type_size_of(type));
+	return lb_emit_runtime_call(p, "default_hasher_n", args);
+}
+
 lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
 lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
 	Type *original_type = type;
 	Type *original_type = type;
 	type = core_type(type);
 	type = core_type(type);
@@ -9259,11 +9285,9 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
 
 
 	auto key = hash_type(type);
 	auto key = hash_type(type);
 	lbProcedure **found = map_get(&m->hasher_procs, key);
 	lbProcedure **found = map_get(&m->hasher_procs, key);
-	lbProcedure *hasher_proc = nullptr;
 	if (found) {
 	if (found) {
-		hasher_proc = *found;
-		GB_ASSERT(hasher_proc != nullptr);
-		return {hasher_proc->value, hasher_proc->type};
+		GB_ASSERT(*found != nullptr);
+		return {(*found)->value, (*found)->type};
 	}
 	}
 
 
 	static u32 proc_index = 0;
 	static u32 proc_index = 0;
@@ -9276,102 +9300,77 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
 	lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_hasher_proc);
 	lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_hasher_proc);
 	map_set(&m->hasher_procs, key, p);
 	map_set(&m->hasher_procs, key, p);
 	lb_begin_procedure_body(p);
 	lb_begin_procedure_body(p);
+	defer (lb_end_procedure_body(p));
 
 
 	LLVMValueRef x = LLVMGetParam(p->value, 0);
 	LLVMValueRef x = LLVMGetParam(p->value, 0);
 	LLVMValueRef y = LLVMGetParam(p->value, 1);
 	LLVMValueRef y = LLVMGetParam(p->value, 1);
 	lbValue data = {x, t_rawptr};
 	lbValue data = {x, t_rawptr};
 	lbValue seed = {y, t_uintptr};
 	lbValue seed = {y, t_uintptr};
 
 
+	if (is_type_simple_compare(type)) {
+		lbValue res = lb_simple_compare_hash(p, type, data, seed);
+		LLVMBuildRet(p->builder, res.value);
+		return {p->value, p->type};
+	}
+
 	if (type->kind == Type_Struct)  {
 	if (type->kind == Type_Struct)  {
 		type_set_offsets(type);
 		type_set_offsets(type);
-		if (is_type_simple_compare(type)) {
-			i64 sz = type_size_of(type);
-			auto args = array_make<lbValue>(permanent_allocator(), 3);
-			args[0] = data;
-			args[1] = seed;
-			args[2] = lb_const_int(m, t_int, sz);
-			lbValue res = lb_emit_runtime_call(p, "default_hasher_n", args);
-			LLVMBuildRet(p->builder, res.value);
-		} else {
-			data = lb_emit_conv(p, data, t_u8_ptr);
+		data = lb_emit_conv(p, data, t_u8_ptr);
 
 
-			auto args = array_make<lbValue>(permanent_allocator(), 2);
-			for_array(i, type->Struct.fields) {
-				i64 offset = type->Struct.offsets[i];
-				Entity *field = type->Struct.fields[i];
-				lbValue field_hasher = lb_get_hasher_proc_for_type(m, field->type);
-				lbValue ptr = lb_emit_ptr_offset(p, data, lb_const_int(m, t_uintptr, offset));
+		auto args = array_make<lbValue>(permanent_allocator(), 2);
+		for_array(i, type->Struct.fields) {
+			i64 offset = type->Struct.offsets[i];
+			Entity *field = type->Struct.fields[i];
+			lbValue field_hasher = lb_get_hasher_proc_for_type(m, field->type);
+			lbValue ptr = lb_emit_ptr_offset(p, data, lb_const_int(m, t_uintptr, offset));
 
 
-				args[0] = ptr;
-				args[1] = seed;
-				seed = lb_emit_call(p, field_hasher, args);
-			}
-			LLVMBuildRet(p->builder, seed.value);
+			args[0] = ptr;
+			args[1] = seed;
+			seed = lb_emit_call(p, field_hasher, args);
 		}
 		}
+		LLVMBuildRet(p->builder, seed.value);
 	} else if (type->kind == Type_Array) {
 	} else if (type->kind == Type_Array) {
-		if (is_type_simple_compare(type)) {
-			i64 sz = type_size_of(type);
-			auto args = array_make<lbValue>(permanent_allocator(), 3);
-			args[0] = data;
-			args[1] = seed;
-			args[2] = lb_const_int(m, t_int, sz);
-			lbValue res = lb_emit_runtime_call(p, "default_hasher_n", args);
-			LLVMBuildRet(p->builder, res.value);
-		} else {
-			lbAddr pres = lb_add_local_generated(p, t_uintptr, false);
-			lb_addr_store(p, pres, seed);
+		lbAddr pres = lb_add_local_generated(p, t_uintptr, false);
+		lb_addr_store(p, pres, seed);
 
 
-			auto args = array_make<lbValue>(permanent_allocator(), 2);
-			lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->Array.elem);
+		auto args = array_make<lbValue>(permanent_allocator(), 2);
+		lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->Array.elem);
 
 
-			auto loop_data = lb_loop_start(p, type->Array.count, t_i32);
+		auto loop_data = lb_loop_start(p, type->Array.count, t_i32);
 
 
-			data = lb_emit_conv(p, data, pt);
+		data = lb_emit_conv(p, data, pt);
 
 
-			lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
-			args[0] = ptr;
-			args[1] = lb_addr_load(p, pres);
-			lbValue new_seed = lb_emit_call(p, elem_hasher, args);
-			lb_addr_store(p, pres, new_seed);
+		lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
+		args[0] = ptr;
+		args[1] = lb_addr_load(p, pres);
+		lbValue new_seed = lb_emit_call(p, elem_hasher, args);
+		lb_addr_store(p, pres, new_seed);
 
 
-			lb_loop_end(p, loop_data);
+		lb_loop_end(p, loop_data);
 
 
-			lbValue res = lb_addr_load(p, pres);
-			LLVMBuildRet(p->builder, res.value);
-		}
+		lbValue res = lb_addr_load(p, pres);
+		LLVMBuildRet(p->builder, res.value);
 	} else if (type->kind == Type_EnumeratedArray) {
 	} else if (type->kind == Type_EnumeratedArray) {
-		if (is_type_simple_compare(type)) {
-			i64 sz = type_size_of(type);
-			auto args = array_make<lbValue>(permanent_allocator(), 3);
-			args[0] = data;
-			args[1] = seed;
-			args[2] = lb_const_int(m, t_int, sz);
-			lbValue res = lb_emit_runtime_call(p, "default_hasher_n", args);
-			LLVMBuildRet(p->builder, res.value);
-		} else {
-			lbAddr res = lb_add_local_generated(p, t_uintptr, false);
-			lb_addr_store(p, res, seed);
-
-			auto args = array_make<lbValue>(permanent_allocator(), 2);
-			lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->EnumeratedArray.elem);
+		lbAddr res = lb_add_local_generated(p, t_uintptr, false);
+		lb_addr_store(p, res, seed);
 
 
-			auto loop_data = lb_loop_start(p, type->EnumeratedArray.count, t_i32);
+		auto args = array_make<lbValue>(permanent_allocator(), 2);
+		lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->EnumeratedArray.elem);
 
 
-			data = lb_emit_conv(p, data, pt);
+		auto loop_data = lb_loop_start(p, type->EnumeratedArray.count, t_i32);
 
 
-			lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
-			args[0] = ptr;
-			args[1] = lb_addr_load(p, res);
-			lbValue new_seed = lb_emit_call(p, elem_hasher, args);
-			lb_addr_store(p, res, new_seed);
+		data = lb_emit_conv(p, data, pt);
 
 
-			lb_loop_end(p, loop_data);
-
-			lbValue vres = lb_addr_load(p, res);
-			LLVMBuildRet(p->builder, vres.value);
-		}
+		lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
+		args[0] = ptr;
+		args[1] = lb_addr_load(p, res);
+		lbValue new_seed = lb_emit_call(p, elem_hasher, args);
+		lb_addr_store(p, res, new_seed);
 
 
+		lb_loop_end(p, loop_data);
 
 
+		lbValue vres = lb_addr_load(p, res);
+		LLVMBuildRet(p->builder, vres.value);
 	} else if (is_type_cstring(type)) {
 	} else if (is_type_cstring(type)) {
 		auto args = array_make<lbValue>(permanent_allocator(), 2);
 		auto args = array_make<lbValue>(permanent_allocator(), 2);
 		args[0] = data;
 		args[0] = data;
@@ -9385,31 +9384,10 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
 		lbValue res = lb_emit_runtime_call(p, "default_hasher_string", args);
 		lbValue res = lb_emit_runtime_call(p, "default_hasher_string", args);
 		LLVMBuildRet(p->builder, res.value);
 		LLVMBuildRet(p->builder, res.value);
 	} else {
 	} else {
-		GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type));
-
-		i64 sz = type_size_of(type);
-		char const *name = nullptr;
-		switch (sz) {
-		case 1:  name = "default_hasher1";  break;
-		case 2:  name = "default_hasher2";  break;
-		case 4:  name = "default_hasher4";  break;
-		case 8:  name = "default_hasher8";  break;
-		case 16: name = "default_hasher16"; break;
-		default: GB_PANIC("unhandled hasher for key type: %s", type_to_string(type));
-		}
-		GB_ASSERT(name != nullptr);
-
-		auto args = array_make<lbValue>(permanent_allocator(), 2);
-		args[0] = data;
-		args[1] = seed;
-		lbValue res = lb_emit_runtime_call(p, name, args);
-		LLVMBuildRet(p->builder, res.value);
+		GB_PANIC("Unhandled type for hasher: %s", type_to_string(type));
 	}
 	}
 
 
-	lb_end_procedure_body(p);
-
-	hasher_proc = p;
-	return {hasher_proc->value, hasher_proc->type};
+	return {p->value, p->type};
 }
 }