From patchwork Wed Oct 3 06:36:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 978128 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-486855-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ngspbAGh"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42Q5sQ3MHsz9s8J for ; Wed, 3 Oct 2018 16:36:55 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=j3TwKUUHs4zon6QF8540DhWoAuOBR422/bkfkbUQCbEK5vLQlC fL7v8ygTEhNx93+poHYeq3KowVLMIFa53t3BybgAVWERZivx52wl0Mk7r7RFDgC6 HDrwl6aEaUfAvB7fIs1RedH1BnXADZHZTO7Usv86Gbs3e8XexivvpvR/8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=lUM1K4RNc9pxDMUmje7Nv2b6bQE=; b=ngspbAGhDKyKvYJPA4TE qjeJPJRbysAcV5IH/9mqPOfW5h2rtWooZg/+ROUEELVhcLt/AsnbaVQlPrACZinM tV7rPoDJspkf7EojWhhBS4STu/kwTzvslNwBAEYatm5ZkjrB1a/obR2sA7saO1GM HPyPhYuUdqCYie7lzDcanbg= Received: (qmail 36741 invoked by alias); 3 Oct 2018 06:36:40 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 36663 invoked by uid 89); 3 Oct 2018 06:36:29 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=sticky, aim, vr, adjusting X-HELO: mail-wm1-f50.google.com Received: from mail-wm1-f50.google.com (HELO mail-wm1-f50.google.com) (209.85.128.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 03 Oct 2018 06:36:23 +0000 Received: by mail-wm1-f50.google.com with SMTP id a8-v6so388846wmf.1 for ; Tue, 02 Oct 2018 23:36:22 -0700 (PDT) Received: from abulafia.quesejoda.com (athedsl-262404.home.otenet.gr. [85.73.72.162]) by smtp.gmail.com with ESMTPSA id k93-v6sm876842wrc.89.2018.10.02.23.36.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Oct 2018 23:36:19 -0700 (PDT) To: Richard Biener Cc: gcc-patches From: Aldy Hernandez Subject: RFC: Implementing a new API for value_range Message-ID: Date: Wed, 3 Oct 2018 02:36:15 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 MIME-Version: 1.0 X-IsSubscribed: yes Hi Richard. Hi folks. I'd like to implement a clean API that disallows direct access to any of the value_range internals. My aim is a clean API with no change in functionality. This is mostly a clean-up, but could also pave the way for possibly changing the underlying implementation in the future so we can unite VPR and the on-demand work with a single common code base. I am quoting the main structure below to give an idea where I'd like to head, and am also attaching a proof-of-concept patch to tree-vrp.[hc]. It is untested and only builds cc1. Ideally I'd like to evolve this to include other methods that make the VRP / vr-values code more readable. Note: I have added a tree type field (m_type) to make it easy to determine the tree type of the range. Right now a value_range looses the range type if UNDEFINED or VARYING, as both min/max are NULL. If there is strong objection to the extra word, we could set min/max to integer_zero_node in the type if UNDEFINED/VARYING. But really, all this will be hidden in the API, so we could change the underlying representation at will. Would you be ok with this if I continue down this path? Thanks. Aldy struct GTY((for_user)) value_range { value_range (); value_range (tree type); value_range (tree type, value_range_type, tree, tree, bitmap = NULL); value_range (const value_range &); bool operator== (const value_range &) const; bool operator!= (const value_range &) const; void intersect (const value_range *); void union_ (const value_range *); /* Types of value ranges. */ bool undefined_p () const; bool varying_p () const; bool symbolic_p () const; bool numeric_p () const; void set_undefined (); void set_varying (); /* Equivalence bitmap methods. */ bitmap equiv () const; void set_equiv (bitmap); void equiv_free (); void equiv_copy (const value_range *); void equiv_clear (); void equiv_and (const value_range *); void equiv_ior (const value_range *); /* Misc methods. */ tree type () const; bool null_p () const; bool may_contain_p (tree) const; tree singleton () const; void canonicalize (); void copy_with_equiv_update (const value_range *); void dump () const; /* Temporary accessors that should eventually be removed. */ enum value_range_type vrtype () const; tree min () const; tree max () const; /* private: These are public because of GTY stupidity. */ enum value_range_type m_vrtype; tree m_min; tree m_max; tree m_type; /* Set of SSA names whose value ranges are equivalent to this one. This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */ bitmap m_equiv; private: void init (tree type, value_range_type, tree, tree, bitmap); void check (); }; diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h index 655cf055f0a..b2b9f971bae 100644 --- a/gcc/tree-vrp.h +++ b/gcc/tree-vrp.h @@ -29,31 +29,177 @@ enum value_range_type { VR_UNDEFINED, VR_RANGE, has executed. */ struct GTY((for_user)) value_range { - /* Lattice value represented by this range. */ - enum value_range_type type; + value_range (); + value_range (tree type); + value_range (tree type, value_range_type, tree, tree, bitmap = NULL); + value_range (const value_range &); + bool operator== (const value_range &) const; + bool operator!= (const value_range &) const; + void intersect (const value_range *); + void union_ (const value_range *); - /* Minimum and maximum values represented by this range. These - values should be interpreted as follows: + /* Types of value ranges. */ + bool undefined_p () const; + bool varying_p () const; + bool symbolic_p () const; + bool numeric_p () const; + void set_undefined (); + void set_varying (); - - If TYPE is VR_UNDEFINED or VR_VARYING then MIN and MAX must - be NULL. + /* Equivalence bitmap methods. */ + bitmap equiv () const; + void set_equiv (bitmap); + void equiv_free (); + void equiv_copy (const value_range *); + void equiv_clear (); + void equiv_and (const value_range *); + void equiv_ior (const value_range *); - - If TYPE == VR_RANGE then MIN holds the minimum value and - MAX holds the maximum value of the range [MIN, MAX]. + /* Misc methods. */ + tree type () const; + bool null_p () const; + bool may_contain_p (tree) const; + tree singleton () const; + void canonicalize (); + void copy_with_equiv_update (const value_range *); + void dump () const; - - If TYPE == ANTI_RANGE the variable is known to NOT - take any values in the range [MIN, MAX]. */ - tree min; - tree max; + /* Temporary accessors that should eventually be removed. */ + enum value_range_type vrtype () const; + tree min () const; + tree max () const; + /* private: These are public because of GTY stupidity. */ + enum value_range_type m_vrtype; + tree m_min; + tree m_max; + tree m_type; /* Set of SSA names whose value ranges are equivalent to this one. This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */ - bitmap equiv; + bitmap m_equiv; - /* Dump value range to stderr. */ - void dump () const; + private: + void init (tree type, value_range_type, tree, tree, bitmap); + void check (); }; +value_range::value_range () +{ + m_type = m_min = m_max = NULL; + m_vrtype = VR_UNDEFINED; + m_equiv = NULL; +} + +value_range::value_range (tree type) +{ + m_vrtype = VR_UNDEFINED; + m_min = m_max = NULL; + m_equiv = NULL; + m_type = type; +} + +value_range::value_range (const value_range &other) +{ + *this = other; +} + +inline value_range_type +value_range::vrtype () const +{ + return m_vrtype; +} + +inline tree +value_range::type () const +{ + return m_type; +} + +inline bitmap +value_range::equiv () const +{ + return m_equiv; +} + +inline tree +value_range::min () const +{ + return m_min; +} + +inline tree +value_range::max () const +{ + return m_max; +} + +inline void +value_range::set_undefined () +{ + if (m_equiv) + bitmap_clear (m_equiv); + *this = value_range (m_type, VR_UNDEFINED, NULL, NULL, m_equiv); +} + +inline void +value_range::set_varying () +{ + if (m_equiv) + bitmap_clear (m_equiv); + *this = value_range (m_type, VR_VARYING, NULL, NULL, m_equiv); +} + +inline bool +value_range::varying_p () const +{ + return m_vrtype == VR_VARYING; +} + +inline bool +value_range::undefined_p () const +{ + return m_vrtype == VR_UNDEFINED; +} + +inline void +value_range::equiv_free () +{ + BITMAP_FREE (m_equiv); + m_equiv = NULL; +} + +inline void +value_range::set_equiv (bitmap b) +{ + m_equiv = b; +} + +inline void +value_range::equiv_copy (const value_range *other) +{ + bitmap_copy (m_equiv, other->m_equiv); +} + +inline void +value_range::equiv_clear () +{ + if (m_equiv) + bitmap_clear (m_equiv); +} + +inline void +value_range::equiv_and (const value_range *other) +{ + if (m_equiv && other->m_equiv) + bitmap_and_into (m_equiv, other->m_equiv); +} + +inline void +value_range::equiv_ior (const value_range *other) +{ + bitmap_ior_into (m_equiv, other->m_equiv); +} + extern void vrp_intersect_ranges (value_range *vr0, const value_range *vr1); extern void vrp_meet (value_range *vr0, const value_range *vr1); extern void dump_value_range (FILE *, const value_range *); @@ -97,7 +243,6 @@ extern void set_and_canonicalize_value_range (value_range *, tree, tree, bitmap); extern bool vrp_bitmap_equal_p (const_bitmap, const_bitmap); extern tree value_range_constant_singleton (const value_range *); -extern bool symbolic_range_p (const value_range *); extern int compare_values (tree, tree); extern int compare_values_warnv (tree, tree, bool *); extern bool vrp_val_is_min (const_tree); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 005fc2ffe2d..34d76b5b5a6 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -73,6 +73,260 @@ along with GCC; see the file COPYING3. If not see for still active basic-blocks. */ static sbitmap *live; +void +value_range::init (tree type, enum value_range_type vrtype, + tree min, tree max, bitmap equiv) +{ + m_type = type; + m_vrtype = vrtype; + m_min = min; + m_max = max; + + /* Since updating the equivalence set involves deep copying the + bitmaps, only do it if absolutely necessary. + + All equivalence bitmaps are allocated from the same obstack. So + we can use the obstack associated with EQUIV to allocate vr->equiv. */ + if (m_equiv == NULL + && equiv != NULL) + m_equiv = BITMAP_ALLOC (equiv->obstack); + + if (equiv != m_equiv) + { + if (equiv && !bitmap_empty_p (equiv)) + bitmap_copy (m_equiv, equiv); + else + bitmap_clear (m_equiv); + } +} + +value_range::value_range (tree type, value_range_type vrtype, + tree min, tree max, bitmap equiv) +{ + m_equiv = NULL; + init (type, vrtype, min, max, equiv); + if (flag_checking) + check (); +} + +void +value_range::copy_with_equiv_update (const value_range *from) +{ + init (from->m_type, from->m_vrtype, from->m_min, from->m_max, + from->m_equiv); +} + +/* Check the validity of the range. */ + +void +value_range::check () +{ + if (flag_checking + && (m_vrtype == VR_RANGE || m_vrtype == VR_ANTI_RANGE)) + { + int cmp; + + gcc_assert (m_min && m_max); + + gcc_assert (!TREE_OVERFLOW_P (m_min) && !TREE_OVERFLOW_P (m_max)); + + if (INTEGRAL_TYPE_P (TREE_TYPE (m_min)) && m_vrtype == VR_ANTI_RANGE) + gcc_assert (!vrp_val_is_min (m_min) || !vrp_val_is_max (m_max)); + + cmp = compare_values (m_min, m_max); + gcc_assert (cmp == 0 || cmp == -1 || cmp == -2); + } + + if (flag_checking + && (m_vrtype == VR_UNDEFINED || m_vrtype == VR_VARYING)) + { + gcc_assert (m_min == NULL_TREE && m_max == NULL_TREE); + gcc_assert (m_equiv == NULL || bitmap_empty_p (m_equiv)); + } + +} + +bool +value_range::operator== (const value_range &other) const +{ + return (m_type == other.m_type + && m_vrtype == other.m_vrtype + && vrp_operand_equal_p (m_min, other.m_min) + && vrp_operand_equal_p (m_max, other.m_max) + && vrp_bitmap_equal_p (m_equiv, other.m_equiv)); +} + +bool +value_range::operator!= (const value_range &other) const +{ + return !(*this == other); +} + +bool +value_range::null_p () const +{ + return (m_vrtype == VR_RANGE + && integer_zerop (m_min) + && integer_zerop (m_max)); +} + +bool +value_range::symbolic_p () const +{ + return (!varying_p () + && !undefined_p () + && (!is_gimple_min_invariant (m_min) + || !is_gimple_min_invariant (m_max))); +} + +/* NOTE: Numeric is not the inverse of symbolic_p because the range + could also be varying or undefined. Ideally they should be inverse + of each other, with varying only applying to symbolics. Varying of + numerics would be represented as [-MIN, +MAX]. */ + +bool +value_range::numeric_p () const +{ + return (!varying_p () + && !undefined_p () + && TREE_CODE (m_min) == INTEGER_CST + && TREE_CODE (m_max) == INTEGER_CST); +} + +bool +value_range::may_contain_p (tree val) const +{ + if (varying_p ()) + return true; + + if (undefined_p ()) + return true; + + if (m_vrtype == VR_ANTI_RANGE) + { + int res = value_inside_range (val, m_min, m_max); + return res == 0 || res == -2; + } + return value_inside_range (val, m_min, m_max) != 0; +} + +tree +value_range::singleton () const +{ + if (range_int_cst_p (this) && vrp_operand_equal_p (m_min, m_max)) + { + gcc_assert (is_gimple_min_invariant (m_min)); + return m_min; + } + return NULL; +} + +/* Canonicalize the current value_range. This means adjusting for + wrapping ranges with MAX < MIN covering [MIN, type_max] U + [type_min, MAX] as anti-rage ~[MAX+1, MIN-1]. Likewise for + wrapping anti-ranges. In corner cases where MAX+1 or MIN-1 wraps + this will fall back to varying. This routine exists to ease + canonicalization in the case where we extract ranges from var + CST + op limit. */ + +void +value_range::canonicalize () +{ + if (undefined_p () || varying_p ()) + return; + + /* Nothing to canonicalize for symbolic ranges. */ + if (TREE_CODE (m_min) != INTEGER_CST + || TREE_CODE (m_max) != INTEGER_CST) + return; + + /* Wrong order for min and max, to swap them and the VR type we need + to adjust them. */ + if (tree_int_cst_lt (m_max, m_min)) + { + tree one, tmp; + + /* For one bit precision if max < min, then the swapped + range covers all values, so for VR_RANGE it is varying and + for VR_ANTI_RANGE empty range, so drop to varying as well. */ + if (TYPE_PRECISION (TREE_TYPE (m_min)) == 1) + { + set_varying (); + return; + } + + one = build_int_cst (TREE_TYPE (m_min), 1); + tmp = int_const_binop (PLUS_EXPR, m_max, one); + m_max = int_const_binop (MINUS_EXPR, m_min, one); + m_min = tmp; + + /* There's one corner case, if we had [C+1, C] before we now have + that again. But this represents an empty value range, so drop + to varying in this case. */ + if (tree_int_cst_lt (m_max, m_min)) + { + set_varying (); + return; + } + + m_vrtype = m_vrtype == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE; + } + + /* Anti-ranges that can be represented as ranges should be so. */ + if (m_vrtype == VR_ANTI_RANGE) + { + /* For -fstrict-enums we may receive out-of-range ranges so consider + values < -INF and values > INF as -INF/INF as well. */ + tree type = TREE_TYPE (m_min); + bool is_min = (INTEGRAL_TYPE_P (type) + && tree_int_cst_compare (m_min, + TYPE_MIN_VALUE (type)) <= 0); + bool is_max = (INTEGRAL_TYPE_P (type) + && tree_int_cst_compare (m_max, + TYPE_MAX_VALUE (type)) >= 0); + + if (is_min && is_max) + { + /* We cannot deal with empty ranges, drop to varying. + ??? This could be VR_UNDEFINED instead. */ + set_varying (); + return; + } + else if (TYPE_PRECISION (TREE_TYPE (m_min)) == 1 + && (is_min || is_max)) + { + /* Non-empty boolean ranges can always be represented + as a singleton range. */ + if (is_min) + m_min = m_max = vrp_val_max (TREE_TYPE (m_min)); + else + m_min = m_max = vrp_val_min (TREE_TYPE (m_min)); + m_vrtype = VR_RANGE; + } + else if (is_min + /* As a special exception preserve non-null ranges. */ + && !(TYPE_UNSIGNED (TREE_TYPE (m_min)) + && integer_zerop (m_max))) + { + tree one = build_int_cst (TREE_TYPE (m_max), 1); + m_min = int_const_binop (PLUS_EXPR, m_max, one); + m_max = vrp_val_max (TREE_TYPE (m_max)); + m_vrtype = VR_RANGE; + } + else if (is_max) + { + tree one = build_int_cst (TREE_TYPE (m_min), 1); + m_max = int_const_binop (MINUS_EXPR, m_min, one); + m_min = vrp_val_min (TREE_TYPE (m_min)); + m_vrtype = VR_RANGE; + } + } + + /* Do not drop [-INF(OVF), +INF(OVF)] to varying. (OVF) has to be sticky + to make sure VRP iteration terminates, otherwise we can get into + oscillations. */ +} + /* Return true if the SSA name NAME is live on the edge E. */ static bool @@ -245,10 +499,7 @@ intersect_range_with_nonzero_bits (enum value_range_type vr_type, static inline void set_value_range_to_undefined (value_range *vr) { - vr->type = VR_UNDEFINED; - vr->min = vr->max = NULL_TREE; - if (vr->equiv) - bitmap_clear (vr->equiv); + vr->set_undefined (); } /* Set value range VR to VR_VARYING. */ @@ -256,183 +507,26 @@ set_value_range_to_undefined (value_range *vr) void set_value_range_to_varying (value_range *vr) { - vr->type = VR_VARYING; - vr->min = vr->max = NULL_TREE; - if (vr->equiv) - bitmap_clear (vr->equiv); + vr->set_varying (); } /* Set value range VR to {T, MIN, MAX, EQUIV}. */ void -set_value_range (value_range *vr, enum value_range_type t, tree min, - tree max, bitmap equiv) +set_value_range (value_range *vr, tree type, enum value_range_type vrtype, + tree min, tree max, bitmap equiv) { - /* Check the validity of the range. */ - if (flag_checking - && (t == VR_RANGE || t == VR_ANTI_RANGE)) - { - int cmp; - - gcc_assert (min && max); - - gcc_assert (!TREE_OVERFLOW_P (min) && !TREE_OVERFLOW_P (max)); - - if (INTEGRAL_TYPE_P (TREE_TYPE (min)) && t == VR_ANTI_RANGE) - gcc_assert (!vrp_val_is_min (min) || !vrp_val_is_max (max)); - - cmp = compare_values (min, max); - gcc_assert (cmp == 0 || cmp == -1 || cmp == -2); - } - - if (flag_checking - && (t == VR_UNDEFINED || t == VR_VARYING)) - { - gcc_assert (min == NULL_TREE && max == NULL_TREE); - gcc_assert (equiv == NULL || bitmap_empty_p (equiv)); - } - - vr->type = t; - vr->min = min; - vr->max = max; - - /* Since updating the equivalence set involves deep copying the - bitmaps, only do it if absolutely necessary. - - All equivalence bitmaps are allocated from the same obstack. So - we can use the obstack associated with EQUIV to allocate vr->equiv. */ - if (vr->equiv == NULL - && equiv != NULL) - vr->equiv = BITMAP_ALLOC (equiv->obstack); - - if (equiv != vr->equiv) - { - if (equiv && !bitmap_empty_p (equiv)) - bitmap_copy (vr->equiv, equiv); - else - bitmap_clear (vr->equiv); - } + value_range tmp (type, vrtype, min, max, equiv); + vr->copy_with_equiv_update (&tmp); } - -/* Set value range VR to the canonical form of {T, MIN, MAX, EQUIV}. - This means adjusting T, MIN and MAX representing the case of a - wrapping range with MAX < MIN covering [MIN, type_max] U [type_min, MAX] - as anti-rage ~[MAX+1, MIN-1]. Likewise for wrapping anti-ranges. - In corner cases where MAX+1 or MIN-1 wraps this will fall back - to varying. - This routine exists to ease canonicalization in the case where we - extract ranges from var + CST op limit. */ - void -set_and_canonicalize_value_range (value_range *vr, enum value_range_type t, +set_and_canonicalize_value_range (value_range *vr, + enum value_range_type vrtype, tree min, tree max, bitmap equiv) { - /* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */ - if (t == VR_UNDEFINED) - { - set_value_range_to_undefined (vr); - return; - } - else if (t == VR_VARYING) - { - set_value_range_to_varying (vr); - return; - } - - /* Nothing to canonicalize for symbolic ranges. */ - if (TREE_CODE (min) != INTEGER_CST - || TREE_CODE (max) != INTEGER_CST) - { - set_value_range (vr, t, min, max, equiv); - return; - } - - /* Wrong order for min and max, to swap them and the VR type we need - to adjust them. */ - if (tree_int_cst_lt (max, min)) - { - tree one, tmp; - - /* For one bit precision if max < min, then the swapped - range covers all values, so for VR_RANGE it is varying and - for VR_ANTI_RANGE empty range, so drop to varying as well. */ - if (TYPE_PRECISION (TREE_TYPE (min)) == 1) - { - set_value_range_to_varying (vr); - return; - } - - one = build_int_cst (TREE_TYPE (min), 1); - tmp = int_const_binop (PLUS_EXPR, max, one); - max = int_const_binop (MINUS_EXPR, min, one); - min = tmp; - - /* There's one corner case, if we had [C+1, C] before we now have - that again. But this represents an empty value range, so drop - to varying in this case. */ - if (tree_int_cst_lt (max, min)) - { - set_value_range_to_varying (vr); - return; - } - - t = t == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE; - } - - /* Anti-ranges that can be represented as ranges should be so. */ - if (t == VR_ANTI_RANGE) - { - /* For -fstrict-enums we may receive out-of-range ranges so consider - values < -INF and values > INF as -INF/INF as well. */ - tree type = TREE_TYPE (min); - bool is_min = (INTEGRAL_TYPE_P (type) - && tree_int_cst_compare (min, TYPE_MIN_VALUE (type)) <= 0); - bool is_max = (INTEGRAL_TYPE_P (type) - && tree_int_cst_compare (max, TYPE_MAX_VALUE (type)) >= 0); - - if (is_min && is_max) - { - /* We cannot deal with empty ranges, drop to varying. - ??? This could be VR_UNDEFINED instead. */ - set_value_range_to_varying (vr); - return; - } - else if (TYPE_PRECISION (TREE_TYPE (min)) == 1 - && (is_min || is_max)) - { - /* Non-empty boolean ranges can always be represented - as a singleton range. */ - if (is_min) - min = max = vrp_val_max (TREE_TYPE (min)); - else - min = max = vrp_val_min (TREE_TYPE (min)); - t = VR_RANGE; - } - else if (is_min - /* As a special exception preserve non-null ranges. */ - && !(TYPE_UNSIGNED (TREE_TYPE (min)) - && integer_zerop (max))) - { - tree one = build_int_cst (TREE_TYPE (max), 1); - min = int_const_binop (PLUS_EXPR, max, one); - max = vrp_val_max (TREE_TYPE (max)); - t = VR_RANGE; - } - else if (is_max) - { - tree one = build_int_cst (TREE_TYPE (min), 1); - max = int_const_binop (MINUS_EXPR, min, one); - min = vrp_val_min (TREE_TYPE (min)); - t = VR_RANGE; - } - } - - /* Do not drop [-INF(OVF), +INF(OVF)] to varying. (OVF) has to be sticky - to make sure VRP iteration terminates, otherwise we can get into - oscillations. */ - - set_value_range (vr, t, min, max, equiv); + *vr = value_range (vr->type (), vrtype, min, max, equiv); + vr->canonicalize (); } /* Copy value range FROM into value range TO. */ @@ -440,7 +534,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t, void copy_value_range (value_range *to, const value_range *from) { - set_value_range (to, from->type, from->min, from->max, from->equiv); + to->copy_with_equiv_update (from); } /* Set value range VR to a single value. This function is only called @@ -462,7 +556,7 @@ void set_value_range_to_nonnull (value_range *vr, tree type) { tree zero = build_int_cst (type, 0); - set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv); + set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv ()); } @@ -471,7 +565,7 @@ set_value_range_to_nonnull (value_range *vr, tree type) void set_value_range_to_null (value_range *vr, tree type) { - set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv); + set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv ()); } /* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */ @@ -503,9 +597,15 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2) static inline bool range_is_null (const value_range *vr) { - return vr->type == VR_RANGE - && integer_zerop (vr->min) - && integer_zerop (vr->max); + return vr->null_p (); +} + +static inline bool +range_is_nonnull (const value_range *vr) +{ + return (vr->vrtype () == VR_ANTI_RANGE + && vr->min () == vr->max () + && integer_zerop (vr->min ())); } /* Return true if max and min of VR are INTEGER_CST. It's not necessary @@ -514,9 +614,9 @@ range_is_null (const value_range *vr) bool range_int_cst_p (const value_range *vr) { - return (vr->type == VR_RANGE - && TREE_CODE (vr->max) == INTEGER_CST - && TREE_CODE (vr->min) == INTEGER_CST); + return (vr->vrtype () == VR_RANGE + && TREE_CODE (vr->min ()) == INTEGER_CST + && TREE_CODE (vr->max ()) == INTEGER_CST); } /* Return true if VR is a INTEGER_CST singleton. */ @@ -525,16 +625,7 @@ bool range_int_cst_singleton_p (const value_range *vr) { return (range_int_cst_p (vr) - && tree_int_cst_equal (vr->min, vr->max)); -} - -/* Return true if value range VR involves at least one symbol. */ - -bool -symbolic_range_p (const value_range *vr) -{ - return (!is_gimple_min_invariant (vr->min) - || !is_gimple_min_invariant (vr->max)); + && tree_int_cst_equal (vr->min (), vr->max ())); } /* Return the single symbol (an SSA_NAME) contained in T if any, or NULL_TREE @@ -849,20 +940,8 @@ value_inside_range (tree val, tree min, tree max) bool range_includes_zero_p (const value_range *vr) { - if (vr->type == VR_VARYING) - return true; - - /* Ughh, we don't know. We choose not to optimize. */ - if (vr->type == VR_UNDEFINED) - return true; - - tree zero = build_int_cst (TREE_TYPE (vr->min), 0); - if (vr->type == VR_ANTI_RANGE) - { - int res = value_inside_range (zero, vr->min, vr->max); - return res == 0 || res == -2; - } - return value_inside_range (zero, vr->min, vr->max) != 0; + tree zero = build_int_cst (TREE_TYPE (vr->type ()), 0); + return vr->may_contain_p (zero); } /* If *VR has a value rante that is a single constant value return that, @@ -871,12 +950,7 @@ range_includes_zero_p (const value_range *vr) tree value_range_constant_singleton (const value_range *vr) { - if (vr->type == VR_RANGE - && vrp_operand_equal_p (vr->min, vr->max) - && is_gimple_min_invariant (vr->min)) - return vr->min; - - return NULL_TREE; + return vr->singleton (); } /* Value range wrapper for wide_int_range_set_zero_nonzero_bits. @@ -899,8 +973,8 @@ vrp_set_zero_nonzero_bits (const tree expr_type, return false; } wide_int_range_set_zero_nonzero_bits (TYPE_SIGN (expr_type), - wi::to_wide (vr->min), - wi::to_wide (vr->max), + wi::to_wide (vr->min ()), + wi::to_wide (vr->max ()), *may_be_nonzero, *must_be_nonzero); return true; } @@ -914,40 +988,36 @@ static bool ranges_from_anti_range (const value_range *ar, value_range *vr0, value_range *vr1) { - tree type = TREE_TYPE (ar->min); + tree type = TREE_TYPE (ar->type ()); - vr0->type = VR_UNDEFINED; - vr1->type = VR_UNDEFINED; + vr0->set_undefined (); + vr1->set_undefined (); /* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U [A+1, +INF]. Not sure if this helps in practice, though. */ - if (ar->type != VR_ANTI_RANGE - || TREE_CODE (ar->min) != INTEGER_CST - || TREE_CODE (ar->max) != INTEGER_CST + if (ar->vrtype () != VR_ANTI_RANGE + || TREE_CODE (ar->min ()) != INTEGER_CST + || TREE_CODE (ar->max ()) != INTEGER_CST || !vrp_val_min (type) || !vrp_val_max (type)) return false; - if (!vrp_val_is_min (ar->min)) - { - vr0->type = VR_RANGE; - vr0->min = vrp_val_min (type); - vr0->max = wide_int_to_tree (type, wi::to_wide (ar->min) - 1); - } - if (!vrp_val_is_max (ar->max)) - { - vr1->type = VR_RANGE; - vr1->min = wide_int_to_tree (type, wi::to_wide (ar->max) + 1); - vr1->max = vrp_val_max (type); - } - if (vr0->type == VR_UNDEFINED) + if (!vrp_val_is_min (ar->min ())) + *vr0 = value_range (type, VR_RANGE, + vrp_val_min (type), + wide_int_to_tree (type, wi::to_wide (ar->min ()) - 1)); + if (!vrp_val_is_max (ar->max ())) + *vr1 = value_range (type, VR_RANGE, + wide_int_to_tree (type, wi::to_wide (ar->max ()) + 1), + vrp_val_max (type)); + if (vr0->undefined_p ()) { *vr0 = *vr1; - vr1->type = VR_UNDEFINED; + vr1->set_undefined (); } - return vr0->type != VR_UNDEFINED; + return !vr0->undefined_p (); } /* Extract the components of a value range into a pair of wide ints in @@ -961,13 +1031,11 @@ extract_range_into_wide_ints (const value_range *vr, signop sign, unsigned prec, wide_int &wmin, wide_int &wmax) { - if ((vr->type == VR_RANGE - || vr->type == VR_ANTI_RANGE) - && TREE_CODE (vr->min) == INTEGER_CST - && TREE_CODE (vr->max) == INTEGER_CST) + gcc_assert (vr->vrtype () != VR_ANTI_RANGE); + if (range_int_cst_p (vr)) { - wmin = wi::to_wide (vr->min); - wmax = wi::to_wide (vr->max); + wmin = wi::to_wide (vr->min ()); + wmax = wi::to_wide (vr->max ()); } else { @@ -994,14 +1062,15 @@ extract_range_from_multiplicative_op (value_range *vr, || code == ROUND_DIV_EXPR || code == RSHIFT_EXPR || code == LSHIFT_EXPR); - gcc_assert (vr0->type == VR_RANGE && vr0->type == vr1->type); + gcc_assert (vr0->vrtype () == VR_RANGE + && vr0->vrtype () == vr1->vrtype ()); - tree type = TREE_TYPE (vr0->min); + tree type = vr0->type (); wide_int res_lb, res_ub; - wide_int vr0_lb = wi::to_wide (vr0->min); - wide_int vr0_ub = wi::to_wide (vr0->max); - wide_int vr1_lb = wi::to_wide (vr1->min); - wide_int vr1_ub = wi::to_wide (vr1->max); + wide_int vr0_lb = wi::to_wide (vr0->min ()); + wide_int vr0_ub = wi::to_wide (vr0->max ()); + wide_int vr1_lb = wi::to_wide (vr1->min ()); + wide_int vr1_ub = wi::to_wide (vr1->max ()); bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (type); bool overflow_wraps = TYPE_OVERFLOW_WRAPS (type); unsigned prec = TYPE_PRECISION (type); @@ -1114,8 +1183,6 @@ set_value_range_with_overflow (value_range &vr, { const signop sgn = TYPE_SIGN (type); const unsigned int prec = TYPE_PRECISION (type); - vr.type = VR_RANGE; - vr.equiv = NULL; if (TYPE_OVERFLOW_WRAPS (type)) { /* If overflow wraps, truncate the values and adjust the @@ -1126,8 +1193,10 @@ set_value_range_with_overflow (value_range &vr, { /* No overflow or both overflow or underflow. The range kind stays VR_RANGE. */ - vr.min = wide_int_to_tree (type, tmin); - vr.max = wide_int_to_tree (type, tmax); + vr = value_range (type, VR_RANGE, + wide_int_to_tree (type, tmin), + wide_int_to_tree (type, tmax)); + return; } else if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE) || (max_ovf == wi::OVF_OVERFLOW && min_ovf == wi::OVF_NONE)) @@ -1136,7 +1205,6 @@ set_value_range_with_overflow (value_range &vr, changes to VR_ANTI_RANGE. */ bool covers = false; wide_int tem = tmin; - vr.type = VR_ANTI_RANGE; tmin = tmax + 1; if (wi::cmp (tmin, tmax, sgn) < 0) covers = true; @@ -1151,8 +1219,10 @@ set_value_range_with_overflow (value_range &vr, set_value_range_to_varying (&vr); return; } - vr.min = wide_int_to_tree (type, tmin); - vr.max = wide_int_to_tree (type, tmax); + vr = value_range (type, VR_ANTI_RANGE, + wide_int_to_tree (type, tmin), + wide_int_to_tree (type, tmax)); + return; } else { @@ -1167,19 +1237,21 @@ set_value_range_with_overflow (value_range &vr, value. */ wide_int type_min = wi::min_value (prec, sgn); wide_int type_max = wi::max_value (prec, sgn); + tree min, max; if (min_ovf == wi::OVF_UNDERFLOW) - vr.min = wide_int_to_tree (type, type_min); + min = wide_int_to_tree (type, type_min); else if (min_ovf == wi::OVF_OVERFLOW) - vr.min = wide_int_to_tree (type, type_max); + min = wide_int_to_tree (type, type_max); else - vr.min = wide_int_to_tree (type, wmin); + min = wide_int_to_tree (type, wmin); if (max_ovf == wi::OVF_UNDERFLOW) - vr.max = wide_int_to_tree (type, type_min); + max = wide_int_to_tree (type, type_min); else if (max_ovf == wi::OVF_OVERFLOW) - vr.max = wide_int_to_tree (type, type_max); + max = wide_int_to_tree (type, type_max); else - vr.max = wide_int_to_tree (type, wmax); + max = wide_int_to_tree (type, wmax); + vr = value_range (type, VR_RANGE, min, max); } } @@ -1196,7 +1268,7 @@ extract_range_from_binary_expr_1 (value_range *vr, signop sign = TYPE_SIGN (expr_type); unsigned int prec = TYPE_PRECISION (expr_type); value_range vr0 = *vr0_, vr1 = *vr1_; - value_range vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER; + value_range vrtem0 (expr_type), vrtem1 (expr_type); enum value_range_type type; tree min = NULL_TREE, max = NULL_TREE; int cmp; @@ -1233,7 +1305,7 @@ extract_range_from_binary_expr_1 (value_range *vr, } /* If both ranges are UNDEFINED, so is the result. */ - if (vr0.type == VR_UNDEFINED && vr1.type == VR_UNDEFINED) + if (vr0.undefined_p () && vr1.undefined_p ()) { set_value_range_to_undefined (vr); return; @@ -1242,19 +1314,16 @@ extract_range_from_binary_expr_1 (value_range *vr, code. At some point we may want to special-case operations that have UNDEFINED result for all or some value-ranges of the not UNDEFINED operand. */ - else if (vr0.type == VR_UNDEFINED) + else if (vr0.undefined_p ()) set_value_range_to_varying (&vr0); - else if (vr1.type == VR_UNDEFINED) + else if (vr1.undefined_p ()) set_value_range_to_varying (&vr1); /* We get imprecise results from ranges_from_anti_range when code is EXACT_DIV_EXPR. We could mask out bits in the resulting range, but then we also need to hack up vrp_meet. It's just easier to special case when vr0 is ~[0,0] for EXACT_DIV_EXPR. */ - if (code == EXACT_DIV_EXPR - && vr0.type == VR_ANTI_RANGE - && vr0.min == vr0.max - && integer_zerop (vr0.min)) + if (code == EXACT_DIV_EXPR && range_is_nonnull (&vr0)) { set_value_range_to_nonnull (vr, expr_type); return; @@ -1262,27 +1331,26 @@ extract_range_from_binary_expr_1 (value_range *vr, /* Now canonicalize anti-ranges to ranges when they are not symbolic and express ~[] op X as ([]' op X) U ([]'' op X). */ - if (vr0.type == VR_ANTI_RANGE + if (vr0.vrtype () == VR_ANTI_RANGE && ranges_from_anti_range (&vr0, &vrtem0, &vrtem1)) { extract_range_from_binary_expr_1 (vr, code, expr_type, &vrtem0, vr1_); - if (vrtem1.type != VR_UNDEFINED) + if (!vrtem1.undefined_p ()) { - value_range vrres = VR_INITIALIZER; - extract_range_from_binary_expr_1 (&vrres, code, expr_type, - &vrtem1, vr1_); + value_range vrres (expr_type); + extract_range_from_binary_expr_1 (&vrres, code, expr_type, &vrtem1, vr1_); vrp_meet (vr, &vrres); } return; } /* Likewise for X op ~[]. */ - if (vr1.type == VR_ANTI_RANGE + if (vr1.vrtype () == VR_ANTI_RANGE && ranges_from_anti_range (&vr1, &vrtem0, &vrtem1)) { extract_range_from_binary_expr_1 (vr, code, expr_type, vr0_, &vrtem0); - if (vrtem1.type != VR_UNDEFINED) + if (!vrtem1.undefined_p ()) { - value_range vrres = VR_INITIALIZER; + value_range vrres (expr_type); extract_range_from_binary_expr_1 (&vrres, code, expr_type, vr0_, &vrtem1); vrp_meet (vr, &vrres); @@ -1291,7 +1359,7 @@ extract_range_from_binary_expr_1 (value_range *vr, } /* The type of the resulting value range defaults to VR0.TYPE. */ - type = vr0.type; + type = vr0.vrtype (); /* Refuse to operate on VARYING ranges, ranges of different kinds and symbolic ranges. As an exception, we allow BIT_{AND,IOR} @@ -1314,11 +1382,11 @@ extract_range_from_binary_expr_1 (value_range *vr, && code != MINUS_EXPR && code != RSHIFT_EXPR && code != POINTER_PLUS_EXPR - && (vr0.type == VR_VARYING - || vr1.type == VR_VARYING - || vr0.type != vr1.type - || symbolic_range_p (&vr0) - || symbolic_range_p (&vr1))) + && (vr0.varying_p () + || vr1.varying_p () + || vr0.vrtype () != vr1.vrtype () + || vr0.symbolic_p () + || vr1.symbolic_p ())) { set_value_range_to_varying (vr); return; @@ -1376,24 +1444,20 @@ extract_range_from_binary_expr_1 (value_range *vr, /* This will normalize things such that calculating [0,0] - VR_VARYING is not dropped to varying, but is calculated as [MIN+1, MAX]. */ - if (vr0.type == VR_VARYING) - { - vr0.type = VR_RANGE; - vr0.min = vrp_val_min (expr_type); - vr0.max = vrp_val_max (expr_type); - } - if (vr1.type == VR_VARYING) - { - vr1.type = VR_RANGE; - vr1.min = vrp_val_min (expr_type); - vr1.max = vrp_val_max (expr_type); - } + if (vr0.varying_p ()) + vr0 = value_range (vr0.type (), VR_RANGE, + vrp_val_min (expr_type), + vrp_val_max (expr_type), vr0.equiv ()); + if (vr1.varying_p ()) + vr1 = value_range (vr1.type (), VR_RANGE, + vrp_val_min (expr_type), + vrp_val_max (expr_type), vr0.equiv ()); const bool minus_p = (code == MINUS_EXPR); - tree min_op0 = vr0.min; - tree min_op1 = minus_p ? vr1.max : vr1.min; - tree max_op0 = vr0.max; - tree max_op1 = minus_p ? vr1.min : vr1.max; + tree min_op0 = vr0.min (); + tree min_op1 = minus_p ? vr1.max () : vr1.min (); + tree max_op0 = vr0.max (); + tree max_op1 = minus_p ? vr1.min () : vr1.max (); tree sym_min_op0 = NULL_TREE; tree sym_min_op1 = NULL_TREE; tree sym_max_op0 = NULL_TREE; @@ -1406,7 +1470,7 @@ extract_range_from_binary_expr_1 (value_range *vr, single-symbolic ranges, try to compute the precise resulting range, but only if we know that this resulting range will also be constant or single-symbolic. */ - if (vr0.type == VR_RANGE && vr1.type == VR_RANGE + if (vr0.vrtype () == VR_RANGE && vr1.vrtype () == VR_RANGE && (TREE_CODE (min_op0) == INTEGER_CST || (sym_min_op0 = get_single_symbol (min_op0, &neg_min_op0, &min_op0))) @@ -1446,21 +1510,19 @@ extract_range_from_binary_expr_1 (value_range *vr, /* Adjust the range for possible overflow. */ set_value_range_with_overflow (*vr, expr_type, wmin, wmax, min_ovf, max_ovf); - if (vr->type == VR_VARYING) + if (vr->varying_p ()) return; /* Build the symbolic bounds if needed. */ - adjust_symbolic_bound (vr->min, code, expr_type, + min = vr->min (); + max = vr->max (); + adjust_symbolic_bound (min, code, expr_type, sym_min_op0, sym_min_op1, neg_min_op0, neg_min_op1); - adjust_symbolic_bound (vr->max, code, expr_type, + adjust_symbolic_bound (max, code, expr_type, sym_max_op0, sym_max_op1, neg_max_op0, neg_max_op1); - /* ?? It would probably be cleaner to eliminate min/max/type - entirely and hold these values in VR directly. */ - min = vr->min; - max = vr->max; - type = vr->type; + type = vr->vrtype (); } else { @@ -1513,19 +1575,21 @@ extract_range_from_binary_expr_1 (value_range *vr, { if (range_int_cst_p (&vr1) && !wide_int_range_shift_undefined_p (prec, - wi::to_wide (vr1.min), - wi::to_wide (vr1.max))) + wi::to_wide (vr1.min ()), + wi::to_wide (vr1.max ()))) { if (code == RSHIFT_EXPR) { /* Even if vr0 is VARYING or otherwise not usable, we can derive useful ranges just from the shift count. E.g. x >> 63 for signed 64-bit x is always [-1, 0]. */ - if (vr0.type != VR_RANGE || symbolic_range_p (&vr0)) + if (vr0.vrtype () != VR_RANGE || vr0.symbolic_p ()) { - vr0.type = type = VR_RANGE; - vr0.min = vrp_val_min (expr_type); - vr0.max = vrp_val_max (expr_type); + type = VR_RANGE; + vr0 = value_range (vr0.type (), type, + vrp_val_min (expr_type), + vrp_val_max (expr_type), + vr0.equiv ()); } extract_range_from_multiplicative_op (vr, code, &vr0, &vr1); return; @@ -1535,10 +1599,10 @@ extract_range_from_binary_expr_1 (value_range *vr, { wide_int res_lb, res_ub; if (wide_int_range_lshift (res_lb, res_ub, sign, prec, - wi::to_wide (vr0.min), - wi::to_wide (vr0.max), - wi::to_wide (vr1.min), - wi::to_wide (vr1.max), + wi::to_wide (vr0.min ()), + wi::to_wide (vr0.max ()), + wi::to_wide (vr1.min ()), + wi::to_wide (vr1.max ()), TYPE_OVERFLOW_UNDEFINED (expr_type), TYPE_OVERFLOW_WRAPS (expr_type))) { @@ -1596,7 +1660,7 @@ extract_range_from_binary_expr_1 (value_range *vr, wide_int_to_tree (expr_type, wmax), NULL); if (extra_range_p) { - value_range extra_range = VR_INITIALIZER; + value_range extra_range (expr_type); set_value_range (&extra_range, VR_RANGE, wide_int_to_tree (expr_type, extra_min), wide_int_to_tree (expr_type, extra_max), NULL); @@ -1733,7 +1797,9 @@ extract_range_from_unary_expr (value_range *vr, { signop sign = TYPE_SIGN (type); unsigned int prec = TYPE_PRECISION (type); - value_range vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER; + value_range vr0 = *vr0_; + value_range vrtem0 (vr0.type ()); + value_range vrtem1 (vr0.type ()); /* VRP only operates on integral and pointer types. */ if (!(INTEGRAL_TYPE_P (op0_type) @@ -1746,7 +1812,7 @@ extract_range_from_unary_expr (value_range *vr, } /* If VR0 is UNDEFINED, so is the result. */ - if (vr0.type == VR_UNDEFINED) + if (vr0.undefined_p ()) { set_value_range_to_undefined (vr); return; @@ -1763,7 +1829,7 @@ extract_range_from_unary_expr (value_range *vr, { /* -X is simply 0 - X, so re-use existing code that also handles anti-ranges fine. */ - value_range zero = VR_INITIALIZER; + value_range zero (type); set_value_range_to_value (&zero, build_int_cst (type, 0), NULL); extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &zero, &vr0); return; @@ -1772,7 +1838,7 @@ extract_range_from_unary_expr (value_range *vr, { /* ~X is simply -1 - X, so re-use existing code that also handles anti-ranges fine. */ - value_range minusone = VR_INITIALIZER; + value_range minusone (type); set_value_range_to_value (&minusone, build_int_cst (type, -1), NULL); extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &minusone, &vr0); @@ -1781,13 +1847,13 @@ extract_range_from_unary_expr (value_range *vr, /* Now canonicalize anti-ranges to ranges when they are not symbolic and express op ~[] as (op []') U (op []''). */ - if (vr0.type == VR_ANTI_RANGE + if (vr0.vrtype () == VR_ANTI_RANGE && ranges_from_anti_range (&vr0, &vrtem0, &vrtem1)) { extract_range_from_unary_expr (vr, code, type, &vrtem0, op0_type); - if (vrtem1.type != VR_UNDEFINED) + if (!vrtem1.undefined_p ()) { - value_range vrres = VR_INITIALIZER; + value_range vrres (type); extract_range_from_unary_expr (&vrres, code, type, &vrtem1, op0_type); vrp_meet (vr, &vrres); @@ -1822,8 +1888,8 @@ extract_range_from_unary_expr (value_range *vr, pointer anti-ranges. Any remaining anti-ranges at this point will be integer conversions from SSA names that will be normalized into VARYING. For instance: ~[x_55, x_55]. */ - gcc_assert (vr0.type != VR_ANTI_RANGE - || TREE_CODE (vr0.min) != INTEGER_CST); + gcc_assert (vr0.vrtype () != VR_ANTI_RANGE + || TREE_CODE (vr0.min ()) != INTEGER_CST); /* NOTES: Previously we were returning VARYING for all symbolics, but we can do better by treating them as [-MIN, +MAX]. For @@ -1888,39 +1954,39 @@ dump_value_range (FILE *file, const value_range *vr) { if (vr == NULL) fprintf (file, "[]"); - else if (vr->type == VR_UNDEFINED) + else if (vr->undefined_p ()) fprintf (file, "UNDEFINED"); - else if (vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE) + else if (vr->vrtype () == VR_RANGE || vr->vrtype () == VR_ANTI_RANGE) { - tree type = TREE_TYPE (vr->min); + tree type = TREE_TYPE (vr->min ()); - fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : ""); + fprintf (file, "%s[", (vr->vrtype () == VR_ANTI_RANGE) ? "~" : ""); if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type) - && vrp_val_is_min (vr->min)) + && vrp_val_is_min (vr->min ())) fprintf (file, "-INF"); else - print_generic_expr (file, vr->min); + print_generic_expr (file, vr->min ()); fprintf (file, ", "); if (INTEGRAL_TYPE_P (type) - && vrp_val_is_max (vr->max)) + && vrp_val_is_max (vr->max ())) fprintf (file, "+INF"); else - print_generic_expr (file, vr->max); + print_generic_expr (file, vr->max ()); fprintf (file, "]"); - if (vr->equiv) + if (vr->equiv ()) { bitmap_iterator bi; unsigned i, c = 0; fprintf (file, " EQUIVALENCES: { "); - EXECUTE_IF_SET_IN_BITMAP (vr->equiv, 0, i, bi) + EXECUTE_IF_SET_IN_BITMAP (vr->equiv (), 0, i, bi) { print_generic_expr (file, ssa_name (i)); fprintf (file, " "); @@ -1930,7 +1996,7 @@ dump_value_range (FILE *file, const value_range *vr) fprintf (file, "} (%u elements)", c); } } - else if (vr->type == VR_VARYING) + else if (vr->varying_p ()) fprintf (file, "VARYING"); else fprintf (file, "INVALID RANGE"); @@ -4193,14 +4259,14 @@ vrp_prop::check_array_ref (location_t location, tree ref, if (TREE_CODE (low_sub) == SSA_NAME) { vr = get_value_range (low_sub); - if (vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE) + if (!vr->undefined_p () && !vr->varying_p ()) { - low_sub = vr->type == VR_RANGE ? vr->max : vr->min; - up_sub = vr->type == VR_RANGE ? vr->min : vr->max; + low_sub = vr->vrtype () == VR_RANGE ? vr->max () : vr->min (); + up_sub = vr->vrtype () == VR_RANGE ? vr->min () : vr->max (); } } - if (vr && vr->type == VR_ANTI_RANGE) + if (vr && vr->vrtype () == VR_ANTI_RANGE) { if (up_bound && TREE_CODE (up_sub) == INTEGER_CST @@ -4328,21 +4394,24 @@ vrp_prop::check_mem_ref (location_t location, tree ref, break; vr = get_value_range (varoff); - if (!vr || vr->type == VR_UNDEFINED || !vr->min || !vr->max) + // FIXME: If this never triggers, both tests below simplify to: + // if (!vr || !vr->numeric_p ()) + if (!vr->min () || !vr->max ()) + gcc_assert (vr->varying_p ()); + if (!vr || vr->undefined_p () || !vr->min () || !vr->max ()) break; - if (TREE_CODE (vr->min) != INTEGER_CST - || TREE_CODE (vr->max) != INTEGER_CST) + if (!vr->numeric_p ()) break; - if (vr->type == VR_RANGE) + if (vr->vrtype () == VR_RANGE) { - if (tree_int_cst_lt (vr->min, vr->max)) + if (tree_int_cst_lt (vr->min (), vr->max ())) { offset_int min - = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min)); + = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min ())); offset_int max - = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max)); + = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max ())); if (min < max) { offrange[0] += min; @@ -5114,8 +5183,8 @@ find_case_label_range (gswitch *stmt, tree min, tree max, size_t *min_idx, enum ssa_prop_result vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p) { - value_range vr = VR_INITIALIZER; tree lhs = gimple_get_lhs (stmt); + value_range vr (TREE_TYPE (lhs)); extract_range_from_stmt (stmt, taken_edge_p, output_p, &vr); if (*output_p) @@ -5131,7 +5200,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p) fprintf (dump_file, "\n"); } - if (vr.type == VR_VARYING) + if (vr.varying_p ()) return SSA_PROP_VARYING; return SSA_PROP_INTERESTING; @@ -5184,17 +5253,14 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p) SSA_PROP_NOT_INTERESTING. If there are no {REAL,IMAG}PART_EXPR uses at all, return SSA_PROP_VARYING. */ - value_range new_vr = VR_INITIALIZER; + value_range new_vr (TREE_TYPE (lhs)); extract_range_basic (&new_vr, use_stmt); const value_range *old_vr = get_value_range (use_lhs); - if (old_vr->type != new_vr.type - || !vrp_operand_equal_p (old_vr->min, new_vr.min) - || !vrp_operand_equal_p (old_vr->max, new_vr.max) - || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv)) + if (*old_vr != new_vr) res = SSA_PROP_INTERESTING; else res = SSA_PROP_NOT_INTERESTING; - BITMAP_FREE (new_vr.equiv); + new_vr.equiv_free (); if (res == SSA_PROP_INTERESTING) { *output_p = lhs; @@ -5805,8 +5871,6 @@ intersect_ranges (enum value_range_type *vr0type, *vr0min = vr1min; *vr0max = vr1max; } - - return; } @@ -5816,12 +5880,10 @@ intersect_ranges (enum value_range_type *vr0type, static void vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1) { - value_range saved; - /* If either range is VR_VARYING the other one wins. */ - if (vr1->type == VR_VARYING) + if (vr1->varying_p ()) return; - if (vr0->type == VR_VARYING) + if (vr0->varying_p ()) { copy_value_range (vr0, vr1); return; @@ -5829,9 +5891,9 @@ vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1) /* When either range is VR_UNDEFINED the resulting range is VR_UNDEFINED, too. */ - if (vr0->type == VR_UNDEFINED) + if (vr0->undefined_p ()) return; - if (vr1->type == VR_UNDEFINED) + if (vr1->undefined_p ()) { set_value_range_to_undefined (vr0); return; @@ -5839,34 +5901,38 @@ vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1) /* Save the original vr0 so we can return it as conservative intersection result when our worker turns things to varying. */ - saved = *vr0; - intersect_ranges (&vr0->type, &vr0->min, &vr0->max, - vr1->type, vr1->min, vr1->max); + value_range saved (*vr0); + + value_range_type vr0type = vr0->vrtype (); + tree vr0min = vr0->min (); + tree vr0max = vr0->max (); + intersect_ranges (&vr0type, &vr0min, &vr0max, + vr1->vrtype (), vr1->min (), vr1->max ()); + *vr0 = value_range (vr0->type (), vr0type, vr0min, vr0max, vr0->equiv ()); /* Make sure to canonicalize the result though as the inversion of a VR_RANGE can still be a VR_RANGE. */ - set_and_canonicalize_value_range (vr0, vr0->type, - vr0->min, vr0->max, vr0->equiv); + vr0->canonicalize (); /* If that failed, use the saved original VR0. */ - if (vr0->type == VR_VARYING) + if (vr0->varying_p ()) { *vr0 = saved; return; } /* If the result is VR_UNDEFINED there is no need to mess with the equivalencies. */ - if (vr0->type == VR_UNDEFINED) + if (vr0->undefined_p ()) return; /* The resulting set of equivalences for range intersection is the union of the two sets. */ - if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv) - bitmap_ior_into (vr0->equiv, vr1->equiv); - else if (vr1->equiv && !vr0->equiv) + if (vr0->equiv () && vr1->equiv () && vr0->equiv () != vr1->equiv ()) + vr0->equiv_ior (vr1); + else if (vr1->equiv () && !vr0->equiv ()) { /* All equivalence bitmaps are allocated from the same obstack. So we can use the obstack associated with VR to allocate vr0->equiv. */ - vr0->equiv = BITMAP_ALLOC (vr1->equiv->obstack); - bitmap_copy (vr0->equiv, vr1->equiv); + vr0->set_equiv (BITMAP_ALLOC (vr1->equiv ()->obstack)); + vr0->equiv_copy (vr1); } } @@ -5897,36 +5963,39 @@ vrp_intersect_ranges (value_range *vr0, const value_range *vr1) static void vrp_meet_1 (value_range *vr0, const value_range *vr1) { - value_range saved; - - if (vr0->type == VR_UNDEFINED) + if (vr0->undefined_p ()) { - set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->equiv); + set_value_range (vr0, vr1->vrtype (), vr1->min (), vr1->max (), + vr1->equiv ()); return; } - if (vr1->type == VR_UNDEFINED) + if (vr1->undefined_p ()) { /* VR0 already has the resulting range. */ return; } - if (vr0->type == VR_VARYING) + if (vr0->varying_p ()) { /* Nothing to do. VR0 already has the resulting range. */ return; } - if (vr1->type == VR_VARYING) + if (vr1->varying_p ()) { set_value_range_to_varying (vr0); return; } - saved = *vr0; - union_ranges (&vr0->type, &vr0->min, &vr0->max, - vr1->type, vr1->min, vr1->max); - if (vr0->type == VR_VARYING) + value_range saved (*vr0); + value_range_type vr0type = vr0->vrtype (); + tree vr0min = vr0->min (); + tree vr0max = vr0->max (); + union_ranges (&vr0type, &vr0min, &vr0max, + vr1->vrtype (), vr1->min (), vr1->max ()); + *vr0 = value_range (vr0->type (), vr0type, vr0min, vr0max, vr0->equiv ()); + if (vr0->varying_p ()) { /* Failed to find an efficient meet. Before giving up and setting the result to VARYING, see if we can at least derive a useful @@ -5934,29 +6003,27 @@ vrp_meet_1 (value_range *vr0, const value_range *vr1) if (range_includes_zero_p (&saved) == 0 && range_includes_zero_p (vr1) == 0) { - set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min)); + set_value_range_to_nonnull (vr0, saved.type ()); /* Since this meet operation did not result from the meeting of two equivalent names, VR0 cannot have any equivalences. */ - if (vr0->equiv) - bitmap_clear (vr0->equiv); + vr0->equiv_clear (); return; } set_value_range_to_varying (vr0); return; } - set_and_canonicalize_value_range (vr0, vr0->type, vr0->min, vr0->max, - vr0->equiv); - if (vr0->type == VR_VARYING) + vr0->canonicalize (); + if (vr0->varying_p ()) return; /* The resulting set of equivalences is always the intersection of the two sets. */ - if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv) - bitmap_and_into (vr0->equiv, vr1->equiv); - else if (vr0->equiv && !vr1->equiv) - bitmap_clear (vr0->equiv); + if (vr0->equiv () != vr1->equiv ()) + vr0->equiv_and (vr1); + else if (!vr1->equiv ()) + vr0->equiv_clear (); } void @@ -5988,7 +6055,7 @@ enum ssa_prop_result vrp_prop::visit_phi (gphi *phi) { tree lhs = PHI_RESULT (phi); - value_range vr_result = VR_INITIALIZER; + value_range vr_result (TREE_TYPE (lhs)); extract_range_from_phi_node (phi, &vr_result); if (update_value_range (lhs, &vr_result)) { @@ -6001,7 +6068,7 @@ vrp_prop::visit_phi (gphi *phi) fprintf (dump_file, "\n"); } - if (vr_result.type == VR_VARYING) + if (vr_result.varying_p ()) return SSA_PROP_VARYING; return SSA_PROP_INTERESTING; @@ -6185,16 +6252,17 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, op = lhs_of_dominating_assert (op, bb, stmt); const value_range *vr = vr_values->get_value_range (op); - if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE) - || symbolic_range_p (vr)) + if (vr->undefined_p () + || vr->varying_p () + || vr->symbolic_p ()) return NULL_TREE; - if (vr->type == VR_RANGE) + if (vr->vrtype () == VR_RANGE) { size_t i, j; /* Get the range of labels that contain a part of the operand's value range. */ - find_case_label_range (switch_stmt, vr->min, vr->max, &i, &j); + find_case_label_range (switch_stmt, vr->min (), vr->max (), &i, &j); /* Is there only one such label? */ if (i == j) @@ -6204,10 +6272,13 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, /* The i'th label will be taken only if the value range of the operand is entirely within the bounds of this label. */ if (CASE_HIGH (label) != NULL_TREE - ? (tree_int_cst_compare (CASE_LOW (label), vr->min) <= 0 - && tree_int_cst_compare (CASE_HIGH (label), vr->max) >= 0) - : (tree_int_cst_equal (CASE_LOW (label), vr->min) - && tree_int_cst_equal (vr->min, vr->max))) + // FIXME: Rewrite in terms of an API call + // vr->contains_p() or some such. + ? (tree_int_cst_compare (CASE_LOW (label), vr->min ()) <= 0 + && tree_int_cst_compare (CASE_HIGH (label), + vr->max ()) >= 0) + : (tree_int_cst_equal (CASE_LOW (label), vr->min ()) + && tree_int_cst_equal (vr->min (), vr->max ()))) return label; } @@ -6217,7 +6288,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, return gimple_switch_label (switch_stmt, 0); } - if (vr->type == VR_ANTI_RANGE) + if (vr->vrtype () == VR_ANTI_RANGE) { unsigned n = gimple_switch_num_labels (switch_stmt); tree min_label = gimple_switch_label (switch_stmt, 1); @@ -6226,10 +6297,14 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, /* The default label will be taken only if the anti-range of the operand is entirely outside the bounds of all the (non-default) case labels. */ - if (tree_int_cst_compare (vr->min, CASE_LOW (min_label)) <= 0 + // FIXME: Rewrite in terms of an API call vr->contains_p() + // or some such. + if (tree_int_cst_compare (vr->min (), CASE_LOW (min_label)) <= 0 && (CASE_HIGH (max_label) != NULL_TREE - ? tree_int_cst_compare (vr->max, CASE_HIGH (max_label)) >= 0 - : tree_int_cst_compare (vr->max, CASE_LOW (max_label)) >= 0)) + ? tree_int_cst_compare (vr->max (), + CASE_HIGH (max_label)) >= 0 + : tree_int_cst_compare (vr->max (), + CASE_LOW (max_label)) >= 0)) return gimple_switch_label (switch_stmt, 0); } @@ -6246,11 +6321,12 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, { edge dummy_e; tree dummy_tree; - value_range new_vr = VR_INITIALIZER; + value_range new_vr (TREE_TYPE (lhs)); vr_values->extract_range_from_stmt (stmt, &dummy_e, &dummy_tree, &new_vr); - if (range_int_cst_singleton_p (&new_vr)) - return new_vr.min; + tree singleton = new_vr.singleton (); + if (singleton) + return singleton; } } @@ -6422,20 +6498,16 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p) continue; const value_range *vr = get_value_range (name); - if (!name - || (vr->type == VR_VARYING) - || (vr->type == VR_UNDEFINED) - || (TREE_CODE (vr->min) != INTEGER_CST) - || (TREE_CODE (vr->max) != INTEGER_CST)) + if (!name || vr->numeric_p ()) continue; if (POINTER_TYPE_P (TREE_TYPE (name)) && range_includes_zero_p (vr) == 0) set_ptr_nonnull (name); else if (!POINTER_TYPE_P (TREE_TYPE (name))) - set_range_info (name, vr->type, - wi::to_wide (vr->min), - wi::to_wide (vr->max)); + set_range_info (name, vr->vrtype (), + wi::to_wide (vr->min ()), + wi::to_wide (vr->max ())); } /* If we're checking array refs, we want to merge information on @@ -6627,7 +6699,8 @@ determine_value_range_1 (value_range *vr, tree expr) { if (BINARY_CLASS_P (expr)) { - value_range vr0 = VR_INITIALIZER, vr1 = VR_INITIALIZER; + value_range vr0 (TREE_TYPE (TREE_OPERAND (expr, 0))); + value_range vr1 (TREE_TYPE (TREE_OPERAND (expr, 1))); determine_value_range_1 (&vr0, TREE_OPERAND (expr, 0)); determine_value_range_1 (&vr1, TREE_OPERAND (expr, 1)); extract_range_from_binary_expr_1 (vr, TREE_CODE (expr), TREE_TYPE (expr), @@ -6635,7 +6708,7 @@ determine_value_range_1 (value_range *vr, tree expr) } else if (UNARY_CLASS_P (expr)) { - value_range vr0 = VR_INITIALIZER; + value_range vr0 (TREE_TYPE (TREE_OPERAND (expr, 0))); determine_value_range_1 (&vr0, TREE_OPERAND (expr, 0)); extract_range_from_unary_expr (vr, TREE_CODE (expr), TREE_TYPE (expr), &vr0, TREE_TYPE (TREE_OPERAND (expr, 0))); @@ -6664,15 +6737,13 @@ determine_value_range_1 (value_range *vr, tree expr) value_range_type determine_value_range (tree expr, wide_int *min, wide_int *max) { - value_range vr = VR_INITIALIZER; + value_range vr (TREE_TYPE (expr)); determine_value_range_1 (&vr, expr); - if ((vr.type == VR_RANGE - || vr.type == VR_ANTI_RANGE) - && !symbolic_range_p (&vr)) + if (vr.numeric_p ()) { - *min = wi::to_wide (vr.min); - *max = wi::to_wide (vr.max); - return vr.type; + *min = wi::to_wide (vr.min ()); + *max = wi::to_wide (vr.max ()); + return vr.vrtype (); } return VR_VARYING;