1 /* Support routines for value ranges. 2 Copyright (C) 2019-2022 Free Software Foundation, Inc. 3 Contributed by Aldy Hernandez <aldyh (at) redhat.com> and 4 Andrew Macleod <amacleod (at) redhat.com>. 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3, or (at your option) 11 any later version. 12 13 GCC is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GCC; see the file COPYING3. If not see 20 <http://www.gnu.org/licenses/>. */ 21 22 #ifndef GCC_VALUE_RANGE_H 23 #define GCC_VALUE_RANGE_H 24 25 // Types of value ranges. 26 enum value_range_kind 27 { 28 /* Empty range. */ 29 VR_UNDEFINED, 30 /* Range spans the entire domain. */ 31 VR_VARYING, 32 /* Range is [MIN, MAX]. */ 33 VR_RANGE, 34 /* Range is ~[MIN, MAX]. */ 35 VR_ANTI_RANGE, 36 /* Range is a nice guy. */ 37 VR_LAST 38 }; 39 40 // Range of values that can be associated with an SSA_NAME. 41 // 42 // This is the base class without any storage. 43 44 class GTY((user)) irange 45 { 46 friend class irange_allocator; 47 public: 48 // In-place setters. 49 void set (tree, tree, value_range_kind = VR_RANGE); 50 void set_nonzero (tree); 51 void set_zero (tree); 52 void set_varying (tree type); 53 void set_undefined (); 54 55 // Range types. 56 static bool supports_type_p (tree); 57 tree type () const; 58 59 // Iteration over sub-ranges. 60 unsigned num_pairs () const; 61 wide_int lower_bound (unsigned = 0) const; 62 wide_int upper_bound (unsigned) const; 63 wide_int upper_bound () const; 64 65 // Predicates. 66 bool zero_p () const; 67 bool nonzero_p () const; 68 bool undefined_p () const; 69 bool varying_p () const; 70 bool singleton_p (tree *result = NULL) const; 71 bool contains_p (tree) const; 72 73 // In-place operators. 74 void union_ (const irange &); 75 void intersect (const irange &); 76 void intersect (const wide_int& lb, const wide_int& ub); 77 void invert (); 78 79 // Operator overloads. 80 irange& operator= (const irange &); 81 bool operator== (const irange &) const; 82 bool operator!= (const irange &r) const { return !(*this == r); } 83 84 // Misc methods. 85 bool fits_p (const irange &r) { return m_max_ranges >= r.num_pairs (); } 86 void dump (FILE * = stderr) const; 87 void debug () const; 88 89 // Deprecated legacy public methods. 90 enum value_range_kind kind () const; // DEPRECATED 91 tree min () const; // DEPRECATED 92 tree max () const; // DEPRECATED 93 bool symbolic_p () const; // DEPRECATED 94 bool constant_p () const; // DEPRECATED 95 void normalize_symbolics (); // DEPRECATED 96 void normalize_addresses (); // DEPRECATED 97 bool may_contain_p (tree) const; // DEPRECATED 98 void set (tree); // DEPRECATED 99 bool equal_p (const irange &) const; // DEPRECATED 100 void union_ (const class irange *); // DEPRECATED 101 void intersect (const irange *); // DEPRECATED 102 103 protected: 104 irange (tree *, unsigned); 105 // potential promotion to public? 106 tree tree_lower_bound (unsigned = 0) const; 107 tree tree_upper_bound (unsigned) const; 108 tree tree_upper_bound () const; 109 110 // In-place operators. 111 void irange_union (const irange &); 112 void irange_intersect (const irange &); 113 void irange_set (tree, tree); 114 void irange_set_anti_range (tree, tree); 115 116 void normalize_kind (); 117 118 bool legacy_mode_p () const; 119 bool legacy_equal_p (const irange &) const; 120 void legacy_union (irange *, const irange *); 121 void legacy_intersect (irange *, const irange *); 122 void verify_range (); 123 wide_int legacy_lower_bound (unsigned = 0) const; 124 wide_int legacy_upper_bound (unsigned) const; 125 int value_inside_range (tree) const; 126 bool maybe_anti_range () const; 127 void copy_to_legacy (const irange &); 128 void copy_legacy_to_multi_range (const irange &); 129 130 private: 131 friend void gt_ggc_mx (irange *); 132 friend void gt_pch_nx (irange *); 133 friend void gt_pch_nx (irange *, gt_pointer_operator, void *); 134 135 void irange_set_1bit_anti_range (tree, tree); 136 bool varying_compatible_p () const; 137 138 unsigned char m_num_ranges; 139 unsigned char m_max_ranges; 140 ENUM_BITFIELD(value_range_kind) m_kind : 8; 141 tree *m_base; 142 }; 143 144 // Here we describe an irange with N pairs of ranges. The storage for 145 // the pairs is embedded in the class as an array. 146 147 template<unsigned N> 148 class GTY((user)) int_range : public irange 149 { 150 public: 151 int_range (); 152 int_range (tree, tree, value_range_kind = VR_RANGE); 153 int_range (tree type, const wide_int &, const wide_int &, 154 value_range_kind = VR_RANGE); 155 int_range (tree type); 156 int_range (const int_range &); 157 int_range (const irange &); 158 int_range& operator= (const int_range &); 159 private: 160 template <unsigned X> friend void gt_ggc_mx (int_range<X> *); 161 template <unsigned X> friend void gt_pch_nx (int_range<X> *); 162 template <unsigned X> friend void gt_pch_nx (int_range<X> *, 163 gt_pointer_operator, void *); 164 165 // ?? These stubs are for ipa-prop.cc which use a value_range in a 166 // hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &) 167 // instead of picking up the gt_ggc_mx (T *) version. 168 friend void gt_ggc_mx (int_range<1> *&); 169 friend void gt_pch_nx (int_range<1> *&); 170 171 tree m_ranges[N*2]; 172 }; 173 174 // This is a special int_range<1> with only one pair, plus 175 // VR_ANTI_RANGE magic to describe slightly more than can be described 176 // in one pair. It is described in the code as a "legacy range" (as 177 // opposed to multi-ranges which have multiple sub-ranges). It is 178 // provided for backward compatibility with code that has not been 179 // converted to multi-range irange's. 180 // 181 // There are copy operators to seamlessly copy to/fro multi-ranges. 182 typedef int_range<1> value_range; 183 184 // This is an "infinite" precision irange for use in temporary 185 // calculations. 186 typedef int_range<255> int_range_max; 187 188 // Returns true for an old-school value_range as described above. 189 inline bool 190 irange::legacy_mode_p () const 191 { 192 return m_max_ranges == 1; 193 } 194 195 extern bool range_has_numeric_bounds_p (const irange *); 196 extern bool ranges_from_anti_range (const value_range *, 197 value_range *, value_range *); 198 extern void dump_value_range (FILE *, const irange *); 199 extern bool vrp_val_is_min (const_tree); 200 extern bool vrp_val_is_max (const_tree); 201 extern bool vrp_operand_equal_p (const_tree, const_tree); 202 203 inline value_range_kind 204 irange::kind () const 205 { 206 return m_kind; 207 } 208 209 // Number of sub-ranges in a range. 210 211 inline unsigned 212 irange::num_pairs () const 213 { 214 if (m_kind == VR_ANTI_RANGE) 215 return constant_p () ? 2 : 1; 216 else 217 return m_num_ranges; 218 } 219 220 inline tree 221 irange::type () const 222 { 223 gcc_checking_assert (m_num_ranges > 0); 224 return TREE_TYPE (m_base[0]); 225 } 226 227 // Return the lower bound of a sub-range expressed as a tree. PAIR is 228 // the sub-range in question. 229 230 inline tree 231 irange::tree_lower_bound (unsigned pair) const 232 { 233 return m_base[pair * 2]; 234 } 235 236 // Return the upper bound of a sub-range expressed as a tree. PAIR is 237 // the sub-range in question. 238 239 inline tree 240 irange::tree_upper_bound (unsigned pair) const 241 { 242 return m_base[pair * 2 + 1]; 243 } 244 245 // Return the highest bound of a range expressed as a tree. 246 247 inline tree 248 irange::tree_upper_bound () const 249 { 250 gcc_checking_assert (m_num_ranges); 251 return tree_upper_bound (m_num_ranges - 1); 252 } 253 254 inline tree 255 irange::min () const 256 { 257 return tree_lower_bound (0); 258 } 259 260 inline tree 261 irange::max () const 262 { 263 if (m_num_ranges) 264 return tree_upper_bound (); 265 else 266 return NULL; 267 } 268 269 inline bool 270 irange::varying_compatible_p () const 271 { 272 if (m_num_ranges != 1) 273 return false; 274 275 tree l = m_base[0]; 276 tree u = m_base[1]; 277 tree t = TREE_TYPE (l); 278 279 if (m_kind == VR_VARYING && t == error_mark_node) 280 return true; 281 282 unsigned prec = TYPE_PRECISION (t); 283 signop sign = TYPE_SIGN (t); 284 if (INTEGRAL_TYPE_P (t)) 285 return (wi::to_wide (l) == wi::min_value (prec, sign) 286 && wi::to_wide (u) == wi::max_value (prec, sign)); 287 if (POINTER_TYPE_P (t)) 288 return (wi::to_wide (l) == 0 289 && wi::to_wide (u) == wi::max_value (prec, sign)); 290 return true; 291 } 292 293 inline bool 294 irange::varying_p () const 295 { 296 return m_kind == VR_VARYING; 297 } 298 299 inline bool 300 irange::undefined_p () const 301 { 302 return m_kind == VR_UNDEFINED; 303 } 304 305 inline bool 306 irange::zero_p () const 307 { 308 return (m_kind == VR_RANGE && m_num_ranges == 1 309 && integer_zerop (tree_lower_bound (0)) 310 && integer_zerop (tree_upper_bound (0))); 311 } 312 313 inline bool 314 irange::nonzero_p () const 315 { 316 if (undefined_p ()) 317 return false; 318 319 tree zero = build_zero_cst (type ()); 320 return *this == int_range<1> (zero, zero, VR_ANTI_RANGE); 321 } 322 323 inline bool 324 irange::supports_type_p (tree type) 325 { 326 if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))) 327 return type; 328 return false; 329 } 330 331 inline bool 332 range_includes_zero_p (const irange *vr) 333 { 334 if (vr->undefined_p ()) 335 return false; 336 337 if (vr->varying_p ()) 338 return true; 339 340 return vr->may_contain_p (build_zero_cst (vr->type ())); 341 } 342 343 inline void 344 gt_ggc_mx (irange *x) 345 { 346 for (unsigned i = 0; i < x->m_num_ranges; ++i) 347 { 348 gt_ggc_mx (x->m_base[i * 2]); 349 gt_ggc_mx (x->m_base[i * 2 + 1]); 350 } 351 } 352 353 inline void 354 gt_pch_nx (irange *x) 355 { 356 for (unsigned i = 0; i < x->m_num_ranges; ++i) 357 { 358 gt_pch_nx (x->m_base[i * 2]); 359 gt_pch_nx (x->m_base[i * 2 + 1]); 360 } 361 } 362 363 inline void 364 gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie) 365 { 366 for (unsigned i = 0; i < x->m_num_ranges; ++i) 367 { 368 op (&x->m_base[i * 2], NULL, cookie); 369 op (&x->m_base[i * 2 + 1], NULL, cookie); 370 } 371 } 372 373 template<unsigned N> 374 inline void 375 gt_ggc_mx (int_range<N> *x) 376 { 377 gt_ggc_mx ((irange *) x); 378 } 379 380 template<unsigned N> 381 inline void 382 gt_pch_nx (int_range<N> *x) 383 { 384 gt_pch_nx ((irange *) x); 385 } 386 387 template<unsigned N> 388 inline void 389 gt_pch_nx (int_range<N> *x, gt_pointer_operator op, void *cookie) 390 { 391 gt_pch_nx ((irange *) x, op, cookie); 392 } 393 394 // Constructors for irange 395 396 inline 397 irange::irange (tree *base, unsigned nranges) 398 { 399 m_base = base; 400 m_num_ranges = 0; 401 m_max_ranges = nranges; 402 m_kind = VR_UNDEFINED; 403 } 404 405 // Constructors for int_range<>. 406 407 template<unsigned N> 408 inline 409 int_range<N>::int_range () 410 : irange (m_ranges, N) 411 { 412 } 413 414 template<unsigned N> 415 int_range<N>::int_range (const int_range &other) 416 : irange (m_ranges, N) 417 { 418 irange::operator= (other); 419 } 420 421 template<unsigned N> 422 int_range<N>::int_range (tree min, tree max, value_range_kind kind) 423 : irange (m_ranges, N) 424 { 425 irange::set (min, max, kind); 426 } 427 428 template<unsigned N> 429 int_range<N>::int_range (tree type) 430 : irange (m_ranges, N) 431 { 432 set_varying (type); 433 } 434 435 template<unsigned N> 436 int_range<N>::int_range (tree type, const wide_int &wmin, const wide_int &wmax, 437 value_range_kind kind) 438 : irange (m_ranges, N) 439 { 440 tree min = wide_int_to_tree (type, wmin); 441 tree max = wide_int_to_tree (type, wmax); 442 set (min, max, kind); 443 } 444 445 template<unsigned N> 446 int_range<N>::int_range (const irange &other) 447 : irange (m_ranges, N) 448 { 449 irange::operator= (other); 450 } 451 452 template<unsigned N> 453 int_range<N>& 454 int_range<N>::operator= (const int_range &src) 455 { 456 irange::operator= (src); 457 return *this; 458 } 459 460 inline void 461 irange::set (tree val) 462 { 463 set (val, val); 464 } 465 466 inline void 467 irange::set_undefined () 468 { 469 m_kind = VR_UNDEFINED; 470 m_num_ranges = 0; 471 } 472 473 inline void 474 irange::set_varying (tree type) 475 { 476 m_kind = VR_VARYING; 477 m_num_ranges = 1; 478 479 if (INTEGRAL_TYPE_P (type)) 480 { 481 // Strict enum's require varying to be not TYPE_MIN/MAX, but rather 482 // min_value and max_value. 483 wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)); 484 wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); 485 if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type))) 486 && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type)))) 487 { 488 m_base[0] = TYPE_MIN_VALUE (type); 489 m_base[1] = TYPE_MAX_VALUE (type); 490 } 491 else 492 { 493 m_base[0] = wide_int_to_tree (type, min); 494 m_base[1] = wide_int_to_tree (type, max); 495 } 496 } 497 else if (POINTER_TYPE_P (type)) 498 { 499 m_base[0] = build_int_cst (type, 0); 500 m_base[1] = build_int_cst (type, -1); 501 } 502 else 503 m_base[0] = m_base[1] = error_mark_node; 504 } 505 506 inline bool 507 irange::operator== (const irange &r) const 508 { 509 return equal_p (r); 510 } 511 512 // Return the lower bound of a sub-range. PAIR is the sub-range in 513 // question. 514 515 inline wide_int 516 irange::lower_bound (unsigned pair) const 517 { 518 if (legacy_mode_p ()) 519 return legacy_lower_bound (pair); 520 gcc_checking_assert (m_num_ranges > 0); 521 gcc_checking_assert (pair + 1 <= num_pairs ()); 522 return wi::to_wide (tree_lower_bound (pair)); 523 } 524 525 // Return the upper bound of a sub-range. PAIR is the sub-range in 526 // question. 527 528 inline wide_int 529 irange::upper_bound (unsigned pair) const 530 { 531 if (legacy_mode_p ()) 532 return legacy_upper_bound (pair); 533 gcc_checking_assert (m_num_ranges > 0); 534 gcc_checking_assert (pair + 1 <= num_pairs ()); 535 return wi::to_wide (tree_upper_bound (pair)); 536 } 537 538 // Return the highest bound of a range. 539 540 inline wide_int 541 irange::upper_bound () const 542 { 543 unsigned pairs = num_pairs (); 544 gcc_checking_assert (pairs > 0); 545 return upper_bound (pairs - 1); 546 } 547 548 inline void 549 irange::union_ (const irange &r) 550 { 551 dump_flags_t m_flags = dump_flags; 552 dump_flags &= ~TDF_DETAILS; 553 irange::union_ (&r); 554 dump_flags = m_flags; 555 } 556 557 inline void 558 irange::intersect (const irange &r) 559 { 560 dump_flags_t m_flags = dump_flags; 561 dump_flags &= ~TDF_DETAILS; 562 irange::intersect (&r); 563 dump_flags = m_flags; 564 } 565 566 // Set value range VR to a nonzero range of type TYPE. 567 568 inline void 569 irange::set_nonzero (tree type) 570 { 571 tree zero = build_int_cst (type, 0); 572 if (legacy_mode_p ()) 573 set (zero, zero, VR_ANTI_RANGE); 574 else 575 irange_set_anti_range (zero, zero); 576 } 577 578 // Set value range VR to a ZERO range of type TYPE. 579 580 inline void 581 irange::set_zero (tree type) 582 { 583 tree z = build_int_cst (type, 0); 584 if (legacy_mode_p ()) 585 set (z); 586 else 587 irange_set (z, z); 588 } 589 590 // Normalize a range to VARYING or UNDEFINED if possible. 591 592 inline void 593 irange::normalize_kind () 594 { 595 if (m_num_ranges == 0) 596 m_kind = VR_UNDEFINED; 597 else if (varying_compatible_p ()) 598 { 599 if (m_kind == VR_RANGE) 600 m_kind = VR_VARYING; 601 else if (m_kind == VR_ANTI_RANGE) 602 set_undefined (); 603 else 604 gcc_unreachable (); 605 } 606 } 607 608 inline bool 609 contains_zero_p (const irange &r) 610 { 611 if (r.undefined_p ()) 612 return false; 613 614 tree zero = build_zero_cst (r.type ()); 615 return r.contains_p (zero); 616 } 617 618 // Return the maximum value for TYPE. 619 620 inline tree 621 vrp_val_max (const_tree type) 622 { 623 if (INTEGRAL_TYPE_P (type)) 624 return TYPE_MAX_VALUE (type); 625 if (POINTER_TYPE_P (type)) 626 { 627 wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); 628 return wide_int_to_tree (const_cast<tree> (type), max); 629 } 630 return NULL_TREE; 631 } 632 633 // Return the minimum value for TYPE. 634 635 inline tree 636 vrp_val_min (const_tree type) 637 { 638 if (INTEGRAL_TYPE_P (type)) 639 return TYPE_MIN_VALUE (type); 640 if (POINTER_TYPE_P (type)) 641 return build_zero_cst (const_cast<tree> (type)); 642 return NULL_TREE; 643 } 644 645 // This is the irange storage class. It is used to allocate the 646 // minimum amount of storage needed for a given irange. Storage is 647 // automatically freed at destruction of the storage class. 648 // 649 // It is meant for long term storage, as opposed to int_range_max 650 // which is meant for intermediate temporary results on the stack. 651 // 652 // The newly allocated irange is initialized to the empty set 653 // (undefined_p() is true). 654 655 class irange_allocator 656 { 657 public: 658 irange_allocator (); 659 ~irange_allocator (); 660 // Return a new range with NUM_PAIRS. 661 irange *allocate (unsigned num_pairs); 662 // Return a copy of SRC with the minimum amount of sub-ranges needed 663 // to represent it. 664 irange *allocate (const irange &src); 665 void *get_memory (unsigned num_bytes); 666 private: 667 DISABLE_COPY_AND_ASSIGN (irange_allocator); 668 struct obstack m_obstack; 669 }; 670 671 inline 672 irange_allocator::irange_allocator () 673 { 674 obstack_init (&m_obstack); 675 } 676 677 inline 678 irange_allocator::~irange_allocator () 679 { 680 obstack_free (&m_obstack, NULL); 681 } 682 683 // Provide a hunk of memory from the obstack. 684 inline void * 685 irange_allocator::get_memory (unsigned num_bytes) 686 { 687 void *r = obstack_alloc (&m_obstack, num_bytes); 688 return r; 689 } 690 691 // Return a new range with NUM_PAIRS. 692 693 inline irange * 694 irange_allocator::allocate (unsigned num_pairs) 695 { 696 // Never allocate 0 pairs. 697 // Don't allocate 1 either, or we get legacy value_range's. 698 if (num_pairs < 2) 699 num_pairs = 2; 700 701 size_t nbytes = sizeof (tree) * 2 * num_pairs; 702 703 // Allocate the irange and required memory for the vector. 704 void *r = obstack_alloc (&m_obstack, sizeof (irange)); 705 tree *mem = (tree *) obstack_alloc (&m_obstack, nbytes); 706 return new (r) irange (mem, num_pairs); 707 } 708 709 inline irange * 710 irange_allocator::allocate (const irange &src) 711 { 712 irange *r = allocate (src.num_pairs ()); 713 *r = src; 714 return r; 715 } 716 717 #endif // GCC_VALUE_RANGE_H 718