From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x433.google.com (mail-pf1-x433.google.com [IPv6:2607:f8b0:4864:20::433]) by sourceware.org (Postfix) with ESMTPS id 9D28C3858038 for ; Mon, 19 Jul 2021 08:50:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9D28C3858038 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pf1-x433.google.com with SMTP id d9so4665510pfv.4 for ; Mon, 19 Jul 2021 01:50:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=f83qUIaEDBXWPWzNkXqGaiTmP6hGs3qM56SUlRV+W10=; b=SrCsjU+euONQ4BF5GIAyfkiZrv4Bg7c1dw7hipXjy/ECO5tatOLjZUK1re9Px7hI9M h2YgZxjlr39Ly4k0oJwmDrTFSmKkgsa0hmEe3xWIGbGewanbMKVxwqI91kg1BUU7kAuA +37TWmOsPvGKmKw8LtY9b3OVYZUxCgcia/mq6leODRKWQuOIf1gnfYcY7EcKxS4w8Ud/ 2TrWepJ9Ye6I4/os/MZ/KuVC9wHzFu/WY53cm2/zDprEomIBFZsjn7XvsG8JYj9PlZ+7 Z0aEzX9fv4D+UODR7T0lMZUEk8+qx4Wity6xpvgOtPfDQr/gUEhyzt0I/M4Sbs1CjidC Ptgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=f83qUIaEDBXWPWzNkXqGaiTmP6hGs3qM56SUlRV+W10=; b=pJ1vI4p47XSL/xJ8y0h6Zj8aF5Wucany1b24oQ43lvt9n0Yb+IrAFY6yDiJpjatdpo XlzasIfmm8qxp5Qrk6/RD3IT/dtMBesDmXfBydVI/tNM/bOn2Mc7NY+vHLJj2EvFG4D9 DFojyg2dBJbtz3ScbOX0R3T+IX6ZlBqaACs7fX4pKi8fvPQ8/6U4UCeQfLP7KHn51jNm H6G+4s5m9i4vTyvqOT9K88eVZxkmgfyi2MvZhosBWW+xVY+byJRyI5D8zFF0THoiXnQY c9nI5HBIWJzi3SVzBsYrXHd23D38dSQtVpcTnKcPIewb5N8eFZJzhWGlEvtRTLapRXl0 ob6Q== X-Gm-Message-State: AOAM532Id9mNnVVDEKrHQ7BcSh1YmkYrnMIRqPuAE678S4e/FYWu2vpw 5u0l595jqxmWcCbLC+4h39xCDW9PM8n5pQ== X-Google-Smtp-Source: ABdhPJyVV3X5PpgPzHUe315echOzwe40PRk6NJ3FRJE7hKVFNHawmzBdsTI/dZnVySm2+0/OZ2i1KA== X-Received: by 2002:a65:498a:: with SMTP id r10mr24435686pgs.7.1626684626331; Mon, 19 Jul 2021 01:50:26 -0700 (PDT) Received: from hsinchu02.internal.sifive.com (59-124-168-89.HINET-IP.hinet.net. [59.124.168.89]) by smtp.gmail.com with ESMTPSA id e21sm19531809pfc.172.2021.07.19.01.50.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jul 2021 01:50:25 -0700 (PDT) From: Kito Cheng To: newlib@sourceware.org, kito.cheng@gmail.com, Aldy Hernandez , Andrew MacLeod Cc: Kito Cheng Subject: [PATCH] libm: Fixing overflow handling issue for scalbnf and scalbn Date: Mon, 19 Jul 2021 16:50:22 +0800 Message-Id: <20210719085022.8157-1-kito.cheng@sifive.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-14.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GB_TO_NAME_FREEMAIL, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Newlib mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Jul 2021 08:50:30 -0000 cc Aldy Hernandez and Andrew MacLeod , they are author of new VRP analysis for GCC, just to make sure I didn't mis-understanding or mis-interpreting anything on GCC site. GCC 11 have better value range analysis, that give GCC more confidence to perform more aggressive optimization, but it cause scalbn/scalbnf get wrong result. Using scalbn to demostrate what happened on GCC 11, see comments with VRP prefix: ```c double scalbn (double x, int n) { /* VRP RESULT: n = [-INF, +INF] */ __int32_t k,hx,lx; ... k = (hx&0x7ff00000)>>20; /* VRP RESULT: k = [0, 2047] */ if (k==0) { /* VRP RESULT: k = 0 */ ... k = ((hx&0x7ff00000)>>20) - 54; if (n< -50000) return tiny*x; /*underflow*/ /* VRP RESULT: k = -54 */ } /* VRP RESULT: k = [-54, 2047] */ if (k==0x7ff) return x+x; /* NaN or Inf */ /* VRP RESULT: k = [-54, 2046] */ k = k+n; if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */ /* VRP RESULT: k = [-INF, 2046] */ /* VRP RESULT: n = [-INF, 2100], because k + n <= 0x7fe is false, so: 1. -INF < [-54, 2046] + n <= 0x7fe(2046) < INF 2. -INF < [-54, 2046] + n <= 2046 < INF 3. -INF < n <= 2046 - [-54, 2046] < INF 4. -INF < n <= [0, 2100] < INF 5. n = [-INF, 2100] */ if (k > 0) /* normal result */ {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} if (k <= -54) { /* VRP OPT: Evaluate n > 50000 as true...*/ if (n > 50000) /* in case integer overflow in n+k */ return huge*copysign(huge,x); /*overflow*/ else return tiny*copysign(tiny,x); /*underflow*/ } k += 54; /* subnormal result */ SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x*twom54; } ``` However give the input n = INT32_MAX, k = k+n will overflow, and then we expect got `huge*copysign(huge,x)`, but new VRP optimization think `n > 50000` is never be true, so optimize that into `tiny*copysign(tiny,x)`. so the solution here is to moving the overflow handle logic before `k = k + n`. --- newlib/libm/common/s_scalbn.c | 9 ++++----- newlib/libm/common/sf_scalbn.c | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/newlib/libm/common/s_scalbn.c b/newlib/libm/common/s_scalbn.c index e9dbb16ac..72da0e4a1 100644 --- a/newlib/libm/common/s_scalbn.c +++ b/newlib/libm/common/s_scalbn.c @@ -93,15 +93,14 @@ tiny = 1.0e-300; if (n< -50000) return tiny*x; /*underflow*/ } if (k==0x7ff) return x+x; /* NaN or Inf */ + if (n > 50000) /* in case integer overflow in n+k */ + return huge*copysign(huge,x); /*overflow*/ k = k+n; if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */ if (k > 0) /* normal result */ {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return huge*copysign(huge,x); /*overflow*/ - else return tiny*copysign(tiny,x); /*underflow*/ - } + if (k <= -54) + return tiny*copysign(tiny,x); /*underflow*/ k += 54; /* subnormal result */ SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x*twom54; diff --git a/newlib/libm/common/sf_scalbn.c b/newlib/libm/common/sf_scalbn.c index 700060010..747a421ef 100644 --- a/newlib/libm/common/sf_scalbn.c +++ b/newlib/libm/common/sf_scalbn.c @@ -56,15 +56,14 @@ tiny = 1.0e-30; k = ((ix&0x7f800000)>>23) - 25; if (n< -50000) return tiny*x; /*underflow*/ } + if (n > OVERFLOW_INT) /* in case integer overflow in n+k */ + return huge*copysignf(huge,x); /*overflow*/ k = k+n; if (k > FLT_LARGEST_EXP) return huge*copysignf(huge,x); /* overflow */ if (k > 0) /* normal result */ {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;} - if (k < FLT_SMALLEST_EXP) { - if (n > OVERFLOW_INT) /* in case integer overflow in n+k */ - return huge*copysignf(huge,x); /*overflow*/ - else return tiny*copysignf(tiny,x); /*underflow*/ - } + if (k < FLT_SMALLEST_EXP) + return tiny*copysignf(tiny,x); /*underflow*/ k += 25; /* subnormal result */ SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x*twom25; -- 2.31.1