aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_general.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-08-11 15:19:27 +0100
committergingerBill <bill@gingerbill.org>2022-08-11 15:19:27 +0100
commit03f683f9e77b82b1239633db08463924785e2630 (patch)
tree2a529500e0f33e299e132b3cf66cc1b723f40f58 /src/llvm_backend_general.cpp
parenta5a56e061cf9949986807c14834c9fc010b0da27 (diff)
Improve emit store for large constants
Diffstat (limited to 'src/llvm_backend_general.cpp')
-rw-r--r--src/llvm_backend_general.cpp46
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)) {