From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by sourceware.org (Postfix) with ESMTPS id 91242385382B for ; Tue, 4 Oct 2022 07:55:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 91242385382B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ej1-x62d.google.com with SMTP id hy2so27059735ejc.8 for ; Tue, 04 Oct 2022 00:55:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:in-reply-to:cc:references:message-id:date:subject:mime-version :from:content-transfer-encoding:from:to:cc:subject:date; bh=qJSz+d6cPNGt9EeUWPa8S4yts6+JgUQls25g/LALhOg=; b=HADFxIQOj9RxhmFko/fuZW22NUhTMIdhtOYKcNm9PBUkqtCYaXJXU3U3ys9jv9pQuD CWavnkmw1pJN1lBGiqNXLZqnOrOkdI1VKQPbwnLcTGlki4fIpM4g+OwAe5+dUSpzMqOV 7ULW4ZkLeY3BDy3M0s/ffANU5yNGSQMVglsVFrbZ8+96/0QnHN5A9WCWqIUKgKU54aVp YUZoo+PGkuPf2rn90sKKFPEy8GaH2VaztM2pKj0Wx99DfNxOGK/0cmaSY3Nb/AbIGHMP xQAi+oh57Ni1SBWw0LMWgwTE/ZT8znizlJKy7PFpHmXauE9tkaguj8HkU54aZ3tJ/WVS wIEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:in-reply-to:cc:references:message-id:date:subject:mime-version :from:content-transfer-encoding:x-gm-message-state:from:to:cc :subject:date; bh=qJSz+d6cPNGt9EeUWPa8S4yts6+JgUQls25g/LALhOg=; b=p7ZmSrnRlfSEA3yCMesDfat/iwP6NVvH25/qcZy3AI/F2T77mtYACp9F3dCDmj66D6 8DVR9bVOTZhC3QFlGBfNSwXg//xoPByucSx2xLWR89l5cuLKEKW/y8QyIPti5X84udz6 ctN97OAV99O0tKdRAm3fk+Mh2mKfxJClvvy4+XjeHi0/qrXmWc7qiEEVPTBRj5jVEI+q h7hgW3bpxvlyKpBxxSKwbI1ioe3NP7LVD06OGm3T1Q5qQHvwezO9lyXbn6bpe7Ix2MLP dD+BpQ3s/pfsi+rEoVKlh9EvRNtBeI8k89+c9bFErIj7rwoPDIaTffgpUIcJM7UbP8Ch eA4w== X-Gm-Message-State: ACrzQf1fUkY2n6uHjYW0pWaijKfkQ1oxnrX8Sh7zoZ5GJ2U71L3WO3GI k1czMzBNJAmdwPV6b46sXWo= X-Google-Smtp-Source: AMsMyM4R+C5JNLmycTLUbOM1RxxL/tKYY+BQIRHhxDkVkA3V8A4+0NDmCpY8B9+eBC/hBD0erBqFng== X-Received: by 2002:a17:906:4fcc:b0:782:e248:c8a8 with SMTP id i12-20020a1709064fcc00b00782e248c8a8mr18257325ejw.717.1664870119811; Tue, 04 Oct 2022 00:55:19 -0700 (PDT) Received: from smtpclient.apple (dynamic-077-004-088-060.77.4.pool.telefonica.de. [77.4.88.60]) by smtp.gmail.com with ESMTPSA id m14-20020a170906234e00b0076fa6d9d891sm6550230eja.46.2022.10.04.00.55.18 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 04 Oct 2022 00:55:18 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable From: Richard Biener Mime-Version: 1.0 (1.0) Subject: Re: [COMMITTED] Convert nonzero mask in irange to wide_int. Date: Tue, 4 Oct 2022 09:55:17 +0200 Message-Id: References: <20221004073530.1461390-1-aldyh@redhat.com> Cc: GCC patches In-Reply-To: <20221004073530.1461390-1-aldyh@redhat.com> To: Aldy Hernandez X-Mailer: iPhone Mail (19H12) X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,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: Am 04.10.2022 um 09:36 schrieb Aldy Hernandez via Gcc-patches : >=20 > =EF=BB=BFThe reason the nonzero mask was kept in a tree was basically iner= tia, > as everything in irange is a tree. However, there's no need to keep > it in a tree, as the conversions to and from wide ints are very > annoying. That, plus special casing NULL masks to be -1 is prone > to error. >=20 > I have not only rewritten all the uses to assume a wide int, but > have corrected a few places where we weren't propagating the masks, or > rather pessimizing them to -1. This will become more important in > upcoming patches where we make better use of the masks. >=20 > Performance testing shows a trivial improvement in VRP, as things like > irange::contains_p() are tied to a tree. Ughh, can't wait for trees in > iranges to go away. You want trailing wide int storage though. A wide_int is quite large. > gcc/ChangeLog: >=20 > * value-range-storage.cc (irange_storage_slot::set_irange): Remove > special case. > * value-range.cc (irange::irange_set): Adjust for nonzero mask > being a wide int. > (irange::irange_set_anti_range): Same. > (irange::set): Same. > (irange::verify_range): Same. > (irange::legacy_equal_p): Same. > (irange::operator=3D=3D): Same. > (irange::contains_p): Same. > (irange::legacy_intersect): Same. > (irange::legacy_union): Same. > (irange::irange_single_pair_union): Call union_nonzero_bits. > (irange::irange_union): Same. > (irange::irange_intersect): Call intersect_nonzero_bits. > (irange::intersect): Adjust for nonzero mask being a wide int. > (irange::invert): Same. > (irange::set_nonzero_bits): Same. > (irange::get_nonzero_bits_from_range): New. > (irange::set_range_from_nonzero_bits): New. > (irange::get_nonzero_bits): Adjust for nonzero mask being a wide > int. > (irange::intersect_nonzero_bits): Same. > (irange::union_nonzero_bits): Same. > (range_tests_nonzero_bits): Remove test. > * value-range.h (irange::varying_compatible_p): Adjust for nonzero > mask being a wide int. > (gt_ggc_mx): Same. > (gt_pch_nx): Same. > (irange::set_undefined): Same. > (irange::set_varying): Same. > (irange::normalize_kind): Same. > --- > gcc/value-range-storage.cc | 6 +- > gcc/value-range.cc | 270 ++++++++++++++++--------------------- > gcc/value-range.h | 25 ++-- > 3 files changed, 130 insertions(+), 171 deletions(-) >=20 > diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc > index de7575ed48d..6e054622830 100644 > --- a/gcc/value-range-storage.cc > +++ b/gcc/value-range-storage.cc > @@ -150,11 +150,7 @@ irange_storage_slot::set_irange (const irange &r) > { > gcc_checking_assert (fits_p (r)); >=20 > - // Avoid calling unsupported get_nonzero_bits on legacy. > - if (r.legacy_mode_p ()) > - m_ints[0] =3D -1; > - else > - m_ints[0] =3D r.get_nonzero_bits (); > + m_ints[0] =3D r.get_nonzero_bits (); >=20 > unsigned pairs =3D r.num_pairs (); > for (unsigned i =3D 0; i < pairs; ++i) > diff --git a/gcc/value-range.cc b/gcc/value-range.cc > index 6e196574de9..afb26a40083 100644 > --- a/gcc/value-range.cc > +++ b/gcc/value-range.cc > @@ -940,7 +940,7 @@ irange::irange_set (tree min, tree max) > m_base[1] =3D max; > m_num_ranges =3D 1; > m_kind =3D VR_RANGE; > - m_nonzero_mask =3D NULL; > + m_nonzero_mask =3D wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min))); > normalize_kind (); >=20 > if (flag_checking) > @@ -1014,7 +1014,7 @@ irange::irange_set_anti_range (tree min, tree max) > } >=20 > m_kind =3D VR_RANGE; > - m_nonzero_mask =3D NULL; > + m_nonzero_mask =3D wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min))); > normalize_kind (); >=20 > if (flag_checking) > @@ -1071,7 +1071,7 @@ irange::set (tree min, tree max, value_range_kind ki= nd) > m_base[0] =3D min; > m_base[1] =3D max; > m_num_ranges =3D 1; > - m_nonzero_mask =3D NULL; > + m_nonzero_mask =3D wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min)));= > return; > } >=20 > @@ -1121,7 +1121,7 @@ irange::set (tree min, tree max, value_range_kind ki= nd) > m_base[0] =3D min; > m_base[1] =3D max; > m_num_ranges =3D 1; > - m_nonzero_mask =3D NULL; > + m_nonzero_mask =3D wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min))); > normalize_kind (); > if (flag_checking) > verify_range (); > @@ -1136,14 +1136,11 @@ irange::verify_range () > if (m_kind =3D=3D VR_UNDEFINED) > { > gcc_checking_assert (m_num_ranges =3D=3D 0); > - gcc_checking_assert (!m_nonzero_mask); > return; > } > - if (m_nonzero_mask) > - gcc_checking_assert (wi::to_wide (m_nonzero_mask) !=3D -1); > if (m_kind =3D=3D VR_VARYING) > { > - gcc_checking_assert (!m_nonzero_mask); > + gcc_checking_assert (m_nonzero_mask =3D=3D -1); > gcc_checking_assert (m_num_ranges =3D=3D 1); > gcc_checking_assert (varying_compatible_p ()); > return; > @@ -1238,7 +1235,7 @@ irange::legacy_equal_p (const irange &other) const > other.tree_lower_bound (0)) > && vrp_operand_equal_p (tree_upper_bound (0), > other.tree_upper_bound (0)) > - && vrp_operand_equal_p (m_nonzero_mask, other.m_nonzero_mask)); > + && get_nonzero_bits () =3D=3D other.get_nonzero_bits ()); > } >=20 > bool > @@ -1273,7 +1270,7 @@ irange::operator=3D=3D (const irange &other) const > || !operand_equal_p (ub, ub_other, 0)) > return false; > } > - return vrp_operand_equal_p (m_nonzero_mask, other.m_nonzero_mask); > + return get_nonzero_bits () =3D=3D other.get_nonzero_bits (); > } >=20 > /* Return TRUE if this is a symbolic range. */ > @@ -1416,10 +1413,11 @@ irange::contains_p (tree cst) const >=20 > gcc_checking_assert (TREE_CODE (cst) =3D=3D INTEGER_CST); >=20 > - if (m_nonzero_mask) > + // See if we can exclude CST based on the nonzero bits. > + if (m_nonzero_mask !=3D -1) > { > wide_int cstw =3D wi::to_wide (cst); > - if (cstw !=3D 0 && wi::bit_and (wi::to_wide (m_nonzero_mask), cstw)= =3D=3D 0) > + if (cstw !=3D 0 && wi::bit_and (m_nonzero_mask, cstw) =3D=3D 0) > return false; > } >=20 > @@ -1878,9 +1876,6 @@ irange::legacy_intersect (irange *vr0, const irange *= vr1) > intersect_ranges (&vr0kind, &vr0min, &vr0max, > vr1->kind (), vr1->min (), vr1->max ()); >=20 > - // Pessimize nonzero masks, as we don't support them. > - m_nonzero_mask =3D NULL; > - > /* Make sure to canonicalize the result though as the inversion of a > VR_RANGE can still be a VR_RANGE. */ > if (vr0kind =3D=3D VR_UNDEFINED) > @@ -2202,9 +2197,6 @@ irange::legacy_union (irange *vr0, const irange *vr1= ) > union_ranges (&vr0kind, &vr0min, &vr0max, > vr1->kind (), vr1->min (), vr1->max ()); >=20 > - // Pessimize nonzero masks, as we don't support them. > - m_nonzero_mask =3D NULL; > - > if (vr0kind =3D=3D VR_UNDEFINED) > vr0->set_undefined (); > else if (vr0kind =3D=3D VR_VARYING) > @@ -2310,8 +2302,6 @@ irange::legacy_verbose_intersect (const irange *othe= r) >=20 > // Perform an efficient union with R when both ranges have only a single p= air. > // Excluded are VARYING and UNDEFINED ranges. > -// > -// NOTE: It is the caller's responsibility to set the nonzero mask. >=20 > bool > irange::irange_single_pair_union (const irange &r) > @@ -2325,7 +2315,7 @@ irange::irange_single_pair_union (const irange &r) > { > // If current upper bound is new upper bound, we're done. > if (wi::le_p (wi::to_wide (r.m_base[1]), wi::to_wide (m_base[1]), si= gn)) > - return false; > + return union_nonzero_bits (r); > // Otherwise R has the new upper bound. > // Check for overlap/touching ranges, or single target range. > if (m_max_ranges =3D=3D 1 > @@ -2338,8 +2328,7 @@ irange::irange_single_pair_union (const irange &r) > m_base[3] =3D r.m_base[1]; > m_num_ranges =3D 2; > } > - if (varying_compatible_p ()) > - m_kind =3D VR_VARYING; > + union_nonzero_bits (r); > return true; > } >=20 > @@ -2353,11 +2342,7 @@ irange::irange_single_pair_union (const irange &r) > // Check for overlapping ranges, or target limited to a single range. > else if (m_max_ranges =3D=3D 1 > || wi::to_widest (r.m_base[1]) + 1 >=3D wi::to_widest (lb)) > - { > - // This has the new upper bound, just check for varying. > - if (varying_compatible_p ()) > - m_kind =3D VR_VARYING; > - } > + ; > else > { > // Left with 2 pairs. > @@ -2366,8 +2351,7 @@ irange::irange_single_pair_union (const irange &r) > m_base[3] =3D m_base[1]; > m_base[1] =3D r.m_base[1]; > } > - if (varying_compatible_p ()) > - m_kind =3D VR_VARYING; > + union_nonzero_bits (r); > return true; > } >=20 > @@ -2398,27 +2382,13 @@ irange::irange_union (const irange &r) > return true; > } >=20 > - // Save the nonzero mask in case the set operations below clobber it. > - bool ret_nz =3D union_nonzero_bits (r); > - tree saved_nz =3D m_nonzero_mask; > - > - // The union_nonzero_bits may have turned things into a varying. > - if (varying_p ()) > - return true; > - > // Special case one range union one range. > if (m_num_ranges =3D=3D 1 && r.m_num_ranges =3D=3D 1) > - { > - bool ret =3D irange_single_pair_union (r); > - set_nonzero_bits (saved_nz); > - if (flag_checking) > - verify_range (); > - return ret || ret_nz; > - } > + return irange_single_pair_union (r); >=20 > // If this ranges fully contains R, then we need do nothing. > if (irange_contains_p (r)) > - return ret_nz; > + return union_nonzero_bits (r); >=20 > // Do not worry about merging and such by reserving twice as many > // pairs as needed, and then simply sort the 2 ranges into this > @@ -2506,11 +2476,7 @@ irange::irange_union (const irange &r) > m_num_ranges =3D i / 2; >=20 > m_kind =3D VR_RANGE; > - m_nonzero_mask =3D saved_nz; > - normalize_kind (); > - > - if (flag_checking) > - verify_range (); > + union_nonzero_bits (r); > return true; > } >=20 > @@ -2576,21 +2542,11 @@ irange::irange_intersect (const irange &r) > set_undefined (); > return true; > } > - > - // Save the nonzero mask in case the set operations below clobber it. > - bool ret_nz =3D intersect_nonzero_bits (r); > - tree saved_nz =3D m_nonzero_mask; > - > if (r.varying_p ()) > - return ret_nz; > - > + return false; > if (varying_p ()) > { > operator=3D (r); > - if (saved_nz) > - set_nonzero_bits (saved_nz); > - if (flag_checking) > - verify_range (); > return true; > } >=20 > @@ -2600,13 +2556,13 @@ irange::irange_intersect (const irange &r) > if (undefined_p ()) > return true; >=20 > - set_nonzero_bits (saved_nz); > - return res || saved_nz; > + res |=3D intersect_nonzero_bits (r); > + return res; > } >=20 > // If R fully contains this, then intersection will change nothing. > if (r.irange_contains_p (*this)) > - return ret_nz; > + return intersect_nonzero_bits (r); >=20 > signop sign =3D TYPE_SIGN (TREE_TYPE(m_base[0])); > unsigned bld_pair =3D 0; > @@ -2675,15 +2631,14 @@ irange::irange_intersect (const irange &r) > // At the exit of this loop, it is one of 2 things: > // ran out of r1, or r2, but either means we are done. > m_num_ranges =3D bld_pair; > + if (m_num_ranges =3D=3D 0) > + { > + set_undefined (); > + return true; > + } >=20 > m_kind =3D VR_RANGE; > - if (!undefined_p ()) > - m_nonzero_mask =3D saved_nz; > - normalize_kind (); > - > - if (flag_checking) > - verify_range (); > - > + intersect_nonzero_bits (r); > return true; > } >=20 > @@ -2749,10 +2704,15 @@ irange::intersect (const wide_int& lb, const wide_= int& ub) > } >=20 > m_num_ranges =3D bld_index; > + if (m_num_ranges =3D=3D 0) > + { > + set_undefined (); > + return true; > + } >=20 > m_kind =3D VR_RANGE; > - normalize_kind (); > - > + // No need to call normalize_kind(), as the caller will do this > + // while intersecting the nonzero mask. > if (flag_checking) > verify_range (); > return true; > @@ -2801,7 +2761,6 @@ irange::invert () > } >=20 > gcc_checking_assert (!undefined_p () && !varying_p ()); > - m_nonzero_mask =3D NULL; >=20 > // We always need one more set of bounds to represent an inverse, so > // if we're at the limit, we can't properly represent things. > @@ -2822,6 +2781,7 @@ irange::invert () > signop sign =3D TYPE_SIGN (ttype); > wide_int type_min =3D wi::min_value (prec, sign); > wide_int type_max =3D wi::max_value (prec, sign); > + m_nonzero_mask =3D wi::shwi (-1, prec); > if (m_num_ranges =3D=3D m_max_ranges > && lower_bound () !=3D type_min > && upper_bound () !=3D type_max) > @@ -2896,127 +2856,140 @@ irange::invert () > verify_range (); > } >=20 > -void > -irange::set_nonzero_bits (tree mask) > +// Return the nonzero bits inherent in the range. > + > +wide_int > +irange::get_nonzero_bits_from_range () const > { > - gcc_checking_assert (!undefined_p ()); > + // For legacy symbolics. > + if (!constant_p ()) > + return wi::shwi (-1, TYPE_PRECISION (type ())); >=20 > - if (!mask) > + wide_int min =3D lower_bound (); > + wide_int max =3D upper_bound (); > + wide_int xorv =3D min ^ max; > + if (xorv !=3D 0) > { > - if (m_nonzero_mask) > - { > - m_nonzero_mask =3D NULL; > - // Clearing the mask may have turned a range into VARYING. > - normalize_kind (); > - } > - return; > + unsigned prec =3D TYPE_PRECISION (type ()); > + xorv =3D wi::mask (prec - wi::clz (xorv), false, prec); > } > - m_nonzero_mask =3D mask; > - // Setting the mask may have turned a VARYING into a range. > - if (m_kind =3D=3D VR_VARYING) > - m_kind =3D VR_RANGE; > - > - if (flag_checking) > - verify_range (); > + return min | xorv; > } >=20 > -void > -irange::set_nonzero_bits (const wide_int_ref &bits) > +// If the the nonzero mask can be trivially converted to a range, do > +// so and return TRUE. > + > +bool > +irange::set_range_from_nonzero_bits () > { > gcc_checking_assert (!undefined_p ()); > + unsigned popcount =3D wi::popcount (m_nonzero_mask); >=20 > - if (bits =3D=3D -1) > - { > - set_nonzero_bits (NULL); > - return; > - } > // If we have only one bit set in the mask, we can figure out the > // range immediately. > - if (wi::popcount (bits) =3D=3D 1) > + if (popcount =3D=3D 1) > { > // Make sure we don't pessimize the range. > - tree tbits =3D wide_int_to_tree (type (), bits); > - if (!contains_p (tbits)) > - { > - set_nonzero_bits (tbits); > - return; > - } > + if (!contains_p (wide_int_to_tree (type (), m_nonzero_mask))) > + return false; >=20 > bool has_zero =3D contains_p (build_zero_cst (type ())); > + wide_int bits =3D m_nonzero_mask; > set (type (), bits, bits); > + m_nonzero_mask =3D bits; > if (has_zero) > { > int_range<2> zero; > zero.set_zero (type ()); > union_ (zero); > } > + return true; > } > - set_nonzero_bits (wide_int_to_tree (type (), bits)); > + return false; > } >=20 > -wide_int > -irange::get_nonzero_bits () const > +void > +irange::set_nonzero_bits (const wide_int_ref &bits) > { > gcc_checking_assert (!undefined_p ()); > + unsigned prec =3D TYPE_PRECISION (type ()); > + gcc_checking_assert (prec =3D=3D bits.get_precision ()); >=20 > - // In case anyone in the legacy world queries us. > - if (!constant_p ()) > - { > - if (m_nonzero_mask) > - return wi::to_wide (m_nonzero_mask); > - return wi::shwi (-1, TYPE_PRECISION (type ())); > - } > + // Drop VARYINGs with a nonzero mask to a plain range. > + if (m_kind =3D=3D VR_VARYING && bits !=3D -1) > + m_kind =3D VR_RANGE; >=20 > - // Calculate the nonzero bits inherent in the range. > - wide_int min =3D lower_bound (); > - wide_int max =3D upper_bound (); > - wide_int xorv =3D min ^ max; > - if (xorv !=3D 0) > - { > - unsigned prec =3D TYPE_PRECISION (type ()); > - xorv =3D wi::mask (prec - wi::clz (xorv), false, prec); > - } > - wide_int mask =3D min | xorv; > + m_nonzero_mask =3D wide_int::from (bits, prec, TYPE_SIGN (type ())); > + if (set_range_from_nonzero_bits ()) > + return; >=20 > - // Return the nonzero bits augmented by the range. > - if (m_nonzero_mask) > - return mask & wi::to_wide (m_nonzero_mask); > + normalize_kind (); > + if (flag_checking) > + verify_range (); > +} >=20 > - return mask; > +// Return the nonzero bitmask. This will return the nonzero bits plus > +// the nonzero bits inherent in the range. > + > +wide_int > +irange::get_nonzero_bits () const > +{ > + gcc_checking_assert (!undefined_p ()); > + // The nonzero mask inherent in the range is calculated on-demand. > + // For example, [0,255] does not have a 0xff nonzero mask by default > + // (unless manually set). This saves us considerable time, because > + // setting it at creation incurs a large penalty for irange::set. > + // At the time of writing there was a 5% slowdown in VRP if we kept > + // the mask precisely up to date at all times. Instead, we default > + // to -1 and set it when explicitly requested. However, this > + // function will always return the correct mask. > + return m_nonzero_mask & get_nonzero_bits_from_range (); > } >=20 > -// Intersect the nonzero bits in R into THIS. > +// Intersect the nonzero bits in R into THIS and normalize the range. > +// Return TRUE if the intersection changed anything. >=20 > bool > irange::intersect_nonzero_bits (const irange &r) > { > gcc_checking_assert (!undefined_p () && !r.undefined_p ()); >=20 > - if (m_nonzero_mask || r.m_nonzero_mask) > + bool changed =3D false; > + if (m_nonzero_mask !=3D r.m_nonzero_mask) > { > - wide_int nz =3D wi::bit_and (get_nonzero_bits (), > - r.get_nonzero_bits ()); > - set_nonzero_bits (nz); > - return true; > + m_nonzero_mask =3D get_nonzero_bits () & r.get_nonzero_bits (); > + if (set_range_from_nonzero_bits ()) > + return true; > + changed =3D true; > } > - return false; > + normalize_kind (); > + if (flag_checking) > + verify_range (); > + return changed; > } >=20 > -// Union the nonzero bits in R into THIS. > +// Union the nonzero bits in R into THIS and normalize the range. > +// Return TRUE if the union changed anything. >=20 > bool > irange::union_nonzero_bits (const irange &r) > { > gcc_checking_assert (!undefined_p () && !r.undefined_p ()); >=20 > - if (m_nonzero_mask || r.m_nonzero_mask) > + bool changed =3D false; > + if (m_nonzero_mask !=3D r.m_nonzero_mask) > { > - wide_int nz =3D wi::bit_or (get_nonzero_bits (), > - r.get_nonzero_bits ()); > - set_nonzero_bits (nz); > - return true; > + m_nonzero_mask =3D get_nonzero_bits () | r.get_nonzero_bits (); > + // No need to call set_range_from_nonzero_bits, because we'll > + // never narrow the range. Besides, it would cause endless > + // recursion because of the union_ in > + // set_range_from_nonzero_bits. > + changed =3D true; > } > - return false; > + normalize_kind (); > + if (flag_checking) > + verify_range (); > + return changed; > } >=20 > void > @@ -3605,13 +3578,6 @@ range_tests_nonzero_bits () > r0.union_ (r1); > ASSERT_TRUE (r0.get_nonzero_bits () =3D=3D 0xff); >=20 > - // Union where the mask of nonzero bits is implicit from the range. > - r0.set_varying (integer_type_node); > - r0.set_nonzero_bits (0xf00); > - r1.set_zero (integer_type_node); // nonzero mask is implicitly 0 > - r0.union_ (r1); > - ASSERT_TRUE (r0.get_nonzero_bits () =3D=3D 0xf00); > - > // Intersect of nonzero bits. > r0.set (INT (0), INT (255)); > r0.set_nonzero_bits (0xfe); > diff --git a/gcc/value-range.h b/gcc/value-range.h > index 556e31aece1..d1663620444 100644 > --- a/gcc/value-range.h > +++ b/gcc/value-range.h > @@ -207,14 +207,15 @@ private: >=20 > void irange_set_1bit_anti_range (tree, tree); > bool varying_compatible_p () const; > - void set_nonzero_bits (tree mask); > bool intersect_nonzero_bits (const irange &r); > bool union_nonzero_bits (const irange &r); > + wide_int get_nonzero_bits_from_range () const; > + bool set_range_from_nonzero_bits (); >=20 > bool intersect (const wide_int& lb, const wide_int& ub); > unsigned char m_num_ranges; > unsigned char m_max_ranges; > - tree m_nonzero_mask; > + wide_int m_nonzero_mask; > tree *m_base; > }; >=20 > @@ -682,10 +683,11 @@ irange::varying_compatible_p () const > if (INTEGRAL_TYPE_P (t)) > return (wi::to_wide (l) =3D=3D wi::min_value (prec, sign) > && wi::to_wide (u) =3D=3D wi::max_value (prec, sign) > - && !m_nonzero_mask); > + && m_nonzero_mask =3D=3D -1); > if (POINTER_TYPE_P (t)) > return (wi::to_wide (l) =3D=3D 0 > - && wi::to_wide (u) =3D=3D wi::max_value (prec, sign)); > + && wi::to_wide (u) =3D=3D wi::max_value (prec, sign) > + && m_nonzero_mask =3D=3D -1); > return true; > } >=20 > @@ -752,8 +754,6 @@ gt_ggc_mx (irange *x) > gt_ggc_mx (x->m_base[i * 2]); > gt_ggc_mx (x->m_base[i * 2 + 1]); > } > - if (x->m_nonzero_mask) > - gt_ggc_mx (x->m_nonzero_mask); > } >=20 > inline void > @@ -764,8 +764,6 @@ gt_pch_nx (irange *x) > gt_pch_nx (x->m_base[i * 2]); > gt_pch_nx (x->m_base[i * 2 + 1]); > } > - if (x->m_nonzero_mask) > - gt_pch_nx (x->m_nonzero_mask); > } >=20 > inline void > @@ -776,8 +774,6 @@ gt_pch_nx (irange *x, gt_pointer_operator op, void *co= okie) > op (&x->m_base[i * 2], NULL, cookie); > op (&x->m_base[i * 2 + 1], NULL, cookie); > } > - if (x->m_nonzero_mask) > - op (&x->m_nonzero_mask, NULL, cookie); > } >=20 > template > @@ -872,7 +868,6 @@ irange::set_undefined () > { > m_kind =3D VR_UNDEFINED; > m_num_ranges =3D 0; > - m_nonzero_mask =3D NULL; > } >=20 > inline void > @@ -880,7 +875,11 @@ irange::set_varying (tree type) > { > m_kind =3D VR_VARYING; > m_num_ranges =3D 1; > - m_nonzero_mask =3D NULL; > + > + if (type =3D=3D error_mark_node) > + m_nonzero_mask =3D wi::shwi (-1, 1); > + else > + m_nonzero_mask =3D wi::shwi (-1, TYPE_PRECISION (type)); >=20 > if (INTEGRAL_TYPE_P (type)) > { > @@ -1002,8 +1001,6 @@ irange::normalize_kind () > m_kind =3D VR_VARYING; > else if (m_kind =3D=3D VR_ANTI_RANGE) > set_undefined (); > - else > - gcc_unreachable (); > } > } >=20 > --=20 > 2.37.1 >=20