From patchwork Fri Jul 21 14:45:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 1810965 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=vQAA09zp; dkim-atps=neutral Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4R6snV56DNz1yYm for ; Sat, 22 Jul 2023 00:46:22 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6B2D5385417F for ; Fri, 21 Jul 2023 14:46:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6B2D5385417F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1689950780; bh=3RLAI6+21M8maCxoWe3uGwk5TaUsLH58rA03cJB8pb8=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=vQAA09zpuOUCusalaHpSW/uT7gloYgpmj7PoPYjQ681Aptu7GuRdOMJo3zmhjGqYS okRf8GIuG5JZITi2+kZmmw5/fnD0z7IYj28R01Ag4eunPjXxMjrBOhkGrY6aLRWxkl wid2YYQMt4PriX2en2+yC6ikC218nr6BkVUR+/sY= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from nikam.ms.mff.cuni.cz (nikam.ms.mff.cuni.cz [195.113.20.16]) by sourceware.org (Postfix) with ESMTPS id ACB623858409 for ; Fri, 21 Jul 2023 14:45:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org ACB623858409 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id C68D628270F; Fri, 21 Jul 2023 16:45:54 +0200 (CEST) Date: Fri, 21 Jul 2023 16:45:54 +0200 To: gcc-patches@gcc.gnu.org Subject: Fix sreal::to_int and implement sreal::to_nearest_int Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jan Hubicka via Gcc-patches From: Jan Hubicka Reply-To: Jan Hubicka Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Fix sreal::to_int and implement sreal::to_nearest_int while exploring new loop estimate dumps, I noticed that loop iterating 1.8 times by profile is etimated as iterating once instead of 2 by nb_estimate. While nb_estimate should really be a sreal and I will convert it incrementally, I found problem is in previous patch doing: + *nit = (snit + 0.5).to_int (); this does not work for sreal because it has only constructor from integer, so first 0.5 is rounded to 0 and then added to snit. Some code uses sreal(1, -1) which produces 0.5, but it reuqires unnecessary addition, so I decided to add to_nearest_int. Testing it I noticed that to_int is buggy: (sreal(3)/2).to_int () == 1 while (sreal(-3)/2).to_int () == -2 Probably not big deal in practice as we do not do conversions on negative values. Fix is easy, we need to correctly shift in positive values. This patch fixes it and adds the to_nearest_int alternative. Bootstrapped/regtested x86_64-linux, will commit it shortly. gcc/ChangeLog: * sreal.cc (sreal::to_nearest_int): New. (sreal_verify_basics): Verify also to_nearest_int. (verify_aritmetics): Likewise. (sreal_verify_conversions): New. (sreal_cc_tests): Call sreal_verify_conversions. * sreal.h: (sreal::to_nearest_int): Declare diff --git a/gcc/sreal.cc b/gcc/sreal.cc index 8e99d871420..606a571e339 100644 --- a/gcc/sreal.cc +++ b/gcc/sreal.cc @@ -116,7 +116,26 @@ sreal::to_int () const if (m_exp > 0) return sign * (SREAL_ABS ((int64_t)m_sig) << m_exp); if (m_exp < 0) - return m_sig >> -m_exp; + return sign * (SREAL_ABS ((int64_t)m_sig) >> -m_exp); + return m_sig; +} + +/* Return nearest integer value of *this. */ + +int64_t +sreal::to_nearest_int () const +{ + int64_t sign = SREAL_SIGN (m_sig); + + if (m_exp <= -SREAL_BITS) + return 0; + if (m_exp >= SREAL_PART_BITS) + return sign * INTTYPE_MAXIMUM (int64_t); + if (m_exp > 0) + return sign * (SREAL_ABS ((int64_t)m_sig) << m_exp); + if (m_exp < 0) + return sign * ((SREAL_ABS ((int64_t)m_sig) >> -m_exp) + + ((SREAL_ABS (m_sig) >> (-m_exp - 1)) & 1)); return m_sig; } @@ -286,6 +305,8 @@ sreal_verify_basics (void) ASSERT_EQ (INT_MIN/2, minimum.to_int ()); ASSERT_EQ (INT_MAX/2, maximum.to_int ()); + ASSERT_EQ (INT_MIN/2, minimum.to_nearest_int ()); + ASSERT_EQ (INT_MAX/2, maximum.to_nearest_int ()); ASSERT_FALSE (minus_two < minus_two); ASSERT_FALSE (seven < seven); @@ -315,6 +336,10 @@ verify_aritmetics (int64_t a, int64_t b) ASSERT_EQ (a - b, (sreal (a) - sreal (b)).to_int ()); ASSERT_EQ (b + a, (sreal (b) + sreal (a)).to_int ()); ASSERT_EQ (b - a, (sreal (b) - sreal (a)).to_int ()); + ASSERT_EQ (a + b, (sreal (a) + sreal (b)).to_nearest_int ()); + ASSERT_EQ (a - b, (sreal (a) - sreal (b)).to_nearest_int ()); + ASSERT_EQ (b + a, (sreal (b) + sreal (a)).to_nearest_int ()); + ASSERT_EQ (b - a, (sreal (b) - sreal (a)).to_nearest_int ()); } /* Verify arithmetics for interesting numbers. */ @@ -377,6 +402,33 @@ sreal_verify_negative_division (void) ASSERT_EQ (sreal (1234567) / sreal (-1234567), sreal (-1)); } +static void +sreal_verify_conversions (void) +{ + ASSERT_EQ ((sreal (11) / sreal (3)).to_int (), 3); + ASSERT_EQ ((sreal (11) / sreal (3)).to_nearest_int (), 4); + ASSERT_EQ ((sreal (10) / sreal (3)).to_int (), 3); + ASSERT_EQ ((sreal (10) / sreal (3)).to_nearest_int (), 3); + ASSERT_EQ ((sreal (9) / sreal (3)).to_int (), 3); + ASSERT_EQ ((sreal (9) / sreal (3)).to_nearest_int (), 3); + ASSERT_EQ ((sreal (-11) / sreal (3)).to_int (), -3); + ASSERT_EQ ((sreal (-11) / sreal (3)).to_nearest_int (), -4); + ASSERT_EQ ((sreal (-10) / sreal (3)).to_int (), -3); + ASSERT_EQ ((sreal (-10) / sreal (3)).to_nearest_int (), -3); + ASSERT_EQ ((sreal (-3)).to_int (), -3); + ASSERT_EQ ((sreal (-3)).to_nearest_int (), -3); + for (int i = -100000 ; i < 100000; i += 123) + for (int j = -10000 ; j < 100000; j += 71) + if (j != 0) + { + sreal sval = ((sreal)i) / (sreal)j; + double val = (double)i / (double)j; + ASSERT_EQ ((fabs (sval.to_double () - val) < 0.00001), true); + ASSERT_EQ (sval.to_int (), (int)val); + ASSERT_EQ (sval.to_nearest_int (), lround (val)); + } +} + /* Run all of the selftests within this file. */ void sreal_cc_tests () @@ -385,6 +437,7 @@ void sreal_cc_tests () sreal_verify_arithmetics (); sreal_verify_shifting (); sreal_verify_negative_division (); + sreal_verify_conversions (); } } // namespace selftest diff --git a/gcc/sreal.h b/gcc/sreal.h index 8700807a131..4dbb83c3005 100644 --- a/gcc/sreal.h +++ b/gcc/sreal.h @@ -51,6 +51,7 @@ public: void dump (FILE *) const; int64_t to_int () const; + int64_t to_nearest_int () const; double to_double () const; void stream_out (struct output_block *); static sreal stream_in (class lto_input_block *);