From f276d77c0c37e5a4bad17a9fad48d5756cfe58f6 Mon Sep 17 00:00:00 2001 From: misomosi Date: Wed, 1 Jul 2026 10:58:53 -0400 Subject: [PATCH 1/2] Fix misuse of lb_emit_(min|max) in simd_(min|max) --- src/llvm_backend_expr.cpp | 1 + src/llvm_backend_proc.cpp | 20 ++++++++++++++++++-- src/llvm_backend_utility.cpp | 4 ++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 7eb32279e..62f626d91 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3878,6 +3878,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left break; } + GB_ASSERT(res.value != nullptr); return res; } else if (is_type_soa_pointer(a)) { diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index d48f190eb..e268607fc 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1693,7 +1693,15 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; case BuiltinProc_simd_min: if (is_float) { - return lb_emit_min(p, res.type, arg0, arg1); + bool use_llvm_intrinsic = !is_arch_wasm(); + if (use_llvm_intrinsic) { + LLVMValueRef args[2] = {arg0.value, arg1.value}; + LLVMTypeRef types[1] = {lb_type(p->module, res.type)}; + res.value = lb_call_intrinsic(p, "llvm.minnum", args, gb_count_of(args), types, gb_count_of(types)); + } else { + LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOLT, arg0.value, arg1.value, ""); + res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); + } } else { LLVMValueRef cond = LLVMBuildICmp(p->builder, is_signed ? LLVMIntSLT : LLVMIntULT, arg0.value, arg1.value, ""); res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); @@ -1701,7 +1709,15 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; case BuiltinProc_simd_max: if (is_float) { - return lb_emit_max(p, res.type, arg0, arg1); + bool use_llvm_intrinsic = !is_arch_wasm(); + if (use_llvm_intrinsic) { + LLVMValueRef args[2] = {arg0.value, arg1.value}; + LLVMTypeRef types[1] = {lb_type(p->module, res.type)}; + res.value = lb_call_intrinsic(p, "llvm.maxnum", args, gb_count_of(args), types, gb_count_of(types)); + } else { + LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOGT, arg0.value, arg1.value, ""); + res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); + } } else { LLVMValueRef cond = LLVMBuildICmp(p->builder, is_signed ? LLVMIntSGT : LLVMIntUGT, arg0.value, arg1.value, ""); res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index a92e8610e..dfcb21874 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -153,7 +153,7 @@ gb_internal lbValue lb_emit_select(lbProcedure *p, lbValue cond, lbValue x, lbVa gb_internal lbValue lb_emit_min(lbProcedure *p, Type *t, lbValue x, lbValue y) { x = lb_emit_conv(p, x, t); y = lb_emit_conv(p, y, t); - bool use_llvm_intrinsic = !is_arch_wasm() && (is_type_float(t) || (is_type_simd_vector(t) && is_type_float(base_array_type(t)))); + bool use_llvm_intrinsic = !is_arch_wasm() && is_type_float(t); if (use_llvm_intrinsic) { LLVMValueRef args[2] = {x.value, y.value}; LLVMTypeRef types[1] = {lb_type(p->module, t)}; @@ -169,7 +169,7 @@ gb_internal lbValue lb_emit_min(lbProcedure *p, Type *t, lbValue x, lbValue y) { gb_internal lbValue lb_emit_max(lbProcedure *p, Type *t, lbValue x, lbValue y) { x = lb_emit_conv(p, x, t); y = lb_emit_conv(p, y, t); - bool use_llvm_intrinsic = !is_arch_wasm() && (is_type_float(t) || (is_type_simd_vector(t) && is_type_float(base_array_type(t)))); + bool use_llvm_intrinsic = !is_arch_wasm() && is_type_float(t); if (use_llvm_intrinsic) { LLVMValueRef args[2] = {x.value, y.value}; LLVMTypeRef types[1] = {lb_type(p->module, t)}; From b5e3b08a8ca3c7e5c6979f8618071e4403dd39bf Mon Sep 17 00:00:00 2001 From: misomosi Date: Thu, 2 Jul 2026 09:56:38 -0400 Subject: [PATCH 2/2] Remove use of llvm.(max|min)num in SIMD builtins --- src/llvm_backend_proc.cpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index e268607fc..d91551157 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1693,15 +1693,8 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; case BuiltinProc_simd_min: if (is_float) { - bool use_llvm_intrinsic = !is_arch_wasm(); - if (use_llvm_intrinsic) { - LLVMValueRef args[2] = {arg0.value, arg1.value}; - LLVMTypeRef types[1] = {lb_type(p->module, res.type)}; - res.value = lb_call_intrinsic(p, "llvm.minnum", args, gb_count_of(args), types, gb_count_of(types)); - } else { - LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOLT, arg0.value, arg1.value, ""); - res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); - } + LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOLT, arg0.value, arg1.value, ""); + res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); } else { LLVMValueRef cond = LLVMBuildICmp(p->builder, is_signed ? LLVMIntSLT : LLVMIntULT, arg0.value, arg1.value, ""); res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); @@ -1709,15 +1702,8 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; case BuiltinProc_simd_max: if (is_float) { - bool use_llvm_intrinsic = !is_arch_wasm(); - if (use_llvm_intrinsic) { - LLVMValueRef args[2] = {arg0.value, arg1.value}; - LLVMTypeRef types[1] = {lb_type(p->module, res.type)}; - res.value = lb_call_intrinsic(p, "llvm.maxnum", args, gb_count_of(args), types, gb_count_of(types)); - } else { - LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOGT, arg0.value, arg1.value, ""); - res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); - } + LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOGT, arg0.value, arg1.value, ""); + res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, ""); } else { LLVMValueRef cond = LLVMBuildICmp(p->builder, is_signed ? LLVMIntSGT : LLVMIntUGT, arg0.value, arg1.value, ""); res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, "");