From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-44.mimecast.com (us-smtp-delivery-44.mimecast.com [207.211.30.44]) by sourceware.org (Postfix) with ESMTPS id 6B242384474A for ; Sat, 4 May 2024 08:31:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6B242384474A Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=none smtp.mailfrom=localhost.redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6B242384474A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=207.211.30.44 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714811467; cv=none; b=Gj0+3fFOHUEy444LJJ2/bZavRGlb/zjgdxhtUkzeUNigkRVr7L7iiXLhv9jpyjsM2uTBScQ0W5yjrg9hUsFqWF/DiypsuwRVqaFf7ZQj6ia6egAXxvNFYZ1xJRpITXX9CrAyKycyBPl9jagcL65Ls+CLM5cB6slY5EVgV5iLD0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714811467; c=relaxed/simple; bh=QsPpK/2SniPXznRhvlCL8xdbkye3pyp6pld4yZksC2k=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=kpNyYioy2AUZoP3hcvWDgdTjKrbwH9k6VF6bh0feKWctZndUuxCFtbEucUlVG6D2pEib6NCZnhgZafU3PEZObLfOVo/Gf98BxgtqCUtHQyiaO2Mi+fcqgh/Y3rp9Dayb8vgZiS6eeZvxNYDjVLWGSTM0la/USl/mvhF6KzPynFY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1714811463; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rj6uyud8xHA8tXWIIqd9WyNag1BKK6P9+AHSc3ugCjA=; b=Q8j3+atEOY1TFF3wA5wcaHOpG1uaZ3pF+rdUEKHk+CYrxy2OqGE76T77bkNEZp2E15UWZA FIxQQxwkq5uo+g1b/skweSTY9rFqfBB0W6+Wyp/DR+4vd8WNgOCfPs4twZlTpY/Ue/Bcxs 9kPRo0XpeYVL1iBCWxlq/O3UPpGFFDY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-489-9inAgugNMfydb60l0iIIVA-1; Sat, 04 May 2024 04:31:01 -0400 X-MC-Unique: 9inAgugNMfydb60l0iIIVA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id ABC0B8943A1 for ; Sat, 4 May 2024 08:31:00 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.192.71]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 436F6200B08F; Sat, 4 May 2024 08:31:00 +0000 (UTC) Received: from abulafia.quesejoda.com (localhost [127.0.0.1]) by abulafia.quesejoda.com (8.18.1/8.17.1) with ESMTPS id 4448Uw31139792 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sat, 4 May 2024 10:30:59 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.18.1/8.18.1/Submit) id 4448Uwnf139791; Sat, 4 May 2024 10:30:58 +0200 From: Aldy Hernandez To: GCC patches Cc: Andrew MacLeod , Aldy Hernandez Subject: [COMMITTED 02/23] Implement basic prange class. Date: Sat, 4 May 2024 10:30:30 +0200 Message-ID: <20240504083056.139719-3-aldyh@redhat.com> In-Reply-To: <20240504083056.139719-1-aldyh@redhat.com> References: <20240504083056.139719-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=WINDOWS-1252; x-default=true X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,NO_DNS_FOR_FROM,RCVD_IN_DNSWL_LOW,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: This provides a bare prange class with bounds and bitmasks. It will be a drop-in replacement for pointer ranges, so we can pull their support from irange. The range-op code will be contributed as a follow-up. The code is disabled by default, as irange::supports_p still accepts pointers: inline bool irange::supports_p (const_tree type) { return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type); } Once the prange operators are implemented in range-ops, pointer support will be removed from irange to activate pranges. gcc/ChangeLog: =09* value-range-pretty-print.cc (vrange_printer::visit): New. =09* value-range-pretty-print.h: Declare prange visit() method. =09* value-range.cc (vrange::operator=3D): Add prange support. =09(vrange::operator=3D=3D): Same. =09(prange::accept): New. =09(prange::set_nonnegative): New. =09(prange::set): New. =09(prange::contains_p): New. =09(prange::singleton_p): New. =09(prange::lbound): New. =09(prange::ubound): New. =09(prange::union_): New. =09(prange::intersect): New. =09(prange::operator=3D): New. =09(prange::operator=3D=3D): New. =09(prange::invert): New. =09(prange::verify_range): New. =09(prange::update_bitmask): New. =09(range_tests_misc): Use prange. =09* value-range.h (enum value_range_discriminator): Add VR_PRANGE. =09(class prange): New. =09(Value_Range::init): Add prange support. =09(Value_Range::operator=3D): Same. =09(Value_Range::supports_type_p): Same. =09(prange::prange): New. =09(prange::supports_p): New. =09(prange::supports_type_p): New. =09(prange::set_undefined): New. =09(prange::set_varying): New. =09(prange::set_nonzero): New. =09(prange::set_zero): New. =09(prange::contains_p): New. =09(prange::zero_p): New. =09(prange::nonzero_p): New. =09(prange::type): New. =09(prange::lower_bound): New. =09(prange::upper_bound): New. =09(prange::varying_compatible_p): New. =09(prange::get_bitmask): New. =09(prange::fits_p): New. --- gcc/value-range-pretty-print.cc | 25 +++ gcc/value-range-pretty-print.h | 1 + gcc/value-range.cc | 303 +++++++++++++++++++++++++++++++- gcc/value-range.h | 199 ++++++++++++++++++--- 4 files changed, 500 insertions(+), 28 deletions(-) diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print= .cc index b6d23dce6d2..b11d6494774 100644 --- a/gcc/value-range-pretty-print.cc +++ b/gcc/value-range-pretty-print.cc @@ -112,6 +112,31 @@ vrange_printer::visit (const irange &r) const print_irange_bitmasks (pp, r.m_bitmask); } =20 +void +vrange_printer::visit (const prange &r) const +{ + pp_string (pp, "[prange] "); + if (r.undefined_p ()) + { + pp_string (pp, "UNDEFINED"); + return; + } + dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false); + pp_character (pp, ' '); + if (r.varying_p ()) + { + pp_string (pp, "VARYING"); + return; + } + + pp_character (pp, '['); + print_int_bound (pp, r.lower_bound (), r.type ()); + pp_string (pp, ", "); + print_int_bound (pp, r.upper_bound (), r.type ()); + pp_character (pp, ']'); + print_irange_bitmasks (pp, r.m_bitmask); +} + void vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) con= st { diff --git a/gcc/value-range-pretty-print.h b/gcc/value-range-pretty-print.= h index 44cd6e81298..5522aad0673 100644 --- a/gcc/value-range-pretty-print.h +++ b/gcc/value-range-pretty-print.h @@ -27,6 +27,7 @@ public: vrange_printer (pretty_printer *pp_) : pp (pp_) { } void visit (const unsupported_range &) const override; void visit (const irange &) const override; + void visit (const prange &) const override; void visit (const frange &) const override; private: void print_frange_nan (const frange &) const; diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 7250115261f..84113ccfbd0 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -251,6 +251,8 @@ vrange::operator=3D (const vrange &src) { if (is_a (src)) as_a (*this) =3D as_a (src); + else if (is_a (src)) + as_a (*this) =3D as_a (src); else if (is_a (src)) as_a (*this) =3D as_a (src); else @@ -268,6 +270,8 @@ vrange::operator=3D=3D (const vrange &src) const { if (is_a (src)) return as_a (*this) =3D=3D as_a (src); + if (is_a (src)) + return as_a (*this) =3D=3D as_a (src); if (is_a (src)) return as_a (*this) =3D=3D as_a (src); gcc_unreachable (); @@ -397,6 +401,294 @@ irange::set_nonnegative (tree type) wi::to_wide (TYPE_MAX_VALUE (type))); } =20 +// Prange implementation. + +void +prange::accept (const vrange_visitor &v) const +{ + v.visit (*this); +} + +void +prange::set_nonnegative (tree type) +{ + set (type, + wi::zero (TYPE_PRECISION (type)), + wi::max_value (TYPE_PRECISION (type), UNSIGNED)); +} + +void +prange::set (tree min, tree max, value_range_kind kind) +{ + return set (TREE_TYPE (min), wi::to_wide (min), wi::to_wide (max), kind)= ; +} + +void +prange::set (tree type, const wide_int &min, const wide_int &max, +=09 value_range_kind kind) +{ + if (kind =3D=3D VR_UNDEFINED) + { + set_undefined (); + return; + } + if (kind =3D=3D VR_VARYING) + { + set_varying (type); + return; + } + if (kind =3D=3D VR_ANTI_RANGE) + { + gcc_checking_assert (min =3D=3D 0 && max =3D=3D 0); + set_nonzero (type); + return; + } + m_type =3D type; + m_min =3D min; + m_max =3D max; + if (m_min =3D=3D 0 && m_max =3D=3D -1) + { + m_kind =3D VR_VARYING; + m_bitmask.set_unknown (TYPE_PRECISION (type)); + if (flag_checking) +=09verify_range (); + return; + } + + m_kind =3D VR_RANGE; + m_bitmask =3D get_bitmask_from_range (type, min, max); + if (flag_checking) + verify_range (); +} + +bool +prange::contains_p (const wide_int &w) const +{ + if (undefined_p ()) + return false; + + if (varying_p ()) + return true; + + return (wi::le_p (lower_bound (), w, UNSIGNED) +=09 && wi::ge_p (upper_bound (), w, UNSIGNED)); +} + +bool +prange::singleton_p (tree *result) const +{ + if (m_kind =3D=3D VR_RANGE && lower_bound () =3D=3D upper_bound ()) + { + if (result) +=09*result =3D wide_int_to_tree (type (), m_min); + return true; + } + return false; +} + +tree +prange::lbound () const +{ + return wide_int_to_tree (type (), m_min); +} + +tree +prange::ubound () const +{ + return wide_int_to_tree (type (), m_max); +} + +bool +prange::union_ (const vrange &v) +{ + const prange &r =3D as_a (v); + + if (r.undefined_p ()) + return false; + if (undefined_p ()) + { + *this =3D r; + if (flag_checking) +=09verify_range (); + return true; + } + if (varying_p ()) + return false; + if (r.varying_p ()) + { + set_varying (type ()); + return true; + } + + wide_int new_lb =3D wi::min (r.lower_bound (), lower_bound (), UNSIGNED)= ; + wide_int new_ub =3D wi::max (r.upper_bound (), upper_bound (), UNSIGNED)= ; + prange new_range (type (), new_lb, new_ub); + new_range.m_bitmask.union_ (m_bitmask); + new_range.m_bitmask.union_ (r.m_bitmask); + if (new_range.varying_compatible_p ()) + { + set_varying (type ()); + return true; + } + if (flag_checking) + new_range.verify_range (); + if (new_range =3D=3D *this) + return false; + *this =3D new_range; + return true; +} + +bool +prange::intersect (const vrange &v) +{ + const prange &r =3D as_a (v); + gcc_checking_assert (undefined_p () || r.undefined_p () +=09=09 || range_compatible_p (type (), r.type ())); + + if (undefined_p ()) + return false; + if (r.undefined_p ()) + { + set_undefined (); + return true; + } + if (r.varying_p ()) + return false; + if (varying_p ()) + { + *this =3D r; + return true; + } + + prange save =3D *this; + m_min =3D wi::max (r.lower_bound (), lower_bound (), UNSIGNED); + m_max =3D wi::min (r.upper_bound (), upper_bound (), UNSIGNED); + if (wi::gt_p (m_min, m_max, UNSIGNED)) + { + set_undefined (); + return true; + } + + // Intersect all bitmasks: the old one, the new one, and the other opera= nd's. + irange_bitmask new_bitmask =3D get_bitmask_from_range (m_type, m_min, m_= max); + m_bitmask.intersect (new_bitmask); + m_bitmask.intersect (r.m_bitmask); + + if (flag_checking) + verify_range (); + if (*this =3D=3D save) + return false; + return true; +} + +prange & +prange::operator=3D (const prange &src) +{ + m_type =3D src.m_type; + m_kind =3D src.m_kind; + m_min =3D src.m_min; + m_max =3D src.m_max; + m_bitmask =3D src.m_bitmask; + if (flag_checking) + verify_range (); + return *this; +} + +bool +prange::operator=3D=3D (const prange &src) const +{ + if (m_kind =3D=3D src.m_kind) + { + if (undefined_p ()) +=09return true; + + if (varying_p ()) +=09return types_compatible_p (type (), src.type ()); + + return (m_min =3D=3D src.m_min && m_max =3D=3D src.m_max +=09 && m_bitmask =3D=3D src.m_bitmask); + } + return false; +} + +void +prange::invert () +{ + gcc_checking_assert (!undefined_p () && !varying_p ()); + + wide_int new_lb, new_ub; + unsigned prec =3D TYPE_PRECISION (type ()); + wide_int type_min =3D wi::zero (prec); + wide_int type_max =3D wi::max_value (prec, UNSIGNED); + wi::overflow_type ovf; + + if (lower_bound () =3D=3D type_min) + { + new_lb =3D wi::add (upper_bound (), 1, UNSIGNED, &ovf); + if (ovf) +=09new_lb =3D type_min; + new_ub =3D type_max; + set (type (), new_lb, new_ub); + } + else if (upper_bound () =3D=3D type_max) + { + wi::overflow_type ovf; + new_lb =3D type_min; + new_ub =3D wi::sub (lower_bound (), 1, UNSIGNED, &ovf); + if (ovf) +=09new_ub =3D type_max; + set (type (), new_lb, new_ub); + } + else + set_varying (type ()); +} + +void +prange::verify_range () const +{ + gcc_checking_assert (m_discriminator =3D=3D VR_PRANGE); + + if (m_kind =3D=3D VR_UNDEFINED) + return; + + gcc_checking_assert (supports_p (type ())); + + if (m_kind =3D=3D VR_VARYING) + { + gcc_checking_assert (varying_compatible_p ()); + return; + } + gcc_checking_assert (!varying_compatible_p ()); + gcc_checking_assert (m_kind =3D=3D VR_RANGE); +} + +void +prange::update_bitmask (const irange_bitmask &bm) +{ + gcc_checking_assert (!undefined_p ()); + + // If all the bits are known, this is a singleton. + if (bm.mask () =3D=3D 0) + { + set (type (), m_bitmask.value (), m_bitmask.value ()); + return; + } + + // Drop VARYINGs with known bits to a plain range. + if (m_kind =3D=3D VR_VARYING && !bm.unknown_p ()) + m_kind =3D VR_RANGE; + + m_bitmask =3D bm; + if (varying_compatible_p ()) + m_kind =3D VR_VARYING; + + if (flag_checking) + verify_range (); +} + + +// Frange implementation. + void frange::accept (const vrange_visitor &v) const { @@ -2542,11 +2834,12 @@ range_tests_misc () // Make sure NULL and non-NULL of pointer types work, and that // inverses of them are consistent. tree voidp =3D build_pointer_type (void_type_node); - r0.set_zero (voidp); - r1 =3D r0; - r0.invert (); - r0.invert (); - ASSERT_TRUE (r0 =3D=3D r1); + prange p0; + p0.set_zero (voidp); + prange p1 =3D p0; + p0.invert (); + p0.invert (); + ASSERT_TRUE (p0 =3D=3D p1); =20 // [10,20] U [15, 30] =3D> [10, 30]. r0 =3D range_int (10, 20); diff --git a/gcc/value-range.h b/gcc/value-range.h index f52d5165707..6fe31d67582 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -47,6 +47,8 @@ enum value_range_discriminator { // Range holds an integer or pointer. VR_IRANGE, + // Pointer range. + VR_PRANGE, // Floating point range. VR_FRANGE, // Range holds an unsupported type. @@ -380,32 +382,49 @@ private: =20 class prange : public vrange { + friend class prange_storage; + friend class vrange_printer; public: - static bool supports_p (const_tree) { return false; } - virtual bool supports_type_p (const_tree) const final override { return = false; } - virtual void accept (const vrange_visitor &) const final override {} - virtual void set_undefined () final override {} - virtual void set_varying (tree) final override {} - virtual void set_nonzero (tree) final override {} - virtual void set_zero (tree) final override; - virtual void set_nonnegative (tree) final override {} - virtual bool contains_p (tree) const final override { return false; } - virtual bool fits_p (const vrange &) const final override { return false= ; } - virtual bool singleton_p (tree * =3D NULL) const final override { return= false; } - virtual bool zero_p () const final override { return false; } - virtual bool nonzero_p () const final override { return false; } - virtual void set (tree, tree, value_range_kind =3D VR_RANGE) final overr= ide {} - virtual tree type () const final override { return NULL; } - virtual bool union_ (const vrange &) final override { return false; } - virtual bool intersect (const vrange &) final override { return false; } - virtual tree lbound () const final override { return NULL; } - virtual tree ubound () const final override { return NULL; } - + prange (); + prange (const prange &); + prange (tree type); + prange (tree type, const wide_int &, const wide_int &, +=09 value_range_kind =3D VR_RANGE); + static bool supports_p (const_tree type); + virtual bool supports_type_p (const_tree type) const final override; + virtual void accept (const vrange_visitor &v) const final override; + virtual void set_undefined () final override; + virtual void set_varying (tree type) final override; + virtual void set_nonzero (tree type) final override; + virtual void set_zero (tree type) final override; + virtual void set_nonnegative (tree type) final override; + virtual bool contains_p (tree cst) const final override; + virtual bool fits_p (const vrange &v) const final override; + virtual bool singleton_p (tree *result =3D NULL) const final override; + virtual bool zero_p () const final override; + virtual bool nonzero_p () const final override; + virtual void set (tree, tree, value_range_kind =3D VR_RANGE) final overr= ide; + virtual tree type () const final override; + virtual bool union_ (const vrange &v) final override; + virtual bool intersect (const vrange &v) final override; + virtual tree lbound () const final override; + virtual tree ubound () const final override; + + prange& operator=3D (const prange &); + bool operator=3D=3D (const prange &) const; + void set (tree type, const wide_int &, const wide_int &, +=09 value_range_kind =3D VR_RANGE); + void invert (); + bool contains_p (const wide_int &) const; wide_int lower_bound () const; wide_int upper_bound () const; + void verify_range () const; irange_bitmask get_bitmask () const final override; - void update_bitmask (const irange_bitmask &) final override {} -private: + void update_bitmask (const irange_bitmask &) final override; +protected: + bool varying_compatible_p () const; + + tree m_type; wide_int m_min; wide_int m_max; irange_bitmask m_bitmask; @@ -656,6 +675,13 @@ is_a (vrange &v) return v.m_discriminator =3D=3D VR_IRANGE; } =20 +template <> +inline bool +is_a (vrange &v) +{ + return v.m_discriminator =3D=3D VR_PRANGE; +} + template <> inline bool is_a (vrange &v) @@ -708,6 +734,7 @@ class vrange_visitor { public: virtual void visit (const irange &) const { } + virtual void visit (const prange &) const { } virtual void visit (const frange &) const { } virtual void visit (const unsupported_range &) const { } }; @@ -775,6 +802,7 @@ private: vrange *m_vrange; // The buffer must be at least the size of the largest range. static_assert (sizeof (int_range_max) > sizeof (frange), ""); + static_assert (sizeof (int_range_max) > sizeof (prange), ""); char m_buffer[sizeof (int_range_max)]; }; =20 @@ -850,6 +878,8 @@ Value_Range::init (tree type) =20 if (irange::supports_p (type)) m_vrange =3D new (&m_buffer) int_range_max (); + else if (prange::supports_p (type)) + m_vrange =3D new (&m_buffer) prange (); else if (frange::supports_p (type)) m_vrange =3D new (&m_buffer) frange (); else @@ -863,6 +893,8 @@ Value_Range::init (const vrange &r) { if (is_a (r)) m_vrange =3D new (&m_buffer) int_range_max (as_a (r)); + else if (is_a (r)) + m_vrange =3D new (&m_buffer) prange (as_a (r)); else if (is_a (r)) m_vrange =3D new (&m_buffer) frange (as_a (r)); else @@ -920,7 +952,9 @@ Value_Range::operator const vrange &() const inline bool Value_Range::supports_type_p (const_tree type) { - return irange::supports_p (type) || frange::supports_p (type); + return irange::supports_p (type) + || prange::supports_p (type) + || frange::supports_p (type); } =20 extern value_range_kind get_legacy_range (const vrange &, tree &min, tree = &max); @@ -1220,32 +1254,151 @@ irange_val_max (const_tree type) return wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); } =20 +inline +prange::prange () + : vrange (VR_PRANGE) +{ + set_undefined (); +} + +inline +prange::prange (const prange &r) + : vrange (VR_PRANGE) +{ + *this =3D r; +} + +inline +prange::prange (tree type) + : vrange (VR_PRANGE) +{ + set_varying (type); +} + +inline +prange::prange (tree type, const wide_int &lb, const wide_int &ub, +=09=09value_range_kind kind) + : vrange (VR_PRANGE) +{ + set (type, lb, ub, kind); +} + +inline bool +prange::supports_p (const_tree type) +{ + return POINTER_TYPE_P (type); +} + +inline bool +prange::supports_type_p (const_tree type) const +{ + return POINTER_TYPE_P (type); +} + +inline void +prange::set_undefined () +{ + m_kind =3D VR_UNDEFINED; +} + +inline void +prange::set_varying (tree type) +{ + m_kind =3D VR_VARYING; + m_type =3D type; + m_min =3D wi::zero (TYPE_PRECISION (type)); + m_max =3D wi::max_value (TYPE_PRECISION (type), UNSIGNED); + m_bitmask.set_unknown (TYPE_PRECISION (type)); + + if (flag_checking) + verify_range (); +} + +inline void +prange::set_nonzero (tree type) +{ + m_kind =3D VR_RANGE; + m_type =3D type; + m_min =3D wi::one (TYPE_PRECISION (type)); + m_max =3D wi::max_value (TYPE_PRECISION (type), UNSIGNED); + m_bitmask.set_unknown (TYPE_PRECISION (type)); + + if (flag_checking) + verify_range (); +} + inline void prange::set_zero (tree type) { + m_kind =3D VR_RANGE; + m_type =3D type; wide_int zero =3D wi::zero (TYPE_PRECISION (type)); m_min =3D m_max =3D zero; m_bitmask =3D irange_bitmask (zero, zero); + + if (flag_checking) + verify_range (); +} + +inline bool +prange::contains_p (tree cst) const +{ + return contains_p (wi::to_wide (cst)); +} + +inline bool +prange::zero_p () const +{ + return m_kind =3D=3D VR_RANGE && m_min =3D=3D 0 && m_max =3D=3D 0; +} + +inline bool +prange::nonzero_p () const +{ + return m_kind =3D=3D VR_RANGE && m_min =3D=3D 1 && m_max =3D=3D -1; +} + +inline tree +prange::type () const +{ + gcc_checking_assert (!undefined_p ()); + return m_type; } =20 inline wide_int prange::lower_bound () const { + gcc_checking_assert (!undefined_p ()); return m_min; } =20 inline wide_int prange::upper_bound () const { + gcc_checking_assert (!undefined_p ()); return m_max; } =20 +inline bool +prange::varying_compatible_p () const +{ + return (!undefined_p () +=09 && m_min =3D=3D 0 && m_max =3D=3D -1 && get_bitmask ().unknown_p ()); +} + inline irange_bitmask prange::get_bitmask () const { return m_bitmask; } =20 +inline bool +prange::fits_p (const vrange &) const +{ + return true; +} + + inline frange::frange () : vrange (VR_FRANGE) --=20 2.44.0