diff options
| author | gingerBill <bill@gingerbill.org> | 2022-08-11 15:19:27 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2022-08-11 15:19:27 +0100 |
| commit | 03f683f9e77b82b1239633db08463924785e2630 (patch) | |
| tree | 2a529500e0f33e299e132b3cf66cc1b723f40f58 /src/llvm_backend_general.cpp | |
| parent | a5a56e061cf9949986807c14834c9fc010b0da27 (diff) | |
Improve emit store for large constants
Diffstat (limited to 'src/llvm_backend_general.cpp')
| -rw-r--r-- | src/llvm_backend_general.cpp | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 082163b2f..bcbd041ae 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -567,6 +567,13 @@ void lb_emit_slice_bounds_check(lbProcedure *p, Token token, lbValue low, lbValu } } +unsigned lb_try_get_alignment(LLVMValueRef addr_ptr, unsigned default_alignment) { + if (LLVMIsAGlobalValue(addr_ptr) || LLVMIsAAllocaInst(addr_ptr) || LLVMIsALoadInst(addr_ptr)) { + return LLVMGetAlignment(addr_ptr); + } + return default_alignment; +} + bool lb_try_update_alignment(LLVMValueRef addr_ptr, unsigned alignment) { if (LLVMIsAGlobalValue(addr_ptr) || LLVMIsAAllocaInst(addr_ptr) || LLVMIsALoadInst(addr_ptr)) { if (LLVMGetAlignment(addr_ptr) < alignment) { @@ -914,16 +921,35 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { enum {MAX_STORE_SIZE = 64}; - if (LLVMIsALoadInst(value.value) && lb_sizeof(LLVMTypeOf(value.value)) > MAX_STORE_SIZE) { - LLVMValueRef dst_ptr = ptr.value; - LLVMValueRef src_ptr = LLVMGetOperand(value.value, 0); - src_ptr = LLVMBuildPointerCast(p->builder, src_ptr, LLVMTypeOf(dst_ptr), ""); - - LLVMBuildMemMove(p->builder, - dst_ptr, 1, - src_ptr, 1, - LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); - return; + if (lb_sizeof(LLVMTypeOf(value.value)) > MAX_STORE_SIZE) { + if (LLVMIsALoadInst(value.value)) { + LLVMValueRef dst_ptr = ptr.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)); + return; + } else if (LLVMIsConstant(value.value)) { + lbAddr addr = lb_add_global_generated(p->module, value.type, value, nullptr); + LLVMValueRef global_data = addr.addr.value; + // make it truly private data + LLVMSetLinkage(global_data, LLVMPrivateLinkage); + LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr); + LLVMSetGlobalConstant(global_data, true); + + LLVMValueRef dst_ptr = ptr.value; + LLVMValueRef src_ptr = global_data; + src_ptr = LLVMBuildPointerCast(p->builder, src_ptr, LLVMTypeOf(dst_ptr), ""); + + LLVMBuildMemMove(p->builder, + dst_ptr, lb_try_get_alignment(dst_ptr, 1), + src_ptr, lb_try_get_alignment(global_data, 1), + LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); + return; + } } if (lb_is_type_proc_recursive(a)) { |