Browse Source

Force memset instead of store zeroinitializer when the value is large

gingerBill 3 years ago
parent
commit
e6ab4f4856
4 changed files with 19 additions and 8 deletions
  1. 4 0
      src/llvm_backend.hpp
  2. 9 3
      src/llvm_backend_general.cpp
  3. 2 1
      src/llvm_backend_stmt.cpp
  4. 4 4
      src/llvm_backend_utility.cpp

+ 4 - 0
src/llvm_backend.hpp

@@ -482,7 +482,11 @@ LLVMValueRef llvm_basic_shuffle(lbProcedure *p, LLVMValueRef vector, LLVMValueRe
 
 void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
 void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
+LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile);
 
+i64 lb_max_zero_init_size(void) {
+	return cast(i64)(4*build_context.word_size);
+}
 
 #define LB_STARTUP_RUNTIME_PROC_NAME   "__$startup_runtime"
 #define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"

+ 9 - 3
src/llvm_backend_general.cpp

@@ -855,7 +855,11 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
 
 	if (LLVMIsNull(value.value)) {
 		LLVMTypeRef src_t = LLVMGetElementType(LLVMTypeOf(ptr.value));
-		LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
+		if (lb_sizeof(src_t) <= lb_max_zero_init_size()) {
+			LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
+		} else {
+			lb_mem_zero_ptr(p, ptr.value, a, LLVMGetAlignment(ptr.value));
+		}
 		return;
 	}
 	if (is_type_boolean(a)) {
@@ -2737,13 +2741,15 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero_init, i32 p
 	if (!zero_init && !force_no_init) {
 		// If there is any padding of any kind, just zero init regardless of zero_init parameter
 		LLVMTypeKind kind = LLVMGetTypeKind(llvm_type);
+		if (kind == LLVMArrayTypeKind) {
+			kind = LLVMGetTypeKind(lb_type(p->module, core_array_type(type)));
+		}
+
 		if (kind == LLVMStructTypeKind) {
 			i64 sz = type_size_of(type);
 			if (type_size_of_struct_pretend_is_packed(type) != sz) {
 				zero_init = true;
 			}
-		} else if (kind == LLVMArrayTypeKind) {
-			zero_init = true;
 		}
 	}
 

+ 2 - 1
src/llvm_backend_stmt.cpp

@@ -2082,7 +2082,8 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 			lbAddr lval = {};
 			if (!is_blank_ident(name)) {
 				Entity *e = entity_of_node(name);
-				bool zero_init = true; // Always do it
+				// bool zero_init = true; // Always do it
+				bool zero_init = vd->values.count == 0;
 				lval = lb_add_local(p, e->type, e, zero_init);
 			}
 			array_add(&lvals, lval);

+ 4 - 4
src/llvm_backend_utility.cpp

@@ -50,14 +50,14 @@ lbValue lb_correct_endianness(lbProcedure *p, lbValue value) {
 	return value;
 }
 
-void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) {
+LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) {
 	bool is_inlinable = false;
 
 	i64 const_len = 0;
 	if (LLVMIsConstant(len)) {
 		const_len = cast(i64)LLVMConstIntGetSExtValue(len);
 		// TODO(bill): Determine when it is better to do the `*.inline` versions
-		if (const_len <= 4*build_context.word_size) {
+		if (const_len <= lb_max_zero_init_size()) {
 			is_inlinable = true;
 		}
 	}
@@ -83,7 +83,7 @@ void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len
 		args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
 		args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false);
 
-		LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+		return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
 	} else {
 		LLVMValueRef ip = lb_lookup_runtime_procedure(p->module, str_lit("memset")).value;
 
@@ -92,7 +92,7 @@ void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len
 		args[1] = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), 0, false);
 		args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
 
-		LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+		return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
 	}
 
 }