| ... | @@ -57,6 +57,9 @@ static const char *symbols_that_llvm_depends_on[] = { | ... | @@ -57,6 +57,9 @@ static const char *symbols_that_llvm_depends_on[] = { |
| 57 | "log10", | 57 | "log10", |
| 58 | "log2", | 58 | "log2", |
| 59 | "fma", | 59 | "fma", |
| | 60 | "fmaf", |
| | 61 | "fmal", |
| | 62 | "fmaq", |
| 60 | "fabs", | 63 | "fabs", |
| 61 | "minnum", | 64 | "minnum", |
| 62 | "maxnum", | 65 | "maxnum", |
| ... | @@ -832,10 +835,25 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn | ... | @@ -832,10 +835,25 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn |
| 832 | | 835 | |
| 833 | bool is_vector = (type_entry->id == ZigTypeIdVector); | 836 | bool is_vector = (type_entry->id == ZigTypeIdVector); |
| 834 | ZigType *float_type = is_vector ? type_entry->data.vector.elem_type : type_entry; | 837 | ZigType *float_type = is_vector ? type_entry->data.vector.elem_type : type_entry; |
| | 838 | uint32_t float_bits = float_type->data.floating.bit_count; |
| | 839 | |
| | 840 | // LLVM incorrectly lowers the fma builtin for f128 to fmal, which is for |
| | 841 | // `long double`. On some targets this will be correct; on others it will be incorrect. |
| | 842 | if (fn_id == ZigLLVMFnIdFMA && float_bits == 128 && |
| | 843 | !target_long_double_is_f128(g->zig_target)) |
| | 844 | { |
| | 845 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, "fmaq"); |
| | 846 | if (existing_llvm_fn != nullptr) return existing_llvm_fn; |
| | 847 | |
| | 848 | LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry); |
| | 849 | LLVMTypeRef return_elem_types[3] = { float_type_ref, float_type_ref, float_type_ref }; |
| | 850 | LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, return_elem_types, 3, false); |
| | 851 | return LLVMAddFunction(g->module, "fmaq", fn_type); |
| | 852 | } |
| 835 | | 853 | |
| 836 | ZigLLVMFnKey key = {}; | 854 | ZigLLVMFnKey key = {}; |
| 837 | key.id = fn_id; | 855 | key.id = fn_id; |
| 838 | key.data.floating.bit_count = (uint32_t)float_type->data.floating.bit_count; | 856 | key.data.floating.bit_count = float_bits; |
| 839 | key.data.floating.vector_len = is_vector ? (uint32_t)type_entry->data.vector.len : 0; | 857 | key.data.floating.vector_len = is_vector ? (uint32_t)type_entry->data.vector.len : 0; |
| 840 | key.data.floating.op = op; | 858 | key.data.floating.op = op; |
| 841 | | 859 | |
| ... | @@ -861,11 +879,7 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn | ... | @@ -861,11 +879,7 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn |
| 861 | else | 879 | else |
| 862 | sprintf(fn_name, "llvm.%s.f%" PRIu32, name, key.data.floating.bit_count); | 880 | sprintf(fn_name, "llvm.%s.f%" PRIu32, name, key.data.floating.bit_count); |
| 863 | LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry); | 881 | LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry); |
| 864 | LLVMTypeRef return_elem_types[3] = { | 882 | LLVMTypeRef return_elem_types[3] = { float_type_ref, float_type_ref, float_type_ref }; |
| 865 | float_type_ref, | | |
| 866 | float_type_ref, | | |
| 867 | float_type_ref, | | |
| 868 | }; | | |
| 869 | LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, return_elem_types, num_args, false); | 883 | LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, return_elem_types, num_args, false); |
| 870 | LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type); | 884 | LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type); |
| 871 | assert(LLVMGetIntrinsicID(fn_val)); | 885 | assert(LLVMGetIntrinsicID(fn_val)); |
| ... | @@ -6583,11 +6597,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1A | ... | @@ -6583,11 +6597,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1A |
| 6583 | assert(instruction->base.value->type->id == ZigTypeIdFloat || | 6597 | assert(instruction->base.value->type->id == ZigTypeIdFloat || |
| 6584 | instruction->base.value->type->id == ZigTypeIdVector); | 6598 | instruction->base.value->type->id == ZigTypeIdVector); |
| 6585 | LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd); | 6599 | LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd); |
| 6586 | LLVMValueRef args[3] = { | 6600 | LLVMValueRef args[3] = { op1, op2, op3 }; |
| 6587 | op1, | | |
| 6588 | op2, | | |
| 6589 | op3, | | |
| 6590 | }; | | |
| 6591 | return LLVMBuildCall(g->builder, fn_val, args, 3, ""); | 6601 | return LLVMBuildCall(g->builder, fn_val, args, 3, ""); |
| 6592 | } | 6602 | } |
| 6593 | | 6603 | |