diff options
author | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-06-20 17:54:34 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-06-20 17:54:34 +0000 |
commit | d062880a07bae2882313abeca4fd98239a33ca7c (patch) | |
tree | fda3b97198d0b34a02590925895d70dcc9df768e /gcc | |
parent | 5cf12989a937cadd57e32ae33c6901b431954361 (diff) | |
download | gcc-d062880a07bae2882313abeca4fd98239a33ca7c.zip gcc-d062880a07bae2882313abeca4fd98239a33ca7c.tar.gz gcc-d062880a07bae2882313abeca4fd98239a33ca7c.tar.bz2 |
Enforce value_range canonicalization.
From-SVN: r272516
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/range.c | 7 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 147 | ||||
-rw-r--r-- | gcc/tree-vrp.h | 2 | ||||
-rw-r--r-- | gcc/vr-values.c | 6 |
4 files changed, 77 insertions, 85 deletions
diff --git a/gcc/range.c b/gcc/range.c index 351a55b..92a446e 100644 --- a/gcc/range.c +++ b/gcc/range.c @@ -571,13 +571,6 @@ irange::canonicalize () else ++p; } - if (TREE_CODE (m_type) == ENUMERAL_TYPE) - { - /* For -fstrict-enums we may receive out-of-range ranges. Chop - things off appropriately. */ - irange bits (TYPE_MIN_VALUE (m_type), TYPE_MAX_VALUE (m_type)); - intersect (bits); - } if (flag_checking) check (); } diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index b4d5698..cf5daf3 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -81,18 +81,10 @@ ranges_from_anti_range (const value_range_base *ar, static sbitmap *live; void -value_range_base::set (enum value_range_kind kind, tree min, tree max) -{ - m_kind = kind; - m_min = min; - m_max = max; - if (flag_checking) - check (); -} - -void value_range::set_equiv (bitmap equiv) { + if (undefined_p () || varying_p ()) + equiv = NULL; /* Since updating the equivalence set involves deep copying the bitmaps, only do it if absolutely necessary. @@ -154,7 +146,7 @@ value_range_base::value_range_base (enum value_range_kind kind, tree min = wide_int_to_tree (type, wmin); tree max = wide_int_to_tree (type, wmax); gcc_assert (kind == VR_RANGE || kind == VR_ANTI_RANGE); - set_and_canonicalize (kind, min, max); + set (kind, min, max); } value_range_base::value_range_base (tree type, @@ -163,7 +155,7 @@ value_range_base::value_range_base (tree type, { tree min = wide_int_to_tree (type, wmin); tree max = wide_int_to_tree (type, wmax); - set_and_canonicalize (VR_RANGE, min, max); + set (VR_RANGE, min, max); } value_range_base::value_range_base (tree min, tree max) @@ -310,7 +302,8 @@ value_range_base::constant_p () const void value_range_base::set_undefined (tree type) { - set (VR_UNDEFINED, type, type); + m_kind = VR_UNDEFINED; + m_min = m_max = type; } void @@ -323,7 +316,8 @@ value_range::set_undefined (tree type) void value_range_base::set_varying (tree type) { - set (VR_VARYING, type, type); + m_kind = VR_VARYING; + m_min = m_max = type; } void @@ -707,8 +701,7 @@ intersect_range_with_nonzero_bits (enum value_range_kind vr_type, extract ranges from var + CST op limit. */ void -value_range_base::set_and_canonicalize (enum value_range_kind kind, - tree min, tree max) +value_range_base::set (enum value_range_kind kind, tree min, tree max) { if (kind == VR_UNDEFINED) { @@ -727,7 +720,9 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind, if (TREE_CODE (min) != INTEGER_CST || TREE_CODE (max) != INTEGER_CST) { - set (kind, min, max); + m_kind = kind; + m_min = min; + m_max = max; return; } @@ -811,19 +806,18 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind, } } - /* FIXME: The ranger chops off out-of-bound ranges for - -fstrict-enums. Do the same here. This is only here to make - sure the ranger and VRP compare correctly. */ - if (TREE_CODE (type) == ENUMERAL_TYPE - && kind == VR_RANGE) - { - if (tree_int_cst_compare (min, TYPE_MIN_VALUE (type)) < 0) - min = TYPE_MIN_VALUE (type); - if (tree_int_cst_compare (max, TYPE_MAX_VALUE (type)) > 0) - max = TYPE_MAX_VALUE (type); - } + /* Normalize [MIN, MAX] into VARYING and ~[MIN, MAX] into UNDEFINED. - if (vrp_val_is_min (min) && vrp_val_is_max (max)) + Avoid using TYPE_{MIN,MAX}_VALUE because -fstrict-enums can + restrict those to a subset of what actually fits in the type. + Instead use the extremes of the type precision which will allow + compare_range_with_value() to check if a value is inside a range, + whereas if we used TYPE_*_VAL, said function would just punt + upon seeing a VARYING. */ + unsigned prec = TYPE_PRECISION (type); + signop sign = TYPE_SIGN (type); + if (wi::eq_p (wi::to_wide (min), wi::min_value (prec, sign)) + && wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign))) { if (kind == VR_RANGE) set_varying (type); @@ -838,18 +832,11 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind, to make sure VRP iteration terminates, otherwise we can get into oscillations. */ - set (kind, min, max); -} - -void -value_range::set_and_canonicalize (enum value_range_kind kind, - tree min, tree max, bitmap equiv) -{ - value_range_base::set_and_canonicalize (kind, min, max); - if (this->kind () == VR_RANGE || this->kind () == VR_ANTI_RANGE) - set_equiv (equiv); - else - equiv_clear (); + m_kind = kind; + m_min = min; + m_max = max; + if (flag_checking) + check (); } void @@ -1351,7 +1338,8 @@ static void extract_range_from_multiplicative_op (value_range_base *vr, enum tree_code code, const value_range_base *vr0, - const value_range_base *vr1) + const value_range_base *vr1, + tree type) { gcc_assert (code == MULT_EXPR || code == TRUNC_DIV_EXPR @@ -1361,13 +1349,25 @@ extract_range_from_multiplicative_op (value_range_base *vr, || code == ROUND_DIV_EXPR || code == RSHIFT_EXPR || code == LSHIFT_EXPR); - gcc_assert (vr0->kind () == VR_RANGE - && vr0->kind () == vr1->kind ()); + if (!range_int_cst_p (vr1)) + { + vr->set_varying (type); + return; + } + + /* 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]. */ + tree vr0_min = vr0->min (), vr0_max = vr0->max (); + if (vr0->kind () != VR_RANGE || vr0->symbolic_p ()) + { + vr0_min = vrp_val_min (type); + vr0_max = vrp_val_max (type); + } - 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 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); @@ -1377,9 +1377,8 @@ extract_range_from_multiplicative_op (value_range_base *vr, code, TYPE_SIGN (type), prec, vr0_lb, vr0_ub, vr1_lb, vr1_ub, overflow_undefined)) - vr->set_and_canonicalize (VR_RANGE, - wide_int_to_tree (type, res_lb), - wide_int_to_tree (type, res_ub)); + vr->set (VR_RANGE, wide_int_to_tree (type, res_lb), + wide_int_to_tree (type, res_ub)); else vr->set_varying (type); } @@ -2032,19 +2031,30 @@ extract_range_from_binary_expr (value_range_base *vr, range and see what we end up with. */ if (code == PLUS_EXPR || code == MINUS_EXPR) { + value_range_kind vr0_kind = vr0.kind (), vr1_kind = vr1.kind (); + tree vr0_min = vr0.min (), vr0_max = vr0.max (); + tree vr1_min = vr1.min (), vr1_max = vr1.max (); /* 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.varying_p ()) - vr0.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type)); + { + vr0_kind = VR_RANGE; + vr0_min = vrp_val_min (expr_type); + vr0_max = vrp_val_max (expr_type); + } if (vr1.varying_p ()) - vr1.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type)); + { + vr1_kind = VR_RANGE; + vr1_min = vrp_val_min (expr_type); + vr1_max = vrp_val_max (expr_type); + } 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; @@ -2057,7 +2067,7 @@ extract_range_from_binary_expr (value_range_base *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.kind () == VR_RANGE && vr1.kind () == VR_RANGE + if (vr0_kind == VR_RANGE && vr1_kind == VR_RANGE && (TREE_CODE (min_op0) == INTEGER_CST || (sym_min_op0 = get_single_symbol (min_op0, &neg_min_op0, &min_op0))) @@ -2155,7 +2165,7 @@ extract_range_from_binary_expr (value_range_base *vr, vr->set_varying (expr_type); return; } - extract_range_from_multiplicative_op (vr, code, &vr0, &vr1); + extract_range_from_multiplicative_op (vr, code, &vr0, &vr1, expr_type); return; } else if (code == RSHIFT_EXPR @@ -2170,13 +2180,8 @@ extract_range_from_binary_expr (value_range_base *vr, { 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.kind () != VR_RANGE || vr0.symbolic_p ()) - vr0.set (VR_RANGE, vrp_val_min (expr_type), - vrp_val_max (expr_type)); - extract_range_from_multiplicative_op (vr, code, &vr0, &vr1); + extract_range_from_multiplicative_op (vr, code, &vr0, &vr1, + expr_type); return; } else if (code == LSHIFT_EXPR @@ -2192,7 +2197,7 @@ extract_range_from_binary_expr (value_range_base *vr, { min = wide_int_to_tree (expr_type, res_lb); max = wide_int_to_tree (expr_type, res_ub); - vr->set_and_canonicalize (VR_RANGE, min, max); + vr->set (VR_RANGE, min, max); return; } } @@ -2518,7 +2523,7 @@ extract_range_from_unary_expr (value_range_base *vr, { tree min = wide_int_to_tree (outer_type, wmin); tree max = wide_int_to_tree (outer_type, wmax); - vr->set_and_canonicalize (VR_RANGE, min, max); + vr->set (VR_RANGE, min, max); } else vr->set_varying (outer_type); @@ -6433,7 +6438,7 @@ value_range_base::intersect_helper (const value_range_base *vr0, vr0min = TREE_TYPE (vr0->min ()); vr0max = TREE_TYPE (vr0->min ()); } - tem.set_and_canonicalize (vr0type, vr0min, vr0max); + tem.set (vr0type, vr0min, vr0max); /* If that failed, use the saved original VR0. */ if (tem.varying_p ()) return *vr0; @@ -6543,7 +6548,7 @@ value_range_base::union_helper (const value_range_base *vr0, vr0min = TREE_TYPE (vr0->min ()); vr0max = TREE_TYPE (vr0->min ()); } - tem.set_and_canonicalize (vr0type, vr0min, vr0max); + tem.set (vr0type, vr0min, vr0max); /* Failed to find an efficient meet. Before giving up and setting the result to VARYING, see if we can at least derive a useful @@ -6776,10 +6781,6 @@ value_range_base::contains_p (tree cst) const void value_range_base::invert () { - /* Canonicalize first to consider [MIN, MAX] as VARYING and ~[MIN, - MAX] as UNDEFINED. */ - set_and_canonicalize (m_kind, m_min, m_max); - if (undefined_p ()) set_varying (type ()); else if (varying_p ()) diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h index 80fcc4a..41fa3ef 100644 --- a/gcc/tree-vrp.h +++ b/gcc/tree-vrp.h @@ -80,7 +80,6 @@ public: /* Misc methods. */ tree type () const; bool may_contain_p (tree) const; - void set_and_canonicalize (enum value_range_kind, tree, tree); bool zero_p () const; bool nonzero_p () const; bool singleton_p (tree *result = NULL) const; @@ -170,7 +169,6 @@ class GTY((user)) value_range : public value_range_base /* Misc methods. */ void deep_copy (const value_range *); - void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap = NULL); void dump (FILE *) const; private: diff --git a/gcc/vr-values.c b/gcc/vr-values.c index def5a16..c0477da 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -534,9 +534,9 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var, vice-versa. Use set_and_canonicalize which does this for us. */ if (cond_code == LE_EXPR) - vr_p->set_and_canonicalize (VR_RANGE, min, max, vr_p->equiv ()); + vr_p->set (VR_RANGE, min, max, vr_p->equiv ()); else if (cond_code == GT_EXPR) - vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ()); + vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ()); else gcc_unreachable (); } @@ -608,7 +608,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var, && vrp_val_is_max (max)) min = max = limit; - vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ()); + vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ()); } else if (cond_code == LE_EXPR || cond_code == LT_EXPR) { |