From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id D3FD23858C2B for ; Sat, 14 Oct 2023 08:20:46 +0000 (GMT) ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D3FD23858C2B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1697271648; cv=none; b=ssL1qU7znWNPVrhJ7YFa1g1a7FmS0+B45oGx7cAElo2+aFOBTEOqydRz4x04Mp4KEaQxpxFLq1nhAZB1GeT0MvuehU8qPbqfDD4iRY9pGXZNg7XnYias0hcbLTHmXnHOAUd37oTntwziOmO1f1gQs6BzkLEEZppue9qsqW3bqRo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1697271648; c=relaxed/simple; bh=WU3GeEQ2Jpo8RKzVF9lALdWoNvvt2AKqVxOYOMiJeWI=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=kQ7ZRUarbm5LFPDZcJSobDmzCBNPSyKzZdKmUa/VZYDHuD64jhZg/zYneLs4qYFar0bXuEkXCnv6UrrFa8uJujLR0MQ2J71EOC4xYqIzxLiKLDmffTmLqlQZUM/MHPV/EGbYDTI9nsib3C3jYREk03g1NzpusWFjoYka/8fM1OI= ARC-Authentication-Results: i=1; server2.sourceware.org DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D3FD23858C2B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1697271646; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=UuHKpRWNsx4WdteBWH3wTrpe1+s7jDaRR4woIOIocTA=; b=UdRALhcXE6n8wLKNnMQikmTAAP2qwAA7BLDBm7erGY536Lb/xNUA/YekWbF3wUGg21l0yP BPZjOqDgXlfB+t3TNFF97xUQ9JTlF6mZS9nEvBkfXTQcNf3WqBeFF0t7Z2DI1BL+p0xBuH dCKEXOd8WA4uPKHe37L34b6VLn4YWRc= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-673-aoF8ylAqNwqUb6Vd2bbaxg-1; Sat, 14 Oct 2023 04:20:43 -0400 X-MC-Unique: aoF8ylAqNwqUb6Vd2bbaxg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8E56D1C068D1; Sat, 14 Oct 2023 08:20:42 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.193.202]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 46FFB1130514; Sat, 14 Oct 2023 08:20:42 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 39E8Kd2C3491806 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sat, 14 Oct 2023 10:20:39 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 39E8KchW3491805; Sat, 14 Oct 2023 10:20:38 +0200 Date: Sat, 14 Oct 2023 10:20:37 +0200 From: Jakub Jelinek To: Richard Biener , Richard Sandiford Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] wide-int: Fix estimation of buffer sizes for wide_int printing [PR111800] Message-ID: Reply-To: Jakub Jelinek MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Hi! As mentioned in the PR, my estimations on needed buffer size for wide_int and especially widest_int printing were incorrect, I've used get_len () in the estimations, but that is true only for !wi::neg_p (x) values. Under the hood, we have 3 ways to print numbers. print_decs which if if ((wi.get_precision () <= HOST_BITS_PER_WIDE_INT) || (wi.get_len () == 1)) uses sprintf which always fits into WIDE_INT_PRINT_BUFFER_SIZE (positive or negative) and otherwise uses print_hex, print_decu which if if ((wi.get_precision () <= HOST_BITS_PER_WIDE_INT) || (wi.get_len () == 1 && !wi::neg_p (wi))) uses sprintf which always fits into WIDE_INT_PRINT_BUFFER_SIZE (positive only) and print_hex, which doesn't print most significant limbs which are zero and the first limb which is non-zero prints such that redundant 0 hex digits aren't printed, while all limbs below that are printed with "%016" PRIx64. For wi::neg_p (x) values, the first limb of the precision is always non-zero, so we print all the limbs for the precision. So, the current estimations are accurate if !wi::neg_p (x), or when print_decs will be used and x.get_len () == 1, otherwise we need to use estimation based on get_precision () rather than get_len (). The following patch does that, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? The patch doesn't address what I've talked about earlier, that we might actually stop using print_hex when asked for print_dec{s,u} - we could for negative print_decs just negate and call print_decu, and in print_decu e.g. in a loop UNSIGNED wi::divmod_trunc by HOST_WIDE_INT_UC (10000000000000000000) and print the 19 decimal digits of remainder if quotient is non-zero, otherwise non-padded rest, and then reshuffle the buffer. And/or perhaps print_hex should also take signop and print negative hex constants as -0x..... if asked for SIGNED. And finally, I think we should try to rewrite tree-ssa-ccp.cc bit-cp from widest_int to wide_int, even the earlier: PHI node value: CONSTANT 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2 (0x19) in the -fdump-tree-ccp-details dumps is horribly confusing when the type is say just 32-bit or 64-bit, and with the recent widest_int changes those are now around with > 32000 f hex digits in there. Not to mention we shouldn't really care about state of bits beyond the precision and I think we always have the type in question around (x.val is INTEGER_CST of the right type and we just to::widest it, just x.mask is widest_int). 2023-10-14 Jakub Jelinek PR tree-optimization/111800 gcc/ * wide-int.cc (assert_deceq): Use wi.get_len () for buffer size estimation only if !wi::neg_p (wi) or if len is 1 and sgn is SIGNED, otherwise use WIDE_INT_MAX_HWIS for wi.get_precision (). (assert_hexeq): Use wi.get_len () for buffer size estimation only if !wi::neg_p (wi), otherwise use WIDE_INT_MAX_HWIS for wi.get_precision (). * wide-int-print.cc (print_decs): Use wi.get_len () for buffer size estimation only if !wi::neg_p (wi) or if len is 1, otherwise use WIDE_INT_MAX_HWIS for wi.get_precision (). (print_decu): Use wi.get_len () for buffer size estimation only if !wi::neg_p (wi), otherwise use WIDE_INT_MAX_HWIS for wi.get_precision (). (print_hex): Likewise. * value-range.cc (irange_bitmask::dump): Use get_len () for buffer size estimation only if !wi::neg_p (wi), otherwise use WIDE_INT_MAX_HWIS for get_precision (). * value-range-pretty-print.cc (vrange_printer::print_irange_bitmasks): Likewise. * tree-ssa-loop-niter.cc (do_warn_aggressive_loop_optimizations): Use i_bound.get_len () for buffer size estimation only if !wi::neg_p (i_bound) or if len is 1 and !TYPE_UNSIGNED, otherwise use WIDE_INT_MAX_HWIS for i_bound.get_precision (). Use TYPE_SIGN macro in print_dec call argument. gcc/c-family/ * c-warn.cc (match_case_to_enum_1): Assert w.get_precision () is smaller or equal to WIDE_INT_MAX_INL_PRECISION rather than w.get_len () is smaller or equal to WIDE_INT_MAX_INL_ELTS. --- gcc/wide-int.cc.jj 2023-10-13 19:34:44.288830022 +0200 +++ gcc/wide-int.cc 2023-10-13 20:23:12.889386810 +0200 @@ -2450,7 +2450,9 @@ static void assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn) { char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; unsigned len = wi.get_len (); + if ((len != 1 || sgn == UNSIGNED) && wi::neg_p (wi)) + len = WIDE_INT_MAX_HWIS (wi.get_precision ()); if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); print_dec (wi, p, sgn); @@ -2463,7 +2465,11 @@ static void assert_hexeq (const char *expected, const wide_int_ref &wi) { char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; - unsigned len = wi.get_len (); + unsigned len; + if (wi::neg_p (wi)) + len = WIDE_INT_MAX_HWIS (wi.get_precision ()); + else + len = wi.get_len (); if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); print_hex (wi, p); --- gcc/wide-int-print.cc.jj 2023-10-13 19:34:44.282830103 +0200 +++ gcc/wide-int-print.cc 2023-10-13 20:24:17.240518824 +0200 @@ -76,6 +76,8 @@ print_decs (const wide_int_ref &wi, FILE { char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; unsigned len = wi.get_len (); + if (len != 1 && wi::neg_p (wi)) + len = WIDE_INT_MAX_HWIS (wi.get_precision ()); if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); print_decs (wi, p); @@ -103,6 +105,10 @@ print_decu (const wide_int_ref &wi, FILE { char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; - unsigned len = wi.get_len (); + unsigned len; + if (wi::neg_p (wi)) + len = WIDE_INT_MAX_HWIS (wi.get_precision ()); + else + len = wi.get_len (); if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); print_decu (wi, p); @@ -141,7 +147,11 @@ void print_hex (const wide_int_ref &wi, FILE *file) { char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf; - unsigned len = wi.get_len (); + unsigned len; + if (wi::neg_p (wi)) + len = WIDE_INT_MAX_HWIS (wi.get_precision ()); + else + len = wi.get_len (); if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); print_hex (wi, p); --- gcc/value-range.cc.jj 2023-10-13 19:34:44.281830116 +0200 +++ gcc/value-range.cc 2023-10-13 20:22:11.810210668 +0200 @@ -251,8 +251,15 @@ irange_bitmask::dump (FILE *file) const pp_needs_newline (&buffer) = true; buffer.buffer->stream = file; pp_string (&buffer, "MASK "); - unsigned len_mask = m_mask.get_len (); - unsigned len_val = m_value.get_len (); + unsigned len_mask, len_val; + if (wi::neg_p (m_mask)) + len_mask = WIDE_INT_MAX_HWIS (m_mask.get_precision ()); + else + len_mask = m_mask.get_len (); + if (wi::neg_p (m_value)) + len_val = WIDE_INT_MAX_HWIS (m_value.get_precision ()); + else + len_val = m_value.get_len (); unsigned len = MAX (len_mask, len_val); if (len > WIDE_INT_MAX_INL_ELTS) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); --- gcc/value-range-pretty-print.cc.jj 2023-10-13 19:34:44.260830398 +0200 +++ gcc/value-range-pretty-print.cc 2023-10-13 20:20:11.740830199 +0200 @@ -100,8 +100,15 @@ vrange_printer::print_irange_bitmasks (c pp_string (pp, " MASK "); char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p; - unsigned len_mask = bm.mask ().get_len (); - unsigned len_val = bm.value ().get_len (); + unsigned len_mask, len_val; + if (wi::neg_p (bm.mask ())) + len_mask = WIDE_INT_MAX_HWIS (bm.mask ().get_precision ()); + else + len_mask = bm.mask ().get_len (); + if (wi::neg_p (bm.value ())) + len_val = WIDE_INT_MAX_HWIS (bm.value ().get_precision ()); + else + len_val = bm.value ().get_len (); unsigned len = MAX (len_mask, len_val); if (len > WIDE_INT_MAX_INL_ELTS) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); --- gcc/tree-ssa-loop-niter.cc.jj 2023-10-13 19:34:44.220830936 +0200 +++ gcc/tree-ssa-loop-niter.cc 2023-10-14 09:43:59.343845355 +0200 @@ -3875,12 +3875,14 @@ do_warn_aggressive_loop_optimizations (c gimple *estmt = last_nondebug_stmt (e->src); char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p; unsigned len = i_bound.get_len (); + if ((len != 1 || TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))) + && wi::neg_p (i_bound)) + len = WIDE_INT_MAX_HWIS (i_bound.get_precision ()); if (len > WIDE_INT_MAX_INL_ELTS) p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4); else p = buf; - print_dec (i_bound, p, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations)) - ? UNSIGNED : SIGNED); + print_dec (i_bound, p, TYPE_SIGN (TREE_TYPE (loop->nb_iterations))); auto_diagnostic_group d; if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations, "iteration %s invokes undefined behavior", p)) --- gcc/c-family/c-warn.cc.jj 2023-10-13 19:34:43.678838226 +0200 +++ gcc/c-family/c-warn.cc 2023-10-13 20:16:08.246114521 +0200 @@ -1519,7 +1519,7 @@ match_case_to_enum_1 (tree key, tree typ char buf[WIDE_INT_PRINT_BUFFER_SIZE]; wide_int w = wi::to_wide (key); - gcc_assert (w.get_len () <= WIDE_INT_MAX_INL_ELTS); + gcc_assert (w.get_precision () <= WIDE_INT_MAX_INL_PRECISION); if (tree_fits_uhwi_p (key)) print_dec (w, buf, UNSIGNED); else if (tree_fits_shwi_p (key)) Jakub