From a1ee9e70352c6ab0402f98c3b84f8b3f0c86e6f9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 6 Mar 2024 15:04:46 +0000 Subject: [PATCH] Change min/max runtime behaviour to match IEEE 754-2019 --- src/llvm_backend_utility.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 5bd3cd8e2..0f5d7fb43 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -124,11 +124,29 @@ 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); + if (is_type_float(t)) { + // NOTE(bill): f either operand is a NaN, returns NaN. Otherwise returns the lesser of the two arguments. + // -0.0 is considered to be less than +0.0 for this intrinsic. + // These semantics are specified by IEEE 754-2019. + LLVMValueRef args[2] = {x.value, y.value}; + LLVMTypeRef types[1] = {lb_type(p->module, t)}; + LLVMValueRef v = lb_call_intrinsic(p, "llvm.minimum", args, gb_count_of(args), types, gb_count_of(types)); + return {v, t}; + } return lb_emit_select(p, lb_emit_comp(p, Token_Lt, x, y), x, 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); + if (is_type_float(t)) { + // NOTE(bill): If either operand is a NaN, returns NaN. Otherwise returns the greater of the two arguments. + // -0.0 is considered to be less than +0.0 for this intrinsic. + // These semantics are specified by IEEE 754-2019. + LLVMValueRef args[2] = {x.value, y.value}; + LLVMTypeRef types[1] = {lb_type(p->module, t)}; + LLVMValueRef v = lb_call_intrinsic(p, "llvm.maximum", args, gb_count_of(args), types, gb_count_of(types)); + return {v, t}; + } return lb_emit_select(p, lb_emit_comp(p, Token_Gt, x, y), x, y); }