From 573f3f8d487dfd1f56ab71b96ad23af1a2d4162e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 6 Feb 2017 13:50:19 -0500 Subject: [PATCH] coldcc works better * Only use Cold Calling Convention on x86 * Add the cold attribute to functions marked with coldcc --- src/analyze.cpp | 12 +++++++----- src/codegen.cpp | 3 +++ src/zig_llvm.cpp | 8 ++++++++ src/zig_llvm.hpp | 1 + 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 23040f2dd7..df554b6727 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -713,12 +713,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { fn_type->data.fn.fn_type_id = *fn_type_id; if (fn_type_id->is_cold) { - if (g->zig_target.arch.arch == ZigLLVM_arm) { - // TODO we want to use coldcc here but it's causing a segfault on ARM - // https://llvm.org/bugs/show_bug.cgi?id=31875 - fn_type->data.fn.calling_convention = LLVMCCallConv; - } else { + // cold calling convention only works on x86. + // but we can add the cold attribute later. + if (g->zig_target.arch.arch == ZigLLVM_x86 || + g->zig_target.arch.arch == ZigLLVM_x86_64) + { fn_type->data.fn.calling_convention = LLVMColdCallConv; + } else { + fn_type->data.fn.calling_convention = LLVMFastCallConv; } } else if (fn_type_id->is_extern) { fn_type->data.fn.calling_convention = LLVMCCallConv; diff --git a/src/codegen.cpp b/src/codegen.cpp index 7383cf8769..292aa22566 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -268,6 +268,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { LLVMAddFunctionAttr(fn_table_entry->llvm_value, LLVMNoReturnAttribute); } LLVMSetFunctionCallConv(fn_table_entry->llvm_value, fn_type->data.fn.calling_convention); + if (fn_type->data.fn.fn_type_id.is_cold) { + ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); + } LLVMAddFunctionAttr(fn_table_entry->llvm_value, LLVMNoUnwindAttribute); if (!g->is_release_build && fn_table_entry->fn_inline != FnInlineAlways) { ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true"); diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index d6c32b01b2..c59a533a05 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -561,6 +561,14 @@ void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const ch func->setAttributes(new_attr_set); } +void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn_ref) { + Function *func = unwrap(fn_ref); + const AttributeSet attr_set = func->getAttributes(); + const AttributeSet new_attr_set = attr_set.addAttribute(func->getContext(), AttributeSet::FunctionIndex, + Attribute::Cold); + func->setAttributes(new_attr_set); +} + static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, ""); static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, ""); diff --git a/src/zig_llvm.hpp b/src/zig_llvm.hpp index d6795db68c..0062757b95 100644 --- a/src/zig_llvm.hpp +++ b/src/zig_llvm.hpp @@ -165,6 +165,7 @@ ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, ZigLLVMDIScop void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); +void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); unsigned ZigLLVMGetPrefTypeAlignment(LLVMTargetDataRef TD, LLVMTypeRef Ty);