diff options
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 75 |
1 files changed, 65 insertions, 10 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index fb7e6441c..ca8b3d5a2 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3483,6 +3483,40 @@ lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *f return v; } +void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment) { + 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) { + is_inlinable = true; + } + } + + char const *name = "llvm.memset"; + if (is_inlinable) { + name = "llvm.memset.inline"; + } + + LLVMTypeRef types[2] = { + lb_type(p->module, t_rawptr), + lb_type(p->module, t_int) + }; + unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name)); + GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]), LLVMPrintTypeToString(types[2])); + LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types)); + + LLVMValueRef args[4] = {}; + args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], ""); + args[1] = LLVMConstInt(LLVMInt8TypeInContext(p->module->ctx), 0, false); + args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, ""); + args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, false); // is_volatile parameter + + LLVMBuildCall(p->builder, ip, args, gb_count_of(args), ""); +} + void lb_mem_zero_ptr(lbProcedure *p, LLVMValueRef ptr, Type *type, unsigned alignment) { LLVMTypeRef llvm_type = lb_type(p->module, type); @@ -3493,10 +3527,8 @@ void lb_mem_zero_ptr(lbProcedure *p, LLVMValueRef ptr, Type *type, unsigned alig case LLVMArrayTypeKind: { // NOTE(bill): Enforce zeroing through memset to make sure padding is zeroed too - LLVMTypeRef type_i8 = LLVMInt8TypeInContext(p->module->ctx); - LLVMTypeRef type_i32 = LLVMInt32TypeInContext(p->module->ctx); i32 sz = cast(i32)type_size_of(type); - LLVMBuildMemSet(p->builder, ptr, LLVMConstNull(type_i8), LLVMConstInt(type_i32, sz, false), alignment); + lb_mem_zero_ptr_internal(p, ptr, lb_const_int(p->module, t_int, sz).value, alignment); } break; default: @@ -4953,10 +4985,12 @@ lbCopyElisionHint lb_set_copy_elision_hint(lbProcedure *p, lbAddr const &addr, A p->copy_elision_hint.used = false; p->copy_elision_hint.ptr = {}; p->copy_elision_hint.ast = nullptr; +#if 0 if (addr.kind == lbAddr_Default && addr.addr.value != nullptr) { p->copy_elision_hint.ptr = lb_addr_get_ptr(p, addr); p->copy_elision_hint.ast = unparen_expr(ast); } +#endif return prev; } @@ -5056,12 +5090,12 @@ void lb_build_assignment(lbProcedure *p, Array<lbAddr> &lvals, Slice<Ast *> cons array_add(&inits, v); } } else { - // auto prev_hint = lb_set_copy_elision_hint(p, lvals[inits.count], rhs); + auto prev_hint = lb_set_copy_elision_hint(p, lvals[inits.count], rhs); lbValue init = lb_build_expr(p, rhs); if (p->copy_elision_hint.used) { lvals[inits.count] = {}; // zero lval } - // lb_reset_copy_elision_hint(p, prev_hint); + lb_reset_copy_elision_hint(p, prev_hint); array_add(&inits, init); } } @@ -9485,10 +9519,33 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, src = lb_emit_conv(p, src, t_rawptr); len = lb_emit_conv(p, len, t_int); + bool is_inlinable = false; + + if (ce->args[2]->tav.mode == Addressing_Constant) { + ExactValue ev = exact_value_to_integer(ce->args[2]->tav.value); + i64 const_len = exact_value_to_i64(ev); + // TODO(bill): Determine when it is better to do the `*.inline` versions + if (const_len <= 4*build_context.word_size) { + is_inlinable = true; + } + } + char const *name = nullptr; switch (id) { - case BuiltinProc_mem_copy: name = "llvm.memmove"; break; - case BuiltinProc_mem_copy_non_overlapping: name = "llvm.memcpy"; break; + case BuiltinProc_mem_copy: + if (is_inlinable) { + name = "llvm.memmove.inline"; + } else { + name = "llvm.memmove"; + } + break; + case BuiltinProc_mem_copy_non_overlapping: + if (is_inlinable) { + name = "llvm.memcpy.line"; + } else { + name = "llvm.memcpy"; + } + break; } LLVMTypeRef types[3] = { @@ -9518,10 +9575,8 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, ptr = lb_emit_conv(p, ptr, t_rawptr); len = lb_emit_conv(p, len, t_int); - LLVMTypeRef type_i8 = LLVMInt8TypeInContext(p->module->ctx); unsigned alignment = 1; - LLVMBuildMemSet(p->builder, ptr.value, LLVMConstNull(type_i8), len.value, alignment); - + lb_mem_zero_ptr_internal(p, ptr.value, len.value, alignment); return {}; } |