arm: fix typo in dg-require-effective-target [PR118089]
[official-gcc.git] / gcc / analyzer / constraint-manager.cc
blob55d8996bc7b283db203d1972e7239d7970202079
1 /* Tracking equivalence classes and constraints at a point on an execution path.
2 Copyright (C) 2019-2025 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #define INCLUDE_VECTOR
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "function.h"
27 #include "basic-block.h"
28 #include "gimple.h"
29 #include "gimple-iterator.h"
30 #include "fold-const.h"
31 #include "selftest.h"
32 #include "diagnostic-core.h"
33 #include "graphviz.h"
34 #include "analyzer/analyzer.h"
35 #include "ordered-hash-map.h"
36 #include "options.h"
37 #include "cgraph.h"
38 #include "cfg.h"
39 #include "digraph.h"
40 #include "analyzer/supergraph.h"
41 #include "sbitmap.h"
42 #include "bitmap.h"
43 #include "analyzer/analyzer-logging.h"
44 #include "analyzer/call-string.h"
45 #include "analyzer/program-point.h"
46 #include "analyzer/store.h"
47 #include "analyzer/region-model.h"
48 #include "analyzer/constraint-manager.h"
49 #include "analyzer/call-summary.h"
50 #include "analyzer/analyzer-selftests.h"
51 #include "tree-pretty-print.h"
52 #include "make-unique.h"
54 #if ENABLE_ANALYZER
56 namespace ana {
58 tristate
59 compare_constants (tree lhs_const, enum tree_code op, tree rhs_const)
61 tree comparison
62 = fold_binary (op, boolean_type_node, lhs_const, rhs_const);
63 if (comparison == boolean_true_node)
64 return tristate (tristate::TS_TRUE);
65 if (comparison == boolean_false_node)
66 return tristate (tristate::TS_FALSE);
67 return tristate (tristate::TS_UNKNOWN);
70 /* Return true iff CST is below the maximum value for its type. */
72 static bool
73 can_plus_one_p (tree cst)
75 gcc_assert (CONSTANT_CLASS_P (cst));
76 return tree_int_cst_lt (cst, TYPE_MAX_VALUE (TREE_TYPE (cst)));
79 /* Return (CST + 1). */
81 static tree
82 plus_one (tree cst)
84 gcc_assert (CONSTANT_CLASS_P (cst));
85 gcc_assert (can_plus_one_p (cst));
86 tree result = fold_build2 (PLUS_EXPR, TREE_TYPE (cst),
87 cst, integer_one_node);
88 gcc_assert (CONSTANT_CLASS_P (result));
89 return result;
92 /* Return true iff CST is above the minimum value for its type. */
94 static bool
95 can_minus_one_p (tree cst)
97 gcc_assert (CONSTANT_CLASS_P (cst));
98 return tree_int_cst_lt (TYPE_MIN_VALUE (TREE_TYPE (cst)), cst);
101 /* Return (CST - 1). */
103 static tree
104 minus_one (tree cst)
106 gcc_assert (CONSTANT_CLASS_P (cst));
107 gcc_assert (can_minus_one_p (cst));
108 tree result = fold_build2 (MINUS_EXPR, TREE_TYPE (cst),
109 cst, integer_one_node);
110 gcc_assert (CONSTANT_CLASS_P (result));
111 return result;
114 /* struct bound. */
116 /* Ensure that this bound is closed by converting an open bound to a
117 closed one. */
119 void
120 bound::ensure_closed (enum bound_kind bound_kind)
122 if (!m_closed)
124 /* Offset by 1 in the appropriate direction.
125 For example, convert 3 < x into 4 <= x,
126 and convert x < 5 into x <= 4. */
127 gcc_assert (CONSTANT_CLASS_P (m_constant));
128 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (m_constant)));
129 m_constant = fold_build2 (bound_kind == BK_UPPER ? MINUS_EXPR : PLUS_EXPR,
130 TREE_TYPE (m_constant),
131 m_constant, integer_one_node);
132 gcc_assert (CONSTANT_CLASS_P (m_constant));
133 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (m_constant)));
134 m_closed = true;
138 /* Get "<=" vs "<" for this bound. */
140 const char *
141 bound::get_relation_as_str () const
143 if (m_closed)
144 return "<=";
145 else
146 return "<";
149 /* struct range. */
151 /* Dump this range to PP, which must support %E for tree. */
153 void
154 range::dump_to_pp (pretty_printer *pp) const
156 if (m_lower_bound.m_constant)
158 if (m_upper_bound.m_constant)
159 pp_printf (pp, "%qE %s x %s %qE",
160 m_lower_bound.m_constant,
161 m_lower_bound.get_relation_as_str (),
162 m_upper_bound.get_relation_as_str (),
163 m_upper_bound.m_constant);
164 else
165 pp_printf (pp, "%qE %s x",
166 m_lower_bound.m_constant,
167 m_lower_bound.get_relation_as_str ());
169 else
171 if (m_upper_bound.m_constant)
172 pp_printf (pp, "x %s %qE",
173 m_upper_bound.get_relation_as_str (),
174 m_upper_bound.m_constant);
175 else
176 pp_string (pp, "x");
180 /* Dump this range to stderr. */
182 DEBUG_FUNCTION void
183 range::dump () const
185 tree_dump_pretty_printer pp (stderr);
186 dump_to_pp (&pp);
187 pp_newline (&pp);
190 /* Determine if there is only one possible value for this range.
191 If so, return the constant; otherwise, return NULL_TREE. */
193 tree
194 range::constrained_to_single_element ()
196 if (m_lower_bound.m_constant == NULL_TREE
197 || m_upper_bound.m_constant == NULL_TREE)
198 return NULL_TREE;
200 if (!INTEGRAL_TYPE_P (TREE_TYPE (m_lower_bound.m_constant)))
201 return NULL_TREE;
202 if (!INTEGRAL_TYPE_P (TREE_TYPE (m_upper_bound.m_constant)))
203 return NULL_TREE;
205 /* Convert any open bounds to closed bounds. */
206 m_lower_bound.ensure_closed (BK_LOWER);
207 m_upper_bound.ensure_closed (BK_UPPER);
209 // Are they equal?
210 tree comparison = fold_binary (EQ_EXPR, boolean_type_node,
211 m_lower_bound.m_constant,
212 m_upper_bound.m_constant);
213 if (comparison == boolean_true_node)
214 return m_lower_bound.m_constant;
215 else
216 return NULL_TREE;
219 /* Eval the condition "X OP RHS_CONST" for X within the range. */
221 tristate
222 range::eval_condition (enum tree_code op, tree rhs_const) const
224 range copy (*this);
225 if (tree single_element = copy.constrained_to_single_element ())
226 return compare_constants (single_element, op, rhs_const);
228 switch (op)
230 case EQ_EXPR:
231 if (below_lower_bound (rhs_const))
232 return tristate (tristate::TS_FALSE);
233 if (above_upper_bound (rhs_const))
234 return tristate (tristate::TS_FALSE);
235 break;
237 case LT_EXPR:
238 case LE_EXPR:
239 /* Qn: "X </<= RHS_CONST". */
240 /* If RHS_CONST > upper bound, then it's true.
241 If RHS_CONST < lower bound, then it's false.
242 Otherwise unknown. */
243 if (above_upper_bound (rhs_const))
244 return tristate (tristate::TS_TRUE);
245 if (below_lower_bound (rhs_const))
246 return tristate (tristate::TS_FALSE);
247 break;
249 case NE_EXPR:
250 /* Qn: "X != RHS_CONST". */
251 /* If RHS_CONST < lower bound, then it's true.
252 If RHS_CONST > upper bound, then it's false.
253 Otherwise unknown. */
254 if (below_lower_bound (rhs_const))
255 return tristate (tristate::TS_TRUE);
256 if (above_upper_bound (rhs_const))
257 return tristate (tristate::TS_TRUE);
258 break;
260 case GE_EXPR:
261 case GT_EXPR:
262 /* Qn: "X >=/> RHS_CONST". */
263 if (above_upper_bound (rhs_const))
264 return tristate (tristate::TS_FALSE);
265 if (below_lower_bound (rhs_const))
266 return tristate (tristate::TS_TRUE);
267 break;
269 default:
270 gcc_unreachable ();
271 break;
273 return tristate (tristate::TS_UNKNOWN);
276 /* Return true if RHS_CONST is below the lower bound of this range. */
278 bool
279 range::below_lower_bound (tree rhs_const) const
281 if (!m_lower_bound.m_constant)
282 return false;
284 return compare_constants (rhs_const,
285 m_lower_bound.m_closed ? LT_EXPR : LE_EXPR,
286 m_lower_bound.m_constant).is_true ();
289 /* Return true if RHS_CONST is above the upper bound of this range. */
291 bool
292 range::above_upper_bound (tree rhs_const) const
294 if (!m_upper_bound.m_constant)
295 return false;
297 return compare_constants (rhs_const,
298 m_upper_bound.m_closed ? GT_EXPR : GE_EXPR,
299 m_upper_bound.m_constant).is_true ();
302 /* Attempt to add B to the bound of the given kind of this range.
303 Return true if feasible; false if infeasible. */
305 bool
306 range::add_bound (bound b, enum bound_kind bound_kind)
308 /* Bail out on floating point constants. */
309 if (!INTEGRAL_TYPE_P (TREE_TYPE (b.m_constant)))
310 return true;
312 b.ensure_closed (bound_kind);
314 switch (bound_kind)
316 default:
317 gcc_unreachable ();
318 case BK_LOWER:
319 /* Discard redundant bounds. */
320 if (m_lower_bound.m_constant)
322 m_lower_bound.ensure_closed (BK_LOWER);
323 if (tree_int_cst_le (b.m_constant,
324 m_lower_bound.m_constant))
325 return true;
327 if (m_upper_bound.m_constant)
329 m_upper_bound.ensure_closed (BK_UPPER);
330 /* Reject B <= V <= UPPER when B > UPPER. */
331 if (!tree_int_cst_le (b.m_constant,
332 m_upper_bound.m_constant))
333 return false;
335 m_lower_bound = b;
336 break;
338 case BK_UPPER:
339 /* Discard redundant bounds. */
340 if (m_upper_bound.m_constant)
342 m_upper_bound.ensure_closed (BK_UPPER);
343 if (!tree_int_cst_lt (b.m_constant,
344 m_upper_bound.m_constant))
345 return true;
347 if (m_lower_bound.m_constant)
349 m_lower_bound.ensure_closed (BK_LOWER);
350 /* Reject LOWER <= V <= B when LOWER > B. */
351 if (!tree_int_cst_le (m_lower_bound.m_constant,
352 b.m_constant))
353 return false;
355 m_upper_bound = b;
356 break;
359 return true;
362 /* Attempt to add (RANGE OP RHS_CONST) as a bound to this range.
363 Return true if feasible; false if infeasible. */
365 bool
366 range::add_bound (enum tree_code op, tree rhs_const)
368 switch (op)
370 default:
371 return true;
372 case LT_EXPR:
373 /* "V < RHS_CONST" */
374 return add_bound (bound (rhs_const, false), BK_UPPER);
375 case LE_EXPR:
376 /* "V <= RHS_CONST" */
377 return add_bound (bound (rhs_const, true), BK_UPPER);
378 case GE_EXPR:
379 /* "V >= RHS_CONST" */
380 return add_bound (bound (rhs_const, true), BK_LOWER);
381 case GT_EXPR:
382 /* "V > RHS_CONST" */
383 return add_bound (bound (rhs_const, false), BK_LOWER);
387 /* struct bounded_range. */
389 bounded_range::bounded_range (const_tree lower, const_tree upper)
390 : m_lower (const_cast<tree> (lower)),
391 m_upper (const_cast<tree> (upper))
393 if (lower && upper)
395 gcc_assert (TREE_CODE (m_lower) == INTEGER_CST);
396 gcc_assert (TREE_CODE (m_upper) == INTEGER_CST);
397 /* We should have lower <= upper. */
398 gcc_assert (!tree_int_cst_lt (m_upper, m_lower));
400 else
402 /* Purely for pending on-stack values, for
403 writing back to. */
404 gcc_assert (m_lower == NULL_TREE);
405 gcc_assert (m_lower == NULL_TREE);
409 static void
410 dump_cst (pretty_printer *pp, tree cst, bool show_types)
412 gcc_assert (cst);
413 if (show_types)
415 pp_character (pp, '(');
416 dump_generic_node (pp, TREE_TYPE (cst), 0, (dump_flags_t)0, false);
417 pp_character (pp, ')');
419 dump_generic_node (pp, cst, 0, (dump_flags_t)0, false);
422 /* Dump this object to PP. */
424 void
425 bounded_range::dump_to_pp (pretty_printer *pp, bool show_types) const
427 if (singleton_p ())
428 dump_cst (pp, m_lower, show_types);
429 else
431 pp_character (pp, '[');
432 dump_cst (pp, m_lower, show_types);
433 pp_string (pp, ", ");
434 dump_cst (pp, m_upper, show_types);
435 pp_character (pp, ']');
439 /* Dump this object to stderr. */
441 void
442 bounded_range::dump (bool show_types) const
444 tree_dump_pretty_printer pp (stderr);
445 dump_to_pp (&pp, show_types);
446 pp_newline (&pp);
449 std::unique_ptr<json::object>
450 bounded_range::to_json () const
452 auto range_obj = ::make_unique<json::object> ();
453 set_json_attr (*range_obj, "lower", m_lower);
454 set_json_attr (*range_obj, "upper", m_upper);
455 return range_obj;
458 std::unique_ptr<text_art::widget>
459 bounded_range::make_dump_widget (const text_art::dump_widget_info &dwi) const
461 using text_art::tree_widget;
462 return tree_widget::from_fmt (dwi, default_tree_printer,
463 "%qE ... %qE", m_lower, m_upper);
466 /* Subroutine of bounded_range::to_json. */
468 void
469 bounded_range::set_json_attr (json::object &obj, const char *name, tree value)
471 pretty_printer pp;
472 pp_format_decoder (&pp) = default_tree_printer;
473 pp_printf (&pp, "%E", value);
474 obj.set_string (name, pp_formatted_text (&pp));
478 /* Return true iff CST is within this range. */
480 bool
481 bounded_range::contains_p (tree cst) const
483 /* Reject if below lower bound. */
484 if (tree_int_cst_lt (cst, m_lower))
485 return false;
486 /* Reject if above lower bound. */
487 if (tree_int_cst_lt (m_upper, cst))
488 return false;
489 return true;
492 /* If this range intersects OTHER, return true, writing
493 the intersection to *OUT if OUT is non-NULL.
494 Return false if they do not intersect. */
496 bool
497 bounded_range::intersects_p (const bounded_range &other,
498 bounded_range *out) const
500 const tree max_lower
501 = (tree_int_cst_le (m_lower, other.m_lower)
502 ? other.m_lower : m_lower);
503 gcc_assert (TREE_CODE (max_lower) == INTEGER_CST);
504 const tree min_upper
505 = (tree_int_cst_le (m_upper, other.m_upper)
506 ? m_upper : other.m_upper);
507 gcc_assert (TREE_CODE (min_upper) == INTEGER_CST);
509 if (tree_int_cst_le (max_lower, min_upper))
511 if (out)
512 *out = bounded_range (max_lower, min_upper);
513 return true;
515 else
516 return false;
519 bool
520 bounded_range::operator== (const bounded_range &other) const
522 return (TREE_TYPE (m_lower) == TREE_TYPE (other.m_lower)
523 && TREE_TYPE (m_upper) == TREE_TYPE (other.m_upper)
524 && tree_int_cst_equal (m_lower, other.m_lower)
525 && tree_int_cst_equal (m_upper, other.m_upper));
529 bounded_range::cmp (const bounded_range &br1, const bounded_range &br2)
531 if (int cmp_lower = tree_int_cst_compare (br1.m_lower,
532 br2.m_lower))
533 return cmp_lower;
534 return tree_int_cst_compare (br1.m_upper, br2.m_upper);
537 /* struct bounded_ranges. */
539 /* Construct a bounded_ranges instance from a single range. */
541 bounded_ranges::bounded_ranges (const bounded_range &range)
542 : m_ranges (1)
544 m_ranges.quick_push (range);
545 canonicalize ();
546 validate ();
549 /* Construct a bounded_ranges instance from multiple ranges. */
551 bounded_ranges::bounded_ranges (const vec<bounded_range> &ranges)
552 : m_ranges (ranges.length ())
554 m_ranges.safe_splice (ranges);
555 canonicalize ();
556 validate ();
559 /* Construct a bounded_ranges instance for values of LHS for which
560 (LHS OP RHS_CONST) is true (e.g. "(LHS > 3)". */
562 bounded_ranges::bounded_ranges (enum tree_code op, tree rhs_const)
563 : m_ranges ()
565 gcc_assert (TREE_CODE (rhs_const) == INTEGER_CST);
566 tree type = TREE_TYPE (rhs_const);
567 switch (op)
569 default:
570 gcc_unreachable ();
571 case EQ_EXPR:
572 m_ranges.safe_push (bounded_range (rhs_const, rhs_const));
573 break;
575 case GE_EXPR:
576 m_ranges.safe_push (bounded_range (rhs_const, TYPE_MAX_VALUE (type)));
577 break;
579 case LE_EXPR:
580 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type), rhs_const));
581 break;
583 case NE_EXPR:
584 if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const))
585 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type),
586 minus_one (rhs_const)));
587 if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type)))
588 m_ranges.safe_push (bounded_range (plus_one (rhs_const),
589 TYPE_MAX_VALUE (type)));
590 break;
591 case GT_EXPR:
592 if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type)))
593 m_ranges.safe_push (bounded_range (plus_one (rhs_const),
594 TYPE_MAX_VALUE (type)));
595 break;
596 case LT_EXPR:
597 if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const))
598 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type),
599 minus_one (rhs_const)));
600 break;
602 canonicalize ();
603 validate ();
606 /* Subroutine of ctors for fixing up m_ranges.
607 Also, initialize m_hash. */
609 void
610 bounded_ranges::canonicalize ()
612 /* Sort the ranges. */
613 m_ranges.qsort ([](const void *p1, const void *p2) -> int
615 const bounded_range &br1 = *(const bounded_range *)p1;
616 const bounded_range &br2 = *(const bounded_range *)p2;
617 return bounded_range::cmp (br1, br2);
620 /* Merge ranges that are touching or overlapping. */
621 for (unsigned i = 1; i < m_ranges.length (); )
623 bounded_range *prev = &m_ranges[i - 1];
624 const bounded_range *next = &m_ranges[i];
625 if (prev->intersects_p (*next, NULL)
626 || (can_plus_one_p (prev->m_upper)
627 && tree_int_cst_equal (plus_one (prev->m_upper),
628 next->m_lower)))
630 prev->m_upper = next->m_upper;
631 m_ranges.ordered_remove (i);
633 else
634 i++;
637 /* Initialize m_hash. */
638 inchash::hash hstate (0);
639 for (const auto &iter : m_ranges)
641 inchash::add_expr (iter.m_lower, hstate);
642 inchash::add_expr (iter.m_upper, hstate);
644 m_hash = hstate.end ();
647 /* Assert that this object is valid. */
649 void
650 bounded_ranges::validate () const
652 /* Skip this in a release build. */
653 #if !CHECKING_P
654 return;
655 #endif
657 for (unsigned i = 1; i < m_ranges.length (); i++)
659 const bounded_range &prev = m_ranges[i - 1];
660 const bounded_range &next = m_ranges[i];
662 /* Give up if we somehow have incompatible different types. */
663 if (!types_compatible_p (TREE_TYPE (prev.m_upper),
664 TREE_TYPE (next.m_lower)))
665 continue;
667 /* Verify sorted. */
668 gcc_assert (tree_int_cst_lt (prev.m_upper, next.m_lower));
670 gcc_assert (can_plus_one_p (prev.m_upper));
671 /* otherwise there's no room for "next". */
673 /* Verify no ranges touch each other. */
674 gcc_assert (tree_int_cst_lt (plus_one (prev.m_upper), next.m_lower));
678 /* bounded_ranges equality operator. */
680 bool
681 bounded_ranges::operator== (const bounded_ranges &other) const
683 if (m_ranges.length () != other.m_ranges.length ())
684 return false;
685 for (unsigned i = 0; i < m_ranges.length (); i++)
687 if (m_ranges[i] != other.m_ranges[i])
688 return false;
690 return true;
693 /* Dump this object to PP. */
695 void
696 bounded_ranges::dump_to_pp (pretty_printer *pp, bool show_types) const
698 pp_character (pp, '{');
699 for (unsigned i = 0; i < m_ranges.length (); ++i)
701 if (i > 0)
702 pp_string (pp, ", ");
703 m_ranges[i].dump_to_pp (pp, show_types);
705 pp_character (pp, '}');
708 /* Dump this object to stderr. */
710 DEBUG_FUNCTION void
711 bounded_ranges::dump (bool show_types) const
713 tree_dump_pretty_printer pp (stderr);
714 dump_to_pp (&pp, show_types);
715 pp_newline (&pp);
718 std::unique_ptr<json::value>
719 bounded_ranges::to_json () const
721 auto arr_obj = ::make_unique<json::array> ();
723 for (unsigned i = 0; i < m_ranges.length (); ++i)
724 arr_obj->append (m_ranges[i].to_json ());
726 return arr_obj;
729 void
730 bounded_ranges::add_to_dump_widget (text_art::tree_widget &parent,
731 const text_art::dump_widget_info &dwi) const
733 for (auto &range : m_ranges)
734 parent.add_child (range.make_dump_widget (dwi));
737 /* Determine whether (X OP RHS_CONST) is known to be true or false
738 for all X in the ranges expressed by this object. */
740 tristate
741 bounded_ranges::eval_condition (enum tree_code op,
742 tree rhs_const,
743 bounded_ranges_manager *mgr) const
745 /* Convert (X OP RHS_CONST) to a bounded_ranges instance and find
746 the intersection of that with this object. */
747 bounded_ranges other (op, rhs_const);
748 const bounded_ranges *intersection
749 = mgr->get_or_create_intersection (this, &other);
751 if (intersection->m_ranges.length () > 0)
753 /* We can use pointer equality to check for equality,
754 due to instance consolidation. */
755 if (intersection == this)
756 return tristate (tristate::TS_TRUE);
757 else
758 return tristate (tristate::TS_UNKNOWN);
760 else
761 /* No intersection. */
762 return tristate (tristate::TS_FALSE);
765 /* Return true if CST is within any of the ranges. */
767 bool
768 bounded_ranges::contain_p (tree cst) const
770 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
771 for (const auto &iter : m_ranges)
773 /* TODO: should we optimize this based on sorting? */
774 if (iter.contains_p (cst))
775 return true;
777 return false;
781 bounded_ranges::cmp (const bounded_ranges *a, const bounded_ranges *b)
783 if (int cmp_length = ((int)a->m_ranges.length ()
784 - (int)b->m_ranges.length ()))
785 return cmp_length;
786 for (unsigned i = 0; i < a->m_ranges.length (); i++)
788 if (int cmp_range = bounded_range::cmp (a->m_ranges[i], b->m_ranges[i]))
789 return cmp_range;
791 /* They are equal. They ought to have been consolidated, so we should
792 have two pointers to the same object. */
793 gcc_assert (a == b);
794 return 0;
797 /* class bounded_ranges_manager. */
799 /* bounded_ranges_manager's dtor. */
801 bounded_ranges_manager::~bounded_ranges_manager ()
803 /* Delete the managed objects. */
804 for (const auto &iter : m_map)
805 delete iter.second;
808 /* Get the bounded_ranges instance for the empty set, creating it if
809 necessary. */
811 const bounded_ranges *
812 bounded_ranges_manager::get_or_create_empty ()
814 auto_vec<bounded_range> empty_vec;
816 return consolidate (new bounded_ranges (empty_vec));
819 /* Get the bounded_ranges instance for {CST}, creating it if necessary. */
821 const bounded_ranges *
822 bounded_ranges_manager::get_or_create_point (const_tree cst)
824 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
826 return get_or_create_range (cst, cst);
829 /* Get the bounded_ranges instance for {[LOWER_BOUND..UPPER_BOUND]},
830 creating it if necessary. */
832 const bounded_ranges *
833 bounded_ranges_manager::get_or_create_range (const_tree lower_bound,
834 const_tree upper_bound)
836 gcc_assert (TREE_CODE (lower_bound) == INTEGER_CST);
837 gcc_assert (TREE_CODE (upper_bound) == INTEGER_CST);
839 return consolidate
840 (new bounded_ranges (bounded_range (lower_bound, upper_bound)));
843 /* Get the bounded_ranges instance for the union of OTHERS,
844 creating it if necessary. */
846 const bounded_ranges *
847 bounded_ranges_manager::
848 get_or_create_union (const vec <const bounded_ranges *> &others)
850 auto_vec<bounded_range> ranges;
851 for (const auto &r : others)
852 ranges.safe_splice (r->m_ranges);
853 return consolidate (new bounded_ranges (ranges));
856 /* Get the bounded_ranges instance for the intersection of A and B,
857 creating it if necessary. */
859 const bounded_ranges *
860 bounded_ranges_manager::get_or_create_intersection (const bounded_ranges *a,
861 const bounded_ranges *b)
863 auto_vec<bounded_range> ranges;
864 unsigned a_idx = 0;
865 unsigned b_idx = 0;
866 while (a_idx < a->m_ranges.length ()
867 && b_idx < b->m_ranges.length ())
869 const bounded_range &r_a = a->m_ranges[a_idx];
870 const bounded_range &r_b = b->m_ranges[b_idx];
872 bounded_range intersection (NULL_TREE, NULL_TREE);
873 if (r_a.intersects_p (r_b, &intersection))
875 ranges.safe_push (intersection);
877 if (tree_int_cst_lt (r_a.m_lower, r_b.m_lower))
879 a_idx++;
881 else
883 if (tree_int_cst_lt (r_a.m_upper, r_b.m_upper))
884 a_idx++;
885 else
886 b_idx++;
890 return consolidate (new bounded_ranges (ranges));
893 /* Get the bounded_ranges instance for the inverse of OTHER relative
894 to TYPE, creating it if necessary.
895 This is for use when handling "default" in switch statements, where
896 OTHER represents all the other cases. */
898 const bounded_ranges *
899 bounded_ranges_manager::get_or_create_inverse (const bounded_ranges *other,
900 tree type)
902 tree min_val = TYPE_MIN_VALUE (type);
903 tree max_val = TYPE_MAX_VALUE (type);
904 if (other->m_ranges.length () == 0)
905 return get_or_create_range (min_val, max_val);
906 auto_vec<bounded_range> ranges;
907 tree first_lb = other->m_ranges[0].m_lower;
908 if (tree_int_cst_lt (min_val, first_lb)
909 && can_minus_one_p (first_lb))
910 ranges.safe_push (bounded_range (min_val,
911 minus_one (first_lb)));
912 for (unsigned i = 1; i < other->m_ranges.length (); i++)
914 tree prev_ub = other->m_ranges[i - 1].m_upper;
915 tree iter_lb = other->m_ranges[i].m_lower;
916 gcc_assert (tree_int_cst_lt (prev_ub, iter_lb));
917 if (can_plus_one_p (prev_ub) && can_minus_one_p (iter_lb))
918 ranges.safe_push (bounded_range (plus_one (prev_ub),
919 minus_one (iter_lb)));
921 tree last_ub
922 = other->m_ranges[other->m_ranges.length () - 1].m_upper;
923 if (tree_int_cst_lt (last_ub, max_val)
924 && can_plus_one_p (last_ub))
925 ranges.safe_push (bounded_range (plus_one (last_ub), max_val));
927 return consolidate (new bounded_ranges (ranges));
930 /* If an object equal to INST is already present, delete INST and
931 return the existing object.
932 Otherwise add INST and return it. */
934 const bounded_ranges *
935 bounded_ranges_manager::consolidate (bounded_ranges *inst)
937 if (bounded_ranges **slot = m_map.get (inst))
939 delete inst;
940 return *slot;
942 m_map.put (inst, inst);
943 return inst;
946 /* Get the bounded_ranges instance for EDGE of SWITCH_STMT,
947 creating it if necessary, and caching it by edge. */
949 const bounded_ranges *
950 bounded_ranges_manager::
951 get_or_create_ranges_for_switch (const switch_cfg_superedge *edge,
952 const gswitch *switch_stmt)
954 /* Look in per-edge cache. */
955 if (const bounded_ranges ** slot = m_edge_cache.get (edge))
956 return *slot;
958 /* Not yet in cache. */
959 const bounded_ranges *all_cases_ranges
960 = create_ranges_for_switch (*edge, switch_stmt);
961 m_edge_cache.put (edge, all_cases_ranges);
962 return all_cases_ranges;
965 /* Get the bounded_ranges instance for EDGE of SWITCH_STMT,
966 creating it if necessary, for edges for which the per-edge
967 cache has not yet been populated. */
969 const bounded_ranges *
970 bounded_ranges_manager::
971 create_ranges_for_switch (const switch_cfg_superedge &edge,
972 const gswitch *switch_stmt)
974 /* Get the ranges for each case label. */
975 auto_vec <const bounded_ranges *> case_ranges_vec
976 (gimple_switch_num_labels (switch_stmt));
978 for (tree case_label : edge.get_case_labels ())
980 /* Get the ranges for this case label. */
981 const bounded_ranges *case_ranges
982 = make_case_label_ranges (switch_stmt, case_label);
983 case_ranges_vec.quick_push (case_ranges);
986 /* Combine all the ranges for each case label into a single collection
987 of ranges. */
988 const bounded_ranges *all_cases_ranges
989 = get_or_create_union (case_ranges_vec);
990 return all_cases_ranges;
993 /* Get the bounded_ranges instance for CASE_LABEL within
994 SWITCH_STMT. */
996 const bounded_ranges *
997 bounded_ranges_manager::
998 make_case_label_ranges (const gswitch *switch_stmt,
999 tree case_label)
1001 gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR);
1002 tree lower_bound = CASE_LOW (case_label);
1003 tree upper_bound = CASE_HIGH (case_label);
1004 if (lower_bound)
1006 if (upper_bound)
1007 /* Range. */
1008 return get_or_create_range (lower_bound, upper_bound);
1009 else
1010 /* Single-value. */
1011 return get_or_create_point (lower_bound);
1013 else
1015 /* The default case.
1016 Add exclusions based on the other cases. */
1017 auto_vec <const bounded_ranges *> other_case_ranges
1018 (gimple_switch_num_labels (switch_stmt));
1019 for (unsigned other_idx = 1;
1020 other_idx < gimple_switch_num_labels (switch_stmt);
1021 other_idx++)
1023 tree other_label = gimple_switch_label (switch_stmt,
1024 other_idx);
1025 const bounded_ranges *other_ranges
1026 = make_case_label_ranges (switch_stmt, other_label);
1027 other_case_ranges.quick_push (other_ranges);
1029 const bounded_ranges *other_cases_ranges
1030 = get_or_create_union (other_case_ranges);
1031 tree type = TREE_TYPE (gimple_switch_index (switch_stmt));
1032 return get_or_create_inverse (other_cases_ranges, type);
1036 /* Dump the number of objects of each class that were managed by this
1037 manager to LOGGER.
1038 If SHOW_OBJS is true, also dump the objects themselves. */
1040 void
1041 bounded_ranges_manager::log_stats (logger *logger, bool show_objs) const
1043 LOG_SCOPE (logger);
1044 logger->log (" # %s: %li", "ranges", (long)m_map.elements ());
1045 if (!show_objs)
1046 return;
1048 auto_vec<const bounded_ranges *> vec_objs (m_map.elements ());
1049 for (const auto &iter : m_map)
1050 vec_objs.quick_push (iter.second);
1051 vec_objs.qsort
1052 ([](const void *p1, const void *p2) -> int
1054 const bounded_ranges *br1 = *(const bounded_ranges * const *)p1;
1055 const bounded_ranges *br2 = *(const bounded_ranges * const *)p2;
1056 return bounded_ranges::cmp (br1, br2);
1059 for (const auto &iter : vec_objs)
1061 logger->start_log_line ();
1062 pretty_printer *pp = logger->get_printer ();
1063 pp_string (pp, " ");
1064 iter->dump_to_pp (pp, true);
1065 logger->end_log_line ();
1069 /* class equiv_class. */
1071 /* equiv_class's default ctor. */
1073 equiv_class::equiv_class ()
1074 : m_constant (NULL_TREE), m_cst_sval (NULL), m_vars ()
1078 /* equiv_class's copy ctor. */
1080 equiv_class::equiv_class (const equiv_class &other)
1081 : m_constant (other.m_constant), m_cst_sval (other.m_cst_sval),
1082 m_vars (other.m_vars.length ())
1084 for (const svalue *sval : other.m_vars)
1085 m_vars.quick_push (sval);
1088 /* Print an all-on-one-line representation of this equiv_class to PP,
1089 which must support %E for trees. */
1091 void
1092 equiv_class::print (pretty_printer *pp) const
1094 pp_character (pp, '{');
1095 int i;
1096 const svalue *sval;
1097 FOR_EACH_VEC_ELT (m_vars, i, sval)
1099 if (i > 0)
1100 pp_string (pp, " == ");
1101 sval->dump_to_pp (pp, true);
1103 if (m_constant)
1105 if (i > 0)
1106 pp_string (pp, " == ");
1107 pp_printf (pp, "[m_constant]%qE", m_constant);
1109 pp_character (pp, '}');
1112 /* Return a new json::object of the form
1113 {"svals" : [str],
1114 "constant" : optional str}. */
1116 std::unique_ptr<json::object>
1117 equiv_class::to_json () const
1119 auto ec_obj = ::make_unique<json::object> ();
1121 auto sval_arr = ::make_unique<json::array> ();
1122 for (const svalue *sval : m_vars)
1123 sval_arr->append (sval->to_json ());
1124 ec_obj->set ("svals", std::move (sval_arr));
1126 if (m_constant)
1128 pretty_printer pp;
1129 pp_format_decoder (&pp) = default_tree_printer;
1130 pp_printf (&pp, "%qE", m_constant);
1131 ec_obj->set_string ("constant", pp_formatted_text (&pp));
1134 return ec_obj;
1137 std::unique_ptr<text_art::tree_widget>
1138 equiv_class::make_dump_widget (const text_art::dump_widget_info &dwi,
1139 unsigned id) const
1141 using text_art::tree_widget;
1142 std::unique_ptr<tree_widget> ec_widget;
1145 pretty_printer pp;
1146 pp_string (&pp, "Equivalence class ");
1147 equiv_class_id (id).print (&pp);
1148 ec_widget = tree_widget::make (dwi, &pp);
1151 for (const svalue *sval : m_vars)
1153 pretty_printer pp;
1154 pp_format_decoder (&pp) = default_tree_printer;
1155 sval->dump_to_pp (&pp, true);
1156 ec_widget->add_child (tree_widget::make (dwi, &pp));
1159 if (m_constant)
1161 pretty_printer pp;
1162 pp_format_decoder (&pp) = default_tree_printer;
1163 pp_printf (&pp, "%qE", m_constant);
1164 ec_widget->add_child (tree_widget::make (dwi, &pp));
1167 return ec_widget;
1170 /* Generate a hash value for this equiv_class.
1171 This relies on the ordering of m_vars, and so this object needs to
1172 have been canonicalized for this to be meaningful. */
1174 hashval_t
1175 equiv_class::hash () const
1177 inchash::hash hstate;
1179 inchash::add_expr (m_constant, hstate);
1180 for (const svalue * sval : m_vars)
1181 hstate.add_ptr (sval);
1182 return hstate.end ();
1185 /* Equality operator for equiv_class.
1186 This relies on the ordering of m_vars, and so this object
1187 and OTHER need to have been canonicalized for this to be
1188 meaningful. */
1190 bool
1191 equiv_class::operator== (const equiv_class &other)
1193 if (m_constant != other.m_constant)
1194 return false; // TODO: use tree equality here?
1196 /* FIXME: should we compare m_cst_sval? */
1198 if (m_vars.length () != other.m_vars.length ())
1199 return false;
1201 int i;
1202 const svalue *sval;
1203 FOR_EACH_VEC_ELT (m_vars, i, sval)
1204 if (sval != other.m_vars[i])
1205 return false;
1207 return true;
1210 /* Add SID to this equiv_class, using CM to check if it's a constant. */
1212 void
1213 equiv_class::add (const svalue *sval)
1215 gcc_assert (sval);
1216 if (tree cst = sval->maybe_get_constant ())
1218 gcc_assert (CONSTANT_CLASS_P (cst));
1219 /* FIXME: should we canonicalize which svalue is the constant
1220 when there are multiple equal constants? */
1221 m_constant = cst;
1222 m_cst_sval = sval;
1224 m_vars.safe_push (sval);
1227 /* Remove SID from this equivalence class.
1228 Return true if SID was the last var in the equivalence class (suggesting
1229 a possible leak). */
1231 bool
1232 equiv_class::del (const svalue *sval)
1234 gcc_assert (sval);
1235 gcc_assert (sval != m_cst_sval);
1237 int i;
1238 const svalue *iv;
1239 FOR_EACH_VEC_ELT (m_vars, i, iv)
1241 if (iv == sval)
1243 m_vars[i] = m_vars[m_vars.length () - 1];
1244 m_vars.pop ();
1245 return m_vars.length () == 0;
1249 /* SVAL must be in the class. */
1250 gcc_unreachable ();
1251 return false;
1254 /* Get a representative member of this class, for handling cases
1255 where the IDs can change mid-traversal. */
1257 const svalue *
1258 equiv_class::get_representative () const
1260 gcc_assert (m_vars.length () > 0);
1261 return m_vars[0];
1264 /* Sort the svalues within this equiv_class. */
1266 void
1267 equiv_class::canonicalize ()
1269 m_vars.qsort (svalue::cmp_ptr_ptr);
1272 /* Return true if this EC contains a variable, false if it merely
1273 contains constants.
1274 Subroutine of constraint_manager::canonicalize, for removing
1275 redundant ECs. */
1277 bool
1278 equiv_class::contains_non_constant_p () const
1280 if (m_constant)
1282 for (auto iter : m_vars)
1283 if (iter->maybe_get_constant ())
1284 continue;
1285 else
1286 /* We have {non-constant == constant}. */
1287 return true;
1288 /* We only have constants. */
1289 return false;
1291 else
1292 /* Return true if we have {non-constant == non-constant}. */
1293 return m_vars.length () > 1;
1296 /* Get a debug string for C_OP. */
1298 const char *
1299 constraint_op_code (enum constraint_op c_op)
1301 switch (c_op)
1303 default:
1304 gcc_unreachable ();
1305 case CONSTRAINT_NE: return "!=";
1306 case CONSTRAINT_LT: return "<";
1307 case CONSTRAINT_LE: return "<=";
1311 /* Convert C_OP to an enum tree_code. */
1313 enum tree_code
1314 constraint_tree_code (enum constraint_op c_op)
1316 switch (c_op)
1318 default:
1319 gcc_unreachable ();
1320 case CONSTRAINT_NE: return NE_EXPR;
1321 case CONSTRAINT_LT: return LT_EXPR;
1322 case CONSTRAINT_LE: return LE_EXPR;
1326 /* Given "lhs C_OP rhs", determine "lhs T_OP rhs".
1328 For example, given "x < y", then "x > y" is false. */
1330 static tristate
1331 eval_constraint_op_for_op (enum constraint_op c_op, enum tree_code t_op)
1333 switch (c_op)
1335 default:
1336 gcc_unreachable ();
1337 case CONSTRAINT_NE:
1338 if (t_op == EQ_EXPR)
1339 return tristate (tristate::TS_FALSE);
1340 if (t_op == NE_EXPR)
1341 return tristate (tristate::TS_TRUE);
1342 break;
1343 case CONSTRAINT_LT:
1344 if (t_op == LT_EXPR || t_op == LE_EXPR || t_op == NE_EXPR)
1345 return tristate (tristate::TS_TRUE);
1346 if (t_op == EQ_EXPR || t_op == GT_EXPR || t_op == GE_EXPR)
1347 return tristate (tristate::TS_FALSE);
1348 break;
1349 case CONSTRAINT_LE:
1350 if (t_op == LE_EXPR)
1351 return tristate (tristate::TS_TRUE);
1352 if (t_op == GT_EXPR)
1353 return tristate (tristate::TS_FALSE);
1354 break;
1356 return tristate (tristate::TS_UNKNOWN);
1359 /* class constraint. */
1361 /* Print this constraint to PP (which must support %E for trees),
1362 using CM to look up equiv_class instances from ids. */
1364 void
1365 constraint::print (pretty_printer *pp, const constraint_manager &cm) const
1367 m_lhs.print (pp);
1368 pp_string (pp, ": ");
1369 m_lhs.get_obj (cm).print (pp);
1370 pp_string (pp, " ");
1371 pp_string (pp, constraint_op_code (m_op));
1372 pp_string (pp, " ");
1373 m_rhs.print (pp);
1374 pp_string (pp, ": ");
1375 m_rhs.get_obj (cm).print (pp);
1378 /* Return a new json::object of the form
1379 {"lhs" : int, the EC index
1380 "op" : str,
1381 "rhs" : int, the EC index}. */
1383 std::unique_ptr<json::object>
1384 constraint::to_json () const
1386 auto con_obj = ::make_unique<json::object> ();
1388 con_obj->set_integer ("lhs", m_lhs.as_int ());
1389 con_obj->set_string ("op", constraint_op_code (m_op));
1390 con_obj->set_integer ("rhs", m_rhs.as_int ());
1392 return con_obj;
1395 std::unique_ptr<text_art::widget>
1396 constraint::make_dump_widget (const text_art::dump_widget_info &dwi,
1397 const constraint_manager &cm) const
1399 pretty_printer pp;
1400 pp_format_decoder (&pp) = default_tree_printer;
1401 pp_show_color (&pp) = true;
1402 print (&pp, cm);
1403 return text_art::tree_widget::make (dwi, &pp);
1406 /* Generate a hash value for this constraint. */
1408 hashval_t
1409 constraint::hash () const
1411 inchash::hash hstate;
1412 hstate.add_int (m_lhs.m_idx);
1413 hstate.add_int (m_op);
1414 hstate.add_int (m_rhs.m_idx);
1415 return hstate.end ();
1418 /* Equality operator for constraints. */
1420 bool
1421 constraint::operator== (const constraint &other) const
1423 if (m_lhs != other.m_lhs)
1424 return false;
1425 if (m_op != other.m_op)
1426 return false;
1427 if (m_rhs != other.m_rhs)
1428 return false;
1429 return true;
1432 /* Return true if this constraint is implied by OTHER. */
1434 bool
1435 constraint::implied_by (const constraint &other,
1436 const constraint_manager &cm) const
1438 if (m_lhs == other.m_lhs)
1439 if (tree rhs_const = m_rhs.get_obj (cm).get_any_constant ())
1440 if (tree other_rhs_const = other.m_rhs.get_obj (cm).get_any_constant ())
1441 if (m_lhs.get_obj (cm).get_any_constant () == NULL_TREE)
1442 if (m_op == other.m_op)
1443 switch (m_op)
1445 default:
1446 break;
1447 case CONSTRAINT_LE:
1448 case CONSTRAINT_LT:
1449 if (compare_constants (rhs_const,
1450 GE_EXPR,
1451 other_rhs_const).is_true ())
1452 return true;
1453 break;
1455 return false;
1458 /* class bounded_ranges_constraint. */
1460 void
1461 bounded_ranges_constraint::print (pretty_printer *pp,
1462 const constraint_manager &cm) const
1464 m_ec_id.print (pp);
1465 pp_string (pp, ": ");
1466 m_ec_id.get_obj (cm).print (pp);
1467 pp_string (pp, ": ");
1468 m_ranges->dump_to_pp (pp, true);
1471 std::unique_ptr<json::object>
1472 bounded_ranges_constraint::to_json () const
1474 auto con_obj = ::make_unique<json::object> ();
1476 con_obj->set_integer ("ec", m_ec_id.as_int ());
1477 con_obj->set ("ranges", m_ranges->to_json ());
1479 return con_obj;
1482 std::unique_ptr<text_art::tree_widget>
1483 bounded_ranges_constraint::
1484 make_dump_widget (const text_art::dump_widget_info &dwi) const
1486 using text_art::tree_widget;
1487 std::unique_ptr<tree_widget> brc_widget
1488 (tree_widget::from_fmt (dwi, nullptr,
1489 "ec%i bounded ranges", m_ec_id.as_int ()));
1490 m_ranges->add_to_dump_widget (*brc_widget.get (), dwi);
1491 return brc_widget;
1494 bool
1495 bounded_ranges_constraint::
1496 operator== (const bounded_ranges_constraint &other) const
1498 if (m_ec_id != other.m_ec_id)
1499 return false;
1501 /* We can compare by pointer, since the bounded_ranges_manager
1502 consolidates instances. */
1503 return m_ranges == other.m_ranges;
1506 void
1507 bounded_ranges_constraint::add_to_hash (inchash::hash *hstate) const
1509 hstate->add_int (m_ec_id.m_idx);
1510 hstate->merge_hash (m_ranges->get_hash ());
1513 /* class equiv_class_id. */
1515 /* Get the underlying equiv_class for this ID from CM. */
1517 const equiv_class &
1518 equiv_class_id::get_obj (const constraint_manager &cm) const
1520 return cm.get_equiv_class_by_index (m_idx);
1523 /* Access the underlying equiv_class for this ID from CM. */
1525 equiv_class &
1526 equiv_class_id::get_obj (constraint_manager &cm) const
1528 return cm.get_equiv_class_by_index (m_idx);
1531 /* Print this equiv_class_id to PP. */
1533 void
1534 equiv_class_id::print (pretty_printer *pp) const
1536 if (null_p ())
1537 pp_printf (pp, "null");
1538 else
1539 pp_printf (pp, "ec%i", m_idx);
1542 /* class constraint_manager. */
1544 /* constraint_manager's copy ctor. */
1546 constraint_manager::constraint_manager (const constraint_manager &other)
1547 : m_equiv_classes (other.m_equiv_classes.length ()),
1548 m_constraints (other.m_constraints.length ()),
1549 m_bounded_ranges_constraints (other.m_bounded_ranges_constraints.length ()),
1550 m_mgr (other.m_mgr)
1552 int i;
1553 equiv_class *ec;
1554 FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
1555 m_equiv_classes.quick_push (new equiv_class (*ec));
1556 constraint *c;
1557 FOR_EACH_VEC_ELT (other.m_constraints, i, c)
1558 m_constraints.quick_push (*c);
1559 for (const auto &iter : other.m_bounded_ranges_constraints)
1560 m_bounded_ranges_constraints.quick_push (iter);
1563 /* constraint_manager's assignment operator. */
1565 constraint_manager&
1566 constraint_manager::operator= (const constraint_manager &other)
1568 gcc_assert (m_equiv_classes.length () == 0);
1569 gcc_assert (m_constraints.length () == 0);
1570 gcc_assert (m_bounded_ranges_constraints.length () == 0);
1572 int i;
1573 equiv_class *ec;
1574 m_equiv_classes.reserve (other.m_equiv_classes.length ());
1575 FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
1576 m_equiv_classes.quick_push (new equiv_class (*ec));
1577 constraint *c;
1578 m_constraints.reserve (other.m_constraints.length ());
1579 FOR_EACH_VEC_ELT (other.m_constraints, i, c)
1580 m_constraints.quick_push (*c);
1581 for (const auto &iter : other.m_bounded_ranges_constraints)
1582 m_bounded_ranges_constraints.quick_push (iter);
1584 return *this;
1587 /* Generate a hash value for this constraint_manager. */
1589 hashval_t
1590 constraint_manager::hash () const
1592 inchash::hash hstate;
1593 int i;
1594 equiv_class *ec;
1595 constraint *c;
1597 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1598 hstate.merge_hash (ec->hash ());
1599 FOR_EACH_VEC_ELT (m_constraints, i, c)
1600 hstate.merge_hash (c->hash ());
1601 for (const auto &iter : m_bounded_ranges_constraints)
1602 iter.add_to_hash (&hstate);
1603 return hstate.end ();
1606 /* Equality operator for constraint_manager. */
1608 bool
1609 constraint_manager::operator== (const constraint_manager &other) const
1611 if (m_equiv_classes.length () != other.m_equiv_classes.length ())
1612 return false;
1613 if (m_constraints.length () != other.m_constraints.length ())
1614 return false;
1615 if (m_bounded_ranges_constraints.length ()
1616 != other.m_bounded_ranges_constraints.length ())
1617 return false;
1619 int i;
1620 equiv_class *ec;
1622 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1623 if (!(*ec == *other.m_equiv_classes[i]))
1624 return false;
1626 constraint *c;
1628 FOR_EACH_VEC_ELT (m_constraints, i, c)
1629 if (!(*c == other.m_constraints[i]))
1630 return false;
1632 for (unsigned i = 0; i < m_bounded_ranges_constraints.length (); i++)
1634 if (m_bounded_ranges_constraints[i]
1635 != other.m_bounded_ranges_constraints[i])
1636 return false;
1639 return true;
1642 /* Print this constraint_manager to PP (which must support %E for trees). */
1644 void
1645 constraint_manager::print (pretty_printer *pp) const
1647 pp_string (pp, "{");
1648 int i;
1649 equiv_class *ec;
1650 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1652 if (i > 0)
1653 pp_string (pp, ", ");
1654 equiv_class_id (i).print (pp);
1655 pp_string (pp, ": ");
1656 ec->print (pp);
1658 pp_string (pp, " | ");
1659 constraint *c;
1660 FOR_EACH_VEC_ELT (m_constraints, i, c)
1662 if (i > 0)
1663 pp_string (pp, " && ");
1664 c->print (pp, *this);
1666 if (m_bounded_ranges_constraints.length ())
1668 pp_string (pp, " | ");
1669 i = 0;
1670 for (const auto &iter : m_bounded_ranges_constraints)
1672 if (i > 0)
1673 pp_string (pp, " && ");
1674 iter.print (pp, *this);
1675 i++;
1678 pp_printf (pp, "}");
1681 /* Dump a representation of this constraint_manager to PP
1682 (which must support %E for trees). */
1684 void
1685 constraint_manager::dump_to_pp (pretty_printer *pp, bool multiline) const
1687 if (multiline)
1688 pp_string (pp, " ");
1689 pp_string (pp, "equiv classes:");
1690 if (multiline)
1691 pp_newline (pp);
1692 else
1693 pp_string (pp, " {");
1694 int i;
1695 equiv_class *ec;
1696 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1698 if (multiline)
1699 pp_string (pp, " ");
1700 else if (i > 0)
1701 pp_string (pp, ", ");
1702 equiv_class_id (i).print (pp);
1703 pp_string (pp, ": ");
1704 ec->print (pp);
1705 if (multiline)
1706 pp_newline (pp);
1708 if (multiline)
1709 pp_string (pp, " ");
1710 else
1711 pp_string (pp, "}");
1712 pp_string (pp, "constraints:");
1713 if (multiline)
1714 pp_newline (pp);
1715 else
1716 pp_string (pp, "{");
1717 constraint *c;
1718 FOR_EACH_VEC_ELT (m_constraints, i, c)
1720 if (multiline)
1721 pp_string (pp, " ");
1722 pp_printf (pp, "%i: ", i);
1723 c->print (pp, *this);
1724 if (multiline)
1725 pp_newline (pp);
1727 if (!multiline)
1728 pp_string (pp, "}");
1729 if (m_bounded_ranges_constraints.length ())
1731 if (multiline)
1732 pp_string (pp, " ");
1733 pp_string (pp, "ranges:");
1734 if (multiline)
1735 pp_newline (pp);
1736 else
1737 pp_string (pp, "{");
1738 i = 0;
1739 for (const auto &iter : m_bounded_ranges_constraints)
1741 if (multiline)
1742 pp_string (pp, " ");
1743 else if (i > 0)
1744 pp_string (pp, " && ");
1745 iter.print (pp, *this);
1746 if (multiline)
1747 pp_newline (pp);
1748 i++;
1750 if (!multiline)
1751 pp_string (pp, "}");
1755 /* Dump a multiline representation of this constraint_manager to FP. */
1757 void
1758 constraint_manager::dump (FILE *fp) const
1760 tree_dump_pretty_printer pp (fp);
1761 dump_to_pp (&pp, true);
1764 /* Dump a multiline representation of this constraint_manager to stderr. */
1766 DEBUG_FUNCTION void
1767 constraint_manager::dump () const
1769 dump (stderr);
1772 /* Dump a multiline representation of CM to stderr. */
1774 DEBUG_FUNCTION void
1775 debug (const constraint_manager &cm)
1777 cm.dump ();
1780 /* Return a new json::object of the form
1781 {"ecs" : array of objects, one per equiv_class
1782 "constraints" : array of objects, one per constraint}. */
1784 std::unique_ptr<json::object>
1785 constraint_manager::to_json () const
1787 auto cm_obj = ::make_unique<json::object> ();
1789 /* Equivalence classes. */
1791 auto ec_arr = ::make_unique<json::array> ();
1792 for (const equiv_class *ec : m_equiv_classes)
1793 ec_arr->append (ec->to_json ());
1794 cm_obj->set ("ecs", std::move (ec_arr));
1797 /* Constraints. */
1799 auto con_arr = ::make_unique<json::array> ();
1800 for (const constraint &c : m_constraints)
1801 con_arr->append (c.to_json ());
1802 cm_obj->set ("constraints", std::move (con_arr));
1805 /* m_bounded_ranges_constraints. */
1807 auto con_arr = ::make_unique<json::array> ();
1808 for (const auto &c : m_bounded_ranges_constraints)
1809 con_arr->append (c.to_json ());
1810 cm_obj->set ("bounded_ranges_constraints", std::move (con_arr));
1813 return cm_obj;
1816 std::unique_ptr<text_art::tree_widget>
1817 constraint_manager::make_dump_widget (const text_art::dump_widget_info &dwi) const
1819 using text_art::tree_widget;
1820 std::unique_ptr<tree_widget> cm_widget
1821 (tree_widget::make (dwi, "Constraints"));
1823 /* Equivalence classes. */
1824 unsigned i;
1825 equiv_class *ec;
1826 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1827 cm_widget->add_child (ec->make_dump_widget (dwi, i));
1829 /* Constraints. */
1830 for (const constraint &c : m_constraints)
1831 cm_widget->add_child (c.make_dump_widget (dwi, *this));
1833 /* m_bounded_ranges_constraints. */
1834 for (const auto &brc : m_bounded_ranges_constraints)
1835 cm_widget->add_child (brc.make_dump_widget (dwi));
1837 if (cm_widget->get_num_children () == 0)
1838 return nullptr;
1840 return cm_widget;
1843 /* Attempt to add the constraint LHS OP RHS to this constraint_manager.
1844 Return true if the constraint could be added (or is already true).
1845 Return false if the constraint contradicts existing knowledge. */
1847 bool
1848 constraint_manager::add_constraint (const svalue *lhs,
1849 enum tree_code op,
1850 const svalue *rhs)
1852 lhs = lhs->unwrap_any_unmergeable ();
1853 rhs = rhs->unwrap_any_unmergeable ();
1855 /* Nothing can be known about unknown/poisoned values. */
1856 if (!lhs->can_have_associated_state_p ()
1857 || !rhs->can_have_associated_state_p ())
1858 /* Not a contradiction. */
1859 return true;
1861 /* Check the conditions on svalues. */
1863 tristate t_cond = eval_condition (lhs, op, rhs);
1865 /* If we already have the condition, do nothing. */
1866 if (t_cond.is_true ())
1867 return true;
1869 /* Reject a constraint that would contradict existing knowledge, as
1870 unsatisfiable. */
1871 if (t_cond.is_false ())
1872 return false;
1875 equiv_class_id lhs_ec_id = get_or_add_equiv_class (lhs);
1876 equiv_class_id rhs_ec_id = get_or_add_equiv_class (rhs);
1878 /* Check the stronger conditions on ECs. */
1880 tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id);
1882 /* Discard constraints that are already known. */
1883 if (t.is_true ())
1884 return true;
1886 /* Reject unsatisfiable constraints. */
1887 if (t.is_false ())
1888 return false;
1891 /* If adding
1892 (SVAL + OFFSET) > CST,
1893 then that can imply:
1894 SVAL > (CST - OFFSET). */
1895 if (const binop_svalue *lhs_binop = lhs->dyn_cast_binop_svalue ())
1896 if (tree rhs_cst = rhs->maybe_get_constant ())
1897 if (tree offset = lhs_binop->get_arg1 ()->maybe_get_constant ())
1898 if ((op == GT_EXPR || op == LT_EXPR
1899 || op == GE_EXPR || op == LE_EXPR)
1900 && lhs_binop->get_op () == PLUS_EXPR)
1902 tree offset_of_cst = fold_build2 (MINUS_EXPR, TREE_TYPE (rhs_cst),
1903 rhs_cst, offset);
1904 const svalue *implied_lhs = lhs_binop->get_arg0 ();
1905 enum tree_code implied_op = op;
1906 const svalue *implied_rhs
1907 = m_mgr->get_or_create_constant_svalue (offset_of_cst);
1908 if (!add_constraint (implied_lhs, implied_op, implied_rhs))
1909 return false;
1910 /* The above add_constraint could lead to EC merger, so we need
1911 to refresh the EC IDs. */
1912 lhs_ec_id = get_or_add_equiv_class (lhs);
1913 rhs_ec_id = get_or_add_equiv_class (rhs);
1916 add_unknown_constraint (lhs_ec_id, op, rhs_ec_id);
1917 return true;
1920 /* Attempt to add the constraint LHS_EC_ID OP RHS_EC_ID to this
1921 constraint_manager.
1922 Return true if the constraint could be added (or is already true).
1923 Return false if the constraint contradicts existing knowledge. */
1925 bool
1926 constraint_manager::add_constraint (equiv_class_id lhs_ec_id,
1927 enum tree_code op,
1928 equiv_class_id rhs_ec_id)
1930 tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id);
1932 /* Discard constraints that are already known. */
1933 if (t.is_true ())
1934 return true;
1936 /* Reject unsatisfiable constraints. */
1937 if (t.is_false ())
1938 return false;
1940 add_unknown_constraint (lhs_ec_id, op, rhs_ec_id);
1941 return true;
1944 /* Add the constraint LHS_EC_ID OP RHS_EC_ID to this constraint_manager,
1945 where the constraint has already been checked for being "unknown". */
1947 void
1948 constraint_manager::add_unknown_constraint (equiv_class_id lhs_ec_id,
1949 enum tree_code op,
1950 equiv_class_id rhs_ec_id)
1952 gcc_assert (lhs_ec_id != rhs_ec_id);
1954 /* For now, simply accumulate constraints, without attempting any further
1955 optimization. */
1956 switch (op)
1958 case EQ_EXPR:
1960 /* Merge rhs_ec into lhs_ec. */
1961 equiv_class &lhs_ec_obj = lhs_ec_id.get_obj (*this);
1962 const equiv_class &rhs_ec_obj = rhs_ec_id.get_obj (*this);
1964 int i;
1965 const svalue *sval;
1966 FOR_EACH_VEC_ELT (rhs_ec_obj.m_vars, i, sval)
1967 lhs_ec_obj.add (sval);
1969 if (rhs_ec_obj.m_constant)
1971 lhs_ec_obj.m_constant = rhs_ec_obj.m_constant;
1972 lhs_ec_obj.m_cst_sval = rhs_ec_obj.m_cst_sval;
1975 /* Drop rhs equivalence class, overwriting it with the
1976 final ec (which might be the same one). */
1977 equiv_class_id final_ec_id = m_equiv_classes.length () - 1;
1978 equiv_class *old_ec = m_equiv_classes[rhs_ec_id.m_idx];
1979 equiv_class *final_ec = m_equiv_classes.pop ();
1980 if (final_ec != old_ec)
1981 m_equiv_classes[rhs_ec_id.m_idx] = final_ec;
1982 delete old_ec;
1983 if (lhs_ec_id == final_ec_id)
1984 lhs_ec_id = rhs_ec_id;
1986 /* Update the constraints. */
1987 constraint *c;
1988 FOR_EACH_VEC_ELT (m_constraints, i, c)
1990 /* Update references to the rhs_ec so that
1991 they refer to the lhs_ec. */
1992 if (c->m_lhs == rhs_ec_id)
1993 c->m_lhs = lhs_ec_id;
1994 if (c->m_rhs == rhs_ec_id)
1995 c->m_rhs = lhs_ec_id;
1997 /* Renumber all constraints that refer to the final rhs_ec
1998 to the old rhs_ec, where the old final_ec now lives. */
1999 if (c->m_lhs == final_ec_id)
2000 c->m_lhs = rhs_ec_id;
2001 if (c->m_rhs == final_ec_id)
2002 c->m_rhs = rhs_ec_id;
2004 bounded_ranges_constraint *brc;
2005 FOR_EACH_VEC_ELT (m_bounded_ranges_constraints, i, brc)
2007 if (brc->m_ec_id == rhs_ec_id)
2008 brc->m_ec_id = lhs_ec_id;
2009 if (brc->m_ec_id == final_ec_id)
2010 brc->m_ec_id = rhs_ec_id;
2013 /* We may now have self-comparisons due to the merger; these
2014 constraints should be removed. */
2015 unsigned read_index, write_index;
2016 VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c,
2017 (c->m_lhs == c->m_rhs));
2019 break;
2020 case GE_EXPR:
2021 add_constraint_internal (rhs_ec_id, CONSTRAINT_LE, lhs_ec_id);
2022 break;
2023 case LE_EXPR:
2024 add_constraint_internal (lhs_ec_id, CONSTRAINT_LE, rhs_ec_id);
2025 break;
2026 case NE_EXPR:
2027 add_constraint_internal (lhs_ec_id, CONSTRAINT_NE, rhs_ec_id);
2028 break;
2029 case GT_EXPR:
2030 add_constraint_internal (rhs_ec_id, CONSTRAINT_LT, lhs_ec_id);
2031 break;
2032 case LT_EXPR:
2033 add_constraint_internal (lhs_ec_id, CONSTRAINT_LT, rhs_ec_id);
2034 break;
2035 default:
2036 /* do nothing. */
2037 break;
2039 validate ();
2042 /* Subroutine of constraint_manager::add_constraint, for handling all
2043 operations other than equality (for which equiv classes are merged). */
2045 void
2046 constraint_manager::add_constraint_internal (equiv_class_id lhs_id,
2047 enum constraint_op c_op,
2048 equiv_class_id rhs_id)
2050 if (m_constraints.length () >= (unsigned)param_analyzer_max_constraints)
2051 return;
2053 constraint new_c (lhs_id, c_op, rhs_id);
2055 /* Remove existing constraints that would be implied by the
2056 new constraint. */
2057 unsigned read_index, write_index;
2058 constraint *c;
2059 VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c,
2060 (c->implied_by (new_c, *this)));
2062 /* Add the constraint. */
2063 m_constraints.safe_push (new_c);
2065 /* We don't yet update m_bounded_ranges_constraints here yet. */
2067 if (!flag_analyzer_transitivity)
2068 return;
2070 if (c_op != CONSTRAINT_NE)
2072 /* The following can potentially add EQ_EXPR facts, which could lead
2073 to ECs being merged, which would change the meaning of the EC IDs.
2074 Hence we need to do this via representatives. */
2075 const svalue *lhs = lhs_id.get_obj (*this).get_representative ();
2076 const svalue *rhs = rhs_id.get_obj (*this).get_representative ();
2078 /* We have LHS </<= RHS */
2080 /* Handle transitivity of ordering by adding additional constraints
2081 based on what we already knew.
2083 So if we have already have:
2084 (a < b)
2085 (c < d)
2086 Then adding:
2087 (b < c)
2088 will also add:
2089 (a < c)
2090 (b < d)
2091 We need to recurse to ensure we also add:
2092 (a < d).
2093 We call the checked add_constraint to avoid adding constraints
2094 that are already present. Doing so also ensures termination
2095 in the case of cycles.
2097 We also check for single-element ranges, adding EQ_EXPR facts
2098 where we discover them. For example 3 < x < 5 implies
2099 that x == 4 (if x is an integer). */
2100 for (unsigned i = 0; i < m_constraints.length (); i++)
2102 const constraint *other = &m_constraints[i];
2103 if (other->is_ordering_p ())
2105 /* Refresh the EC IDs, in case any mergers have happened. */
2106 lhs_id = get_or_add_equiv_class (lhs);
2107 rhs_id = get_or_add_equiv_class (rhs);
2109 tree lhs_const = lhs_id.get_obj (*this).m_constant;
2110 tree rhs_const = rhs_id.get_obj (*this).m_constant;
2111 tree other_lhs_const
2112 = other->m_lhs.get_obj (*this).m_constant;
2113 tree other_rhs_const
2114 = other->m_rhs.get_obj (*this).m_constant;
2116 /* We have "LHS </<= RHS" and "other.lhs </<= other.rhs". */
2118 /* If we have LHS </<= RHS and RHS </<= LHS, then we have a
2119 cycle. */
2120 if (rhs_id == other->m_lhs
2121 && other->m_rhs == lhs_id)
2123 /* We must have equality for this to be possible. */
2124 gcc_assert (c_op == CONSTRAINT_LE
2125 && other->m_op == CONSTRAINT_LE);
2126 add_constraint (lhs_id, EQ_EXPR, rhs_id);
2127 /* Adding an equality will merge the two ECs and potentially
2128 reorganize the constraints. Stop iterating. */
2129 return;
2131 /* Otherwise, check for transitivity. */
2132 if (rhs_id == other->m_lhs)
2134 /* With RHS == other.lhs, we have:
2135 "LHS </<= (RHS, other.lhs) </<= other.rhs"
2136 and thus this implies "LHS </<= other.rhs". */
2138 /* Do we have a tightly-constrained range? */
2139 if (lhs_const
2140 && !rhs_const
2141 && other_rhs_const)
2143 range r (bound (lhs_const, c_op == CONSTRAINT_LE),
2144 bound (other_rhs_const,
2145 other->m_op == CONSTRAINT_LE));
2146 if (tree constant = r.constrained_to_single_element ())
2148 const svalue *cst_sval
2149 = m_mgr->get_or_create_constant_svalue (constant);
2150 add_constraint
2151 (rhs_id, EQ_EXPR,
2152 get_or_add_equiv_class (cst_sval));
2153 return;
2157 /* Otherwise, add the constraint implied by transitivity. */
2158 enum tree_code new_op
2159 = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
2160 ? LE_EXPR : LT_EXPR);
2161 add_constraint (lhs_id, new_op, other->m_rhs);
2163 else if (other->m_rhs == lhs_id)
2165 /* With other.rhs == LHS, we have:
2166 "other.lhs </<= (other.rhs, LHS) </<= RHS"
2167 and thus this implies "other.lhs </<= RHS". */
2169 /* Do we have a tightly-constrained range? */
2170 if (other_lhs_const
2171 && !lhs_const
2172 && rhs_const)
2174 range r (bound (other_lhs_const,
2175 other->m_op == CONSTRAINT_LE),
2176 bound (rhs_const,
2177 c_op == CONSTRAINT_LE));
2178 if (tree constant = r.constrained_to_single_element ())
2180 const svalue *cst_sval
2181 = m_mgr->get_or_create_constant_svalue (constant);
2182 add_constraint
2183 (lhs_id, EQ_EXPR,
2184 get_or_add_equiv_class (cst_sval));
2185 return;
2189 /* Otherwise, add the constraint implied by transitivity. */
2190 enum tree_code new_op
2191 = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
2192 ? LE_EXPR : LT_EXPR);
2193 add_constraint (other->m_lhs, new_op, rhs_id);
2200 /* Attempt to add the constraint that SVAL is within RANGES to this
2201 constraint_manager.
2203 Return true if the constraint was successfully added (or is already
2204 known to be true).
2205 Return false if the constraint contradicts existing knowledge. */
2207 bool
2208 constraint_manager::add_bounded_ranges (const svalue *sval,
2209 const bounded_ranges *ranges)
2211 /* If RANGES is just a singleton, convert this to adding the constraint:
2212 "SVAL == {the singleton}". */
2213 if (ranges->get_count () == 1
2214 && ranges->get_range (0).singleton_p ())
2216 tree range_cst = ranges->get_range (0).m_lower;
2217 const svalue *range_sval
2218 = m_mgr->get_or_create_constant_svalue (range_cst);
2219 return add_constraint (sval, EQ_EXPR, range_sval);
2222 sval = sval->unwrap_any_unmergeable ();
2224 /* Nothing can be known about unknown/poisoned values. */
2225 if (!sval->can_have_associated_state_p ())
2226 /* Not a contradiction. */
2227 return true;
2229 /* If SVAL is a constant, then we can look at RANGES directly. */
2230 if (tree cst = sval->maybe_get_constant ())
2232 /* If the ranges contain CST, then it's a successful no-op;
2233 otherwise it's a contradiction. */
2234 return ranges->contain_p (cst);
2237 equiv_class_id ec_id = get_or_add_equiv_class (sval);
2239 /* If the EC has a constant, it's either true or false. */
2240 const equiv_class &ec = ec_id.get_obj (*this);
2241 if (tree ec_cst = ec.get_any_constant ())
2243 if (ranges->contain_p (ec_cst))
2244 /* We already have SVAL == EC_CST, within RANGES, so
2245 we can discard RANGES and succeed. */
2246 return true;
2247 else
2248 /* We already have SVAL == EC_CST, not within RANGES, so
2249 we can reject RANGES as a contradiction. */
2250 return false;
2253 /* We have at most one per ec_id. */
2254 /* Iterate through each range in RANGES. */
2255 for (auto iter : m_bounded_ranges_constraints)
2257 if (iter.m_ec_id == ec_id)
2259 /* Update with intersection, or fail if empty. */
2260 bounded_ranges_manager *mgr = get_range_manager ();
2261 const bounded_ranges *intersection
2262 = mgr->get_or_create_intersection (iter.m_ranges, ranges);
2263 if (intersection->empty_p ())
2265 /* No intersection; fail. */
2266 return false;
2268 else
2270 /* Update with intersection; succeed. */
2271 iter.m_ranges = intersection;
2272 validate ();
2273 return true;
2277 m_bounded_ranges_constraints.safe_push
2278 (bounded_ranges_constraint (ec_id, ranges));
2280 validate ();
2282 return true;
2285 /* Look for SVAL within the equivalence classes of this constraint_manager;
2286 if found, return true, writing the id to *OUT if OUT is non-NULL,
2287 otherwise return false. */
2289 bool
2290 constraint_manager::get_equiv_class_by_svalue (const svalue *sval,
2291 equiv_class_id *out) const
2293 /* TODO: should we have a map, rather than these searches? */
2294 int i;
2295 equiv_class *ec;
2296 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2298 int j;
2299 const svalue *iv;
2300 FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
2301 if (iv == sval)
2303 if (out)
2304 *out = equiv_class_id (i);
2305 return true;
2308 return false;
2311 /* Tries to find a svalue inside another svalue. */
2313 class sval_finder : public visitor
2315 public:
2316 sval_finder (const svalue *query) : m_query (query), m_found (false)
2320 bool found_query_p ()
2322 return m_found;
2325 void visit_region_svalue (const region_svalue *sval)
2327 m_found |= m_query == sval;
2330 void visit_constant_svalue (const constant_svalue *sval)
2332 m_found |= m_query == sval;
2335 void visit_unknown_svalue (const unknown_svalue *sval)
2337 m_found |= m_query == sval;
2340 void visit_poisoned_svalue (const poisoned_svalue *sval)
2342 m_found |= m_query == sval;
2345 void visit_setjmp_svalue (const setjmp_svalue *sval)
2347 m_found |= m_query == sval;
2350 void visit_initial_svalue (const initial_svalue *sval)
2352 m_found |= m_query == sval;
2355 void visit_unaryop_svalue (const unaryop_svalue *sval)
2357 m_found |= m_query == sval;
2360 void visit_binop_svalue (const binop_svalue *sval)
2362 m_found |= m_query == sval;
2365 void visit_sub_svalue (const sub_svalue *sval)
2367 m_found |= m_query == sval;
2370 void visit_repeated_svalue (const repeated_svalue *sval)
2372 m_found |= m_query == sval;
2375 void visit_bits_within_svalue (const bits_within_svalue *sval)
2377 m_found |= m_query == sval;
2380 void visit_unmergeable_svalue (const unmergeable_svalue *sval)
2382 m_found |= m_query == sval;
2385 void visit_placeholder_svalue (const placeholder_svalue *sval)
2387 m_found |= m_query == sval;
2390 void visit_widening_svalue (const widening_svalue *sval)
2392 m_found |= m_query == sval;
2395 void visit_compound_svalue (const compound_svalue *sval)
2397 m_found |= m_query == sval;
2400 void visit_conjured_svalue (const conjured_svalue *sval)
2402 m_found |= m_query == sval;
2405 void visit_asm_output_svalue (const asm_output_svalue *sval)
2407 m_found |= m_query == sval;
2410 void visit_const_fn_result_svalue (const const_fn_result_svalue *sval)
2412 m_found |= m_query == sval;
2415 private:
2416 const svalue *m_query;
2417 bool m_found;
2420 /* Returns true if SVAL is constrained. */
2422 bool
2423 constraint_manager::sval_constrained_p (const svalue *sval) const
2425 int i;
2426 equiv_class *ec;
2427 sval_finder finder (sval);
2428 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2430 int j;
2431 const svalue *iv;
2432 FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
2434 iv->accept (&finder);
2435 if (finder.found_query_p ())
2436 return true;
2439 return false;
2442 /* Ensure that SVAL has an equivalence class within this constraint_manager;
2443 return the ID of the class. */
2445 equiv_class_id
2446 constraint_manager::get_or_add_equiv_class (const svalue *sval)
2448 equiv_class_id result (-1);
2450 gcc_assert (sval->can_have_associated_state_p ());
2452 /* Convert all NULL pointers to (void *) to avoid state explosions
2453 involving all of the various (foo *)NULL vs (bar *)NULL. */
2454 if (sval->get_type ())
2455 if (POINTER_TYPE_P (sval->get_type ()))
2456 if (tree cst = sval->maybe_get_constant ())
2457 if (zerop (cst))
2458 sval = m_mgr->get_or_create_constant_svalue (null_pointer_node);
2460 /* Try svalue match. */
2461 if (get_equiv_class_by_svalue (sval, &result))
2462 return result;
2464 /* Try equality of constants. */
2465 if (tree cst = sval->maybe_get_constant ())
2467 int i;
2468 equiv_class *ec;
2469 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2470 if (ec->m_constant
2471 && types_compatible_p (TREE_TYPE (cst),
2472 TREE_TYPE (ec->m_constant)))
2474 tree eq = fold_binary (EQ_EXPR, boolean_type_node,
2475 cst, ec->m_constant);
2476 if (eq == boolean_true_node)
2478 ec->add (sval);
2479 return equiv_class_id (i);
2485 /* Not found. */
2486 equiv_class *new_ec = new equiv_class ();
2487 new_ec->add (sval);
2488 m_equiv_classes.safe_push (new_ec);
2490 equiv_class_id new_id (m_equiv_classes.length () - 1);
2492 return new_id;
2495 /* Evaluate the condition LHS_EC OP RHS_EC. */
2497 tristate
2498 constraint_manager::eval_condition (equiv_class_id lhs_ec,
2499 enum tree_code op,
2500 equiv_class_id rhs_ec) const
2502 if (lhs_ec == rhs_ec)
2504 switch (op)
2506 case EQ_EXPR:
2507 case GE_EXPR:
2508 case LE_EXPR:
2509 return tristate (tristate::TS_TRUE);
2511 case NE_EXPR:
2512 case GT_EXPR:
2513 case LT_EXPR:
2514 return tristate (tristate::TS_FALSE);
2515 default:
2516 break;
2520 tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ();
2521 tree rhs_const = rhs_ec.get_obj (*this).get_any_constant ();
2522 if (lhs_const && rhs_const)
2524 tristate result_for_constants
2525 = compare_constants (lhs_const, op, rhs_const);
2526 if (result_for_constants.is_known ())
2527 return result_for_constants;
2530 enum tree_code swapped_op = swap_tree_comparison (op);
2532 int i;
2533 constraint *c;
2534 FOR_EACH_VEC_ELT (m_constraints, i, c)
2536 if (c->m_lhs == lhs_ec
2537 && c->m_rhs == rhs_ec)
2539 tristate result_for_constraint
2540 = eval_constraint_op_for_op (c->m_op, op);
2541 if (result_for_constraint.is_known ())
2542 return result_for_constraint;
2544 /* Swapped operands. */
2545 if (c->m_lhs == rhs_ec
2546 && c->m_rhs == lhs_ec)
2548 tristate result_for_constraint
2549 = eval_constraint_op_for_op (c->m_op, swapped_op);
2550 if (result_for_constraint.is_known ())
2551 return result_for_constraint;
2555 /* We don't use m_bounded_ranges_constraints here yet. */
2557 return tristate (tristate::TS_UNKNOWN);
2560 range
2561 constraint_manager::get_ec_bounds (equiv_class_id ec_id) const
2563 range result;
2565 int i;
2566 constraint *c;
2567 FOR_EACH_VEC_ELT (m_constraints, i, c)
2569 if (c->m_lhs == ec_id)
2571 if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ())
2572 switch (c->m_op)
2574 default:
2575 gcc_unreachable ();
2576 case CONSTRAINT_NE:
2577 continue;
2579 case CONSTRAINT_LT:
2580 /* We have "EC_ID < OTHER_CST". */
2581 result.add_bound (bound (other_cst, false), BK_UPPER);
2582 break;
2584 case CONSTRAINT_LE:
2585 /* We have "EC_ID <= OTHER_CST". */
2586 result.add_bound (bound (other_cst, true), BK_UPPER);
2587 break;
2590 if (c->m_rhs == ec_id)
2592 if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ())
2593 switch (c->m_op)
2595 default:
2596 gcc_unreachable ();
2597 case CONSTRAINT_NE:
2598 continue;
2600 case CONSTRAINT_LT:
2601 /* We have "OTHER_CST < EC_ID"
2602 i.e. "EC_ID > OTHER_CST". */
2603 result.add_bound (bound (other_cst, false), BK_LOWER);
2604 break;
2606 case CONSTRAINT_LE:
2607 /* We have "OTHER_CST <= EC_ID"
2608 i.e. "EC_ID >= OTHER_CST". */
2609 result.add_bound (bound (other_cst, true), BK_LOWER);
2610 break;
2615 return result;
2618 /* Evaluate the condition LHS_EC OP RHS_CONST, avoiding the creation
2619 of equiv_class instances. */
2621 tristate
2622 constraint_manager::eval_condition (equiv_class_id lhs_ec,
2623 enum tree_code op,
2624 tree rhs_const) const
2626 gcc_assert (!lhs_ec.null_p ());
2627 gcc_assert (CONSTANT_CLASS_P (rhs_const));
2629 if (tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ())
2630 return compare_constants (lhs_const, op, rhs_const);
2632 /* Check for known inequalities of the form
2633 (LHS_EC != OTHER_CST) or (OTHER_CST != LHS_EC).
2634 If RHS_CONST == OTHER_CST, then we also know that LHS_EC != OTHER_CST.
2635 For example, we might have the constraint
2636 ptr != (void *)0
2637 so we want the condition
2638 ptr == (foo *)0
2639 to be false. */
2640 int i;
2641 constraint *c;
2642 FOR_EACH_VEC_ELT (m_constraints, i, c)
2644 if (c->m_op == CONSTRAINT_NE)
2646 if (c->m_lhs == lhs_ec)
2648 if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ())
2649 if (compare_constants
2650 (rhs_const, EQ_EXPR, other_cst).is_true ())
2652 switch (op)
2654 case EQ_EXPR:
2655 return tristate (tristate::TS_FALSE);
2656 case NE_EXPR:
2657 return tristate (tristate::TS_TRUE);
2658 default:
2659 break;
2663 if (c->m_rhs == lhs_ec)
2665 if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ())
2666 if (compare_constants
2667 (rhs_const, EQ_EXPR, other_cst).is_true ())
2669 switch (op)
2671 case EQ_EXPR:
2672 return tristate (tristate::TS_FALSE);
2673 case NE_EXPR:
2674 return tristate (tristate::TS_TRUE);
2675 default:
2676 break;
2683 bounded_ranges_manager *mgr = get_range_manager ();
2684 for (const auto &iter : m_bounded_ranges_constraints)
2685 if (iter.m_ec_id == lhs_ec)
2686 return iter.m_ranges->eval_condition (op, rhs_const, mgr);
2688 /* Look at existing bounds on LHS_EC. */
2689 range lhs_bounds = get_ec_bounds (lhs_ec);
2690 tristate result = lhs_bounds.eval_condition (op, rhs_const);
2691 if (result.is_known ())
2692 return result;
2694 /* Also reject if range::add_bound fails. */
2695 if (!lhs_bounds.add_bound (op, rhs_const))
2696 return tristate (false);
2698 return tristate::unknown ();
2701 /* Return true iff "LHS == RHS" is known to be impossible due to
2702 derived conditions.
2704 Look for an EC containing an EC_VAL of the form (LHS OP CST).
2705 If found, see if (LHS OP CST) == EC_VAL is false.
2706 If so, we know this condition is false.
2708 For example, if we already know that
2709 (X & CST_MASK) == Y
2710 and we're evaluating X == Z, we can test to see if
2711 (Z & CST_MASK) == EC_VAL
2712 and thus if:
2713 (Z & CST_MASK) == Y
2714 and reject this if we know that's false. */
2716 bool
2717 constraint_manager::impossible_derived_conditions_p (const svalue *lhs,
2718 const svalue *rhs) const
2720 int i;
2721 equiv_class *ec;
2722 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2724 for (const svalue *ec_sval : ec->m_vars)
2725 switch (ec_sval->get_kind ())
2727 default:
2728 break;
2729 case SK_BINOP:
2731 const binop_svalue *iter_binop
2732 = as_a <const binop_svalue *> (ec_sval);
2733 if (lhs == iter_binop->get_arg0 ()
2734 && iter_binop->get_type ())
2735 if (iter_binop->get_arg1 ()->get_kind () == SK_CONSTANT)
2737 /* Try evalating EC_SVAL with LHS
2738 as the value of EC_SVAL's lhs, and see if it's
2739 consistent with existing knowledge. */
2740 const svalue *subst_bin_op
2741 = m_mgr->get_or_create_binop
2742 (iter_binop->get_type (),
2743 iter_binop->get_op (),
2744 rhs,
2745 iter_binop->get_arg1 ());
2746 tristate t = eval_condition (subst_bin_op,
2747 EQ_EXPR,
2748 ec_sval);
2749 if (t.is_false ())
2750 return true; /* Impossible. */
2753 break;
2756 /* Not known to be impossible. */
2757 return false;
2761 /* Evaluate the condition LHS OP RHS, without modifying this
2762 constraint_manager (avoiding the creation of equiv_class instances). */
2764 tristate
2765 constraint_manager::eval_condition (const svalue *lhs,
2766 enum tree_code op,
2767 const svalue *rhs) const
2769 lhs = lhs->unwrap_any_unmergeable ();
2770 rhs = rhs->unwrap_any_unmergeable ();
2772 /* Nothing can be known about unknown or poisoned values. */
2773 if (lhs->get_kind () == SK_UNKNOWN
2774 || lhs->get_kind () == SK_POISONED
2775 || rhs->get_kind () == SK_UNKNOWN
2776 || rhs->get_kind () == SK_POISONED)
2777 return tristate (tristate::TS_UNKNOWN);
2779 if (lhs == rhs
2780 && !(FLOAT_TYPE_P (lhs->get_type ())
2781 || FLOAT_TYPE_P (rhs->get_type ())))
2783 switch (op)
2785 case EQ_EXPR:
2786 case GE_EXPR:
2787 case LE_EXPR:
2788 return tristate (tristate::TS_TRUE);
2790 case NE_EXPR:
2791 case GT_EXPR:
2792 case LT_EXPR:
2793 return tristate (tristate::TS_FALSE);
2794 default:
2795 break;
2799 equiv_class_id lhs_ec (-1);
2800 equiv_class_id rhs_ec (-1);
2801 get_equiv_class_by_svalue (lhs, &lhs_ec);
2802 get_equiv_class_by_svalue (rhs, &rhs_ec);
2803 if (!lhs_ec.null_p () && !rhs_ec.null_p ())
2805 tristate result_for_ecs
2806 = eval_condition (lhs_ec, op, rhs_ec);
2807 if (result_for_ecs.is_known ())
2808 return result_for_ecs;
2811 if (op == EQ_EXPR
2812 && impossible_derived_conditions_p (lhs, rhs))
2813 return false;
2815 /* If at least one is not in an EC, we have no constraints
2816 comparing LHS and RHS yet.
2817 They might still be comparable if one (or both) is a constant.
2819 Alternatively, we can also get here if we had ECs but they weren't
2820 comparable. Again, constant comparisons might give an answer. */
2821 tree lhs_const = lhs->maybe_get_constant ();
2822 tree rhs_const = rhs->maybe_get_constant ();
2823 if (lhs_const && rhs_const)
2825 tristate result_for_constants
2826 = compare_constants (lhs_const, op, rhs_const);
2827 if (result_for_constants.is_known ())
2828 return result_for_constants;
2831 if (!lhs_ec.null_p ())
2833 if (rhs_const)
2834 return eval_condition (lhs_ec, op, rhs_const);
2836 if (!rhs_ec.null_p ())
2838 if (lhs_const)
2840 enum tree_code swapped_op = swap_tree_comparison (op);
2841 return eval_condition (rhs_ec, swapped_op, lhs_const);
2845 return tristate (tristate::TS_UNKNOWN);
2848 /* Delete any information about svalues identified by P.
2849 Such instances are removed from equivalence classes, and any
2850 redundant ECs and constraints are also removed.
2851 Accumulate stats into STATS. */
2853 template <typename PurgeCriteria>
2854 void
2855 constraint_manager::purge (const PurgeCriteria &p, purge_stats *stats)
2857 /* Delete any svalues identified by P within the various equivalence
2858 classes. */
2859 for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
2861 equiv_class *ec = m_equiv_classes[ec_idx];
2863 int i;
2864 const svalue *sval;
2865 bool delete_ec = false;
2866 FOR_EACH_VEC_ELT (ec->m_vars, i, sval)
2868 if (sval == ec->m_cst_sval)
2869 continue;
2870 if (p.should_purge_p (sval))
2872 if (ec->del (sval))
2873 if (!ec->m_constant)
2874 delete_ec = true;
2878 if (delete_ec)
2880 delete ec;
2881 m_equiv_classes.ordered_remove (ec_idx);
2882 if (stats)
2883 stats->m_num_equiv_classes++;
2885 /* Update the constraints, potentially removing some. */
2886 for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
2888 constraint *c = &m_constraints[con_idx];
2890 /* Remove constraints that refer to the deleted EC. */
2891 if (c->m_lhs == ec_idx
2892 || c->m_rhs == ec_idx)
2894 m_constraints.ordered_remove (con_idx);
2895 if (stats)
2896 stats->m_num_constraints++;
2898 else
2900 /* Renumber constraints that refer to ECs that have
2901 had their idx changed. */
2902 c->m_lhs.update_for_removal (ec_idx);
2903 c->m_rhs.update_for_removal (ec_idx);
2905 con_idx++;
2909 /* Update bounded_ranges_constraint instances. */
2910 for (unsigned r_idx = 0;
2911 r_idx < m_bounded_ranges_constraints.length (); )
2913 bounded_ranges_constraint *brc
2914 = &m_bounded_ranges_constraints[r_idx];
2916 /* Remove if it refers to the deleted EC. */
2917 if (brc->m_ec_id == ec_idx)
2919 m_bounded_ranges_constraints.ordered_remove (r_idx);
2920 if (stats)
2921 stats->m_num_bounded_ranges_constraints++;
2923 else
2925 /* Renumber any EC ids that refer to ECs that have
2926 had their idx changed. */
2927 brc->m_ec_id.update_for_removal (ec_idx);
2928 r_idx++;
2932 else
2933 ec_idx++;
2936 /* Now delete any constraints that are purely between constants. */
2937 for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
2939 constraint *c = &m_constraints[con_idx];
2940 if (m_equiv_classes[c->m_lhs.m_idx]->m_vars.length () == 0
2941 && m_equiv_classes[c->m_rhs.m_idx]->m_vars.length () == 0)
2943 m_constraints.ordered_remove (con_idx);
2944 if (stats)
2945 stats->m_num_constraints++;
2947 else
2949 con_idx++;
2953 /* Finally, delete any ECs that purely contain constants and aren't
2954 referenced by any constraints. */
2955 for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
2957 equiv_class *ec = m_equiv_classes[ec_idx];
2958 if (ec->m_vars.length () == 0)
2960 equiv_class_id ec_id (ec_idx);
2961 bool has_constraint = false;
2962 for (unsigned con_idx = 0; con_idx < m_constraints.length ();
2963 con_idx++)
2965 constraint *c = &m_constraints[con_idx];
2966 if (c->m_lhs == ec_id
2967 || c->m_rhs == ec_id)
2969 has_constraint = true;
2970 break;
2973 if (!has_constraint)
2975 delete ec;
2976 m_equiv_classes.ordered_remove (ec_idx);
2977 if (stats)
2978 stats->m_num_equiv_classes++;
2980 /* Renumber constraints that refer to ECs that have
2981 had their idx changed. */
2982 for (unsigned con_idx = 0; con_idx < m_constraints.length ();
2983 con_idx++)
2985 constraint *c = &m_constraints[con_idx];
2986 c->m_lhs.update_for_removal (ec_idx);
2987 c->m_rhs.update_for_removal (ec_idx);
2990 /* Likewise for m_bounded_ranges_constraints. */
2991 for (unsigned r_idx = 0;
2992 r_idx < m_bounded_ranges_constraints.length ();
2993 r_idx++)
2995 bounded_ranges_constraint *brc
2996 = &m_bounded_ranges_constraints[r_idx];
2997 brc->m_ec_id.update_for_removal (ec_idx);
3000 continue;
3003 ec_idx++;
3006 validate ();
3009 /* Implementation of PurgeCriteria: purge svalues that are not live
3010 with respect to LIVE_SVALUES and MODEL. */
3012 class dead_svalue_purger
3014 public:
3015 dead_svalue_purger (const svalue_set &live_svalues,
3016 const region_model *model)
3017 : m_live_svalues (live_svalues), m_model (model)
3021 bool should_purge_p (const svalue *sval) const
3023 return !sval->live_p (&m_live_svalues, m_model);
3026 private:
3027 const svalue_set &m_live_svalues;
3028 const region_model *m_model;
3031 /* Purge dead svalues from equivalence classes and update constraints
3032 accordingly. */
3034 void
3035 constraint_manager::
3036 on_liveness_change (const svalue_set &live_svalues,
3037 const region_model *model)
3039 dead_svalue_purger p (live_svalues, model);
3040 purge (p, NULL);
3043 class svalue_purger
3045 public:
3046 svalue_purger (const svalue *sval) : m_sval (sval) {}
3048 bool should_purge_p (const svalue *sval) const
3050 return sval->involves_p (m_sval);
3053 private:
3054 const svalue *m_sval;
3057 /* Purge any state involving SVAL. */
3059 void
3060 constraint_manager::purge_state_involving (const svalue *sval)
3062 svalue_purger p (sval);
3063 purge (p, NULL);
3066 /* Comparator for use by constraint_manager::canonicalize.
3067 Sort a pair of equiv_class instances, using the representative
3068 svalue as a sort key. */
3070 static int
3071 equiv_class_cmp (const void *p1, const void *p2)
3073 const equiv_class *ec1 = *(const equiv_class * const *)p1;
3074 const equiv_class *ec2 = *(const equiv_class * const *)p2;
3076 const svalue *rep1 = ec1->get_representative ();
3077 const svalue *rep2 = ec2->get_representative ();
3079 gcc_assert (rep1);
3080 gcc_assert (rep2);
3082 return svalue::cmp_ptr (rep1, rep2);
3085 /* Comparator for use by constraint_manager::canonicalize.
3086 Sort a pair of constraint instances. */
3088 static int
3089 constraint_cmp (const void *p1, const void *p2)
3091 const constraint *c1 = (const constraint *)p1;
3092 const constraint *c2 = (const constraint *)p2;
3093 int lhs_cmp = c1->m_lhs.as_int () - c2->m_lhs.as_int ();
3094 if (lhs_cmp)
3095 return lhs_cmp;
3096 int rhs_cmp = c1->m_rhs.as_int () - c2->m_rhs.as_int ();
3097 if (rhs_cmp)
3098 return rhs_cmp;
3099 return c1->m_op - c2->m_op;
3102 /* Purge redundant equivalence classes and constraints, and reorder them
3103 within this constraint_manager into a canonical order, to increase the
3104 chances of finding equality with another instance. */
3106 void
3107 constraint_manager::canonicalize ()
3109 /* First, sort svalues within the ECs. */
3110 unsigned i;
3111 equiv_class *ec;
3112 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
3113 ec->canonicalize ();
3115 /* TODO: remove constraints where both sides have a constant, and are
3116 thus implicit. But does this break transitivity? */
3118 /* We will be purging and reordering ECs.
3119 We will need to remap the equiv_class_ids in the constraints,
3120 so we need to store the original index of each EC.
3121 Build a lookup table, mapping from the representative svalue
3122 to the original equiv_class_id of that svalue. */
3123 hash_map<const svalue *, equiv_class_id> original_ec_id;
3124 const unsigned orig_num_equiv_classes = m_equiv_classes.length ();
3125 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
3127 const svalue *rep = ec->get_representative ();
3128 gcc_assert (rep);
3129 original_ec_id.put (rep, i);
3132 /* Find ECs used by constraints. */
3133 hash_set<const equiv_class *> used_ecs;
3134 constraint *c;
3135 FOR_EACH_VEC_ELT (m_constraints, i, c)
3137 used_ecs.add (m_equiv_classes[c->m_lhs.as_int ()]);
3138 used_ecs.add (m_equiv_classes[c->m_rhs.as_int ()]);
3141 for (const auto &iter : m_bounded_ranges_constraints)
3142 used_ecs.add (m_equiv_classes[iter.m_ec_id.as_int ()]);
3144 /* Purge unused ECs: those that aren't used by constraints and
3145 that effectively have only one svalue (either in m_constant
3146 or in m_vars). */
3148 /* "unordered remove if" from a vec. */
3149 unsigned i = 0;
3150 while (i < m_equiv_classes.length ())
3152 equiv_class *ec = m_equiv_classes[i];
3153 if (!used_ecs.contains (ec)
3154 && !ec->contains_non_constant_p ())
3156 m_equiv_classes.unordered_remove (i);
3157 delete ec;
3159 else
3160 i++;
3164 /* Next, sort the surviving ECs into a canonical order. */
3165 m_equiv_classes.qsort (equiv_class_cmp);
3167 /* Populate ec_id_map based on the old vs new EC ids. */
3168 one_way_id_map<equiv_class_id> ec_id_map (orig_num_equiv_classes);
3169 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
3171 const svalue *rep = ec->get_representative ();
3172 gcc_assert (rep);
3173 ec_id_map.put (*original_ec_id.get (rep), i);
3176 /* Use ec_id_map to update the EC ids within the constraints. */
3177 FOR_EACH_VEC_ELT (m_constraints, i, c)
3179 ec_id_map.update (&c->m_lhs);
3180 ec_id_map.update (&c->m_rhs);
3183 for (auto &iter : m_bounded_ranges_constraints)
3184 ec_id_map.update (&iter.m_ec_id);
3186 /* Finally, sort the constraints. */
3187 m_constraints.qsort (constraint_cmp);
3190 /* Concrete subclass of fact_visitor for use by constraint_manager::merge.
3191 For every fact in CM_A, see if it is also true in *CM_B. Add such
3192 facts to *OUT. */
3194 class merger_fact_visitor : public fact_visitor
3196 public:
3197 merger_fact_visitor (const constraint_manager *cm_b,
3198 constraint_manager *out)
3199 : m_cm_b (cm_b), m_out (out)
3202 void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs)
3203 final override
3205 /* Special-case for widening. */
3206 if (lhs->get_kind () == SK_WIDENING)
3207 if (!m_cm_b->get_equiv_class_by_svalue (lhs, NULL))
3209 /* LHS isn't constrained within m_cm_b. */
3210 bool sat = m_out->add_constraint (lhs, code, rhs);
3211 gcc_assert (sat);
3212 return;
3215 if (m_cm_b->eval_condition (lhs, code, rhs).is_true ())
3217 bool sat = m_out->add_constraint (lhs, code, rhs);
3218 if (!sat)
3220 /* If -fanalyzer-transitivity is off, we can encounter cases
3221 where at least one of the two constraint_managers being merged
3222 is infeasible, but we only discover that infeasibility
3223 during merging (PR analyzer/96650).
3224 Silently drop such constraints. */
3225 gcc_assert (!flag_analyzer_transitivity);
3230 void on_ranges (const svalue *lhs_sval,
3231 const bounded_ranges *ranges) final override
3233 for (const auto &iter : m_cm_b->m_bounded_ranges_constraints)
3235 const equiv_class &ec_rhs = iter.m_ec_id.get_obj (*m_cm_b);
3236 for (unsigned i = 0; i < ec_rhs.m_vars.length (); i++)
3238 const svalue *rhs_sval = ec_rhs.m_vars[i];
3239 if (lhs_sval == rhs_sval)
3241 /* Union of the two ranges. */
3242 auto_vec <const bounded_ranges *> pair (2);
3243 pair.quick_push (ranges);
3244 pair.quick_push (iter.m_ranges);
3245 bounded_ranges_manager *ranges_mgr
3246 = m_cm_b->get_range_manager ();
3247 const bounded_ranges *union_
3248 = ranges_mgr->get_or_create_union (pair);
3249 bool sat = m_out->add_bounded_ranges (lhs_sval, union_);
3250 gcc_assert (sat);
3256 private:
3257 const constraint_manager *m_cm_b;
3258 constraint_manager *m_out;
3261 /* Use MERGER to merge CM_A and CM_B into *OUT.
3262 If one thinks of a constraint_manager as a subset of N-dimensional
3263 space, this takes the union of the points of CM_A and CM_B, and
3264 expresses that into *OUT. Alternatively, it can be thought of
3265 as the intersection of the constraints. */
3267 void
3268 constraint_manager::merge (const constraint_manager &cm_a,
3269 const constraint_manager &cm_b,
3270 constraint_manager *out)
3272 /* Merge the equivalence classes and constraints.
3273 The easiest way to do this seems to be to enumerate all of the facts
3274 in cm_a, see which are also true in cm_b,
3275 and add those to *OUT. */
3276 merger_fact_visitor v (&cm_b, out);
3277 cm_a.for_each_fact (&v);
3280 /* Call VISITOR's on_fact vfunc repeatedly to express the various
3281 equivalence classes and constraints.
3282 This is used by constraint_manager::merge to find the common
3283 facts between two input constraint_managers. */
3285 void
3286 constraint_manager::for_each_fact (fact_visitor *visitor) const
3288 /* First, call EQ_EXPR within the various equivalence classes. */
3289 unsigned ec_idx;
3290 equiv_class *ec;
3291 FOR_EACH_VEC_ELT (m_equiv_classes, ec_idx, ec)
3293 if (ec->m_cst_sval)
3295 unsigned i;
3296 const svalue *sval;
3297 FOR_EACH_VEC_ELT (ec->m_vars, i, sval)
3298 visitor->on_fact (ec->m_cst_sval, EQ_EXPR, sval);
3300 for (unsigned i = 0; i < ec->m_vars.length (); i++)
3301 for (unsigned j = i + 1; j < ec->m_vars.length (); j++)
3302 visitor->on_fact (ec->m_vars[i], EQ_EXPR, ec->m_vars[j]);
3305 /* Now, express the various constraints. */
3306 unsigned con_idx;
3307 constraint *c;
3308 FOR_EACH_VEC_ELT (m_constraints, con_idx, c)
3310 const equiv_class &ec_lhs = c->m_lhs.get_obj (*this);
3311 const equiv_class &ec_rhs = c->m_rhs.get_obj (*this);
3312 enum tree_code code = constraint_tree_code (c->m_op);
3314 if (ec_lhs.m_cst_sval)
3316 for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
3318 visitor->on_fact (ec_lhs.m_cst_sval, code, ec_rhs.m_vars[j]);
3321 for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++)
3323 if (ec_rhs.m_cst_sval)
3324 visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_cst_sval);
3325 for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
3326 visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_vars[j]);
3330 for (const auto &iter : m_bounded_ranges_constraints)
3332 const equiv_class &ec_lhs = iter.m_ec_id.get_obj (*this);
3333 for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++)
3335 const svalue *lhs_sval = ec_lhs.m_vars[i];
3336 visitor->on_ranges (lhs_sval, iter.m_ranges);
3341 /* Subclass of fact_visitor for use by
3342 constraint_manager::replay_call_summary. */
3344 class replay_fact_visitor : public fact_visitor
3346 public:
3347 replay_fact_visitor (call_summary_replay &r,
3348 constraint_manager *out)
3349 : m_r (r), m_out (out), m_feasible (true)
3352 bool feasible_p () const { return m_feasible; }
3354 void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs)
3355 final override
3357 const svalue *caller_lhs = m_r.convert_svalue_from_summary (lhs);
3358 if (!caller_lhs)
3359 return;
3360 const svalue *caller_rhs = m_r.convert_svalue_from_summary (rhs);
3361 if (!caller_rhs)
3362 return;
3363 if (!m_out->add_constraint (caller_lhs, code, caller_rhs))
3364 m_feasible = false;
3367 void on_ranges (const svalue *lhs_sval,
3368 const bounded_ranges *ranges) final override
3370 const svalue *caller_lhs = m_r.convert_svalue_from_summary (lhs_sval);
3371 if (!caller_lhs)
3372 return;
3373 if (!m_out->add_bounded_ranges (caller_lhs, ranges))
3374 m_feasible = false;
3377 private:
3378 call_summary_replay &m_r;
3379 constraint_manager *m_out;
3380 bool m_feasible;
3383 /* Attempt to use R to replay the constraints from SUMMARY into this object.
3384 Return true if it is feasible. */
3386 bool
3387 constraint_manager::replay_call_summary (call_summary_replay &r,
3388 const constraint_manager &summary)
3390 replay_fact_visitor v (r, this);
3391 summary.for_each_fact (&v);
3392 return v.feasible_p ();
3395 /* Assert that this object is valid. */
3397 void
3398 constraint_manager::validate () const
3400 /* Skip this in a release build. */
3401 #if !CHECKING_P
3402 return;
3403 #endif
3405 int i;
3406 equiv_class *ec;
3407 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
3409 gcc_assert (ec);
3411 int j;
3412 const svalue *sval;
3413 FOR_EACH_VEC_ELT (ec->m_vars, j, sval)
3414 gcc_assert (sval);
3415 if (ec->m_constant)
3417 gcc_assert (CONSTANT_CLASS_P (ec->m_constant));
3418 gcc_assert (ec->m_cst_sval);
3420 #if 0
3421 else
3422 gcc_assert (ec->m_vars.length () > 0);
3423 #endif
3426 constraint *c;
3427 FOR_EACH_VEC_ELT (m_constraints, i, c)
3429 gcc_assert (!c->m_lhs.null_p ());
3430 gcc_assert (c->m_lhs.as_int () < (int)m_equiv_classes.length ());
3431 gcc_assert (!c->m_rhs.null_p ());
3432 gcc_assert (c->m_rhs.as_int () < (int)m_equiv_classes.length ());
3435 for (const auto &iter : m_bounded_ranges_constraints)
3437 gcc_assert (!iter.m_ec_id.null_p ());
3438 gcc_assert (iter.m_ec_id.as_int () < (int)m_equiv_classes.length ());
3442 bounded_ranges_manager *
3443 constraint_manager::get_range_manager () const
3445 return m_mgr->get_range_manager ();
3448 #if CHECKING_P
3450 namespace selftest {
3452 /* Various constraint_manager selftests.
3453 These have to be written in terms of a region_model, since
3454 the latter is responsible for managing svalue instances. */
3456 /* Verify that range::add_bound works as expected. */
3458 static void
3459 test_range ()
3461 tree int_0 = integer_zero_node;
3462 tree int_1 = integer_one_node;
3463 tree int_2 = build_int_cst (integer_type_node, 2);
3464 tree int_5 = build_int_cst (integer_type_node, 5);
3467 range r;
3468 ASSERT_FALSE (r.constrained_to_single_element ());
3470 /* (r >= 1). */
3471 ASSERT_TRUE (r.add_bound (GE_EXPR, int_1));
3473 /* Redundant. */
3474 ASSERT_TRUE (r.add_bound (GE_EXPR, int_0));
3475 ASSERT_TRUE (r.add_bound (GT_EXPR, int_0));
3477 ASSERT_FALSE (r.constrained_to_single_element ());
3479 /* Contradiction. */
3480 ASSERT_FALSE (r.add_bound (LT_EXPR, int_1));
3482 /* (r < 5). */
3483 ASSERT_TRUE (r.add_bound (LT_EXPR, int_5));
3484 ASSERT_FALSE (r.constrained_to_single_element ());
3486 /* Contradiction. */
3487 ASSERT_FALSE (r.add_bound (GE_EXPR, int_5));
3489 /* (r < 2). */
3490 ASSERT_TRUE (r.add_bound (LT_EXPR, int_2));
3491 ASSERT_TRUE (r.constrained_to_single_element ());
3493 /* Redundant. */
3494 ASSERT_TRUE (r.add_bound (LE_EXPR, int_1));
3495 ASSERT_TRUE (r.constrained_to_single_element ());
3499 /* Verify that setting and getting simple conditions within a region_model
3500 work (thus exercising the underlying constraint_manager). */
3502 static void
3503 test_constraint_conditions ()
3505 tree int_42 = build_int_cst (integer_type_node, 42);
3506 tree int_0 = integer_zero_node;
3508 tree x = build_global_decl ("x", integer_type_node);
3509 tree y = build_global_decl ("y", integer_type_node);
3510 tree z = build_global_decl ("z", integer_type_node);
3512 /* Self-comparisons. */
3514 region_model_manager mgr;
3515 region_model model (&mgr);
3516 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, x);
3517 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, x);
3518 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, x);
3519 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, x);
3520 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, x);
3521 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, x);
3524 /* Adding self-equality shouldn't add equiv classes. */
3526 region_model_manager mgr;
3527 region_model model (&mgr);
3528 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, x);
3529 ADD_SAT_CONSTRAINT (model, int_42, EQ_EXPR, int_42);
3530 /* ...even when done directly via svalues: */
3531 const svalue *sval_int_42 = model.get_rvalue (int_42, NULL);
3532 bool sat = model.get_constraints ()->add_constraint (sval_int_42,
3533 EQ_EXPR,
3534 sval_int_42);
3535 ASSERT_TRUE (sat);
3536 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
3539 /* x == y. */
3541 region_model_manager mgr;
3542 region_model model (&mgr);
3543 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3545 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3547 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, y);
3548 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3549 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3550 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, y);
3551 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3552 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3554 /* Swapped operands. */
3555 ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x);
3556 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3557 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3558 ASSERT_CONDITION_FALSE (model, y, NE_EXPR, x);
3559 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3560 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3562 /* Comparison with other var. */
3563 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
3564 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
3565 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3566 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
3567 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
3568 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
3571 /* x == y, then y == z */
3573 region_model_manager mgr;
3574 region_model model (&mgr);
3575 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3577 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3578 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, z);
3580 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, z);
3581 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, z);
3582 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
3583 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, z);
3584 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, z);
3585 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, z);
3588 /* x != y. */
3590 region_model_manager mgr;
3591 region_model model (&mgr);
3593 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
3595 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3596 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3597 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
3598 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
3599 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
3600 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
3602 /* Swapped operands. */
3603 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3604 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3605 ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
3606 ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
3607 ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
3608 ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
3610 /* Comparison with other var. */
3611 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
3612 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
3613 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3614 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
3615 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
3616 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
3619 /* x < y. */
3621 region_model_manager mgr;
3622 region_model model (&mgr);
3624 ADD_SAT_CONSTRAINT (model, x, LT_EXPR, y);
3626 ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
3627 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3628 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3629 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3630 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3631 ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
3633 /* Swapped operands. */
3634 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3635 ASSERT_CONDITION_FALSE (model, y, LE_EXPR, x);
3636 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3637 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3638 ASSERT_CONDITION_TRUE (model, y, GT_EXPR, x);
3639 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3642 /* x <= y. */
3644 region_model_manager mgr;
3645 region_model model (&mgr);
3647 ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
3649 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
3650 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3651 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
3652 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3653 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3654 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
3656 /* Swapped operands. */
3657 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3658 ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
3659 ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
3660 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
3661 ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
3662 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3665 /* x > y. */
3667 region_model_manager mgr;
3668 region_model model (&mgr);
3670 ADD_SAT_CONSTRAINT (model, x, GT_EXPR, y);
3672 ASSERT_CONDITION_TRUE (model, x, GT_EXPR, y);
3673 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3674 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3675 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3676 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3677 ASSERT_CONDITION_FALSE (model, x, LE_EXPR, y);
3679 /* Swapped operands. */
3680 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3681 ASSERT_CONDITION_FALSE (model, y, GE_EXPR, x);
3682 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3683 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3684 ASSERT_CONDITION_TRUE (model, y, LT_EXPR, x);
3685 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3688 /* x >= y. */
3690 region_model_manager mgr;
3691 region_model model (&mgr);
3693 ADD_SAT_CONSTRAINT (model, x, GE_EXPR, y);
3695 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
3696 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3697 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
3698 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3699 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3700 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
3702 /* Swapped operands. */
3703 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3704 ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
3705 ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
3706 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
3707 ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
3708 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3711 // TODO: implied orderings
3713 /* Constants. */
3715 region_model_manager mgr;
3716 region_model model (&mgr);
3717 ASSERT_CONDITION_FALSE (model, int_0, EQ_EXPR, int_42);
3718 ASSERT_CONDITION_TRUE (model, int_0, NE_EXPR, int_42);
3719 ASSERT_CONDITION_TRUE (model, int_0, LT_EXPR, int_42);
3720 ASSERT_CONDITION_TRUE (model, int_0, LE_EXPR, int_42);
3721 ASSERT_CONDITION_FALSE (model, int_0, GT_EXPR, int_42);
3722 ASSERT_CONDITION_FALSE (model, int_0, GE_EXPR, int_42);
3725 /* x == 0, y == 42. */
3727 region_model_manager mgr;
3728 region_model model (&mgr);
3729 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3730 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, int_42);
3732 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3733 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3734 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3735 ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
3736 ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
3737 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3740 /* Unsatisfiable combinations. */
3742 /* x == y && x != y. */
3744 region_model_manager mgr;
3745 region_model model (&mgr);
3746 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3747 ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, y);
3750 /* x == 0 then x == 42. */
3752 region_model_manager mgr;
3753 region_model model (&mgr);
3754 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3755 ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, int_42);
3758 /* x == 0 then x != 0. */
3760 region_model_manager mgr;
3761 region_model model (&mgr);
3762 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3763 ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, int_0);
3766 /* x == 0 then x > 0. */
3768 region_model_manager mgr;
3769 region_model model (&mgr);
3770 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3771 ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, int_0);
3774 /* x != y && x == y. */
3776 region_model_manager mgr;
3777 region_model model (&mgr);
3778 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
3779 ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, y);
3782 /* x <= y && x > y. */
3784 region_model_manager mgr;
3785 region_model model (&mgr);
3786 ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
3787 ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, y);
3790 // etc
3793 /* Test transitivity of conditions. */
3795 static void
3796 test_transitivity ()
3798 tree a = build_global_decl ("a", integer_type_node);
3799 tree b = build_global_decl ("b", integer_type_node);
3800 tree c = build_global_decl ("c", integer_type_node);
3801 tree d = build_global_decl ("d", integer_type_node);
3803 /* a == b, then c == d, then c == b. */
3805 region_model_manager mgr;
3806 region_model model (&mgr);
3807 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, b);
3808 ASSERT_CONDITION_UNKNOWN (model, b, EQ_EXPR, c);
3809 ASSERT_CONDITION_UNKNOWN (model, c, EQ_EXPR, d);
3810 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
3812 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, b);
3813 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
3815 ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, d);
3816 ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, d);
3817 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
3819 ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, b);
3820 ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, b);
3821 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, d);
3824 /* Transitivity: "a < b", "b < c" should imply "a < c". */
3826 region_model_manager mgr;
3827 region_model model (&mgr);
3828 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
3829 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3831 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3832 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3835 /* Transitivity: "a <= b", "b < c" should imply "a < c". */
3837 region_model_manager mgr;
3838 region_model model (&mgr);
3839 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
3840 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3842 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3843 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3846 /* Transitivity: "a <= b", "b <= c" should imply "a <= c". */
3848 region_model_manager mgr;
3849 region_model model (&mgr);
3850 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
3851 ADD_SAT_CONSTRAINT (model, b, LE_EXPR, c);
3853 ASSERT_CONDITION_TRUE (model, a, LE_EXPR, c);
3854 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
3857 /* Transitivity: "a > b", "b > c" should imply "a > c". */
3859 region_model_manager mgr;
3860 region_model model (&mgr);
3861 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3862 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3864 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
3865 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3868 /* Transitivity: "a >= b", "b > c" should imply " a > c". */
3870 region_model_manager mgr;
3871 region_model model (&mgr);
3872 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3873 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3875 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
3876 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3879 /* Transitivity: "a >= b", "b >= c" should imply "a >= c". */
3881 region_model_manager mgr;
3882 region_model model (&mgr);
3883 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3884 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c);
3886 ASSERT_CONDITION_TRUE (model, a, GE_EXPR, c);
3887 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
3890 /* Transitivity: "(a < b)", "(c < d)", "(b < c)" should
3891 imply the easy cases:
3892 (a < c)
3893 (b < d)
3894 but also that:
3895 (a < d). */
3897 region_model_manager mgr;
3898 region_model model (&mgr);
3899 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
3900 ADD_SAT_CONSTRAINT (model, c, LT_EXPR, d);
3901 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3903 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3904 ASSERT_CONDITION_TRUE (model, b, LT_EXPR, d);
3905 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, d);
3908 /* Transitivity: "a >= b", "b >= a" should imply that a == b. */
3910 region_model_manager mgr;
3911 region_model model (&mgr);
3912 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3913 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, a);
3915 // TODO:
3916 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
3918 /* The ECs for a and b should have merged, and any constraints removed. */
3919 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
3920 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
3923 /* Transitivity: "a >= b", "b > a" should be impossible. */
3925 region_model_manager mgr;
3926 region_model model (&mgr);
3927 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3928 ADD_UNSAT_CONSTRAINT (model, b, GT_EXPR, a);
3931 /* Transitivity: "a >= b", "b >= c", "c >= a" should imply
3932 that a == b == c. */
3934 region_model_manager mgr;
3935 region_model model (&mgr);
3936 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3937 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c);
3938 ADD_SAT_CONSTRAINT (model, c, GE_EXPR, a);
3940 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, c);
3943 /* Transitivity: "a > b", "b > c", "c > a"
3944 should be impossible. */
3946 region_model_manager mgr;
3947 region_model model (&mgr);
3948 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3949 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3950 ADD_UNSAT_CONSTRAINT (model, c, GT_EXPR, a);
3955 /* Test various conditionals involving constants where the results
3956 ought to be implied based on the values of the constants. */
3958 static void
3959 test_constant_comparisons ()
3961 tree int_1 = integer_one_node;
3962 tree int_3 = build_int_cst (integer_type_node, 3);
3963 tree int_4 = build_int_cst (integer_type_node, 4);
3964 tree int_5 = build_int_cst (integer_type_node, 5);
3966 tree int_1023 = build_int_cst (integer_type_node, 1023);
3967 tree int_1024 = build_int_cst (integer_type_node, 1024);
3969 tree a = build_global_decl ("a", integer_type_node);
3970 tree b = build_global_decl ("b", integer_type_node);
3972 tree a_plus_one = build2 (PLUS_EXPR, integer_type_node, a, int_1);
3974 /* Given a >= 1024, then a <= 1023 should be impossible. */
3976 region_model_manager mgr;
3977 region_model model (&mgr);
3978 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_1024);
3979 ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_1023);
3982 /* a > 4. */
3984 region_model_manager mgr;
3985 region_model model (&mgr);
3986 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_4);
3987 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, int_4);
3988 ASSERT_CONDITION_TRUE (model, a, NE_EXPR, int_3);
3989 ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_5);
3992 /* a <= 4. */
3994 region_model_manager mgr;
3995 region_model model (&mgr);
3996 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3997 ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_4);
3998 ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_5);
3999 ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_3);
4002 /* If "a > b" and "a == 3", then "b == 4" ought to be unsatisfiable. */
4004 region_model_manager mgr;
4005 region_model model (&mgr);
4006 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
4007 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_3);
4008 ADD_UNSAT_CONSTRAINT (model, b, EQ_EXPR, int_4);
4011 /* Various tests of int ranges where there is only one possible candidate. */
4013 /* If "a <= 4" && "a > 3", then "a == 4",
4014 assuming a is of integral type. */
4016 region_model_manager mgr;
4017 region_model model (&mgr);
4018 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
4019 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
4020 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
4023 /* If "a > 3" && "a <= 4", then "a == 4",
4024 assuming a is of integral type. */
4026 region_model_manager mgr;
4027 region_model model (&mgr);
4028 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
4029 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
4030 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
4032 /* If "a > 3" && "a < 5", then "a == 4",
4033 assuming a is of integral type. */
4035 region_model_manager mgr;
4036 region_model model (&mgr);
4037 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
4038 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
4039 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
4041 /* If "a >= 4" && "a < 5", then "a == 4",
4042 assuming a is of integral type. */
4044 region_model_manager mgr;
4045 region_model model (&mgr);
4046 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
4047 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
4048 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
4050 /* If "a >= 4" && "a <= 4", then "a == 4". */
4052 region_model_manager mgr;
4053 region_model model (&mgr);
4054 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
4055 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
4056 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
4060 /* As above, but for floating-point:
4061 if "f > 3" && "f <= 4" we don't know that f == 4. */
4063 tree f = build_global_decl ("f", double_type_node);
4064 tree float_3 = build_real_from_int_cst (double_type_node, int_3);
4065 tree float_4 = build_real_from_int_cst (double_type_node, int_4);
4067 region_model_manager mgr;
4068 region_model model (&mgr);
4069 ADD_SAT_CONSTRAINT (model, f, GT_EXPR, float_3);
4070 ADD_SAT_CONSTRAINT (model, f, LE_EXPR, float_4);
4071 ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, float_4);
4072 ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, int_4);
4075 /* "a > 3 && a <= 3" should be impossible. */
4077 region_model_manager mgr;
4078 region_model model (&mgr);
4079 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
4080 ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_3);
4083 /* "(a + 1) > 3 && a < 3" should be impossible. */
4085 region_model_manager mgr;
4087 region_model model (&mgr);
4088 ADD_SAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3);
4089 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_3);
4092 region_model model (&mgr);
4093 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_3);
4094 ADD_UNSAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3);
4098 /* "3 < a < 4" should be impossible for integer a. */
4100 region_model_manager mgr;
4102 region_model model (&mgr);
4103 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
4104 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
4107 region_model model (&mgr);
4108 ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a);
4109 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
4110 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
4111 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
4114 region_model model (&mgr);
4115 ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a);
4116 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
4117 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
4118 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
4121 region_model model (&mgr);
4122 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_4);
4123 ADD_UNSAT_CONSTRAINT (model, int_3, LT_EXPR, a);
4126 region_model model (&mgr);
4127 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
4128 ADD_UNSAT_CONSTRAINT (model, int_4, GT_EXPR, a);
4131 region_model model (&mgr);
4132 ADD_SAT_CONSTRAINT (model, int_4, GT_EXPR, a);
4133 ADD_UNSAT_CONSTRAINT (model, a, GT_EXPR, int_3);
4138 /* Verify various lower-level implementation details about
4139 constraint_manager. */
4141 static void
4142 test_constraint_impl ()
4144 tree int_42 = build_int_cst (integer_type_node, 42);
4145 tree int_0 = integer_zero_node;
4147 tree x = build_global_decl ("x", integer_type_node);
4148 tree y = build_global_decl ("y", integer_type_node);
4149 tree z = build_global_decl ("z", integer_type_node);
4151 /* x == y. */
4153 region_model_manager mgr;
4154 region_model model (&mgr);
4156 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
4158 /* Assert various things about the insides of model. */
4159 constraint_manager *cm = model.get_constraints ();
4160 ASSERT_EQ (cm->m_constraints.length (), 0);
4161 ASSERT_EQ (cm->m_equiv_classes.length (), 1);
4164 /* y <= z; x == y. */
4166 region_model_manager mgr;
4167 region_model model (&mgr);
4168 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
4169 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
4171 ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
4172 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
4173 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
4175 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
4177 /* Assert various things about the insides of model. */
4178 constraint_manager *cm = model.get_constraints ();
4179 ASSERT_EQ (cm->m_constraints.length (), 1);
4180 ASSERT_EQ (cm->m_equiv_classes.length (), 2);
4182 /* Ensure that we merged the constraints. */
4183 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
4186 /* y <= z; y == x. */
4188 region_model_manager mgr;
4189 region_model model (&mgr);
4190 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
4191 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
4193 ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
4194 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
4195 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
4197 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, x);
4199 /* Assert various things about the insides of model. */
4200 constraint_manager *cm = model.get_constraints ();
4201 ASSERT_EQ (cm->m_constraints.length (), 1);
4202 ASSERT_EQ (cm->m_equiv_classes.length (), 2);
4204 /* Ensure that we merged the constraints. */
4205 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
4208 /* x == 0, then x != 42. */
4210 region_model_manager mgr;
4211 region_model model (&mgr);
4213 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
4214 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, int_42);
4216 /* Assert various things about the insides of model. */
4217 constraint_manager *cm = model.get_constraints ();
4218 ASSERT_EQ (cm->m_constraints.length (), 0);
4219 ASSERT_EQ (cm->m_equiv_classes.length (), 1);
4222 // TODO: selftest for merging ecs "in the middle"
4223 // where a non-final one gets overwritten
4225 // TODO: selftest where there are pre-existing constraints
4228 /* Check that operator== and hashing works as expected for the
4229 various types. */
4231 static void
4232 test_equality ()
4234 tree x = build_global_decl ("x", integer_type_node);
4235 tree y = build_global_decl ("y", integer_type_node);
4238 region_model_manager mgr;
4239 region_model model0 (&mgr);
4240 region_model model1 (&mgr);
4242 constraint_manager *cm0 = model0.get_constraints ();
4243 constraint_manager *cm1 = model1.get_constraints ();
4245 ASSERT_EQ (cm0->hash (), cm1->hash ());
4246 ASSERT_EQ (*cm0, *cm1);
4248 ASSERT_EQ (model0.hash (), model1.hash ());
4249 ASSERT_EQ (model0, model1);
4251 ADD_SAT_CONSTRAINT (model1, x, EQ_EXPR, y);
4252 ASSERT_NE (cm0->hash (), cm1->hash ());
4253 ASSERT_NE (*cm0, *cm1);
4255 ASSERT_NE (model0.hash (), model1.hash ());
4256 ASSERT_NE (model0, model1);
4258 region_model model2 (&mgr);
4259 constraint_manager *cm2 = model2.get_constraints ();
4260 /* Make the same change to cm2. */
4261 ADD_SAT_CONSTRAINT (model2, x, EQ_EXPR, y);
4262 ASSERT_EQ (cm1->hash (), cm2->hash ());
4263 ASSERT_EQ (*cm1, *cm2);
4265 ASSERT_EQ (model1.hash (), model2.hash ());
4266 ASSERT_EQ (model1, model2);
4270 /* Verify tracking inequality of a variable against many constants. */
4272 static void
4273 test_many_constants ()
4275 region_model_manager mgr;
4276 program_point point (program_point::origin (mgr));
4277 tree a = build_global_decl ("a", integer_type_node);
4279 region_model model (&mgr);
4280 auto_vec<tree> constants;
4281 for (int i = 0; i < 20; i++)
4283 tree constant = build_int_cst (integer_type_node, i);
4284 constants.safe_push (constant);
4285 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, constant);
4287 /* Merge, and check the result. */
4288 region_model other (model);
4290 region_model merged (&mgr);
4291 ASSERT_TRUE (model.can_merge_with_p (other, point, &merged));
4292 model.canonicalize ();
4293 merged.canonicalize ();
4294 ASSERT_EQ (model, merged);
4296 for (int j = 0; j <= i; j++)
4297 ASSERT_CONDITION_TRUE (model, a, NE_EXPR, constants[j]);
4301 /* Verify that purging state relating to a variable doesn't leave stray
4302 equivalence classes (after canonicalization). */
4304 static void
4305 test_purging (void)
4307 tree int_0 = integer_zero_node;
4308 tree a = build_global_decl ("a", integer_type_node);
4309 tree b = build_global_decl ("b", integer_type_node);
4311 /* "a != 0". */
4313 region_model_manager mgr;
4314 region_model model (&mgr);
4315 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
4316 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4317 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4319 /* Purge state for "a". */
4320 const svalue *sval_a = model.get_rvalue (a, NULL);
4321 model.purge_state_involving (sval_a, NULL);
4322 model.canonicalize ();
4323 /* We should have an empty constraint_manager. */
4324 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
4325 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4328 /* "a != 0" && "b != 0". */
4330 region_model_manager mgr;
4331 region_model model (&mgr);
4332 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
4333 ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
4334 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 3);
4335 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 2);
4337 /* Purge state for "a". */
4338 const svalue *sval_a = model.get_rvalue (a, NULL);
4339 model.purge_state_involving (sval_a, NULL);
4340 model.canonicalize ();
4341 /* We should just have the constraint/ECs involving b != 0. */
4342 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4343 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4344 ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
4347 /* "a != 0" && "b == 0". */
4349 region_model_manager mgr;
4350 region_model model (&mgr);
4351 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
4352 ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
4353 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4354 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4356 /* Purge state for "a". */
4357 const svalue *sval_a = model.get_rvalue (a, NULL);
4358 model.purge_state_involving (sval_a, NULL);
4359 model.canonicalize ();
4360 /* We should just have the EC involving b == 0. */
4361 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4362 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4363 ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
4366 /* "a == 0". */
4368 region_model_manager mgr;
4369 region_model model (&mgr);
4370 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4371 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4372 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4374 /* Purge state for "a". */
4375 const svalue *sval_a = model.get_rvalue (a, NULL);
4376 model.purge_state_involving (sval_a, NULL);
4377 model.canonicalize ();
4378 /* We should have an empty constraint_manager. */
4379 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
4380 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4383 /* "a == 0" && "b != 0". */
4385 region_model_manager mgr;
4386 region_model model (&mgr);
4387 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4388 ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
4389 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4390 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4392 /* Purge state for "a". */
4393 const svalue *sval_a = model.get_rvalue (a, NULL);
4394 model.purge_state_involving (sval_a, NULL);
4395 model.canonicalize ();
4396 /* We should just have the constraint/ECs involving b != 0. */
4397 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4398 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4399 ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
4402 /* "a == 0" && "b == 0". */
4404 region_model_manager mgr;
4405 region_model model (&mgr);
4406 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4407 ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
4408 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4409 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4411 /* Purge state for "a". */
4412 const svalue *sval_a = model.get_rvalue (a, NULL);
4413 model.purge_state_involving (sval_a, NULL);
4414 model.canonicalize ();
4415 /* We should just have the EC involving b == 0. */
4416 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4417 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4418 ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
4422 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4424 static void
4425 assert_dump_bounded_range_eq (const location &loc,
4426 const bounded_range &range,
4427 const char *expected)
4429 auto_fix_quotes sentinel;
4430 pretty_printer pp;
4431 pp_format_decoder (&pp) = default_tree_printer;
4432 range.dump_to_pp (&pp, false);
4433 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4436 /* Assert that BR.dump (false) is EXPECTED. */
4438 #define ASSERT_DUMP_BOUNDED_RANGE_EQ(BR, EXPECTED) \
4439 SELFTEST_BEGIN_STMT \
4440 assert_dump_bounded_range_eq ((SELFTEST_LOCATION), (BR), (EXPECTED)); \
4441 SELFTEST_END_STMT
4443 /* Verify that bounded_range works as expected. */
4445 static void
4446 test_bounded_range ()
4448 tree u8_0 = build_int_cst (unsigned_char_type_node, 0);
4449 tree u8_1 = build_int_cst (unsigned_char_type_node, 1);
4450 tree u8_64 = build_int_cst (unsigned_char_type_node, 64);
4451 tree u8_128 = build_int_cst (unsigned_char_type_node, 128);
4452 tree u8_255 = build_int_cst (unsigned_char_type_node, 255);
4454 tree s8_0 = build_int_cst (signed_char_type_node, 0);
4455 tree s8_1 = build_int_cst (signed_char_type_node, 1);
4456 tree s8_2 = build_int_cst (signed_char_type_node, 2);
4458 bounded_range br_u8_0 (u8_0, u8_0);
4459 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0, "0");
4460 ASSERT_TRUE (br_u8_0.contains_p (u8_0));
4461 ASSERT_FALSE (br_u8_0.contains_p (u8_1));
4462 ASSERT_TRUE (br_u8_0.contains_p (s8_0));
4463 ASSERT_FALSE (br_u8_0.contains_p (s8_1));
4465 bounded_range br_u8_0_1 (u8_0, u8_1);
4466 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0_1, "[0, 1]");
4468 bounded_range tmp (NULL_TREE, NULL_TREE);
4469 ASSERT_TRUE (br_u8_0.intersects_p (br_u8_0_1, &tmp));
4470 ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "0");
4472 bounded_range br_u8_64_128 (u8_64, u8_128);
4473 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_64_128, "[64, 128]");
4475 ASSERT_FALSE (br_u8_0.intersects_p (br_u8_64_128, NULL));
4476 ASSERT_FALSE (br_u8_64_128.intersects_p (br_u8_0, NULL));
4478 bounded_range br_u8_128_255 (u8_128, u8_255);
4479 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_128_255, "[128, 255]");
4480 ASSERT_TRUE (br_u8_128_255.intersects_p (br_u8_64_128, &tmp));
4481 ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "128");
4483 bounded_range br_s8_2 (s8_2, s8_2);
4484 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2, "2");
4485 bounded_range br_s8_2_u8_255 (s8_2, u8_255);
4486 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2_u8_255, "[2, 255]");
4489 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4491 static void
4492 assert_dump_bounded_ranges_eq (const location &loc,
4493 const bounded_ranges *ranges,
4494 const char *expected)
4496 auto_fix_quotes sentinel;
4497 pretty_printer pp;
4498 pp_format_decoder (&pp) = default_tree_printer;
4499 ranges->dump_to_pp (&pp, false);
4500 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4503 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4505 static void
4506 assert_dump_bounded_ranges_eq (const location &loc,
4507 const bounded_ranges &ranges,
4508 const char *expected)
4510 auto_fix_quotes sentinel;
4511 pretty_printer pp;
4512 pp_format_decoder (&pp) = default_tree_printer;
4513 ranges.dump_to_pp (&pp, false);
4514 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4517 /* Assert that BRS.dump (false) is EXPECTED. */
4519 #define ASSERT_DUMP_BOUNDED_RANGES_EQ(BRS, EXPECTED) \
4520 SELFTEST_BEGIN_STMT \
4521 assert_dump_bounded_ranges_eq ((SELFTEST_LOCATION), (BRS), (EXPECTED)); \
4522 SELFTEST_END_STMT
4524 /* Verify that the bounded_ranges class works as expected. */
4526 static void
4527 test_bounded_ranges ()
4529 bounded_ranges_manager mgr;
4531 tree ch0 = build_int_cst (unsigned_char_type_node, 0);
4532 tree ch1 = build_int_cst (unsigned_char_type_node, 1);
4533 tree ch2 = build_int_cst (unsigned_char_type_node, 2);
4534 tree ch3 = build_int_cst (unsigned_char_type_node, 3);
4535 tree ch128 = build_int_cst (unsigned_char_type_node, 128);
4536 tree ch129 = build_int_cst (unsigned_char_type_node, 129);
4537 tree ch254 = build_int_cst (unsigned_char_type_node, 254);
4538 tree ch255 = build_int_cst (unsigned_char_type_node, 255);
4540 const bounded_ranges *empty = mgr.get_or_create_empty ();
4541 ASSERT_DUMP_BOUNDED_RANGES_EQ (empty, "{}");
4543 const bounded_ranges *point0 = mgr.get_or_create_point (ch0);
4544 ASSERT_DUMP_BOUNDED_RANGES_EQ (point0, "{0}");
4546 const bounded_ranges *point1 = mgr.get_or_create_point (ch1);
4547 ASSERT_DUMP_BOUNDED_RANGES_EQ (point1, "{1}");
4549 const bounded_ranges *point2 = mgr.get_or_create_point (ch2);
4550 ASSERT_DUMP_BOUNDED_RANGES_EQ (point2, "{2}");
4552 const bounded_ranges *range0_128 = mgr.get_or_create_range (ch0, ch128);
4553 ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_128, "{[0, 128]}");
4555 const bounded_ranges *range0_255 = mgr.get_or_create_range (ch0, ch255);
4556 ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_255, "{[0, 255]}");
4558 ASSERT_FALSE (empty->contain_p (ch0));
4559 ASSERT_FALSE (empty->contain_p (ch1));
4560 ASSERT_FALSE (empty->contain_p (ch255));
4562 ASSERT_TRUE (point0->contain_p (ch0));
4563 ASSERT_FALSE (point0->contain_p (ch1));
4564 ASSERT_FALSE (point0->contain_p (ch255));
4566 ASSERT_FALSE (point1->contain_p (ch0));
4567 ASSERT_TRUE (point1->contain_p (ch1));
4568 ASSERT_FALSE (point0->contain_p (ch255));
4570 ASSERT_TRUE (range0_128->contain_p (ch0));
4571 ASSERT_TRUE (range0_128->contain_p (ch1));
4572 ASSERT_TRUE (range0_128->contain_p (ch128));
4573 ASSERT_FALSE (range0_128->contain_p (ch129));
4574 ASSERT_FALSE (range0_128->contain_p (ch254));
4575 ASSERT_FALSE (range0_128->contain_p (ch255));
4577 const bounded_ranges *inv0_128
4578 = mgr.get_or_create_inverse (range0_128, unsigned_char_type_node);
4579 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv0_128, "{[129, 255]}");
4581 const bounded_ranges *range128_129 = mgr.get_or_create_range (ch128, ch129);
4582 ASSERT_DUMP_BOUNDED_RANGES_EQ (range128_129, "{[128, 129]}");
4584 const bounded_ranges *inv128_129
4585 = mgr.get_or_create_inverse (range128_129, unsigned_char_type_node);
4586 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv128_129, "{[0, 127], [130, 255]}");
4588 /* Intersection. */
4590 /* Intersection of disjoint ranges should be empty set. */
4591 const bounded_ranges *intersect0_1
4592 = mgr.get_or_create_intersection (point0, point1);
4593 ASSERT_DUMP_BOUNDED_RANGES_EQ (intersect0_1, "{}");
4596 /* Various tests of "union of ranges". */
4599 /* Touching points should be merged into a range. */
4600 auto_vec <const bounded_ranges *> v;
4601 v.safe_push (point0);
4602 v.safe_push (point1);
4603 const bounded_ranges *union_0_and_1 = mgr.get_or_create_union (v);
4604 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_0_and_1, "{[0, 1]}");
4608 /* Overlapping and out-of-order. */
4609 auto_vec <const bounded_ranges *> v;
4610 v.safe_push (inv0_128); // {[129, 255]}
4611 v.safe_push (range128_129);
4612 const bounded_ranges *union_129_255_and_128_129
4613 = mgr.get_or_create_union (v);
4614 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_129_255_and_128_129, "{[128, 255]}");
4618 /* Union of R and inverse(R) should be full range of type. */
4619 auto_vec <const bounded_ranges *> v;
4620 v.safe_push (range128_129);
4621 v.safe_push (inv128_129);
4622 const bounded_ranges *union_ = mgr.get_or_create_union (v);
4623 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{[0, 255]}");
4626 /* Union with an endpoint. */
4628 const bounded_ranges *range2_to_255
4629 = mgr.get_or_create_range (ch2, ch255);
4630 ASSERT_DUMP_BOUNDED_RANGES_EQ (range2_to_255, "{[2, 255]}");
4631 auto_vec <const bounded_ranges *> v;
4632 v.safe_push (point0);
4633 v.safe_push (point2);
4634 v.safe_push (range2_to_255);
4635 const bounded_ranges *union_ = mgr.get_or_create_union (v);
4636 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{0, [2, 255]}");
4639 /* Construct from vector of bounded_range. */
4641 auto_vec<bounded_range> v;
4642 v.safe_push (bounded_range (ch2, ch2));
4643 v.safe_push (bounded_range (ch0, ch0));
4644 v.safe_push (bounded_range (ch2, ch255));
4645 bounded_ranges br (v);
4646 ASSERT_DUMP_BOUNDED_RANGES_EQ (&br, "{0, [2, 255]}");
4650 /* Various tests of "inverse". */
4653 const bounded_ranges *range_1_to_3 = mgr.get_or_create_range (ch1, ch3);
4654 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_3, "{[1, 3]}");
4655 const bounded_ranges *inv
4656 = mgr.get_or_create_inverse (range_1_to_3, unsigned_char_type_node);
4657 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0, [4, 255]}");
4660 const bounded_ranges *range_1_to_255
4661 = mgr.get_or_create_range (ch1, ch255);
4662 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_255, "{[1, 255]}");
4663 const bounded_ranges *inv
4664 = mgr.get_or_create_inverse (range_1_to_255, unsigned_char_type_node);
4665 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0}");
4668 const bounded_ranges *range_0_to_254
4669 = mgr.get_or_create_range (ch0, ch254);
4670 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_0_to_254, "{[0, 254]}");
4671 const bounded_ranges *inv
4672 = mgr.get_or_create_inverse (range_0_to_254, unsigned_char_type_node);
4673 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{255}");
4677 /* "case 'a'-'z': case 'A-Z':" vs "default:", for ASCII. */
4679 tree ch65 = build_int_cst (unsigned_char_type_node, 65);
4680 tree ch90 = build_int_cst (unsigned_char_type_node, 90);
4682 tree ch97 = build_int_cst (unsigned_char_type_node, 97);
4683 tree ch122 = build_int_cst (unsigned_char_type_node, 122);
4685 const bounded_ranges *A_to_Z = mgr.get_or_create_range (ch65, ch90);
4686 ASSERT_DUMP_BOUNDED_RANGES_EQ (A_to_Z, "{[65, 90]}");
4687 const bounded_ranges *a_to_z = mgr.get_or_create_range (ch97, ch122);
4688 ASSERT_DUMP_BOUNDED_RANGES_EQ (a_to_z, "{[97, 122]}");
4689 auto_vec <const bounded_ranges *> v;
4690 v.safe_push (A_to_Z);
4691 v.safe_push (a_to_z);
4692 const bounded_ranges *label_ranges = mgr.get_or_create_union (v);
4693 ASSERT_DUMP_BOUNDED_RANGES_EQ (label_ranges, "{[65, 90], [97, 122]}");
4694 const bounded_ranges *default_ranges
4695 = mgr.get_or_create_inverse (label_ranges, unsigned_char_type_node);
4696 ASSERT_DUMP_BOUNDED_RANGES_EQ (default_ranges,
4697 "{[0, 64], [91, 96], [123, 255]}");
4700 /* Verify ranges from ops. */
4701 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (EQ_EXPR, ch128),
4702 "{128}");
4703 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch128),
4704 "{[0, 127], [129, 255]}");
4705 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch128),
4706 "{[0, 127]}");
4707 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch128),
4708 "{[0, 128]}");
4709 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch128),
4710 "{[128, 255]}");
4711 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch128),
4712 "{[129, 255]}");
4713 /* Ops at endpoints of type ranges. */
4714 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch0),
4715 "{0}");
4716 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch0),
4717 "{}");
4718 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch0),
4719 "{[1, 255]}");
4720 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch255),
4721 "{255}");
4722 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch255),
4723 "{}");
4724 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch255),
4725 "{[0, 254]}");
4727 /* Verify that instances are consolidated by mgr. */
4728 ASSERT_EQ (mgr.get_or_create_point (ch0),
4729 mgr.get_or_create_point (ch0));
4730 ASSERT_NE (mgr.get_or_create_point (ch0),
4731 mgr.get_or_create_point (ch1));
4734 /* Verify that we can handle sufficiently simple bitmasking operations. */
4736 static void
4737 test_bits (void)
4739 region_model_manager mgr;
4741 tree int_0 = integer_zero_node;
4742 tree int_0x80 = build_int_cst (integer_type_node, 0x80);
4743 tree int_0xff = build_int_cst (integer_type_node, 0xff);
4744 tree x = build_global_decl ("x", integer_type_node);
4746 tree x_bit_and_0x80 = build2 (BIT_AND_EXPR, integer_type_node, x, int_0x80);
4747 tree x_bit_and_0xff = build2 (BIT_AND_EXPR, integer_type_node, x, int_0xff);
4749 /* "x & 0x80 == 0x80". */
4751 region_model model (&mgr);
4752 ADD_SAT_CONSTRAINT (model, x_bit_and_0x80, EQ_EXPR, int_0x80);
4753 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0);
4754 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0x80);
4757 /* "x & 0x80 != 0x80". */
4759 region_model model (&mgr);
4760 ADD_SAT_CONSTRAINT (model, x_bit_and_0x80, NE_EXPR, int_0x80);
4761 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0);
4762 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0x80);
4765 /* "x & 0x80 == 0". */
4767 region_model model (&mgr);
4769 ADD_SAT_CONSTRAINT (model, x_bit_and_0x80, EQ_EXPR, int_0);
4770 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0);
4771 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0x80);
4774 /* "x & 0x80 != 0". */
4776 region_model model (&mgr);
4777 ADD_SAT_CONSTRAINT (model, x_bit_and_0x80, NE_EXPR, int_0);
4778 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0);
4779 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0x80);
4782 /* More that one bit in the mask. */
4784 /* "x & 0xff == 0x80". */
4786 region_model model (&mgr);
4787 ADD_SAT_CONSTRAINT (model, x_bit_and_0xff, EQ_EXPR, int_0x80);
4788 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0);
4789 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0x80);
4790 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0xff);
4793 /* "x & 0xff != 0x80". */
4795 region_model model (&mgr);
4796 ADD_SAT_CONSTRAINT (model, x_bit_and_0xff, NE_EXPR, int_0x80);
4797 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0);
4798 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0x80);
4799 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0xff);
4802 /* "x & 0xff == 0". */
4804 region_model model (&mgr);
4806 ADD_SAT_CONSTRAINT (model, x_bit_and_0xff, EQ_EXPR, int_0);
4807 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0);
4808 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0x80);
4809 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0xff);
4812 /* "x & 0xff != 0". */
4814 region_model model (&mgr);
4815 ADD_SAT_CONSTRAINT (model, x_bit_and_0xff, NE_EXPR, int_0);
4816 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, int_0);
4817 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0x80);
4818 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, int_0xff);
4822 /* Run the selftests in this file, temporarily overriding
4823 flag_analyzer_transitivity with TRANSITIVITY. */
4825 static void
4826 run_constraint_manager_tests (bool transitivity)
4828 int saved_flag_analyzer_transitivity = flag_analyzer_transitivity;
4829 flag_analyzer_transitivity = transitivity;
4831 test_range ();
4832 test_constraint_conditions ();
4833 if (flag_analyzer_transitivity)
4835 /* These selftests assume transitivity. */
4836 test_transitivity ();
4838 test_constant_comparisons ();
4839 test_constraint_impl ();
4840 test_equality ();
4841 test_many_constants ();
4842 test_purging ();
4843 test_bounded_range ();
4844 test_bounded_ranges ();
4845 test_bits ();
4847 flag_analyzer_transitivity = saved_flag_analyzer_transitivity;
4850 /* Run all of the selftests within this file. */
4852 void
4853 analyzer_constraint_manager_cc_tests ()
4855 /* Run the tests twice: with and without transitivity. */
4856 run_constraint_manager_tests (true);
4857 run_constraint_manager_tests (false);
4860 } // namespace selftest
4862 #endif /* CHECKING_P */
4864 } // namespace ana
4866 #endif /* #if ENABLE_ANALYZER */