From patchwork Fri Dec 19 16:45:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: James Y Knight X-Patchwork-Id: 126886 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id BBAC14BA2E23 for ; Fri, 19 Dec 2025 16:46:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BBAC14BA2E23 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20230601 header.b=jW5Oqgs/ X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-yx1-f74.google.com (mail-yx1-f74.google.com [74.125.224.74]) by sourceware.org (Postfix) with ESMTPS id 712DB4BA2E04 for ; Fri, 19 Dec 2025 16:46:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 712DB4BA2E04 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=flex--jyknight.bounces.google.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 712DB4BA2E04 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=74.125.224.74 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1766162779; cv=none; b=iXkb0oZ2MIlpth+9MWvNOYy3fG5BjpOm+p3pcAhf7mLvrbq6hxhAluEBw8tSp/LdPVuyHLEriprWBwoRcHa1b1vhEbIuDBauE11PVoFVxVROZCILiC8Fswe35wof8EikKgiM/W1MUL5fmu62mhdlXuMVL2g+jr4vbv2BtDHeg9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1766162779; c=relaxed/simple; bh=4y9c8Bep0iFYiJerqnudywupRZK/nrkM/9g8KjvcFGI=; h=DKIM-Signature:Date:Mime-Version:Message-ID:Subject:From:To; b=Pr7co19LyU1O4vJvTeTCPwCXxsOYhVSR7OYHgEZRM3vRpTfP1kuj3o/x149HgApJe+W23mqgkHj8PoKdmsDxXFyrFl8pYdphd/4n9pRAcIOpbvhaEpQZDLXDd/Rl8OpVXt/ARIdZePHSKKEItDBe492F41NMtxX7SqCska0j540= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 712DB4BA2E04 Received: by mail-yx1-f74.google.com with SMTP id 956f58d0204a3-6445cf02fcbso2247604d50.2 for ; Fri, 19 Dec 2025 08:46:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1766162779; x=1766767579; darn=sourceware.org; h=content-transfer-encoding:cc:to:from:subject:message-id :mime-version:date:from:to:cc:subject:date:message-id:reply-to; bh=Z4uBCDUpmt210u2i/5cOOiSAOqDwlufzvsZ2Bip4YHI=; b=jW5Oqgs/WuzXEPbSI5QhmnOI60joQdbBrQa43J40ZH91ObLOaeUqqiVI8kwxyuphDo 6w8yxQoZ0vga2HOHUBw5SnV8RCqbLUmUE/Lj0aV6ni7kNfmjw500Qj7KInP0jyAKnbHF mU75NbcGNtG02xCmSkzFath3qxzvPZDWSfSsPU/wzZGzf0A4FjPU1YFulIsloYdPdxm6 bZ/RKkzvS4pObyG0WLod76OmIMreSiqA4tCb3piusBB6XWiuVGxGjAuhgWl2LGxsUp0S Q6G42x79RWemBfJ+e5Y6iQeg+AgWuaUW/KvEOVfHarFV4ngB4Div0S33RbOIvP+iwif4 eMtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766162779; x=1766767579; h=content-transfer-encoding:cc:to:from:subject:message-id :mime-version:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Z4uBCDUpmt210u2i/5cOOiSAOqDwlufzvsZ2Bip4YHI=; b=ifZUi5orXecBxvfqW04o48FFCR9kAgW2d2kyHMEfUW2yU5vW0SFgX7oahbV0MaVD7A ttwduxPUXCkD/2Li/YqtaRkh2Z7A/oQEXeZYe8dS0+wCNxbYkwmizMM0iUuqhgyqUdr/ D8xc0FEzCDivsCd0SDu0OvuKvO9+Vr9DtNTjaaGm5/mFnuy2c9Jq5Nvr2Owgfxwlq0gU u6evvCDFGgPeqA1nyvbKBlw7QJHssAbSyTno3ehWACPdUiyc+0PXaCCucU+g0iAOLLEr HU9GYd8QWeEYQvxnTOaRib4vQA7Lvr00XztJvc01IqHbAJI4hjtaGHrDF3FeNAlZgz+0 vi+w== X-Gm-Message-State: AOJu0YxRt4kENvrclTT1TW3p55gPoOQPLbxxlCCnFaShMoCDwJne2oS/ 6Arb790xMJ9seoQ7R/g+hAMRosls6A6I5DbSADaAFjf6tRsWIVXjSxQhrPkg/o97mYOmIpya1SD 9dMJiXiDW+N5HMR58WmInCcfOg8woDYfOVpBccUwLYbpMiJJhaACzTJLtlbwDru5s1wHBPkIP4f 2FtBnEqSiOw35znG1VJbDgTowut7RrYj692S5F0O+q4IPtAq8AeCM= X-Google-Smtp-Source: AGHT+IHf86TmJzgt9t7+T/gz6p8ATWqPEfiCWQr/N96w0k2I1njUvHGpnpKxPSQ7zlE43MZcepIJhyy/delV4A== X-Received: from yxqv8.prod.google.com ([2002:a53:ea48:0:b0:63f:3681:991e]) (user=jyknight job=prod-delivery.src-stubby-dispatcher) by 2002:a05:690c:c4f6:b0:786:5afa:375c with SMTP id 00721157ae682-78fb40d9808mr61566807b3.67.1766162778647; Fri, 19 Dec 2025 08:46:18 -0800 (PST) Date: Fri, 19 Dec 2025 11:45:54 -0500 Mime-Version: 1.0 X-Mailer: git-send-email 2.52.0.322.g1dd061c0dc-goog Message-ID: <20251219164554.552368-1-jyknight@google.com> Subject: [PATCH] math: Order signed zeros in fmin and fmax. From: James Y Knight To: libc-alpha@sourceware.org Cc: joseph@codesourcery.com, James Y Knight X-Spam-Status: No, score=-14.8 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_BL_SPAMCOP_NET, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLOCKED, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org The C standard (at least from C99 till C23) does _not_ require fmin/fmax to order zeros by their sign, so glibc's previous behavior was entirely standards-conforming. However, the standard does recommend that zeros be ordered in a footnote, saying: "If possible, fmax is sensitive to the sign of zero, for example fmax(−0.0, +0.0) ideally returns +0." As this is indeed possible (and not too complicated), implement it as a quality-of-implementation improvement. Many other libc implementations have done so for a long time, such as freebsd, openbsd, android, musl, llvm-libc, and Windows. --- math/libm-test-fmax.inc | 4 ++-- math/libm-test-fmin.inc | 4 ++-- math/s_fmax_template.c | 6 ++++-- math/s_fmin_template.c | 6 ++++-- sysdeps/i386/fpu/s_fmax.S | 6 +++++- sysdeps/i386/fpu/s_fmaxf.S | 6 +++++- sysdeps/i386/fpu/s_fmaxl.S | 5 ++++- sysdeps/i386/fpu/s_fmin.S | 6 +++++- sysdeps/i386/fpu/s_fminf.S | 6 +++++- sysdeps/i386/fpu/s_fminl.S | 5 ++++- sysdeps/i386/i686/fpu/s_fmax.S | 7 ++++++- sysdeps/i386/i686/fpu/s_fmaxf.S | 7 ++++++- sysdeps/i386/i686/fpu/s_fmaxl.S | 6 +++++- sysdeps/i386/i686/fpu/s_fmin.S | 7 ++++++- sysdeps/i386/i686/fpu/s_fminf.S | 7 ++++++- sysdeps/i386/i686/fpu/s_fminl.S | 6 +++++- sysdeps/x86_64/fpu/s_fmax.S | 4 ++++ sysdeps/x86_64/fpu/s_fmaxf.S | 4 ++++ sysdeps/x86_64/fpu/s_fmaxl.S | 7 ++++++- sysdeps/x86_64/fpu/s_fmin.S | 4 ++++ sysdeps/x86_64/fpu/s_fminf.S | 4 ++++ sysdeps/x86_64/fpu/s_fminl.S | 7 ++++++- 22 files changed, 102 insertions(+), 22 deletions(-) diff --git a/math/libm-test-fmax.inc b/math/libm-test-fmax.inc index 2716bcf70e..4276e774f4 100644 --- a/math/libm-test-fmax.inc +++ b/math/libm-test-fmax.inc @@ -22,8 +22,8 @@ static const struct test_ff_f_data fmax_test_data[] = { TEST_ff_f (fmax, 0, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmax, minus_zero, minus_zero, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), - TEST_ff_f (fmax, 0, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|IGNORE_ZERO_INF_SIGN), - TEST_ff_f (fmax, minus_zero, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|IGNORE_ZERO_INF_SIGN), + TEST_ff_f (fmax, 0, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (fmax, minus_zero, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmax, min_subnorm_value, -min_subnorm_value, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmax, -min_subnorm_value, min_subnorm_value, min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmax, min_value, -min_value, min_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), diff --git a/math/libm-test-fmin.inc b/math/libm-test-fmin.inc index d0f5bf6b7e..577f54705b 100644 --- a/math/libm-test-fmin.inc +++ b/math/libm-test-fmin.inc @@ -22,8 +22,8 @@ static const struct test_ff_f_data fmin_test_data[] = { TEST_ff_f (fmin, 0, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmin, minus_zero, minus_zero, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), - TEST_ff_f (fmin, 0, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|IGNORE_ZERO_INF_SIGN), - TEST_ff_f (fmin, minus_zero, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|IGNORE_ZERO_INF_SIGN), + TEST_ff_f (fmin, 0, minus_zero, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (fmin, minus_zero, 0, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmin, min_subnorm_value, -min_subnorm_value, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmin, -min_subnorm_value, min_subnorm_value, -min_subnorm_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (fmin, min_value, -min_value, -min_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), diff --git a/math/s_fmax_template.c b/math/s_fmax_template.c index 87e6ee67df..2bd331c7dd 100644 --- a/math/s_fmax_template.c +++ b/math/s_fmax_template.c @@ -24,9 +24,11 @@ M_DECL_FUNC (__fmax) (FLOAT x, FLOAT y) #if M_USE_BUILTIN (FMAX) return M_SUF (__builtin_fmax) (x, y); #else - if (isgreaterequal (x, y)) + if (isgreaterequal (x, y)) { + if (signbit(x) && !signbit(y)) + return y; return x; - else if (isless (x, y)) + } else if (isless (x, y)) return y; else if (issignaling (x) || issignaling (y)) return x + y; diff --git a/math/s_fmin_template.c b/math/s_fmin_template.c index 9ff330969f..4ac2f2fca1 100644 --- a/math/s_fmin_template.c +++ b/math/s_fmin_template.c @@ -24,9 +24,11 @@ M_DECL_FUNC (__fmin) (FLOAT x, FLOAT y) #if M_USE_BUILTIN (FMIN) return M_SUF (__builtin_fmin) (x, y); #else - if (islessequal (x, y)) + if (islessequal (x, y)) { + if (!signbit(x) && signbit(y)) + return y; return x; - else if (isgreater (x, y)) + } else if (isgreater (x, y)) return y; else if (issignaling (x) || issignaling (y)) return x + y; diff --git a/sysdeps/i386/fpu/s_fmax.S b/sysdeps/i386/fpu/s_fmax.S index 8fa48ae013..7171b048ec 100644 --- a/sysdeps/i386/fpu/s_fmax.S +++ b/sysdeps/i386/fpu/s_fmax.S @@ -33,8 +33,12 @@ ENTRY(__fmax) fucom %st(1) fnstsw sahf - jnc 1f + jnz 2f + jp 2f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 19(%esp) +2: jnc 1f fxch %st(1) 1: fstp %st(1) diff --git a/sysdeps/i386/fpu/s_fmaxf.S b/sysdeps/i386/fpu/s_fmaxf.S index 5c881a849d..c8d0fb0412 100644 --- a/sysdeps/i386/fpu/s_fmaxf.S +++ b/sysdeps/i386/fpu/s_fmaxf.S @@ -33,8 +33,12 @@ ENTRY(__fmaxf) fucom %st(1) fnstsw sahf - jnc 1f + jnz 2f + jp 2f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 11(%esp) +2: jnc 1f fxch %st(1) 1: fstp %st(1) diff --git a/sysdeps/i386/fpu/s_fmaxl.S b/sysdeps/i386/fpu/s_fmaxl.S index 77526e3b99..3655231a2e 100644 --- a/sysdeps/i386/fpu/s_fmaxl.S +++ b/sysdeps/i386/fpu/s_fmaxl.S @@ -39,7 +39,10 @@ ENTRY(__fmaxl) fucom %st(1) fnstsw sahf - jnc 1f + jnz 5f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 25(%esp) +5: jnc 1f fxch %st(1) 1: fstp %st(1) diff --git a/sysdeps/i386/fpu/s_fmin.S b/sysdeps/i386/fpu/s_fmin.S index e15e668a61..5d77b5e77c 100644 --- a/sysdeps/i386/fpu/s_fmin.S +++ b/sysdeps/i386/fpu/s_fmin.S @@ -33,8 +33,12 @@ ENTRY(__fmin) fucom %st(1) fnstsw sahf - jc 2f + jnz 3f + jp 3f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 11(%esp) +3: jc 2f 1: fxch %st(1) 2: fstp %st(1) diff --git a/sysdeps/i386/fpu/s_fminf.S b/sysdeps/i386/fpu/s_fminf.S index a5cc4e28e5..30b2b80ed2 100644 --- a/sysdeps/i386/fpu/s_fminf.S +++ b/sysdeps/i386/fpu/s_fminf.S @@ -33,8 +33,12 @@ ENTRY(__fminf) fucom %st(1) fnstsw sahf - jc 2f + jnz 3f + jp 3f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 7(%esp) +3: jc 2f 1: fxch %st(1) 2: fstp %st(1) diff --git a/sysdeps/i386/fpu/s_fminl.S b/sysdeps/i386/fpu/s_fminl.S index f23a5008da..e0cd4669d7 100644 --- a/sysdeps/i386/fpu/s_fminl.S +++ b/sysdeps/i386/fpu/s_fminl.S @@ -39,7 +39,10 @@ ENTRY(__fminl) fucom %st(1) fnstsw sahf - jc 1f + jnz 5f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 25(%esp) +5: jc 1f fxch %st(1) 1: fstp %st(1) diff --git a/sysdeps/i386/i686/fpu/s_fmax.S b/sysdeps/i386/i686/fpu/s_fmax.S index 3b5b2fee4f..7158c8ae95 100644 --- a/sysdeps/i386/i686/fpu/s_fmax.S +++ b/sysdeps/i386/i686/fpu/s_fmax.S @@ -30,7 +30,12 @@ ENTRY(__fmax) fxch fucomi %st(1), %st - fcmovb %st(1), %st + jnz 1f + jp 1f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 19(%esp) + +1: fcmovb %st(1), %st fstp %st(1) diff --git a/sysdeps/i386/i686/fpu/s_fmaxf.S b/sysdeps/i386/i686/fpu/s_fmaxf.S index 65a42ddffc..da033ea95b 100644 --- a/sysdeps/i386/i686/fpu/s_fmaxf.S +++ b/sysdeps/i386/i686/fpu/s_fmaxf.S @@ -30,7 +30,12 @@ ENTRY(__fmaxf) fxch fucomi %st(1), %st - fcmovb %st(1), %st + jnz 1f + jp 1f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 11(%esp) + +1: fcmovb %st(1), %st fstp %st(1) diff --git a/sysdeps/i386/i686/fpu/s_fmaxl.S b/sysdeps/i386/i686/fpu/s_fmaxl.S index dd1d6a3f00..41c755d91e 100644 --- a/sysdeps/i386/i686/fpu/s_fmaxl.S +++ b/sysdeps/i386/i686/fpu/s_fmaxl.S @@ -25,9 +25,13 @@ ENTRY(__fmaxl) fldt 16(%esp) // x : y fucomi %st(1), %st + jnz 1f jp 2f - fcmovb %st(1), %st + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 13(%esp) + +1: fcmovb %st(1), %st fstp %st(1) ret diff --git a/sysdeps/i386/i686/fpu/s_fmin.S b/sysdeps/i386/i686/fpu/s_fmin.S index 8df9fa32cf..11bbafb6b5 100644 --- a/sysdeps/i386/i686/fpu/s_fmin.S +++ b/sysdeps/i386/i686/fpu/s_fmin.S @@ -28,7 +28,12 @@ ENTRY(__fmin) fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise fucomi %st(1), %st - fcmovnb %st(1), %st + jnz 1f + jp 1f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 11(%esp) + +1: fcmovnb %st(1), %st fstp %st(1) diff --git a/sysdeps/i386/i686/fpu/s_fminf.S b/sysdeps/i386/i686/fpu/s_fminf.S index a4623c40e1..9f088ffe01 100644 --- a/sysdeps/i386/i686/fpu/s_fminf.S +++ b/sysdeps/i386/i686/fpu/s_fminf.S @@ -28,7 +28,12 @@ ENTRY(__fminf) fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise fucomi %st(1), %st - fcmovnb %st(1), %st + jnz 1f + jp 1f + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 7(%esp) + +1: fcmovnb %st(1), %st fstp %st(1) diff --git a/sysdeps/i386/i686/fpu/s_fminl.S b/sysdeps/i386/i686/fpu/s_fminl.S index 90629bda2f..b1922d1cd4 100644 --- a/sysdeps/i386/i686/fpu/s_fminl.S +++ b/sysdeps/i386/i686/fpu/s_fminl.S @@ -25,9 +25,13 @@ ENTRY(__fminl) fldt 16(%esp) // x : y fucomi %st(1), %st + jnz 1f jp 2f - fcmovnb %st(1), %st + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 13(%esp) + +1: fcmovnb %st(1), %st fstp %st(1) ret diff --git a/sysdeps/x86_64/fpu/s_fmax.S b/sysdeps/x86_64/fpu/s_fmax.S index 141539380a..73bc79d974 100644 --- a/sysdeps/x86_64/fpu/s_fmax.S +++ b/sysdeps/x86_64/fpu/s_fmax.S @@ -23,9 +23,13 @@ ENTRY(__fmax) ucomisd %xmm0, %xmm1 jp 1f // jump if unordered + je 5f // jump if equal maxsd %xmm1, %xmm0 jmp 2f +5: pand %xmm1, %xmm0 // and sign bits + jmp 2f + 1: ucomisd %xmm1, %xmm1 // Is xmm1 a NaN? jp 3f // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling. diff --git a/sysdeps/x86_64/fpu/s_fmaxf.S b/sysdeps/x86_64/fpu/s_fmaxf.S index 6607a3a566..24c5817f57 100644 --- a/sysdeps/x86_64/fpu/s_fmaxf.S +++ b/sysdeps/x86_64/fpu/s_fmaxf.S @@ -23,9 +23,13 @@ ENTRY(__fmaxf) ucomiss %xmm0, %xmm1 jp 1f // jump if unordered + je 5f // jump if equal maxss %xmm1, %xmm0 jmp 2f +5: pand %xmm1, %xmm0 // and sign bits + jmp 2f + 1: ucomiss %xmm1, %xmm1 // Is xmm1 a NaN? jp 3f // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling. diff --git a/sysdeps/x86_64/fpu/s_fmaxl.S b/sysdeps/x86_64/fpu/s_fmaxl.S index f2cc11bb49..c9c2df0e8e 100644 --- a/sysdeps/x86_64/fpu/s_fmaxl.S +++ b/sysdeps/x86_64/fpu/s_fmaxl.S @@ -25,8 +25,13 @@ ENTRY(__fmaxl) fldt 24(%rsp) // x : y fucomi %st(1), %st + jnz 1f jp 2f - fcmovb %st(1), %st + + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 17(%rsp) + +1: fcmovb %st(1), %st fstp %st(1) diff --git a/sysdeps/x86_64/fpu/s_fmin.S b/sysdeps/x86_64/fpu/s_fmin.S index 0cbcb6d115..394672b34a 100644 --- a/sysdeps/x86_64/fpu/s_fmin.S +++ b/sysdeps/x86_64/fpu/s_fmin.S @@ -23,9 +23,13 @@ ENTRY(__fmin) ucomisd %xmm0, %xmm1 jp 1f // jump if unordered + je 5f // jump if equal minsd %xmm1, %xmm0 jmp 2f +5: por %xmm1, %xmm0 // or sign bits + jmp 2f + 1: ucomisd %xmm1, %xmm1 // Is xmm1 a NaN? jp 3f // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling. diff --git a/sysdeps/x86_64/fpu/s_fminf.S b/sysdeps/x86_64/fpu/s_fminf.S index 2aa5fb58a7..5a69ae7665 100644 --- a/sysdeps/x86_64/fpu/s_fminf.S +++ b/sysdeps/x86_64/fpu/s_fminf.S @@ -23,9 +23,13 @@ ENTRY(__fminf) ucomiss %xmm0, %xmm1 jp 1f // jump if unordered + je 5f // jump if equal minss %xmm1, %xmm0 jmp 2f +5: por %xmm1, %xmm0 // or sign bits + jmp 2f + 1: ucomiss %xmm1, %xmm1 // Is xmm1 a NaN? jp 3f // xmm0 is a NaN; xmm1 is not. Test if xmm0 is signaling. diff --git a/sysdeps/x86_64/fpu/s_fminl.S b/sysdeps/x86_64/fpu/s_fminl.S index 7f9f17066d..1cdc6b0e44 100644 --- a/sysdeps/x86_64/fpu/s_fminl.S +++ b/sysdeps/x86_64/fpu/s_fminl.S @@ -25,8 +25,13 @@ ENTRY(__fminl) fldt 24(%rsp) // x : y fucomi %st(1), %st + jnz 1f jp 2f - fcmovnb %st(1), %st + + // Equal; check sign, so -0.0 < 0.0 + cmpb $0x80, 17(%rsp) + +1: fcmovnb %st(1), %st fstp %st(1)