c++: Tweaks for -Wredundant-move [PR107363]
[official-gcc.git] / gcc / analyzer / constraint-manager.cc
blobb4e51b089432fc1f5c9b060d9375524101c4caf5
1 /* Tracking equivalence classes and constraints at a point on an execution path.
2 Copyright (C) 2019-2022 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_MEMORY
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"
53 #if ENABLE_ANALYZER
55 namespace ana {
57 static tristate
58 compare_constants (tree lhs_const, enum tree_code op, tree rhs_const)
60 tree comparison
61 = fold_binary (op, boolean_type_node, lhs_const, rhs_const);
62 if (comparison == boolean_true_node)
63 return tristate (tristate::TS_TRUE);
64 if (comparison == boolean_false_node)
65 return tristate (tristate::TS_FALSE);
66 return tristate (tristate::TS_UNKNOWN);
69 /* Return true iff CST is below the maximum value for its type. */
71 static bool
72 can_plus_one_p (tree cst)
74 gcc_assert (CONSTANT_CLASS_P (cst));
75 return tree_int_cst_lt (cst, TYPE_MAX_VALUE (TREE_TYPE (cst)));
78 /* Return (CST + 1). */
80 static tree
81 plus_one (tree cst)
83 gcc_assert (CONSTANT_CLASS_P (cst));
84 gcc_assert (can_plus_one_p (cst));
85 tree result = fold_build2 (PLUS_EXPR, TREE_TYPE (cst),
86 cst, integer_one_node);
87 gcc_assert (CONSTANT_CLASS_P (result));
88 return result;
91 /* Return true iff CST is above the minimum value for its type. */
93 static bool
94 can_minus_one_p (tree cst)
96 gcc_assert (CONSTANT_CLASS_P (cst));
97 return tree_int_cst_lt (TYPE_MIN_VALUE (TREE_TYPE (cst)), cst);
100 /* Return (CST - 1). */
102 static tree
103 minus_one (tree cst)
105 gcc_assert (CONSTANT_CLASS_P (cst));
106 gcc_assert (can_minus_one_p (cst));
107 tree result = fold_build2 (MINUS_EXPR, TREE_TYPE (cst),
108 cst, integer_one_node);
109 gcc_assert (CONSTANT_CLASS_P (result));
110 return result;
113 /* struct bound. */
115 /* Ensure that this bound is closed by converting an open bound to a
116 closed one. */
118 void
119 bound::ensure_closed (enum bound_kind bound_kind)
121 if (!m_closed)
123 /* Offset by 1 in the appropriate direction.
124 For example, convert 3 < x into 4 <= x,
125 and convert x < 5 into x <= 4. */
126 gcc_assert (CONSTANT_CLASS_P (m_constant));
127 m_constant = fold_build2 (bound_kind == BK_UPPER ? MINUS_EXPR : PLUS_EXPR,
128 TREE_TYPE (m_constant),
129 m_constant, integer_one_node);
130 gcc_assert (CONSTANT_CLASS_P (m_constant));
131 m_closed = true;
135 /* Get "<=" vs "<" for this bound. */
137 const char *
138 bound::get_relation_as_str () const
140 if (m_closed)
141 return "<=";
142 else
143 return "<";
146 /* struct range. */
148 /* Dump this range to PP, which must support %E for tree. */
150 void
151 range::dump_to_pp (pretty_printer *pp) const
153 if (m_lower_bound.m_constant)
155 if (m_upper_bound.m_constant)
156 pp_printf (pp, "%qE %s x %s %qE",
157 m_lower_bound.m_constant,
158 m_lower_bound.get_relation_as_str (),
159 m_upper_bound.get_relation_as_str (),
160 m_upper_bound.m_constant);
161 else
162 pp_printf (pp, "%qE %s x",
163 m_lower_bound.m_constant,
164 m_lower_bound.get_relation_as_str ());
166 else
168 if (m_upper_bound.m_constant)
169 pp_printf (pp, "x %s %qE",
170 m_upper_bound.get_relation_as_str (),
171 m_upper_bound.m_constant);
172 else
173 pp_string (pp, "x");
177 /* Dump this range to stderr. */
179 DEBUG_FUNCTION void
180 range::dump () const
182 pretty_printer pp;
183 pp_format_decoder (&pp) = default_tree_printer;
184 pp_show_color (&pp) = pp_show_color (global_dc->printer);
185 pp.buffer->stream = stderr;
186 dump_to_pp (&pp);
187 pp_newline (&pp);
188 pp_flush (&pp);
191 /* Determine if there is only one possible value for this range.
192 If so, return the constant; otherwise, return NULL_TREE. */
194 tree
195 range::constrained_to_single_element ()
197 if (m_lower_bound.m_constant == NULL_TREE
198 || m_upper_bound.m_constant == NULL_TREE)
199 return NULL_TREE;
201 if (!INTEGRAL_TYPE_P (TREE_TYPE (m_lower_bound.m_constant)))
202 return NULL_TREE;
203 if (!INTEGRAL_TYPE_P (TREE_TYPE (m_upper_bound.m_constant)))
204 return NULL_TREE;
206 /* Convert any open bounds to closed bounds. */
207 m_lower_bound.ensure_closed (BK_LOWER);
208 m_upper_bound.ensure_closed (BK_UPPER);
210 // Are they equal?
211 tree comparison = fold_binary (EQ_EXPR, boolean_type_node,
212 m_lower_bound.m_constant,
213 m_upper_bound.m_constant);
214 if (comparison == boolean_true_node)
215 return m_lower_bound.m_constant;
216 else
217 return NULL_TREE;
220 /* Eval the condition "X OP RHS_CONST" for X within the range. */
222 tristate
223 range::eval_condition (enum tree_code op, tree rhs_const) const
225 range copy (*this);
226 if (tree single_element = copy.constrained_to_single_element ())
227 return compare_constants (single_element, op, rhs_const);
229 switch (op)
231 case EQ_EXPR:
232 if (below_lower_bound (rhs_const))
233 return tristate (tristate::TS_FALSE);
234 if (above_upper_bound (rhs_const))
235 return tristate (tristate::TS_FALSE);
236 break;
238 case LT_EXPR:
239 case LE_EXPR:
240 /* Qn: "X </<= RHS_CONST". */
241 /* If RHS_CONST > upper bound, then it's true.
242 If RHS_CONST < lower bound, then it's false.
243 Otherwise unknown. */
244 if (above_upper_bound (rhs_const))
245 return tristate (tristate::TS_TRUE);
246 if (below_lower_bound (rhs_const))
247 return tristate (tristate::TS_FALSE);
248 break;
250 case NE_EXPR:
251 /* Qn: "X != RHS_CONST". */
252 /* If RHS_CONST < lower bound, then it's true.
253 If RHS_CONST > upper bound, then it's false.
254 Otherwise unknown. */
255 if (below_lower_bound (rhs_const))
256 return tristate (tristate::TS_TRUE);
257 if (above_upper_bound (rhs_const))
258 return tristate (tristate::TS_TRUE);
259 break;
261 case GE_EXPR:
262 case GT_EXPR:
263 /* Qn: "X >=/> RHS_CONST". */
264 if (above_upper_bound (rhs_const))
265 return tristate (tristate::TS_FALSE);
266 if (below_lower_bound (rhs_const))
267 return tristate (tristate::TS_TRUE);
268 break;
270 default:
271 gcc_unreachable ();
272 break;
274 return tristate (tristate::TS_UNKNOWN);
277 /* Return true if RHS_CONST is below the lower bound of this range. */
279 bool
280 range::below_lower_bound (tree rhs_const) const
282 if (!m_lower_bound.m_constant)
283 return false;
285 return compare_constants (rhs_const,
286 m_lower_bound.m_closed ? LT_EXPR : LE_EXPR,
287 m_lower_bound.m_constant).is_true ();
290 /* Return true if RHS_CONST is above the upper bound of this range. */
292 bool
293 range::above_upper_bound (tree rhs_const) const
295 if (!m_upper_bound.m_constant)
296 return false;
298 return compare_constants (rhs_const,
299 m_upper_bound.m_closed ? GT_EXPR : GE_EXPR,
300 m_upper_bound.m_constant).is_true ();
303 /* Attempt to add B to the bound of the given kind of this range.
304 Return true if feasible; false if infeasible. */
306 bool
307 range::add_bound (bound b, enum bound_kind bound_kind)
309 b.ensure_closed (bound_kind);
311 switch (bound_kind)
313 default:
314 gcc_unreachable ();
315 case BK_LOWER:
316 /* Discard redundant bounds. */
317 if (m_lower_bound.m_constant)
319 m_lower_bound.ensure_closed (BK_LOWER);
320 if (tree_int_cst_le (b.m_constant,
321 m_lower_bound.m_constant))
322 return true;
324 if (m_upper_bound.m_constant)
326 m_upper_bound.ensure_closed (BK_UPPER);
327 /* Reject B <= V <= UPPER when B > UPPER. */
328 if (!tree_int_cst_le (b.m_constant,
329 m_upper_bound.m_constant))
330 return false;
332 m_lower_bound = b;
333 break;
335 case BK_UPPER:
336 /* Discard redundant bounds. */
337 if (m_upper_bound.m_constant)
339 m_upper_bound.ensure_closed (BK_UPPER);
340 if (!tree_int_cst_lt (b.m_constant,
341 m_upper_bound.m_constant))
342 return true;
344 if (m_lower_bound.m_constant)
346 m_lower_bound.ensure_closed (BK_LOWER);
347 /* Reject LOWER <= V <= B when LOWER > B. */
348 if (!tree_int_cst_le (m_lower_bound.m_constant,
349 b.m_constant))
350 return false;
352 m_upper_bound = b;
353 break;
356 return true;
359 /* Attempt to add (RANGE OP RHS_CONST) as a bound to this range.
360 Return true if feasible; false if infeasible. */
362 bool
363 range::add_bound (enum tree_code op, tree rhs_const)
365 switch (op)
367 default:
368 return true;
369 case LT_EXPR:
370 /* "V < RHS_CONST" */
371 return add_bound (bound (rhs_const, false), BK_UPPER);
372 case LE_EXPR:
373 /* "V <= RHS_CONST" */
374 return add_bound (bound (rhs_const, true), BK_UPPER);
375 case GE_EXPR:
376 /* "V >= RHS_CONST" */
377 return add_bound (bound (rhs_const, true), BK_LOWER);
378 case GT_EXPR:
379 /* "V > RHS_CONST" */
380 return add_bound (bound (rhs_const, false), BK_LOWER);
384 /* struct bounded_range. */
386 bounded_range::bounded_range (const_tree lower, const_tree upper)
387 : m_lower (const_cast<tree> (lower)),
388 m_upper (const_cast<tree> (upper))
390 if (lower && upper)
392 gcc_assert (TREE_CODE (m_lower) == INTEGER_CST);
393 gcc_assert (TREE_CODE (m_upper) == INTEGER_CST);
394 /* We should have lower <= upper. */
395 gcc_assert (!tree_int_cst_lt (m_upper, m_lower));
397 else
399 /* Purely for pending on-stack values, for
400 writing back to. */
401 gcc_assert (m_lower == NULL_TREE);
402 gcc_assert (m_lower == NULL_TREE);
406 static void
407 dump_cst (pretty_printer *pp, tree cst, bool show_types)
409 gcc_assert (cst);
410 if (show_types)
412 pp_character (pp, '(');
413 dump_generic_node (pp, TREE_TYPE (cst), 0, (dump_flags_t)0, false);
414 pp_character (pp, ')');
416 dump_generic_node (pp, cst, 0, (dump_flags_t)0, false);
419 /* Dump this object to PP. */
421 void
422 bounded_range::dump_to_pp (pretty_printer *pp, bool show_types) const
424 if (tree_int_cst_equal (m_lower, m_upper))
425 dump_cst (pp, m_lower, show_types);
426 else
428 pp_character (pp, '[');
429 dump_cst (pp, m_lower, show_types);
430 pp_string (pp, ", ");
431 dump_cst (pp, m_upper, show_types);
432 pp_character (pp, ']');
436 /* Dump this object to stderr. */
438 void
439 bounded_range::dump (bool show_types) const
441 pretty_printer pp;
442 pp_format_decoder (&pp) = default_tree_printer;
443 pp_show_color (&pp) = pp_show_color (global_dc->printer);
444 pp.buffer->stream = stderr;
445 dump_to_pp (&pp, show_types);
446 pp_newline (&pp);
447 pp_flush (&pp);
450 json::object *
451 bounded_range::to_json () const
453 json::object *range_obj = new json::object ();
454 set_json_attr (range_obj, "lower", m_lower);
455 set_json_attr (range_obj, "upper", m_upper);
456 return range_obj;
459 /* Subroutine of bounded_range::to_json. */
461 void
462 bounded_range::set_json_attr (json::object *obj, const char *name, tree value)
464 pretty_printer pp;
465 pp_format_decoder (&pp) = default_tree_printer;
466 pp_printf (&pp, "%E", value);
467 obj->set (name, new json::string (pp_formatted_text (&pp)));
471 /* Return true iff CST is within this range. */
473 bool
474 bounded_range::contains_p (tree cst) const
476 /* Reject if below lower bound. */
477 if (tree_int_cst_lt (cst, m_lower))
478 return false;
479 /* Reject if above lower bound. */
480 if (tree_int_cst_lt (m_upper, cst))
481 return false;
482 return true;
485 /* If this range intersects OTHER, return true, writing
486 the intersection to *OUT if OUT is non-NULL.
487 Return false if they do not intersect. */
489 bool
490 bounded_range::intersects_p (const bounded_range &other,
491 bounded_range *out) const
493 const tree max_lower
494 = (tree_int_cst_le (m_lower, other.m_lower)
495 ? other.m_lower : m_lower);
496 gcc_assert (TREE_CODE (max_lower) == INTEGER_CST);
497 const tree min_upper
498 = (tree_int_cst_le (m_upper, other.m_upper)
499 ? m_upper : other.m_upper);
500 gcc_assert (TREE_CODE (min_upper) == INTEGER_CST);
502 if (tree_int_cst_le (max_lower, min_upper))
504 if (out)
505 *out = bounded_range (max_lower, min_upper);
506 return true;
508 else
509 return false;
512 bool
513 bounded_range::operator== (const bounded_range &other) const
515 return (TREE_TYPE (m_lower) == TREE_TYPE (other.m_lower)
516 && TREE_TYPE (m_upper) == TREE_TYPE (other.m_upper)
517 && tree_int_cst_equal (m_lower, other.m_lower)
518 && tree_int_cst_equal (m_upper, other.m_upper));
522 bounded_range::cmp (const bounded_range &br1, const bounded_range &br2)
524 if (int cmp_lower = tree_int_cst_compare (br1.m_lower,
525 br2.m_lower))
526 return cmp_lower;
527 return tree_int_cst_compare (br1.m_upper, br2.m_upper);
530 /* struct bounded_ranges. */
532 /* Construct a bounded_ranges instance from a single range. */
534 bounded_ranges::bounded_ranges (const bounded_range &range)
535 : m_ranges (1)
537 m_ranges.quick_push (range);
538 canonicalize ();
539 validate ();
542 /* Construct a bounded_ranges instance from multiple ranges. */
544 bounded_ranges::bounded_ranges (const vec<bounded_range> &ranges)
545 : m_ranges (ranges.length ())
547 m_ranges.safe_splice (ranges);
548 canonicalize ();
549 validate ();
552 /* Construct a bounded_ranges instance for values of LHS for which
553 (LHS OP RHS_CONST) is true (e.g. "(LHS > 3)". */
555 bounded_ranges::bounded_ranges (enum tree_code op, tree rhs_const)
556 : m_ranges ()
558 gcc_assert (TREE_CODE (rhs_const) == INTEGER_CST);
559 tree type = TREE_TYPE (rhs_const);
560 switch (op)
562 default:
563 gcc_unreachable ();
564 case EQ_EXPR:
565 m_ranges.safe_push (bounded_range (rhs_const, rhs_const));
566 break;
568 case GE_EXPR:
569 m_ranges.safe_push (bounded_range (rhs_const, TYPE_MAX_VALUE (type)));
570 break;
572 case LE_EXPR:
573 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type), rhs_const));
574 break;
576 case NE_EXPR:
577 if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const))
578 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type),
579 minus_one (rhs_const)));
580 if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type)))
581 m_ranges.safe_push (bounded_range (plus_one (rhs_const),
582 TYPE_MAX_VALUE (type)));
583 break;
584 case GT_EXPR:
585 if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type)))
586 m_ranges.safe_push (bounded_range (plus_one (rhs_const),
587 TYPE_MAX_VALUE (type)));
588 break;
589 case LT_EXPR:
590 if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const))
591 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type),
592 minus_one (rhs_const)));
593 break;
595 canonicalize ();
596 validate ();
599 /* Subroutine of ctors for fixing up m_ranges.
600 Also, initialize m_hash. */
602 void
603 bounded_ranges::canonicalize ()
605 /* Sort the ranges. */
606 m_ranges.qsort ([](const void *p1, const void *p2) -> int
608 const bounded_range &br1 = *(const bounded_range *)p1;
609 const bounded_range &br2 = *(const bounded_range *)p2;
610 return bounded_range::cmp (br1, br2);
613 /* Merge ranges that are touching or overlapping. */
614 for (unsigned i = 1; i < m_ranges.length (); )
616 bounded_range *prev = &m_ranges[i - 1];
617 const bounded_range *next = &m_ranges[i];
618 if (prev->intersects_p (*next, NULL)
619 || (can_plus_one_p (prev->m_upper)
620 && tree_int_cst_equal (plus_one (prev->m_upper),
621 next->m_lower)))
623 prev->m_upper = next->m_upper;
624 m_ranges.ordered_remove (i);
626 else
627 i++;
630 /* Initialize m_hash. */
631 inchash::hash hstate (0);
632 for (const auto &iter : m_ranges)
634 inchash::add_expr (iter.m_lower, hstate);
635 inchash::add_expr (iter.m_upper, hstate);
637 m_hash = hstate.end ();
640 /* Assert that this object is valid. */
642 void
643 bounded_ranges::validate () const
645 /* Skip this in a release build. */
646 #if !CHECKING_P
647 return;
648 #endif
650 for (unsigned i = 1; i < m_ranges.length (); i++)
652 const bounded_range &prev = m_ranges[i - 1];
653 const bounded_range &next = m_ranges[i];
655 /* Give up if we somehow have incompatible different types. */
656 if (!types_compatible_p (TREE_TYPE (prev.m_upper),
657 TREE_TYPE (next.m_lower)))
658 continue;
660 /* Verify sorted. */
661 gcc_assert (tree_int_cst_lt (prev.m_upper, next.m_lower));
663 gcc_assert (can_plus_one_p (prev.m_upper));
664 /* otherwise there's no room for "next". */
666 /* Verify no ranges touch each other. */
667 gcc_assert (tree_int_cst_lt (plus_one (prev.m_upper), next.m_lower));
671 /* bounded_ranges equality operator. */
673 bool
674 bounded_ranges::operator== (const bounded_ranges &other) const
676 if (m_ranges.length () != other.m_ranges.length ())
677 return false;
678 for (unsigned i = 0; i < m_ranges.length (); i++)
680 if (m_ranges[i] != other.m_ranges[i])
681 return false;
683 return true;
686 /* Dump this object to PP. */
688 void
689 bounded_ranges::dump_to_pp (pretty_printer *pp, bool show_types) const
691 pp_character (pp, '{');
692 for (unsigned i = 0; i < m_ranges.length (); ++i)
694 if (i > 0)
695 pp_string (pp, ", ");
696 m_ranges[i].dump_to_pp (pp, show_types);
698 pp_character (pp, '}');
701 /* Dump this object to stderr. */
703 DEBUG_FUNCTION void
704 bounded_ranges::dump (bool show_types) const
706 pretty_printer pp;
707 pp_format_decoder (&pp) = default_tree_printer;
708 pp_show_color (&pp) = pp_show_color (global_dc->printer);
709 pp.buffer->stream = stderr;
710 dump_to_pp (&pp, show_types);
711 pp_newline (&pp);
712 pp_flush (&pp);
715 json::value *
716 bounded_ranges::to_json () const
718 json::array *arr_obj = new json::array ();
720 for (unsigned i = 0; i < m_ranges.length (); ++i)
721 arr_obj->append (m_ranges[i].to_json ());
723 return arr_obj;
726 /* Determine whether (X OP RHS_CONST) is known to be true or false
727 for all X in the ranges expressed by this object. */
729 tristate
730 bounded_ranges::eval_condition (enum tree_code op,
731 tree rhs_const,
732 bounded_ranges_manager *mgr) const
734 /* Convert (X OP RHS_CONST) to a bounded_ranges instance and find
735 the intersection of that with this object. */
736 bounded_ranges other (op, rhs_const);
737 const bounded_ranges *intersection
738 = mgr->get_or_create_intersection (this, &other);
740 if (intersection->m_ranges.length () > 0)
742 /* We can use pointer equality to check for equality,
743 due to instance consolidation. */
744 if (intersection == this)
745 return tristate (tristate::TS_TRUE);
746 else
747 return tristate (tristate::TS_UNKNOWN);
749 else
750 /* No intersection. */
751 return tristate (tristate::TS_FALSE);
754 /* Return true if CST is within any of the ranges. */
756 bool
757 bounded_ranges::contain_p (tree cst) const
759 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
760 for (const auto &iter : m_ranges)
762 /* TODO: should we optimize this based on sorting? */
763 if (iter.contains_p (cst))
764 return true;
766 return false;
770 bounded_ranges::cmp (const bounded_ranges *a, const bounded_ranges *b)
772 if (int cmp_length = ((int)a->m_ranges.length ()
773 - (int)b->m_ranges.length ()))
774 return cmp_length;
775 for (unsigned i = 0; i < a->m_ranges.length (); i++)
777 if (int cmp_range = bounded_range::cmp (a->m_ranges[i], b->m_ranges[i]))
778 return cmp_range;
780 /* They are equal. They ought to have been consolidated, so we should
781 have two pointers to the same object. */
782 gcc_assert (a == b);
783 return 0;
786 /* class bounded_ranges_manager. */
788 /* bounded_ranges_manager's dtor. */
790 bounded_ranges_manager::~bounded_ranges_manager ()
792 /* Delete the managed objects. */
793 for (const auto &iter : m_map)
794 delete iter.second;
797 /* Get the bounded_ranges instance for the empty set, creating it if
798 necessary. */
800 const bounded_ranges *
801 bounded_ranges_manager::get_or_create_empty ()
803 auto_vec<bounded_range> empty_vec;
805 return consolidate (new bounded_ranges (empty_vec));
808 /* Get the bounded_ranges instance for {CST}, creating it if necessary. */
810 const bounded_ranges *
811 bounded_ranges_manager::get_or_create_point (const_tree cst)
813 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
815 return get_or_create_range (cst, cst);
818 /* Get the bounded_ranges instance for {[LOWER_BOUND..UPPER_BOUND]},
819 creating it if necessary. */
821 const bounded_ranges *
822 bounded_ranges_manager::get_or_create_range (const_tree lower_bound,
823 const_tree upper_bound)
825 gcc_assert (TREE_CODE (lower_bound) == INTEGER_CST);
826 gcc_assert (TREE_CODE (upper_bound) == INTEGER_CST);
828 return consolidate
829 (new bounded_ranges (bounded_range (lower_bound, upper_bound)));
832 /* Get the bounded_ranges instance for the union of OTHERS,
833 creating it if necessary. */
835 const bounded_ranges *
836 bounded_ranges_manager::
837 get_or_create_union (const vec <const bounded_ranges *> &others)
839 auto_vec<bounded_range> ranges;
840 for (const auto &r : others)
841 ranges.safe_splice (r->m_ranges);
842 return consolidate (new bounded_ranges (ranges));
845 /* Get the bounded_ranges instance for the intersection of A and B,
846 creating it if necessary. */
848 const bounded_ranges *
849 bounded_ranges_manager::get_or_create_intersection (const bounded_ranges *a,
850 const bounded_ranges *b)
852 auto_vec<bounded_range> ranges;
853 unsigned a_idx = 0;
854 unsigned b_idx = 0;
855 while (a_idx < a->m_ranges.length ()
856 && b_idx < b->m_ranges.length ())
858 const bounded_range &r_a = a->m_ranges[a_idx];
859 const bounded_range &r_b = b->m_ranges[b_idx];
861 bounded_range intersection (NULL_TREE, NULL_TREE);
862 if (r_a.intersects_p (r_b, &intersection))
864 ranges.safe_push (intersection);
866 if (tree_int_cst_lt (r_a.m_lower, r_b.m_lower))
868 a_idx++;
870 else
872 if (tree_int_cst_lt (r_a.m_upper, r_b.m_upper))
873 a_idx++;
874 else
875 b_idx++;
879 return consolidate (new bounded_ranges (ranges));
882 /* Get the bounded_ranges instance for the inverse of OTHER relative
883 to TYPE, creating it if necessary.
884 This is for use when handling "default" in switch statements, where
885 OTHER represents all the other cases. */
887 const bounded_ranges *
888 bounded_ranges_manager::get_or_create_inverse (const bounded_ranges *other,
889 tree type)
891 tree min_val = TYPE_MIN_VALUE (type);
892 tree max_val = TYPE_MAX_VALUE (type);
893 if (other->m_ranges.length () == 0)
894 return get_or_create_range (min_val, max_val);
895 auto_vec<bounded_range> ranges;
896 tree first_lb = other->m_ranges[0].m_lower;
897 if (tree_int_cst_lt (min_val, first_lb)
898 && can_minus_one_p (first_lb))
899 ranges.safe_push (bounded_range (min_val,
900 minus_one (first_lb)));
901 for (unsigned i = 1; i < other->m_ranges.length (); i++)
903 tree prev_ub = other->m_ranges[i - 1].m_upper;
904 tree iter_lb = other->m_ranges[i].m_lower;
905 gcc_assert (tree_int_cst_lt (prev_ub, iter_lb));
906 if (can_plus_one_p (prev_ub) && can_minus_one_p (iter_lb))
907 ranges.safe_push (bounded_range (plus_one (prev_ub),
908 minus_one (iter_lb)));
910 tree last_ub
911 = other->m_ranges[other->m_ranges.length () - 1].m_upper;
912 if (tree_int_cst_lt (last_ub, max_val)
913 && can_plus_one_p (last_ub))
914 ranges.safe_push (bounded_range (plus_one (last_ub), max_val));
916 return consolidate (new bounded_ranges (ranges));
919 /* If an object equal to INST is already present, delete INST and
920 return the existing object.
921 Otherwise add INST and return it. */
923 const bounded_ranges *
924 bounded_ranges_manager::consolidate (bounded_ranges *inst)
926 if (bounded_ranges **slot = m_map.get (inst))
928 delete inst;
929 return *slot;
931 m_map.put (inst, inst);
932 return inst;
935 /* Get the bounded_ranges instance for EDGE of SWITCH_STMT,
936 creating it if necessary, and caching it by edge. */
938 const bounded_ranges *
939 bounded_ranges_manager::
940 get_or_create_ranges_for_switch (const switch_cfg_superedge *edge,
941 const gswitch *switch_stmt)
943 /* Look in per-edge cache. */
944 if (const bounded_ranges ** slot = m_edge_cache.get (edge))
945 return *slot;
947 /* Not yet in cache. */
948 const bounded_ranges *all_cases_ranges
949 = create_ranges_for_switch (*edge, switch_stmt);
950 m_edge_cache.put (edge, all_cases_ranges);
951 return all_cases_ranges;
954 /* Get the bounded_ranges instance for EDGE of SWITCH_STMT,
955 creating it if necessary, for edges for which the per-edge
956 cache has not yet been populated. */
958 const bounded_ranges *
959 bounded_ranges_manager::
960 create_ranges_for_switch (const switch_cfg_superedge &edge,
961 const gswitch *switch_stmt)
963 /* Get the ranges for each case label. */
964 auto_vec <const bounded_ranges *> case_ranges_vec
965 (gimple_switch_num_labels (switch_stmt));
967 for (tree case_label : edge.get_case_labels ())
969 /* Get the ranges for this case label. */
970 const bounded_ranges *case_ranges
971 = make_case_label_ranges (switch_stmt, case_label);
972 case_ranges_vec.quick_push (case_ranges);
975 /* Combine all the ranges for each case label into a single collection
976 of ranges. */
977 const bounded_ranges *all_cases_ranges
978 = get_or_create_union (case_ranges_vec);
979 return all_cases_ranges;
982 /* Get the bounded_ranges instance for CASE_LABEL within
983 SWITCH_STMT. */
985 const bounded_ranges *
986 bounded_ranges_manager::
987 make_case_label_ranges (const gswitch *switch_stmt,
988 tree case_label)
990 gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR);
991 tree lower_bound = CASE_LOW (case_label);
992 tree upper_bound = CASE_HIGH (case_label);
993 if (lower_bound)
995 if (upper_bound)
996 /* Range. */
997 return get_or_create_range (lower_bound, upper_bound);
998 else
999 /* Single-value. */
1000 return get_or_create_point (lower_bound);
1002 else
1004 /* The default case.
1005 Add exclusions based on the other cases. */
1006 auto_vec <const bounded_ranges *> other_case_ranges
1007 (gimple_switch_num_labels (switch_stmt));
1008 for (unsigned other_idx = 1;
1009 other_idx < gimple_switch_num_labels (switch_stmt);
1010 other_idx++)
1012 tree other_label = gimple_switch_label (switch_stmt,
1013 other_idx);
1014 const bounded_ranges *other_ranges
1015 = make_case_label_ranges (switch_stmt, other_label);
1016 other_case_ranges.quick_push (other_ranges);
1018 const bounded_ranges *other_cases_ranges
1019 = get_or_create_union (other_case_ranges);
1020 tree type = TREE_TYPE (gimple_switch_index (switch_stmt));
1021 return get_or_create_inverse (other_cases_ranges, type);
1025 /* Dump the number of objects of each class that were managed by this
1026 manager to LOGGER.
1027 If SHOW_OBJS is true, also dump the objects themselves. */
1029 void
1030 bounded_ranges_manager::log_stats (logger *logger, bool show_objs) const
1032 LOG_SCOPE (logger);
1033 logger->log (" # %s: %li", "ranges", (long)m_map.elements ());
1034 if (!show_objs)
1035 return;
1037 auto_vec<const bounded_ranges *> vec_objs (m_map.elements ());
1038 for (const auto &iter : m_map)
1039 vec_objs.quick_push (iter.second);
1040 vec_objs.qsort
1041 ([](const void *p1, const void *p2) -> int
1043 const bounded_ranges *br1 = *(const bounded_ranges * const *)p1;
1044 const bounded_ranges *br2 = *(const bounded_ranges * const *)p2;
1045 return bounded_ranges::cmp (br1, br2);
1048 for (const auto &iter : vec_objs)
1050 logger->start_log_line ();
1051 pretty_printer *pp = logger->get_printer ();
1052 pp_string (pp, " ");
1053 iter->dump_to_pp (pp, true);
1054 logger->end_log_line ();
1058 /* class equiv_class. */
1060 /* equiv_class's default ctor. */
1062 equiv_class::equiv_class ()
1063 : m_constant (NULL_TREE), m_cst_sval (NULL), m_vars ()
1067 /* equiv_class's copy ctor. */
1069 equiv_class::equiv_class (const equiv_class &other)
1070 : m_constant (other.m_constant), m_cst_sval (other.m_cst_sval),
1071 m_vars (other.m_vars.length ())
1073 for (const svalue *sval : other.m_vars)
1074 m_vars.quick_push (sval);
1077 /* Print an all-on-one-line representation of this equiv_class to PP,
1078 which must support %E for trees. */
1080 void
1081 equiv_class::print (pretty_printer *pp) const
1083 pp_character (pp, '{');
1084 int i;
1085 const svalue *sval;
1086 FOR_EACH_VEC_ELT (m_vars, i, sval)
1088 if (i > 0)
1089 pp_string (pp, " == ");
1090 sval->dump_to_pp (pp, true);
1092 if (m_constant)
1094 if (i > 0)
1095 pp_string (pp, " == ");
1096 pp_printf (pp, "[m_constant]%qE", m_constant);
1098 pp_character (pp, '}');
1101 /* Return a new json::object of the form
1102 {"svals" : [str],
1103 "constant" : optional str}. */
1105 json::object *
1106 equiv_class::to_json () const
1108 json::object *ec_obj = new json::object ();
1110 json::array *sval_arr = new json::array ();
1111 for (const svalue *sval : m_vars)
1112 sval_arr->append (sval->to_json ());
1113 ec_obj->set ("svals", sval_arr);
1115 if (m_constant)
1117 pretty_printer pp;
1118 pp_format_decoder (&pp) = default_tree_printer;
1119 pp_printf (&pp, "%qE", m_constant);
1120 ec_obj->set ("constant", new json::string (pp_formatted_text (&pp)));
1123 return ec_obj;
1126 /* Generate a hash value for this equiv_class.
1127 This relies on the ordering of m_vars, and so this object needs to
1128 have been canonicalized for this to be meaningful. */
1130 hashval_t
1131 equiv_class::hash () const
1133 inchash::hash hstate;
1135 inchash::add_expr (m_constant, hstate);
1136 for (const svalue * sval : m_vars)
1137 hstate.add_ptr (sval);
1138 return hstate.end ();
1141 /* Equality operator for equiv_class.
1142 This relies on the ordering of m_vars, and so this object
1143 and OTHER need to have been canonicalized for this to be
1144 meaningful. */
1146 bool
1147 equiv_class::operator== (const equiv_class &other)
1149 if (m_constant != other.m_constant)
1150 return false; // TODO: use tree equality here?
1152 /* FIXME: should we compare m_cst_sval? */
1154 if (m_vars.length () != other.m_vars.length ())
1155 return false;
1157 int i;
1158 const svalue *sval;
1159 FOR_EACH_VEC_ELT (m_vars, i, sval)
1160 if (sval != other.m_vars[i])
1161 return false;
1163 return true;
1166 /* Add SID to this equiv_class, using CM to check if it's a constant. */
1168 void
1169 equiv_class::add (const svalue *sval)
1171 gcc_assert (sval);
1172 if (tree cst = sval->maybe_get_constant ())
1174 gcc_assert (CONSTANT_CLASS_P (cst));
1175 /* FIXME: should we canonicalize which svalue is the constant
1176 when there are multiple equal constants? */
1177 m_constant = cst;
1178 m_cst_sval = sval;
1180 m_vars.safe_push (sval);
1183 /* Remove SID from this equivalence class.
1184 Return true if SID was the last var in the equivalence class (suggesting
1185 a possible leak). */
1187 bool
1188 equiv_class::del (const svalue *sval)
1190 gcc_assert (sval);
1191 gcc_assert (sval != m_cst_sval);
1193 int i;
1194 const svalue *iv;
1195 FOR_EACH_VEC_ELT (m_vars, i, iv)
1197 if (iv == sval)
1199 m_vars[i] = m_vars[m_vars.length () - 1];
1200 m_vars.pop ();
1201 return m_vars.length () == 0;
1205 /* SVAL must be in the class. */
1206 gcc_unreachable ();
1207 return false;
1210 /* Get a representative member of this class, for handling cases
1211 where the IDs can change mid-traversal. */
1213 const svalue *
1214 equiv_class::get_representative () const
1216 gcc_assert (m_vars.length () > 0);
1217 return m_vars[0];
1220 /* Sort the svalues within this equiv_class. */
1222 void
1223 equiv_class::canonicalize ()
1225 m_vars.qsort (svalue::cmp_ptr_ptr);
1228 /* Return true if this EC contains a variable, false if it merely
1229 contains constants.
1230 Subroutine of constraint_manager::canonicalize, for removing
1231 redundant ECs. */
1233 bool
1234 equiv_class::contains_non_constant_p () const
1236 if (m_constant)
1238 for (auto iter : m_vars)
1239 if (iter->maybe_get_constant ())
1240 continue;
1241 else
1242 /* We have {non-constant == constant}. */
1243 return true;
1244 /* We only have constants. */
1245 return false;
1247 else
1248 /* Return true if we have {non-constant == non-constant}. */
1249 return m_vars.length () > 1;
1252 /* Get a debug string for C_OP. */
1254 const char *
1255 constraint_op_code (enum constraint_op c_op)
1257 switch (c_op)
1259 default:
1260 gcc_unreachable ();
1261 case CONSTRAINT_NE: return "!=";
1262 case CONSTRAINT_LT: return "<";
1263 case CONSTRAINT_LE: return "<=";
1267 /* Convert C_OP to an enum tree_code. */
1269 enum tree_code
1270 constraint_tree_code (enum constraint_op c_op)
1272 switch (c_op)
1274 default:
1275 gcc_unreachable ();
1276 case CONSTRAINT_NE: return NE_EXPR;
1277 case CONSTRAINT_LT: return LT_EXPR;
1278 case CONSTRAINT_LE: return LE_EXPR;
1282 /* Given "lhs C_OP rhs", determine "lhs T_OP rhs".
1284 For example, given "x < y", then "x > y" is false. */
1286 static tristate
1287 eval_constraint_op_for_op (enum constraint_op c_op, enum tree_code t_op)
1289 switch (c_op)
1291 default:
1292 gcc_unreachable ();
1293 case CONSTRAINT_NE:
1294 if (t_op == EQ_EXPR)
1295 return tristate (tristate::TS_FALSE);
1296 if (t_op == NE_EXPR)
1297 return tristate (tristate::TS_TRUE);
1298 break;
1299 case CONSTRAINT_LT:
1300 if (t_op == LT_EXPR || t_op == LE_EXPR || t_op == NE_EXPR)
1301 return tristate (tristate::TS_TRUE);
1302 if (t_op == EQ_EXPR || t_op == GT_EXPR || t_op == GE_EXPR)
1303 return tristate (tristate::TS_FALSE);
1304 break;
1305 case CONSTRAINT_LE:
1306 if (t_op == LE_EXPR)
1307 return tristate (tristate::TS_TRUE);
1308 if (t_op == GT_EXPR)
1309 return tristate (tristate::TS_FALSE);
1310 break;
1312 return tristate (tristate::TS_UNKNOWN);
1315 /* class constraint. */
1317 /* Print this constraint to PP (which must support %E for trees),
1318 using CM to look up equiv_class instances from ids. */
1320 void
1321 constraint::print (pretty_printer *pp, const constraint_manager &cm) const
1323 m_lhs.print (pp);
1324 pp_string (pp, ": ");
1325 m_lhs.get_obj (cm).print (pp);
1326 pp_string (pp, " ");
1327 pp_string (pp, constraint_op_code (m_op));
1328 pp_string (pp, " ");
1329 m_rhs.print (pp);
1330 pp_string (pp, ": ");
1331 m_rhs.get_obj (cm).print (pp);
1334 /* Return a new json::object of the form
1335 {"lhs" : int, the EC index
1336 "op" : str,
1337 "rhs" : int, the EC index}. */
1339 json::object *
1340 constraint::to_json () const
1342 json::object *con_obj = new json::object ();
1344 con_obj->set ("lhs", new json::integer_number (m_lhs.as_int ()));
1345 con_obj->set ("op", new json::string (constraint_op_code (m_op)));
1346 con_obj->set ("rhs", new json::integer_number (m_rhs.as_int ()));
1348 return con_obj;
1351 /* Generate a hash value for this constraint. */
1353 hashval_t
1354 constraint::hash () const
1356 inchash::hash hstate;
1357 hstate.add_int (m_lhs.m_idx);
1358 hstate.add_int (m_op);
1359 hstate.add_int (m_rhs.m_idx);
1360 return hstate.end ();
1363 /* Equality operator for constraints. */
1365 bool
1366 constraint::operator== (const constraint &other) const
1368 if (m_lhs != other.m_lhs)
1369 return false;
1370 if (m_op != other.m_op)
1371 return false;
1372 if (m_rhs != other.m_rhs)
1373 return false;
1374 return true;
1377 /* Return true if this constraint is implied by OTHER. */
1379 bool
1380 constraint::implied_by (const constraint &other,
1381 const constraint_manager &cm) const
1383 if (m_lhs == other.m_lhs)
1384 if (tree rhs_const = m_rhs.get_obj (cm).get_any_constant ())
1385 if (tree other_rhs_const = other.m_rhs.get_obj (cm).get_any_constant ())
1386 if (m_lhs.get_obj (cm).get_any_constant () == NULL_TREE)
1387 if (m_op == other.m_op)
1388 switch (m_op)
1390 default:
1391 break;
1392 case CONSTRAINT_LE:
1393 case CONSTRAINT_LT:
1394 if (compare_constants (rhs_const,
1395 GE_EXPR,
1396 other_rhs_const).is_true ())
1397 return true;
1398 break;
1400 return false;
1403 /* class bounded_ranges_constraint. */
1405 void
1406 bounded_ranges_constraint::print (pretty_printer *pp,
1407 const constraint_manager &cm) const
1409 m_ec_id.print (pp);
1410 pp_string (pp, ": ");
1411 m_ec_id.get_obj (cm).print (pp);
1412 pp_string (pp, ": ");
1413 m_ranges->dump_to_pp (pp, true);
1416 json::object *
1417 bounded_ranges_constraint::to_json () const
1419 json::object *con_obj = new json::object ();
1421 con_obj->set ("ec", new json::integer_number (m_ec_id.as_int ()));
1422 con_obj->set ("ranges", m_ranges->to_json ());
1424 return con_obj;
1427 bool
1428 bounded_ranges_constraint::
1429 operator== (const bounded_ranges_constraint &other) const
1431 if (m_ec_id != other.m_ec_id)
1432 return false;
1434 /* We can compare by pointer, since the bounded_ranges_manager
1435 consolidates instances. */
1436 return m_ranges == other.m_ranges;
1439 void
1440 bounded_ranges_constraint::add_to_hash (inchash::hash *hstate) const
1442 hstate->add_int (m_ec_id.m_idx);
1443 hstate->merge_hash (m_ranges->get_hash ());
1446 /* class equiv_class_id. */
1448 /* Get the underlying equiv_class for this ID from CM. */
1450 const equiv_class &
1451 equiv_class_id::get_obj (const constraint_manager &cm) const
1453 return cm.get_equiv_class_by_index (m_idx);
1456 /* Access the underlying equiv_class for this ID from CM. */
1458 equiv_class &
1459 equiv_class_id::get_obj (constraint_manager &cm) const
1461 return cm.get_equiv_class_by_index (m_idx);
1464 /* Print this equiv_class_id to PP. */
1466 void
1467 equiv_class_id::print (pretty_printer *pp) const
1469 if (null_p ())
1470 pp_printf (pp, "null");
1471 else
1472 pp_printf (pp, "ec%i", m_idx);
1475 /* class constraint_manager. */
1477 /* constraint_manager's copy ctor. */
1479 constraint_manager::constraint_manager (const constraint_manager &other)
1480 : m_equiv_classes (other.m_equiv_classes.length ()),
1481 m_constraints (other.m_constraints.length ()),
1482 m_bounded_ranges_constraints (other.m_bounded_ranges_constraints.length ()),
1483 m_mgr (other.m_mgr)
1485 int i;
1486 equiv_class *ec;
1487 FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
1488 m_equiv_classes.quick_push (new equiv_class (*ec));
1489 constraint *c;
1490 FOR_EACH_VEC_ELT (other.m_constraints, i, c)
1491 m_constraints.quick_push (*c);
1492 for (const auto &iter : other.m_bounded_ranges_constraints)
1493 m_bounded_ranges_constraints.quick_push (iter);
1496 /* constraint_manager's assignment operator. */
1498 constraint_manager&
1499 constraint_manager::operator= (const constraint_manager &other)
1501 gcc_assert (m_equiv_classes.length () == 0);
1502 gcc_assert (m_constraints.length () == 0);
1503 gcc_assert (m_bounded_ranges_constraints.length () == 0);
1505 int i;
1506 equiv_class *ec;
1507 m_equiv_classes.reserve (other.m_equiv_classes.length ());
1508 FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
1509 m_equiv_classes.quick_push (new equiv_class (*ec));
1510 constraint *c;
1511 m_constraints.reserve (other.m_constraints.length ());
1512 FOR_EACH_VEC_ELT (other.m_constraints, i, c)
1513 m_constraints.quick_push (*c);
1514 for (const auto &iter : other.m_bounded_ranges_constraints)
1515 m_bounded_ranges_constraints.quick_push (iter);
1517 return *this;
1520 /* Generate a hash value for this constraint_manager. */
1522 hashval_t
1523 constraint_manager::hash () const
1525 inchash::hash hstate;
1526 int i;
1527 equiv_class *ec;
1528 constraint *c;
1530 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1531 hstate.merge_hash (ec->hash ());
1532 FOR_EACH_VEC_ELT (m_constraints, i, c)
1533 hstate.merge_hash (c->hash ());
1534 for (const auto &iter : m_bounded_ranges_constraints)
1535 iter.add_to_hash (&hstate);
1536 return hstate.end ();
1539 /* Equality operator for constraint_manager. */
1541 bool
1542 constraint_manager::operator== (const constraint_manager &other) const
1544 if (m_equiv_classes.length () != other.m_equiv_classes.length ())
1545 return false;
1546 if (m_constraints.length () != other.m_constraints.length ())
1547 return false;
1548 if (m_bounded_ranges_constraints.length ()
1549 != other.m_bounded_ranges_constraints.length ())
1550 return false;
1552 int i;
1553 equiv_class *ec;
1555 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1556 if (!(*ec == *other.m_equiv_classes[i]))
1557 return false;
1559 constraint *c;
1561 FOR_EACH_VEC_ELT (m_constraints, i, c)
1562 if (!(*c == other.m_constraints[i]))
1563 return false;
1565 for (unsigned i = 0; i < m_bounded_ranges_constraints.length (); i++)
1567 if (m_bounded_ranges_constraints[i]
1568 != other.m_bounded_ranges_constraints[i])
1569 return false;
1572 return true;
1575 /* Print this constraint_manager to PP (which must support %E for trees). */
1577 void
1578 constraint_manager::print (pretty_printer *pp) const
1580 pp_string (pp, "{");
1581 int i;
1582 equiv_class *ec;
1583 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1585 if (i > 0)
1586 pp_string (pp, ", ");
1587 equiv_class_id (i).print (pp);
1588 pp_string (pp, ": ");
1589 ec->print (pp);
1591 pp_string (pp, " | ");
1592 constraint *c;
1593 FOR_EACH_VEC_ELT (m_constraints, i, c)
1595 if (i > 0)
1596 pp_string (pp, " && ");
1597 c->print (pp, *this);
1599 if (m_bounded_ranges_constraints.length ())
1601 pp_string (pp, " | ");
1602 i = 0;
1603 for (const auto &iter : m_bounded_ranges_constraints)
1605 if (i > 0)
1606 pp_string (pp, " && ");
1607 iter.print (pp, *this);
1608 i++;
1611 pp_printf (pp, "}");
1614 /* Dump a representation of this constraint_manager to PP
1615 (which must support %E for trees). */
1617 void
1618 constraint_manager::dump_to_pp (pretty_printer *pp, bool multiline) const
1620 if (multiline)
1621 pp_string (pp, " ");
1622 pp_string (pp, "equiv classes:");
1623 if (multiline)
1624 pp_newline (pp);
1625 else
1626 pp_string (pp, " {");
1627 int i;
1628 equiv_class *ec;
1629 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1631 if (multiline)
1632 pp_string (pp, " ");
1633 else if (i > 0)
1634 pp_string (pp, ", ");
1635 equiv_class_id (i).print (pp);
1636 pp_string (pp, ": ");
1637 ec->print (pp);
1638 if (multiline)
1639 pp_newline (pp);
1641 if (multiline)
1642 pp_string (pp, " ");
1643 else
1644 pp_string (pp, "}");
1645 pp_string (pp, "constraints:");
1646 if (multiline)
1647 pp_newline (pp);
1648 else
1649 pp_string (pp, "{");
1650 constraint *c;
1651 FOR_EACH_VEC_ELT (m_constraints, i, c)
1653 if (multiline)
1654 pp_string (pp, " ");
1655 pp_printf (pp, "%i: ", i);
1656 c->print (pp, *this);
1657 if (multiline)
1658 pp_newline (pp);
1660 if (!multiline)
1661 pp_string (pp, "}");
1662 if (m_bounded_ranges_constraints.length ())
1664 if (multiline)
1665 pp_string (pp, " ");
1666 pp_string (pp, "ranges:");
1667 if (multiline)
1668 pp_newline (pp);
1669 else
1670 pp_string (pp, "{");
1671 i = 0;
1672 for (const auto &iter : m_bounded_ranges_constraints)
1674 if (multiline)
1675 pp_string (pp, " ");
1676 else if (i > 0)
1677 pp_string (pp, " && ");
1678 iter.print (pp, *this);
1679 if (multiline)
1680 pp_newline (pp);
1681 i++;
1683 if (!multiline)
1684 pp_string (pp, "}");
1688 /* Dump a multiline representation of this constraint_manager to FP. */
1690 void
1691 constraint_manager::dump (FILE *fp) const
1693 pretty_printer pp;
1694 pp_format_decoder (&pp) = default_tree_printer;
1695 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1696 pp.buffer->stream = fp;
1697 dump_to_pp (&pp, true);
1698 pp_flush (&pp);
1701 /* Dump a multiline representation of this constraint_manager to stderr. */
1703 DEBUG_FUNCTION void
1704 constraint_manager::dump () const
1706 dump (stderr);
1709 /* Dump a multiline representation of CM to stderr. */
1711 DEBUG_FUNCTION void
1712 debug (const constraint_manager &cm)
1714 cm.dump ();
1717 /* Return a new json::object of the form
1718 {"ecs" : array of objects, one per equiv_class
1719 "constraints" : array of objects, one per constraint}. */
1721 json::object *
1722 constraint_manager::to_json () const
1724 json::object *cm_obj = new json::object ();
1726 /* Equivalence classes. */
1728 json::array *ec_arr = new json::array ();
1729 for (const equiv_class *ec : m_equiv_classes)
1730 ec_arr->append (ec->to_json ());
1731 cm_obj->set ("ecs", ec_arr);
1734 /* Constraints. */
1736 json::array *con_arr = new json::array ();
1737 for (const constraint &c : m_constraints)
1738 con_arr->append (c.to_json ());
1739 cm_obj->set ("constraints", con_arr);
1742 /* m_bounded_ranges_constraints. */
1744 json::array *con_arr = new json::array ();
1745 for (const auto &c : m_bounded_ranges_constraints)
1746 con_arr->append (c.to_json ());
1747 cm_obj->set ("bounded_ranges_constraints", con_arr);
1750 return cm_obj;
1753 /* Attempt to add the constraint LHS OP RHS to this constraint_manager.
1754 Return true if the constraint could be added (or is already true).
1755 Return false if the constraint contradicts existing knowledge. */
1757 bool
1758 constraint_manager::add_constraint (const svalue *lhs,
1759 enum tree_code op,
1760 const svalue *rhs)
1762 lhs = lhs->unwrap_any_unmergeable ();
1763 rhs = rhs->unwrap_any_unmergeable ();
1765 /* Nothing can be known about unknown/poisoned values. */
1766 if (!lhs->can_have_associated_state_p ()
1767 || !rhs->can_have_associated_state_p ())
1768 /* Not a contradiction. */
1769 return true;
1771 /* Check the conditions on svalues. */
1773 tristate t_cond = eval_condition (lhs, op, rhs);
1775 /* If we already have the condition, do nothing. */
1776 if (t_cond.is_true ())
1777 return true;
1779 /* Reject a constraint that would contradict existing knowledge, as
1780 unsatisfiable. */
1781 if (t_cond.is_false ())
1782 return false;
1785 equiv_class_id lhs_ec_id = get_or_add_equiv_class (lhs);
1786 equiv_class_id rhs_ec_id = get_or_add_equiv_class (rhs);
1788 /* Check the stronger conditions on ECs. */
1790 tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id);
1792 /* Discard constraints that are already known. */
1793 if (t.is_true ())
1794 return true;
1796 /* Reject unsatisfiable constraints. */
1797 if (t.is_false ())
1798 return false;
1801 /* If adding
1802 (SVAL + OFFSET) > CST,
1803 then that can imply:
1804 SVAL > (CST - OFFSET). */
1805 if (const binop_svalue *lhs_binop = lhs->dyn_cast_binop_svalue ())
1806 if (tree rhs_cst = rhs->maybe_get_constant ())
1807 if (tree offset = lhs_binop->get_arg1 ()->maybe_get_constant ())
1808 if ((op == GT_EXPR || op == LT_EXPR
1809 || op == GE_EXPR || op == LE_EXPR)
1810 && lhs_binop->get_op () == PLUS_EXPR)
1812 tree offset_of_cst = fold_build2 (MINUS_EXPR, TREE_TYPE (rhs_cst),
1813 rhs_cst, offset);
1814 const svalue *implied_lhs = lhs_binop->get_arg0 ();
1815 enum tree_code implied_op = op;
1816 const svalue *implied_rhs
1817 = m_mgr->get_or_create_constant_svalue (offset_of_cst);
1818 if (!add_constraint (implied_lhs, implied_op, implied_rhs))
1819 return false;
1820 /* The above add_constraint could lead to EC merger, so we need
1821 to refresh the EC IDs. */
1822 lhs_ec_id = get_or_add_equiv_class (lhs);
1823 rhs_ec_id = get_or_add_equiv_class (rhs);
1826 add_unknown_constraint (lhs_ec_id, op, rhs_ec_id);
1827 return true;
1830 /* Attempt to add the constraint LHS_EC_ID OP RHS_EC_ID to this
1831 constraint_manager.
1832 Return true if the constraint could be added (or is already true).
1833 Return false if the constraint contradicts existing knowledge. */
1835 bool
1836 constraint_manager::add_constraint (equiv_class_id lhs_ec_id,
1837 enum tree_code op,
1838 equiv_class_id rhs_ec_id)
1840 tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id);
1842 /* Discard constraints that are already known. */
1843 if (t.is_true ())
1844 return true;
1846 /* Reject unsatisfiable constraints. */
1847 if (t.is_false ())
1848 return false;
1850 add_unknown_constraint (lhs_ec_id, op, rhs_ec_id);
1851 return true;
1854 /* Add the constraint LHS_EC_ID OP RHS_EC_ID to this constraint_manager,
1855 where the constraint has already been checked for being "unknown". */
1857 void
1858 constraint_manager::add_unknown_constraint (equiv_class_id lhs_ec_id,
1859 enum tree_code op,
1860 equiv_class_id rhs_ec_id)
1862 gcc_assert (lhs_ec_id != rhs_ec_id);
1864 /* For now, simply accumulate constraints, without attempting any further
1865 optimization. */
1866 switch (op)
1868 case EQ_EXPR:
1870 /* Merge rhs_ec into lhs_ec. */
1871 equiv_class &lhs_ec_obj = lhs_ec_id.get_obj (*this);
1872 const equiv_class &rhs_ec_obj = rhs_ec_id.get_obj (*this);
1874 int i;
1875 const svalue *sval;
1876 FOR_EACH_VEC_ELT (rhs_ec_obj.m_vars, i, sval)
1877 lhs_ec_obj.add (sval);
1879 if (rhs_ec_obj.m_constant)
1881 lhs_ec_obj.m_constant = rhs_ec_obj.m_constant;
1882 lhs_ec_obj.m_cst_sval = rhs_ec_obj.m_cst_sval;
1885 /* Drop rhs equivalence class, overwriting it with the
1886 final ec (which might be the same one). */
1887 equiv_class_id final_ec_id = m_equiv_classes.length () - 1;
1888 equiv_class *old_ec = m_equiv_classes[rhs_ec_id.m_idx];
1889 equiv_class *final_ec = m_equiv_classes.pop ();
1890 if (final_ec != old_ec)
1891 m_equiv_classes[rhs_ec_id.m_idx] = final_ec;
1892 delete old_ec;
1893 if (lhs_ec_id == final_ec_id)
1894 lhs_ec_id = rhs_ec_id;
1896 /* Update the constraints. */
1897 constraint *c;
1898 FOR_EACH_VEC_ELT (m_constraints, i, c)
1900 /* Update references to the rhs_ec so that
1901 they refer to the lhs_ec. */
1902 if (c->m_lhs == rhs_ec_id)
1903 c->m_lhs = lhs_ec_id;
1904 if (c->m_rhs == rhs_ec_id)
1905 c->m_rhs = lhs_ec_id;
1907 /* Renumber all constraints that refer to the final rhs_ec
1908 to the old rhs_ec, where the old final_ec now lives. */
1909 if (c->m_lhs == final_ec_id)
1910 c->m_lhs = rhs_ec_id;
1911 if (c->m_rhs == final_ec_id)
1912 c->m_rhs = rhs_ec_id;
1914 bounded_ranges_constraint *brc;
1915 FOR_EACH_VEC_ELT (m_bounded_ranges_constraints, i, brc)
1917 if (brc->m_ec_id == rhs_ec_id)
1918 brc->m_ec_id = lhs_ec_id;
1919 if (brc->m_ec_id == final_ec_id)
1920 brc->m_ec_id = rhs_ec_id;
1923 /* We may now have self-comparisons due to the merger; these
1924 constraints should be removed. */
1925 unsigned read_index, write_index;
1926 VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c,
1927 (c->m_lhs == c->m_rhs));
1929 break;
1930 case GE_EXPR:
1931 add_constraint_internal (rhs_ec_id, CONSTRAINT_LE, lhs_ec_id);
1932 break;
1933 case LE_EXPR:
1934 add_constraint_internal (lhs_ec_id, CONSTRAINT_LE, rhs_ec_id);
1935 break;
1936 case NE_EXPR:
1937 add_constraint_internal (lhs_ec_id, CONSTRAINT_NE, rhs_ec_id);
1938 break;
1939 case GT_EXPR:
1940 add_constraint_internal (rhs_ec_id, CONSTRAINT_LT, lhs_ec_id);
1941 break;
1942 case LT_EXPR:
1943 add_constraint_internal (lhs_ec_id, CONSTRAINT_LT, rhs_ec_id);
1944 break;
1945 default:
1946 /* do nothing. */
1947 break;
1949 validate ();
1952 /* Subroutine of constraint_manager::add_constraint, for handling all
1953 operations other than equality (for which equiv classes are merged). */
1955 void
1956 constraint_manager::add_constraint_internal (equiv_class_id lhs_id,
1957 enum constraint_op c_op,
1958 equiv_class_id rhs_id)
1960 if (m_constraints.length () >= (unsigned)param_analyzer_max_constraints)
1961 return;
1963 constraint new_c (lhs_id, c_op, rhs_id);
1965 /* Remove existing constraints that would be implied by the
1966 new constraint. */
1967 unsigned read_index, write_index;
1968 constraint *c;
1969 VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c,
1970 (c->implied_by (new_c, *this)));
1972 /* Add the constraint. */
1973 m_constraints.safe_push (new_c);
1975 /* We don't yet update m_bounded_ranges_constraints here yet. */
1977 if (!flag_analyzer_transitivity)
1978 return;
1980 if (c_op != CONSTRAINT_NE)
1982 /* The following can potentially add EQ_EXPR facts, which could lead
1983 to ECs being merged, which would change the meaning of the EC IDs.
1984 Hence we need to do this via representatives. */
1985 const svalue *lhs = lhs_id.get_obj (*this).get_representative ();
1986 const svalue *rhs = rhs_id.get_obj (*this).get_representative ();
1988 /* We have LHS </<= RHS */
1990 /* Handle transitivity of ordering by adding additional constraints
1991 based on what we already knew.
1993 So if we have already have:
1994 (a < b)
1995 (c < d)
1996 Then adding:
1997 (b < c)
1998 will also add:
1999 (a < c)
2000 (b < d)
2001 We need to recurse to ensure we also add:
2002 (a < d).
2003 We call the checked add_constraint to avoid adding constraints
2004 that are already present. Doing so also ensures termination
2005 in the case of cycles.
2007 We also check for single-element ranges, adding EQ_EXPR facts
2008 where we discover them. For example 3 < x < 5 implies
2009 that x == 4 (if x is an integer). */
2010 for (unsigned i = 0; i < m_constraints.length (); i++)
2012 const constraint *other = &m_constraints[i];
2013 if (other->is_ordering_p ())
2015 /* Refresh the EC IDs, in case any mergers have happened. */
2016 lhs_id = get_or_add_equiv_class (lhs);
2017 rhs_id = get_or_add_equiv_class (rhs);
2019 tree lhs_const = lhs_id.get_obj (*this).m_constant;
2020 tree rhs_const = rhs_id.get_obj (*this).m_constant;
2021 tree other_lhs_const
2022 = other->m_lhs.get_obj (*this).m_constant;
2023 tree other_rhs_const
2024 = other->m_rhs.get_obj (*this).m_constant;
2026 /* We have "LHS </<= RHS" and "other.lhs </<= other.rhs". */
2028 /* If we have LHS </<= RHS and RHS </<= LHS, then we have a
2029 cycle. */
2030 if (rhs_id == other->m_lhs
2031 && other->m_rhs == lhs_id)
2033 /* We must have equality for this to be possible. */
2034 gcc_assert (c_op == CONSTRAINT_LE
2035 && other->m_op == CONSTRAINT_LE);
2036 add_constraint (lhs_id, EQ_EXPR, rhs_id);
2037 /* Adding an equality will merge the two ECs and potentially
2038 reorganize the constraints. Stop iterating. */
2039 return;
2041 /* Otherwise, check for transitivity. */
2042 if (rhs_id == other->m_lhs)
2044 /* With RHS == other.lhs, we have:
2045 "LHS </<= (RHS, other.lhs) </<= other.rhs"
2046 and thus this implies "LHS </<= other.rhs". */
2048 /* Do we have a tightly-constrained range? */
2049 if (lhs_const
2050 && !rhs_const
2051 && other_rhs_const)
2053 range r (bound (lhs_const, c_op == CONSTRAINT_LE),
2054 bound (other_rhs_const,
2055 other->m_op == CONSTRAINT_LE));
2056 if (tree constant = r.constrained_to_single_element ())
2058 const svalue *cst_sval
2059 = m_mgr->get_or_create_constant_svalue (constant);
2060 add_constraint
2061 (rhs_id, EQ_EXPR,
2062 get_or_add_equiv_class (cst_sval));
2063 return;
2067 /* Otherwise, add the constraint implied by transitivity. */
2068 enum tree_code new_op
2069 = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
2070 ? LE_EXPR : LT_EXPR);
2071 add_constraint (lhs_id, new_op, other->m_rhs);
2073 else if (other->m_rhs == lhs_id)
2075 /* With other.rhs == LHS, we have:
2076 "other.lhs </<= (other.rhs, LHS) </<= RHS"
2077 and thus this implies "other.lhs </<= RHS". */
2079 /* Do we have a tightly-constrained range? */
2080 if (other_lhs_const
2081 && !lhs_const
2082 && rhs_const)
2084 range r (bound (other_lhs_const,
2085 other->m_op == CONSTRAINT_LE),
2086 bound (rhs_const,
2087 c_op == CONSTRAINT_LE));
2088 if (tree constant = r.constrained_to_single_element ())
2090 const svalue *cst_sval
2091 = m_mgr->get_or_create_constant_svalue (constant);
2092 add_constraint
2093 (lhs_id, EQ_EXPR,
2094 get_or_add_equiv_class (cst_sval));
2095 return;
2099 /* Otherwise, add the constraint implied by transitivity. */
2100 enum tree_code new_op
2101 = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
2102 ? LE_EXPR : LT_EXPR);
2103 add_constraint (other->m_lhs, new_op, rhs_id);
2110 /* Attempt to add the constraint that SVAL is within RANGES to this
2111 constraint_manager.
2113 Return true if the constraint was successfully added (or is already
2114 known to be true).
2115 Return false if the constraint contradicts existing knowledge. */
2117 bool
2118 constraint_manager::add_bounded_ranges (const svalue *sval,
2119 const bounded_ranges *ranges)
2121 sval = sval->unwrap_any_unmergeable ();
2123 /* Nothing can be known about unknown/poisoned values. */
2124 if (!sval->can_have_associated_state_p ())
2125 /* Not a contradiction. */
2126 return true;
2128 /* If SVAL is a constant, then we can look at RANGES directly. */
2129 if (tree cst = sval->maybe_get_constant ())
2131 /* If the ranges contain CST, then it's a successful no-op;
2132 otherwise it's a contradiction. */
2133 return ranges->contain_p (cst);
2136 equiv_class_id ec_id = get_or_add_equiv_class (sval);
2138 /* If the EC has a constant, it's either true or false. */
2139 const equiv_class &ec = ec_id.get_obj (*this);
2140 if (tree ec_cst = ec.get_any_constant ())
2142 if (ranges->contain_p (ec_cst))
2143 /* We already have SVAL == EC_CST, within RANGES, so
2144 we can discard RANGES and succeed. */
2145 return true;
2146 else
2147 /* We already have SVAL == EC_CST, not within RANGES, so
2148 we can reject RANGES as a contradiction. */
2149 return false;
2152 /* We have at most one per ec_id. */
2153 /* Iterate through each range in RANGES. */
2154 for (auto iter : m_bounded_ranges_constraints)
2156 if (iter.m_ec_id == ec_id)
2158 /* Update with intersection, or fail if empty. */
2159 bounded_ranges_manager *mgr = get_range_manager ();
2160 const bounded_ranges *intersection
2161 = mgr->get_or_create_intersection (iter.m_ranges, ranges);
2162 if (intersection->empty_p ())
2164 /* No intersection; fail. */
2165 return false;
2167 else
2169 /* Update with intersection; succeed. */
2170 iter.m_ranges = intersection;
2171 validate ();
2172 return true;
2176 m_bounded_ranges_constraints.safe_push
2177 (bounded_ranges_constraint (ec_id, ranges));
2179 validate ();
2181 return true;
2184 /* Look for SVAL within the equivalence classes of this constraint_manager;
2185 if found, return true, writing the id to *OUT if OUT is non-NULL,
2186 otherwise return false. */
2188 bool
2189 constraint_manager::get_equiv_class_by_svalue (const svalue *sval,
2190 equiv_class_id *out) const
2192 /* TODO: should we have a map, rather than these searches? */
2193 int i;
2194 equiv_class *ec;
2195 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2197 int j;
2198 const svalue *iv;
2199 FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
2200 if (iv == sval)
2202 if (out)
2203 *out = equiv_class_id (i);
2204 return true;
2207 return false;
2210 /* Ensure that SVAL has an equivalence class within this constraint_manager;
2211 return the ID of the class. */
2213 equiv_class_id
2214 constraint_manager::get_or_add_equiv_class (const svalue *sval)
2216 equiv_class_id result (-1);
2218 gcc_assert (sval->can_have_associated_state_p ());
2220 /* Convert all NULL pointers to (void *) to avoid state explosions
2221 involving all of the various (foo *)NULL vs (bar *)NULL. */
2222 if (sval->get_type ())
2223 if (POINTER_TYPE_P (sval->get_type ()))
2224 if (tree cst = sval->maybe_get_constant ())
2225 if (zerop (cst))
2226 sval = m_mgr->get_or_create_constant_svalue (null_pointer_node);
2228 /* Try svalue match. */
2229 if (get_equiv_class_by_svalue (sval, &result))
2230 return result;
2232 /* Try equality of constants. */
2233 if (tree cst = sval->maybe_get_constant ())
2235 int i;
2236 equiv_class *ec;
2237 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2238 if (ec->m_constant
2239 && types_compatible_p (TREE_TYPE (cst),
2240 TREE_TYPE (ec->m_constant)))
2242 tree eq = fold_binary (EQ_EXPR, boolean_type_node,
2243 cst, ec->m_constant);
2244 if (eq == boolean_true_node)
2246 ec->add (sval);
2247 return equiv_class_id (i);
2253 /* Not found. */
2254 equiv_class *new_ec = new equiv_class ();
2255 new_ec->add (sval);
2256 m_equiv_classes.safe_push (new_ec);
2258 equiv_class_id new_id (m_equiv_classes.length () - 1);
2260 return new_id;
2263 /* Evaluate the condition LHS_EC OP RHS_EC. */
2265 tristate
2266 constraint_manager::eval_condition (equiv_class_id lhs_ec,
2267 enum tree_code op,
2268 equiv_class_id rhs_ec) const
2270 if (lhs_ec == rhs_ec)
2272 switch (op)
2274 case EQ_EXPR:
2275 case GE_EXPR:
2276 case LE_EXPR:
2277 return tristate (tristate::TS_TRUE);
2279 case NE_EXPR:
2280 case GT_EXPR:
2281 case LT_EXPR:
2282 return tristate (tristate::TS_FALSE);
2283 default:
2284 break;
2288 tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ();
2289 tree rhs_const = rhs_ec.get_obj (*this).get_any_constant ();
2290 if (lhs_const && rhs_const)
2292 tristate result_for_constants
2293 = compare_constants (lhs_const, op, rhs_const);
2294 if (result_for_constants.is_known ())
2295 return result_for_constants;
2298 enum tree_code swapped_op = swap_tree_comparison (op);
2300 int i;
2301 constraint *c;
2302 FOR_EACH_VEC_ELT (m_constraints, i, c)
2304 if (c->m_lhs == lhs_ec
2305 && c->m_rhs == rhs_ec)
2307 tristate result_for_constraint
2308 = eval_constraint_op_for_op (c->m_op, op);
2309 if (result_for_constraint.is_known ())
2310 return result_for_constraint;
2312 /* Swapped operands. */
2313 if (c->m_lhs == rhs_ec
2314 && c->m_rhs == lhs_ec)
2316 tristate result_for_constraint
2317 = eval_constraint_op_for_op (c->m_op, swapped_op);
2318 if (result_for_constraint.is_known ())
2319 return result_for_constraint;
2323 /* We don't use m_bounded_ranges_constraints here yet. */
2325 return tristate (tristate::TS_UNKNOWN);
2328 range
2329 constraint_manager::get_ec_bounds (equiv_class_id ec_id) const
2331 range result;
2333 int i;
2334 constraint *c;
2335 FOR_EACH_VEC_ELT (m_constraints, i, c)
2337 if (c->m_lhs == ec_id)
2339 if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ())
2340 switch (c->m_op)
2342 default:
2343 gcc_unreachable ();
2344 case CONSTRAINT_NE:
2345 continue;
2347 case CONSTRAINT_LT:
2348 /* We have "EC_ID < OTHER_CST". */
2349 result.add_bound (bound (other_cst, false), BK_UPPER);
2350 break;
2352 case CONSTRAINT_LE:
2353 /* We have "EC_ID <= OTHER_CST". */
2354 result.add_bound (bound (other_cst, true), BK_UPPER);
2355 break;
2358 if (c->m_rhs == ec_id)
2360 if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ())
2361 switch (c->m_op)
2363 default:
2364 gcc_unreachable ();
2365 case CONSTRAINT_NE:
2366 continue;
2368 case CONSTRAINT_LT:
2369 /* We have "OTHER_CST < EC_ID"
2370 i.e. "EC_ID > OTHER_CST". */
2371 result.add_bound (bound (other_cst, false), BK_LOWER);
2372 break;
2374 case CONSTRAINT_LE:
2375 /* We have "OTHER_CST <= EC_ID"
2376 i.e. "EC_ID >= OTHER_CST". */
2377 result.add_bound (bound (other_cst, true), BK_LOWER);
2378 break;
2383 return result;
2386 /* Evaluate the condition LHS_EC OP RHS_CONST, avoiding the creation
2387 of equiv_class instances. */
2389 tristate
2390 constraint_manager::eval_condition (equiv_class_id lhs_ec,
2391 enum tree_code op,
2392 tree rhs_const) const
2394 gcc_assert (!lhs_ec.null_p ());
2395 gcc_assert (CONSTANT_CLASS_P (rhs_const));
2397 if (tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ())
2398 return compare_constants (lhs_const, op, rhs_const);
2400 /* Check for known inequalities of the form
2401 (LHS_EC != OTHER_CST) or (OTHER_CST != LHS_EC).
2402 If RHS_CONST == OTHER_CST, then we also know that LHS_EC != OTHER_CST.
2403 For example, we might have the constraint
2404 ptr != (void *)0
2405 so we want the condition
2406 ptr == (foo *)0
2407 to be false. */
2408 int i;
2409 constraint *c;
2410 FOR_EACH_VEC_ELT (m_constraints, i, c)
2412 if (c->m_op == CONSTRAINT_NE)
2414 if (c->m_lhs == lhs_ec)
2416 if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ())
2417 if (compare_constants
2418 (rhs_const, EQ_EXPR, other_cst).is_true ())
2420 switch (op)
2422 case EQ_EXPR:
2423 return tristate (tristate::TS_FALSE);
2424 case NE_EXPR:
2425 return tristate (tristate::TS_TRUE);
2426 default:
2427 break;
2431 if (c->m_rhs == lhs_ec)
2433 if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ())
2434 if (compare_constants
2435 (rhs_const, EQ_EXPR, other_cst).is_true ())
2437 switch (op)
2439 case EQ_EXPR:
2440 return tristate (tristate::TS_FALSE);
2441 case NE_EXPR:
2442 return tristate (tristate::TS_TRUE);
2443 default:
2444 break;
2451 bounded_ranges_manager *mgr = get_range_manager ();
2452 for (const auto &iter : m_bounded_ranges_constraints)
2453 if (iter.m_ec_id == lhs_ec)
2454 return iter.m_ranges->eval_condition (op, rhs_const, mgr);
2456 /* Look at existing bounds on LHS_EC. */
2457 range lhs_bounds = get_ec_bounds (lhs_ec);
2458 tristate result = lhs_bounds.eval_condition (op, rhs_const);
2459 if (result.is_known ())
2460 return result;
2462 /* Also reject if range::add_bound fails. */
2463 if (!lhs_bounds.add_bound (op, rhs_const))
2464 return tristate (false);
2466 return tristate::unknown ();
2469 /* Evaluate the condition LHS OP RHS, without modifying this
2470 constraint_manager (avoiding the creation of equiv_class instances). */
2472 tristate
2473 constraint_manager::eval_condition (const svalue *lhs,
2474 enum tree_code op,
2475 const svalue *rhs) const
2477 lhs = lhs->unwrap_any_unmergeable ();
2478 rhs = rhs->unwrap_any_unmergeable ();
2480 /* Nothing can be known about unknown or poisoned values. */
2481 if (lhs->get_kind () == SK_UNKNOWN
2482 || lhs->get_kind () == SK_POISONED
2483 || rhs->get_kind () == SK_UNKNOWN
2484 || rhs->get_kind () == SK_POISONED)
2485 return tristate (tristate::TS_UNKNOWN);
2487 if (lhs == rhs
2488 && !(FLOAT_TYPE_P (lhs->get_type ())
2489 || FLOAT_TYPE_P (rhs->get_type ())))
2491 switch (op)
2493 case EQ_EXPR:
2494 case GE_EXPR:
2495 case LE_EXPR:
2496 return tristate (tristate::TS_TRUE);
2498 case NE_EXPR:
2499 case GT_EXPR:
2500 case LT_EXPR:
2501 return tristate (tristate::TS_FALSE);
2502 default:
2503 break;
2507 equiv_class_id lhs_ec (-1);
2508 equiv_class_id rhs_ec (-1);
2509 get_equiv_class_by_svalue (lhs, &lhs_ec);
2510 get_equiv_class_by_svalue (rhs, &rhs_ec);
2511 if (!lhs_ec.null_p () && !rhs_ec.null_p ())
2513 tristate result_for_ecs
2514 = eval_condition (lhs_ec, op, rhs_ec);
2515 if (result_for_ecs.is_known ())
2516 return result_for_ecs;
2519 /* If at least one is not in an EC, we have no constraints
2520 comparing LHS and RHS yet.
2521 They might still be comparable if one (or both) is a constant.
2523 Alternatively, we can also get here if we had ECs but they weren't
2524 comparable. Again, constant comparisons might give an answer. */
2525 tree lhs_const = lhs->maybe_get_constant ();
2526 tree rhs_const = rhs->maybe_get_constant ();
2527 if (lhs_const && rhs_const)
2529 tristate result_for_constants
2530 = compare_constants (lhs_const, op, rhs_const);
2531 if (result_for_constants.is_known ())
2532 return result_for_constants;
2535 if (!lhs_ec.null_p ())
2537 if (rhs_const)
2538 return eval_condition (lhs_ec, op, rhs_const);
2540 if (!rhs_ec.null_p ())
2542 if (lhs_const)
2544 enum tree_code swapped_op = swap_tree_comparison (op);
2545 return eval_condition (rhs_ec, swapped_op, lhs_const);
2549 return tristate (tristate::TS_UNKNOWN);
2552 /* Delete any information about svalues identified by P.
2553 Such instances are removed from equivalence classes, and any
2554 redundant ECs and constraints are also removed.
2555 Accumulate stats into STATS. */
2557 template <typename PurgeCriteria>
2558 void
2559 constraint_manager::purge (const PurgeCriteria &p, purge_stats *stats)
2561 /* Delete any svalues identified by P within the various equivalence
2562 classes. */
2563 for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
2565 equiv_class *ec = m_equiv_classes[ec_idx];
2567 int i;
2568 const svalue *sval;
2569 bool delete_ec = false;
2570 FOR_EACH_VEC_ELT (ec->m_vars, i, sval)
2572 if (sval == ec->m_cst_sval)
2573 continue;
2574 if (p.should_purge_p (sval))
2576 if (ec->del (sval))
2577 if (!ec->m_constant)
2578 delete_ec = true;
2582 if (delete_ec)
2584 delete ec;
2585 m_equiv_classes.ordered_remove (ec_idx);
2586 if (stats)
2587 stats->m_num_equiv_classes++;
2589 /* Update the constraints, potentially removing some. */
2590 for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
2592 constraint *c = &m_constraints[con_idx];
2594 /* Remove constraints that refer to the deleted EC. */
2595 if (c->m_lhs == ec_idx
2596 || c->m_rhs == ec_idx)
2598 m_constraints.ordered_remove (con_idx);
2599 if (stats)
2600 stats->m_num_constraints++;
2602 else
2604 /* Renumber constraints that refer to ECs that have
2605 had their idx changed. */
2606 c->m_lhs.update_for_removal (ec_idx);
2607 c->m_rhs.update_for_removal (ec_idx);
2609 con_idx++;
2613 /* Update bounded_ranges_constraint instances. */
2614 for (unsigned r_idx = 0;
2615 r_idx < m_bounded_ranges_constraints.length (); )
2617 bounded_ranges_constraint *brc
2618 = &m_bounded_ranges_constraints[r_idx];
2620 /* Remove if it refers to the deleted EC. */
2621 if (brc->m_ec_id == ec_idx)
2623 m_bounded_ranges_constraints.ordered_remove (r_idx);
2624 if (stats)
2625 stats->m_num_bounded_ranges_constraints++;
2627 else
2629 /* Renumber any EC ids that refer to ECs that have
2630 had their idx changed. */
2631 brc->m_ec_id.update_for_removal (ec_idx);
2632 r_idx++;
2636 else
2637 ec_idx++;
2640 /* Now delete any constraints that are purely between constants. */
2641 for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
2643 constraint *c = &m_constraints[con_idx];
2644 if (m_equiv_classes[c->m_lhs.m_idx]->m_vars.length () == 0
2645 && m_equiv_classes[c->m_rhs.m_idx]->m_vars.length () == 0)
2647 m_constraints.ordered_remove (con_idx);
2648 if (stats)
2649 stats->m_num_constraints++;
2651 else
2653 con_idx++;
2657 /* Finally, delete any ECs that purely contain constants and aren't
2658 referenced by any constraints. */
2659 for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
2661 equiv_class *ec = m_equiv_classes[ec_idx];
2662 if (ec->m_vars.length () == 0)
2664 equiv_class_id ec_id (ec_idx);
2665 bool has_constraint = false;
2666 for (unsigned con_idx = 0; con_idx < m_constraints.length ();
2667 con_idx++)
2669 constraint *c = &m_constraints[con_idx];
2670 if (c->m_lhs == ec_id
2671 || c->m_rhs == ec_id)
2673 has_constraint = true;
2674 break;
2677 if (!has_constraint)
2679 delete ec;
2680 m_equiv_classes.ordered_remove (ec_idx);
2681 if (stats)
2682 stats->m_num_equiv_classes++;
2684 /* Renumber constraints that refer to ECs that have
2685 had their idx changed. */
2686 for (unsigned con_idx = 0; con_idx < m_constraints.length ();
2687 con_idx++)
2689 constraint *c = &m_constraints[con_idx];
2690 c->m_lhs.update_for_removal (ec_idx);
2691 c->m_rhs.update_for_removal (ec_idx);
2694 /* Likewise for m_bounded_ranges_constraints. */
2695 for (unsigned r_idx = 0;
2696 r_idx < m_bounded_ranges_constraints.length ();
2697 r_idx++)
2699 bounded_ranges_constraint *brc
2700 = &m_bounded_ranges_constraints[r_idx];
2701 brc->m_ec_id.update_for_removal (ec_idx);
2704 continue;
2707 ec_idx++;
2710 validate ();
2713 /* Implementation of PurgeCriteria: purge svalues that are not live
2714 with respect to LIVE_SVALUES and MODEL. */
2716 class dead_svalue_purger
2718 public:
2719 dead_svalue_purger (const svalue_set &live_svalues,
2720 const region_model *model)
2721 : m_live_svalues (live_svalues), m_model (model)
2725 bool should_purge_p (const svalue *sval) const
2727 return !sval->live_p (&m_live_svalues, m_model);
2730 private:
2731 const svalue_set &m_live_svalues;
2732 const region_model *m_model;
2735 /* Purge dead svalues from equivalence classes and update constraints
2736 accordingly. */
2738 void
2739 constraint_manager::
2740 on_liveness_change (const svalue_set &live_svalues,
2741 const region_model *model)
2743 dead_svalue_purger p (live_svalues, model);
2744 purge (p, NULL);
2747 class svalue_purger
2749 public:
2750 svalue_purger (const svalue *sval) : m_sval (sval) {}
2752 bool should_purge_p (const svalue *sval) const
2754 return sval->involves_p (m_sval);
2757 private:
2758 const svalue *m_sval;
2761 /* Purge any state involving SVAL. */
2763 void
2764 constraint_manager::purge_state_involving (const svalue *sval)
2766 svalue_purger p (sval);
2767 purge (p, NULL);
2770 /* Comparator for use by constraint_manager::canonicalize.
2771 Sort a pair of equiv_class instances, using the representative
2772 svalue as a sort key. */
2774 static int
2775 equiv_class_cmp (const void *p1, const void *p2)
2777 const equiv_class *ec1 = *(const equiv_class * const *)p1;
2778 const equiv_class *ec2 = *(const equiv_class * const *)p2;
2780 const svalue *rep1 = ec1->get_representative ();
2781 const svalue *rep2 = ec2->get_representative ();
2783 gcc_assert (rep1);
2784 gcc_assert (rep2);
2786 return svalue::cmp_ptr (rep1, rep2);
2789 /* Comparator for use by constraint_manager::canonicalize.
2790 Sort a pair of constraint instances. */
2792 static int
2793 constraint_cmp (const void *p1, const void *p2)
2795 const constraint *c1 = (const constraint *)p1;
2796 const constraint *c2 = (const constraint *)p2;
2797 int lhs_cmp = c1->m_lhs.as_int () - c2->m_lhs.as_int ();
2798 if (lhs_cmp)
2799 return lhs_cmp;
2800 int rhs_cmp = c1->m_rhs.as_int () - c2->m_rhs.as_int ();
2801 if (rhs_cmp)
2802 return rhs_cmp;
2803 return c1->m_op - c2->m_op;
2806 /* Purge redundant equivalence classes and constraints, and reorder them
2807 within this constraint_manager into a canonical order, to increase the
2808 chances of finding equality with another instance. */
2810 void
2811 constraint_manager::canonicalize ()
2813 /* First, sort svalues within the ECs. */
2814 unsigned i;
2815 equiv_class *ec;
2816 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2817 ec->canonicalize ();
2819 /* TODO: remove constraints where both sides have a constant, and are
2820 thus implicit. But does this break transitivity? */
2822 /* We will be purging and reordering ECs.
2823 We will need to remap the equiv_class_ids in the constraints,
2824 so we need to store the original index of each EC.
2825 Build a lookup table, mapping from the representative svalue
2826 to the original equiv_class_id of that svalue. */
2827 hash_map<const svalue *, equiv_class_id> original_ec_id;
2828 const unsigned orig_num_equiv_classes = m_equiv_classes.length ();
2829 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2831 const svalue *rep = ec->get_representative ();
2832 gcc_assert (rep);
2833 original_ec_id.put (rep, i);
2836 /* Find ECs used by constraints. */
2837 hash_set<const equiv_class *> used_ecs;
2838 constraint *c;
2839 FOR_EACH_VEC_ELT (m_constraints, i, c)
2841 used_ecs.add (m_equiv_classes[c->m_lhs.as_int ()]);
2842 used_ecs.add (m_equiv_classes[c->m_rhs.as_int ()]);
2845 for (const auto &iter : m_bounded_ranges_constraints)
2846 used_ecs.add (m_equiv_classes[iter.m_ec_id.as_int ()]);
2848 /* Purge unused ECs: those that aren't used by constraints and
2849 that effectively have only one svalue (either in m_constant
2850 or in m_vars). */
2852 /* "unordered remove if" from a vec. */
2853 unsigned i = 0;
2854 while (i < m_equiv_classes.length ())
2856 equiv_class *ec = m_equiv_classes[i];
2857 if (!used_ecs.contains (ec)
2858 && !ec->contains_non_constant_p ())
2860 m_equiv_classes.unordered_remove (i);
2861 delete ec;
2863 else
2864 i++;
2868 /* Next, sort the surviving ECs into a canonical order. */
2869 m_equiv_classes.qsort (equiv_class_cmp);
2871 /* Populate ec_id_map based on the old vs new EC ids. */
2872 one_way_id_map<equiv_class_id> ec_id_map (orig_num_equiv_classes);
2873 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2875 const svalue *rep = ec->get_representative ();
2876 gcc_assert (rep);
2877 ec_id_map.put (*original_ec_id.get (rep), i);
2880 /* Use ec_id_map to update the EC ids within the constraints. */
2881 FOR_EACH_VEC_ELT (m_constraints, i, c)
2883 ec_id_map.update (&c->m_lhs);
2884 ec_id_map.update (&c->m_rhs);
2887 for (auto &iter : m_bounded_ranges_constraints)
2888 ec_id_map.update (&iter.m_ec_id);
2890 /* Finally, sort the constraints. */
2891 m_constraints.qsort (constraint_cmp);
2894 /* Concrete subclass of fact_visitor for use by constraint_manager::merge.
2895 For every fact in CM_A, see if it is also true in *CM_B. Add such
2896 facts to *OUT. */
2898 class merger_fact_visitor : public fact_visitor
2900 public:
2901 merger_fact_visitor (const constraint_manager *cm_b,
2902 constraint_manager *out)
2903 : m_cm_b (cm_b), m_out (out)
2906 void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs)
2907 final override
2909 /* Special-case for widening. */
2910 if (lhs->get_kind () == SK_WIDENING)
2911 if (!m_cm_b->get_equiv_class_by_svalue (lhs, NULL))
2913 /* LHS isn't constrained within m_cm_b. */
2914 bool sat = m_out->add_constraint (lhs, code, rhs);
2915 gcc_assert (sat);
2916 return;
2919 if (m_cm_b->eval_condition (lhs, code, rhs).is_true ())
2921 bool sat = m_out->add_constraint (lhs, code, rhs);
2922 if (!sat)
2924 /* If -fanalyzer-transitivity is off, we can encounter cases
2925 where at least one of the two constraint_managers being merged
2926 is infeasible, but we only discover that infeasibility
2927 during merging (PR analyzer/96650).
2928 Silently drop such constraints. */
2929 gcc_assert (!flag_analyzer_transitivity);
2934 void on_ranges (const svalue *lhs_sval,
2935 const bounded_ranges *ranges) final override
2937 for (const auto &iter : m_cm_b->m_bounded_ranges_constraints)
2939 const equiv_class &ec_rhs = iter.m_ec_id.get_obj (*m_cm_b);
2940 for (unsigned i = 0; i < ec_rhs.m_vars.length (); i++)
2942 const svalue *rhs_sval = ec_rhs.m_vars[i];
2943 if (lhs_sval == rhs_sval)
2945 /* Union of the two ranges. */
2946 auto_vec <const bounded_ranges *> pair (2);
2947 pair.quick_push (ranges);
2948 pair.quick_push (iter.m_ranges);
2949 bounded_ranges_manager *ranges_mgr
2950 = m_cm_b->get_range_manager ();
2951 const bounded_ranges *union_
2952 = ranges_mgr->get_or_create_union (pair);
2953 bool sat = m_out->add_bounded_ranges (lhs_sval, union_);
2954 gcc_assert (sat);
2960 private:
2961 const constraint_manager *m_cm_b;
2962 constraint_manager *m_out;
2965 /* Use MERGER to merge CM_A and CM_B into *OUT.
2966 If one thinks of a constraint_manager as a subset of N-dimensional
2967 space, this takes the union of the points of CM_A and CM_B, and
2968 expresses that into *OUT. Alternatively, it can be thought of
2969 as the intersection of the constraints. */
2971 void
2972 constraint_manager::merge (const constraint_manager &cm_a,
2973 const constraint_manager &cm_b,
2974 constraint_manager *out)
2976 /* Merge the equivalence classes and constraints.
2977 The easiest way to do this seems to be to enumerate all of the facts
2978 in cm_a, see which are also true in cm_b,
2979 and add those to *OUT. */
2980 merger_fact_visitor v (&cm_b, out);
2981 cm_a.for_each_fact (&v);
2984 /* Call VISITOR's on_fact vfunc repeatedly to express the various
2985 equivalence classes and constraints.
2986 This is used by constraint_manager::merge to find the common
2987 facts between two input constraint_managers. */
2989 void
2990 constraint_manager::for_each_fact (fact_visitor *visitor) const
2992 /* First, call EQ_EXPR within the various equivalence classes. */
2993 unsigned ec_idx;
2994 equiv_class *ec;
2995 FOR_EACH_VEC_ELT (m_equiv_classes, ec_idx, ec)
2997 if (ec->m_cst_sval)
2999 unsigned i;
3000 const svalue *sval;
3001 FOR_EACH_VEC_ELT (ec->m_vars, i, sval)
3002 visitor->on_fact (ec->m_cst_sval, EQ_EXPR, sval);
3004 for (unsigned i = 0; i < ec->m_vars.length (); i++)
3005 for (unsigned j = i + 1; j < ec->m_vars.length (); j++)
3006 visitor->on_fact (ec->m_vars[i], EQ_EXPR, ec->m_vars[j]);
3009 /* Now, express the various constraints. */
3010 unsigned con_idx;
3011 constraint *c;
3012 FOR_EACH_VEC_ELT (m_constraints, con_idx, c)
3014 const equiv_class &ec_lhs = c->m_lhs.get_obj (*this);
3015 const equiv_class &ec_rhs = c->m_rhs.get_obj (*this);
3016 enum tree_code code = constraint_tree_code (c->m_op);
3018 if (ec_lhs.m_cst_sval)
3020 for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
3022 visitor->on_fact (ec_lhs.m_cst_sval, code, ec_rhs.m_vars[j]);
3025 for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++)
3027 if (ec_rhs.m_cst_sval)
3028 visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_cst_sval);
3029 for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
3030 visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_vars[j]);
3034 for (const auto &iter : m_bounded_ranges_constraints)
3036 const equiv_class &ec_lhs = iter.m_ec_id.get_obj (*this);
3037 for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++)
3039 const svalue *lhs_sval = ec_lhs.m_vars[i];
3040 visitor->on_ranges (lhs_sval, iter.m_ranges);
3045 /* Subclass of fact_visitor for use by
3046 constraint_manager::replay_call_summary. */
3048 class replay_fact_visitor : public fact_visitor
3050 public:
3051 replay_fact_visitor (call_summary_replay &r,
3052 constraint_manager *out)
3053 : m_r (r), m_out (out), m_feasible (true)
3056 bool feasible_p () const { return m_feasible; }
3058 void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs)
3059 final override
3061 const svalue *caller_lhs = m_r.convert_svalue_from_summary (lhs);
3062 if (!caller_lhs)
3063 return;
3064 const svalue *caller_rhs = m_r.convert_svalue_from_summary (rhs);
3065 if (!caller_rhs)
3066 return;
3067 if (!m_out->add_constraint (caller_lhs, code, caller_rhs))
3068 m_feasible = false;
3071 void on_ranges (const svalue *lhs_sval,
3072 const bounded_ranges *ranges) final override
3074 const svalue *caller_lhs = m_r.convert_svalue_from_summary (lhs_sval);
3075 if (!caller_lhs)
3076 return;
3077 if (!m_out->add_bounded_ranges (caller_lhs, ranges))
3078 m_feasible = false;
3081 private:
3082 call_summary_replay &m_r;
3083 constraint_manager *m_out;
3084 bool m_feasible;
3087 /* Attempt to use R to replay the constraints from SUMMARY into this object.
3088 Return true if it is feasible. */
3090 bool
3091 constraint_manager::replay_call_summary (call_summary_replay &r,
3092 const constraint_manager &summary)
3094 replay_fact_visitor v (r, this);
3095 summary.for_each_fact (&v);
3096 return v.feasible_p ();
3099 /* Assert that this object is valid. */
3101 void
3102 constraint_manager::validate () const
3104 /* Skip this in a release build. */
3105 #if !CHECKING_P
3106 return;
3107 #endif
3109 int i;
3110 equiv_class *ec;
3111 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
3113 gcc_assert (ec);
3115 int j;
3116 const svalue *sval;
3117 FOR_EACH_VEC_ELT (ec->m_vars, j, sval)
3118 gcc_assert (sval);
3119 if (ec->m_constant)
3121 gcc_assert (CONSTANT_CLASS_P (ec->m_constant));
3122 gcc_assert (ec->m_cst_sval);
3124 #if 0
3125 else
3126 gcc_assert (ec->m_vars.length () > 0);
3127 #endif
3130 constraint *c;
3131 FOR_EACH_VEC_ELT (m_constraints, i, c)
3133 gcc_assert (!c->m_lhs.null_p ());
3134 gcc_assert (c->m_lhs.as_int () < (int)m_equiv_classes.length ());
3135 gcc_assert (!c->m_rhs.null_p ());
3136 gcc_assert (c->m_rhs.as_int () < (int)m_equiv_classes.length ());
3139 for (const auto &iter : m_bounded_ranges_constraints)
3141 gcc_assert (!iter.m_ec_id.null_p ());
3142 gcc_assert (iter.m_ec_id.as_int () < (int)m_equiv_classes.length ());
3146 bounded_ranges_manager *
3147 constraint_manager::get_range_manager () const
3149 return m_mgr->get_range_manager ();
3152 #if CHECKING_P
3154 namespace selftest {
3156 /* Various constraint_manager selftests.
3157 These have to be written in terms of a region_model, since
3158 the latter is responsible for managing svalue instances. */
3160 /* Verify that range::add_bound works as expected. */
3162 static void
3163 test_range ()
3165 tree int_0 = build_int_cst (integer_type_node, 0);
3166 tree int_1 = build_int_cst (integer_type_node, 1);
3167 tree int_2 = build_int_cst (integer_type_node, 2);
3168 tree int_5 = build_int_cst (integer_type_node, 5);
3171 range r;
3172 ASSERT_FALSE (r.constrained_to_single_element ());
3174 /* (r >= 1). */
3175 ASSERT_TRUE (r.add_bound (GE_EXPR, int_1));
3177 /* Redundant. */
3178 ASSERT_TRUE (r.add_bound (GE_EXPR, int_0));
3179 ASSERT_TRUE (r.add_bound (GT_EXPR, int_0));
3181 ASSERT_FALSE (r.constrained_to_single_element ());
3183 /* Contradiction. */
3184 ASSERT_FALSE (r.add_bound (LT_EXPR, int_1));
3186 /* (r < 5). */
3187 ASSERT_TRUE (r.add_bound (LT_EXPR, int_5));
3188 ASSERT_FALSE (r.constrained_to_single_element ());
3190 /* Contradiction. */
3191 ASSERT_FALSE (r.add_bound (GE_EXPR, int_5));
3193 /* (r < 2). */
3194 ASSERT_TRUE (r.add_bound (LT_EXPR, int_2));
3195 ASSERT_TRUE (r.constrained_to_single_element ());
3197 /* Redundant. */
3198 ASSERT_TRUE (r.add_bound (LE_EXPR, int_1));
3199 ASSERT_TRUE (r.constrained_to_single_element ());
3203 /* Verify that setting and getting simple conditions within a region_model
3204 work (thus exercising the underlying constraint_manager). */
3206 static void
3207 test_constraint_conditions ()
3209 tree int_42 = build_int_cst (integer_type_node, 42);
3210 tree int_0 = build_int_cst (integer_type_node, 0);
3212 tree x = build_global_decl ("x", integer_type_node);
3213 tree y = build_global_decl ("y", integer_type_node);
3214 tree z = build_global_decl ("z", integer_type_node);
3216 /* Self-comparisons. */
3218 region_model_manager mgr;
3219 region_model model (&mgr);
3220 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, x);
3221 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, x);
3222 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, x);
3223 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, x);
3224 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, x);
3225 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, x);
3228 /* Adding self-equality shouldn't add equiv classes. */
3230 region_model_manager mgr;
3231 region_model model (&mgr);
3232 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, x);
3233 ADD_SAT_CONSTRAINT (model, int_42, EQ_EXPR, int_42);
3234 /* ...even when done directly via svalues: */
3235 const svalue *sval_int_42 = model.get_rvalue (int_42, NULL);
3236 bool sat = model.get_constraints ()->add_constraint (sval_int_42,
3237 EQ_EXPR,
3238 sval_int_42);
3239 ASSERT_TRUE (sat);
3240 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
3243 /* x == y. */
3245 region_model_manager mgr;
3246 region_model model (&mgr);
3247 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3249 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3251 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, y);
3252 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3253 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3254 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, y);
3255 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3256 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3258 /* Swapped operands. */
3259 ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x);
3260 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3261 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3262 ASSERT_CONDITION_FALSE (model, y, NE_EXPR, x);
3263 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3264 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3266 /* Comparison with other var. */
3267 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
3268 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
3269 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3270 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
3271 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
3272 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
3275 /* x == y, then y == z */
3277 region_model_manager mgr;
3278 region_model model (&mgr);
3279 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3281 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3282 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, z);
3284 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, z);
3285 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, z);
3286 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
3287 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, z);
3288 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, z);
3289 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, z);
3292 /* x != y. */
3294 region_model_manager mgr;
3295 region_model model (&mgr);
3297 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
3299 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3300 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3301 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
3302 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
3303 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
3304 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
3306 /* Swapped operands. */
3307 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3308 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3309 ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
3310 ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
3311 ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
3312 ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
3314 /* Comparison with other var. */
3315 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
3316 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
3317 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3318 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
3319 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
3320 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
3323 /* x < y. */
3325 region_model_manager mgr;
3326 region_model model (&mgr);
3328 ADD_SAT_CONSTRAINT (model, x, LT_EXPR, y);
3330 ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
3331 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3332 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3333 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3334 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3335 ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
3337 /* Swapped operands. */
3338 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3339 ASSERT_CONDITION_FALSE (model, y, LE_EXPR, x);
3340 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3341 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3342 ASSERT_CONDITION_TRUE (model, y, GT_EXPR, x);
3343 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3346 /* x <= y. */
3348 region_model_manager mgr;
3349 region_model model (&mgr);
3351 ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
3353 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
3354 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3355 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
3356 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3357 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3358 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
3360 /* Swapped operands. */
3361 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3362 ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
3363 ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
3364 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
3365 ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
3366 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3369 /* x > y. */
3371 region_model_manager mgr;
3372 region_model model (&mgr);
3374 ADD_SAT_CONSTRAINT (model, x, GT_EXPR, y);
3376 ASSERT_CONDITION_TRUE (model, x, GT_EXPR, y);
3377 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3378 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3379 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3380 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3381 ASSERT_CONDITION_FALSE (model, x, LE_EXPR, y);
3383 /* Swapped operands. */
3384 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3385 ASSERT_CONDITION_FALSE (model, y, GE_EXPR, x);
3386 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3387 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3388 ASSERT_CONDITION_TRUE (model, y, LT_EXPR, x);
3389 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3392 /* x >= y. */
3394 region_model_manager mgr;
3395 region_model model (&mgr);
3397 ADD_SAT_CONSTRAINT (model, x, GE_EXPR, y);
3399 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
3400 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3401 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
3402 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3403 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3404 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
3406 /* Swapped operands. */
3407 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3408 ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
3409 ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
3410 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
3411 ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
3412 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3415 // TODO: implied orderings
3417 /* Constants. */
3419 region_model_manager mgr;
3420 region_model model (&mgr);
3421 ASSERT_CONDITION_FALSE (model, int_0, EQ_EXPR, int_42);
3422 ASSERT_CONDITION_TRUE (model, int_0, NE_EXPR, int_42);
3423 ASSERT_CONDITION_TRUE (model, int_0, LT_EXPR, int_42);
3424 ASSERT_CONDITION_TRUE (model, int_0, LE_EXPR, int_42);
3425 ASSERT_CONDITION_FALSE (model, int_0, GT_EXPR, int_42);
3426 ASSERT_CONDITION_FALSE (model, int_0, GE_EXPR, int_42);
3429 /* x == 0, y == 42. */
3431 region_model_manager mgr;
3432 region_model model (&mgr);
3433 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3434 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, int_42);
3436 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3437 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3438 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3439 ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
3440 ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
3441 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3444 /* Unsatisfiable combinations. */
3446 /* x == y && x != y. */
3448 region_model_manager mgr;
3449 region_model model (&mgr);
3450 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3451 ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, y);
3454 /* x == 0 then x == 42. */
3456 region_model_manager mgr;
3457 region_model model (&mgr);
3458 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3459 ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, int_42);
3462 /* x == 0 then x != 0. */
3464 region_model_manager mgr;
3465 region_model model (&mgr);
3466 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3467 ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, int_0);
3470 /* x == 0 then x > 0. */
3472 region_model_manager mgr;
3473 region_model model (&mgr);
3474 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3475 ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, int_0);
3478 /* x != y && x == y. */
3480 region_model_manager mgr;
3481 region_model model (&mgr);
3482 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
3483 ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, y);
3486 /* x <= y && x > y. */
3488 region_model_manager mgr;
3489 region_model model (&mgr);
3490 ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
3491 ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, y);
3494 // etc
3497 /* Test transitivity of conditions. */
3499 static void
3500 test_transitivity ()
3502 tree a = build_global_decl ("a", integer_type_node);
3503 tree b = build_global_decl ("b", integer_type_node);
3504 tree c = build_global_decl ("c", integer_type_node);
3505 tree d = build_global_decl ("d", integer_type_node);
3507 /* a == b, then c == d, then c == b. */
3509 region_model_manager mgr;
3510 region_model model (&mgr);
3511 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, b);
3512 ASSERT_CONDITION_UNKNOWN (model, b, EQ_EXPR, c);
3513 ASSERT_CONDITION_UNKNOWN (model, c, EQ_EXPR, d);
3514 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
3516 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, b);
3517 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
3519 ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, d);
3520 ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, d);
3521 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
3523 ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, b);
3524 ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, b);
3525 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, d);
3528 /* Transitivity: "a < b", "b < c" should imply "a < c". */
3530 region_model_manager mgr;
3531 region_model model (&mgr);
3532 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
3533 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3535 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3536 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3539 /* Transitivity: "a <= b", "b < c" should imply "a < c". */
3541 region_model_manager mgr;
3542 region_model model (&mgr);
3543 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
3544 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3546 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3547 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3550 /* Transitivity: "a <= b", "b <= c" should imply "a <= c". */
3552 region_model_manager mgr;
3553 region_model model (&mgr);
3554 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
3555 ADD_SAT_CONSTRAINT (model, b, LE_EXPR, c);
3557 ASSERT_CONDITION_TRUE (model, a, LE_EXPR, c);
3558 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
3561 /* Transitivity: "a > b", "b > c" should imply "a > c". */
3563 region_model_manager mgr;
3564 region_model model (&mgr);
3565 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3566 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3568 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
3569 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3572 /* Transitivity: "a >= b", "b > c" should imply " a > c". */
3574 region_model_manager mgr;
3575 region_model model (&mgr);
3576 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3577 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3579 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
3580 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3583 /* Transitivity: "a >= b", "b >= c" should imply "a >= c". */
3585 region_model_manager mgr;
3586 region_model model (&mgr);
3587 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3588 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c);
3590 ASSERT_CONDITION_TRUE (model, a, GE_EXPR, c);
3591 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
3594 /* Transitivity: "(a < b)", "(c < d)", "(b < c)" should
3595 imply the easy cases:
3596 (a < c)
3597 (b < d)
3598 but also that:
3599 (a < d). */
3601 region_model_manager mgr;
3602 region_model model (&mgr);
3603 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
3604 ADD_SAT_CONSTRAINT (model, c, LT_EXPR, d);
3605 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3607 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3608 ASSERT_CONDITION_TRUE (model, b, LT_EXPR, d);
3609 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, d);
3612 /* Transitivity: "a >= b", "b >= a" should imply that a == b. */
3614 region_model_manager mgr;
3615 region_model model (&mgr);
3616 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3617 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, a);
3619 // TODO:
3620 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
3622 /* The ECs for a and b should have merged, and any constraints removed. */
3623 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
3624 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
3627 /* Transitivity: "a >= b", "b > a" should be impossible. */
3629 region_model_manager mgr;
3630 region_model model (&mgr);
3631 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3632 ADD_UNSAT_CONSTRAINT (model, b, GT_EXPR, a);
3635 /* Transitivity: "a >= b", "b >= c", "c >= a" should imply
3636 that a == b == c. */
3638 region_model_manager mgr;
3639 region_model model (&mgr);
3640 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3641 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c);
3642 ADD_SAT_CONSTRAINT (model, c, GE_EXPR, a);
3644 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, c);
3647 /* Transitivity: "a > b", "b > c", "c > a"
3648 should be impossible. */
3650 region_model_manager mgr;
3651 region_model model (&mgr);
3652 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3653 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3654 ADD_UNSAT_CONSTRAINT (model, c, GT_EXPR, a);
3659 /* Test various conditionals involving constants where the results
3660 ought to be implied based on the values of the constants. */
3662 static void
3663 test_constant_comparisons ()
3665 tree int_1 = build_int_cst (integer_type_node, 1);
3666 tree int_3 = build_int_cst (integer_type_node, 3);
3667 tree int_4 = build_int_cst (integer_type_node, 4);
3668 tree int_5 = build_int_cst (integer_type_node, 5);
3670 tree int_1023 = build_int_cst (integer_type_node, 1023);
3671 tree int_1024 = build_int_cst (integer_type_node, 1024);
3673 tree a = build_global_decl ("a", integer_type_node);
3674 tree b = build_global_decl ("b", integer_type_node);
3676 tree a_plus_one = build2 (PLUS_EXPR, integer_type_node, a, int_1);
3678 /* Given a >= 1024, then a <= 1023 should be impossible. */
3680 region_model_manager mgr;
3681 region_model model (&mgr);
3682 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_1024);
3683 ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_1023);
3686 /* a > 4. */
3688 region_model_manager mgr;
3689 region_model model (&mgr);
3690 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_4);
3691 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, int_4);
3692 ASSERT_CONDITION_TRUE (model, a, NE_EXPR, int_3);
3693 ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_5);
3696 /* a <= 4. */
3698 region_model_manager mgr;
3699 region_model model (&mgr);
3700 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3701 ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_4);
3702 ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_5);
3703 ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_3);
3706 /* If "a > b" and "a == 3", then "b == 4" ought to be unsatisfiable. */
3708 region_model_manager mgr;
3709 region_model model (&mgr);
3710 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3711 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_3);
3712 ADD_UNSAT_CONSTRAINT (model, b, EQ_EXPR, int_4);
3715 /* Various tests of int ranges where there is only one possible candidate. */
3717 /* If "a <= 4" && "a > 3", then "a == 4",
3718 assuming a is of integral type. */
3720 region_model_manager mgr;
3721 region_model model (&mgr);
3722 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3723 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3724 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3727 /* If "a > 3" && "a <= 4", then "a == 4",
3728 assuming a is of integral type. */
3730 region_model_manager mgr;
3731 region_model model (&mgr);
3732 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3733 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3734 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3736 /* If "a > 3" && "a < 5", then "a == 4",
3737 assuming a is of integral type. */
3739 region_model_manager mgr;
3740 region_model model (&mgr);
3741 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3742 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3743 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3745 /* If "a >= 4" && "a < 5", then "a == 4",
3746 assuming a is of integral type. */
3748 region_model_manager mgr;
3749 region_model model (&mgr);
3750 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
3751 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3752 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3754 /* If "a >= 4" && "a <= 4", then "a == 4". */
3756 region_model_manager mgr;
3757 region_model model (&mgr);
3758 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
3759 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3760 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3764 /* As above, but for floating-point:
3765 if "f > 3" && "f <= 4" we don't know that f == 4. */
3767 tree f = build_global_decl ("f", double_type_node);
3768 tree float_3 = build_real_from_int_cst (double_type_node, int_3);
3769 tree float_4 = build_real_from_int_cst (double_type_node, int_4);
3771 region_model_manager mgr;
3772 region_model model (&mgr);
3773 ADD_SAT_CONSTRAINT (model, f, GT_EXPR, float_3);
3774 ADD_SAT_CONSTRAINT (model, f, LE_EXPR, float_4);
3775 ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, float_4);
3776 ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, int_4);
3779 /* "a > 3 && a <= 3" should be impossible. */
3781 region_model_manager mgr;
3782 region_model model (&mgr);
3783 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3784 ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_3);
3787 /* "(a + 1) > 3 && a < 3" should be impossible. */
3789 region_model_manager mgr;
3791 region_model model (&mgr);
3792 ADD_SAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3);
3793 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_3);
3796 region_model model (&mgr);
3797 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_3);
3798 ADD_UNSAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3);
3802 /* "3 < a < 4" should be impossible for integer a. */
3804 region_model_manager mgr;
3806 region_model model (&mgr);
3807 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3808 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3811 region_model model (&mgr);
3812 ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a);
3813 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3814 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3815 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3818 region_model model (&mgr);
3819 ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a);
3820 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3821 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3822 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3825 region_model model (&mgr);
3826 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3827 ADD_UNSAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3830 region_model model (&mgr);
3831 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3832 ADD_UNSAT_CONSTRAINT (model, int_4, GT_EXPR, a);
3835 region_model model (&mgr);
3836 ADD_SAT_CONSTRAINT (model, int_4, GT_EXPR, a);
3837 ADD_UNSAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3842 /* Verify various lower-level implementation details about
3843 constraint_manager. */
3845 static void
3846 test_constraint_impl ()
3848 tree int_42 = build_int_cst (integer_type_node, 42);
3849 tree int_0 = build_int_cst (integer_type_node, 0);
3851 tree x = build_global_decl ("x", integer_type_node);
3852 tree y = build_global_decl ("y", integer_type_node);
3853 tree z = build_global_decl ("z", integer_type_node);
3855 /* x == y. */
3857 region_model_manager mgr;
3858 region_model model (&mgr);
3860 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3862 /* Assert various things about the insides of model. */
3863 constraint_manager *cm = model.get_constraints ();
3864 ASSERT_EQ (cm->m_constraints.length (), 0);
3865 ASSERT_EQ (cm->m_equiv_classes.length (), 1);
3868 /* y <= z; x == y. */
3870 region_model_manager mgr;
3871 region_model model (&mgr);
3872 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3873 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3875 ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
3876 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
3877 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3879 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3881 /* Assert various things about the insides of model. */
3882 constraint_manager *cm = model.get_constraints ();
3883 ASSERT_EQ (cm->m_constraints.length (), 1);
3884 ASSERT_EQ (cm->m_equiv_classes.length (), 2);
3886 /* Ensure that we merged the constraints. */
3887 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
3890 /* y <= z; y == x. */
3892 region_model_manager mgr;
3893 region_model model (&mgr);
3894 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3895 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3897 ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
3898 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
3899 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3901 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, x);
3903 /* Assert various things about the insides of model. */
3904 constraint_manager *cm = model.get_constraints ();
3905 ASSERT_EQ (cm->m_constraints.length (), 1);
3906 ASSERT_EQ (cm->m_equiv_classes.length (), 2);
3908 /* Ensure that we merged the constraints. */
3909 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
3912 /* x == 0, then x != 42. */
3914 region_model_manager mgr;
3915 region_model model (&mgr);
3917 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3918 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, int_42);
3920 /* Assert various things about the insides of model. */
3921 constraint_manager *cm = model.get_constraints ();
3922 ASSERT_EQ (cm->m_constraints.length (), 0);
3923 ASSERT_EQ (cm->m_equiv_classes.length (), 1);
3926 // TODO: selftest for merging ecs "in the middle"
3927 // where a non-final one gets overwritten
3929 // TODO: selftest where there are pre-existing constraints
3932 /* Check that operator== and hashing works as expected for the
3933 various types. */
3935 static void
3936 test_equality ()
3938 tree x = build_global_decl ("x", integer_type_node);
3939 tree y = build_global_decl ("y", integer_type_node);
3942 region_model_manager mgr;
3943 region_model model0 (&mgr);
3944 region_model model1 (&mgr);
3946 constraint_manager *cm0 = model0.get_constraints ();
3947 constraint_manager *cm1 = model1.get_constraints ();
3949 ASSERT_EQ (cm0->hash (), cm1->hash ());
3950 ASSERT_EQ (*cm0, *cm1);
3952 ASSERT_EQ (model0.hash (), model1.hash ());
3953 ASSERT_EQ (model0, model1);
3955 ADD_SAT_CONSTRAINT (model1, x, EQ_EXPR, y);
3956 ASSERT_NE (cm0->hash (), cm1->hash ());
3957 ASSERT_NE (*cm0, *cm1);
3959 ASSERT_NE (model0.hash (), model1.hash ());
3960 ASSERT_NE (model0, model1);
3962 region_model model2 (&mgr);
3963 constraint_manager *cm2 = model2.get_constraints ();
3964 /* Make the same change to cm2. */
3965 ADD_SAT_CONSTRAINT (model2, x, EQ_EXPR, y);
3966 ASSERT_EQ (cm1->hash (), cm2->hash ());
3967 ASSERT_EQ (*cm1, *cm2);
3969 ASSERT_EQ (model1.hash (), model2.hash ());
3970 ASSERT_EQ (model1, model2);
3974 /* Verify tracking inequality of a variable against many constants. */
3976 static void
3977 test_many_constants ()
3979 region_model_manager mgr;
3980 program_point point (program_point::origin (mgr));
3981 tree a = build_global_decl ("a", integer_type_node);
3983 region_model model (&mgr);
3984 auto_vec<tree> constants;
3985 for (int i = 0; i < 20; i++)
3987 tree constant = build_int_cst (integer_type_node, i);
3988 constants.safe_push (constant);
3989 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, constant);
3991 /* Merge, and check the result. */
3992 region_model other (model);
3994 region_model merged (&mgr);
3995 ASSERT_TRUE (model.can_merge_with_p (other, point, &merged));
3996 model.canonicalize ();
3997 merged.canonicalize ();
3998 ASSERT_EQ (model, merged);
4000 for (int j = 0; j <= i; j++)
4001 ASSERT_CONDITION_TRUE (model, a, NE_EXPR, constants[j]);
4005 /* Verify that purging state relating to a variable doesn't leave stray
4006 equivalence classes (after canonicalization). */
4008 static void
4009 test_purging (void)
4011 tree int_0 = build_int_cst (integer_type_node, 0);
4012 tree a = build_global_decl ("a", integer_type_node);
4013 tree b = build_global_decl ("b", integer_type_node);
4015 /* "a != 0". */
4017 region_model_manager mgr;
4018 region_model model (&mgr);
4019 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
4020 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4021 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4023 /* Purge state for "a". */
4024 const svalue *sval_a = model.get_rvalue (a, NULL);
4025 model.purge_state_involving (sval_a, NULL);
4026 model.canonicalize ();
4027 /* We should have an empty constraint_manager. */
4028 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
4029 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4032 /* "a != 0" && "b != 0". */
4034 region_model_manager mgr;
4035 region_model model (&mgr);
4036 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
4037 ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
4038 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 3);
4039 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 2);
4041 /* Purge state for "a". */
4042 const svalue *sval_a = model.get_rvalue (a, NULL);
4043 model.purge_state_involving (sval_a, NULL);
4044 model.canonicalize ();
4045 /* We should just have the constraint/ECs involving b != 0. */
4046 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4047 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4048 ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
4051 /* "a != 0" && "b == 0". */
4053 region_model_manager mgr;
4054 region_model model (&mgr);
4055 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
4056 ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
4057 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4058 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4060 /* Purge state for "a". */
4061 const svalue *sval_a = model.get_rvalue (a, NULL);
4062 model.purge_state_involving (sval_a, NULL);
4063 model.canonicalize ();
4064 /* We should just have the EC involving b == 0. */
4065 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4066 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4067 ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
4070 /* "a == 0". */
4072 region_model_manager mgr;
4073 region_model model (&mgr);
4074 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4075 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4076 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4078 /* Purge state for "a". */
4079 const svalue *sval_a = model.get_rvalue (a, NULL);
4080 model.purge_state_involving (sval_a, NULL);
4081 model.canonicalize ();
4082 /* We should have an empty constraint_manager. */
4083 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
4084 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4087 /* "a == 0" && "b != 0". */
4089 region_model_manager mgr;
4090 region_model model (&mgr);
4091 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4092 ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
4093 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4094 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4096 /* Purge state for "a". */
4097 const svalue *sval_a = model.get_rvalue (a, NULL);
4098 model.purge_state_involving (sval_a, NULL);
4099 model.canonicalize ();
4100 /* We should just have the constraint/ECs involving b != 0. */
4101 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4102 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4103 ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
4106 /* "a == 0" && "b == 0". */
4108 region_model_manager mgr;
4109 region_model model (&mgr);
4110 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4111 ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
4112 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4113 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4115 /* Purge state for "a". */
4116 const svalue *sval_a = model.get_rvalue (a, NULL);
4117 model.purge_state_involving (sval_a, NULL);
4118 model.canonicalize ();
4119 /* We should just have the EC involving b == 0. */
4120 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4121 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4122 ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
4126 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4128 static void
4129 assert_dump_bounded_range_eq (const location &loc,
4130 const bounded_range &range,
4131 const char *expected)
4133 auto_fix_quotes sentinel;
4134 pretty_printer pp;
4135 pp_format_decoder (&pp) = default_tree_printer;
4136 range.dump_to_pp (&pp, false);
4137 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4140 /* Assert that BR.dump (false) is EXPECTED. */
4142 #define ASSERT_DUMP_BOUNDED_RANGE_EQ(BR, EXPECTED) \
4143 SELFTEST_BEGIN_STMT \
4144 assert_dump_bounded_range_eq ((SELFTEST_LOCATION), (BR), (EXPECTED)); \
4145 SELFTEST_END_STMT
4147 /* Verify that bounded_range works as expected. */
4149 static void
4150 test_bounded_range ()
4152 tree u8_0 = build_int_cst (unsigned_char_type_node, 0);
4153 tree u8_1 = build_int_cst (unsigned_char_type_node, 1);
4154 tree u8_64 = build_int_cst (unsigned_char_type_node, 64);
4155 tree u8_128 = build_int_cst (unsigned_char_type_node, 128);
4156 tree u8_255 = build_int_cst (unsigned_char_type_node, 255);
4158 tree s8_0 = build_int_cst (signed_char_type_node, 0);
4159 tree s8_1 = build_int_cst (signed_char_type_node, 1);
4160 tree s8_2 = build_int_cst (signed_char_type_node, 2);
4162 bounded_range br_u8_0 (u8_0, u8_0);
4163 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0, "0");
4164 ASSERT_TRUE (br_u8_0.contains_p (u8_0));
4165 ASSERT_FALSE (br_u8_0.contains_p (u8_1));
4166 ASSERT_TRUE (br_u8_0.contains_p (s8_0));
4167 ASSERT_FALSE (br_u8_0.contains_p (s8_1));
4169 bounded_range br_u8_0_1 (u8_0, u8_1);
4170 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0_1, "[0, 1]");
4172 bounded_range tmp (NULL_TREE, NULL_TREE);
4173 ASSERT_TRUE (br_u8_0.intersects_p (br_u8_0_1, &tmp));
4174 ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "0");
4176 bounded_range br_u8_64_128 (u8_64, u8_128);
4177 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_64_128, "[64, 128]");
4179 ASSERT_FALSE (br_u8_0.intersects_p (br_u8_64_128, NULL));
4180 ASSERT_FALSE (br_u8_64_128.intersects_p (br_u8_0, NULL));
4182 bounded_range br_u8_128_255 (u8_128, u8_255);
4183 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_128_255, "[128, 255]");
4184 ASSERT_TRUE (br_u8_128_255.intersects_p (br_u8_64_128, &tmp));
4185 ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "128");
4187 bounded_range br_s8_2 (s8_2, s8_2);
4188 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2, "2");
4189 bounded_range br_s8_2_u8_255 (s8_2, u8_255);
4190 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2_u8_255, "[2, 255]");
4193 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4195 static void
4196 assert_dump_bounded_ranges_eq (const location &loc,
4197 const bounded_ranges *ranges,
4198 const char *expected)
4200 auto_fix_quotes sentinel;
4201 pretty_printer pp;
4202 pp_format_decoder (&pp) = default_tree_printer;
4203 ranges->dump_to_pp (&pp, false);
4204 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4207 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4209 static void
4210 assert_dump_bounded_ranges_eq (const location &loc,
4211 const bounded_ranges &ranges,
4212 const char *expected)
4214 auto_fix_quotes sentinel;
4215 pretty_printer pp;
4216 pp_format_decoder (&pp) = default_tree_printer;
4217 ranges.dump_to_pp (&pp, false);
4218 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4221 /* Assert that BRS.dump (false) is EXPECTED. */
4223 #define ASSERT_DUMP_BOUNDED_RANGES_EQ(BRS, EXPECTED) \
4224 SELFTEST_BEGIN_STMT \
4225 assert_dump_bounded_ranges_eq ((SELFTEST_LOCATION), (BRS), (EXPECTED)); \
4226 SELFTEST_END_STMT
4228 /* Verify that the bounded_ranges class works as expected. */
4230 static void
4231 test_bounded_ranges ()
4233 bounded_ranges_manager mgr;
4235 tree ch0 = build_int_cst (unsigned_char_type_node, 0);
4236 tree ch1 = build_int_cst (unsigned_char_type_node, 1);
4237 tree ch2 = build_int_cst (unsigned_char_type_node, 2);
4238 tree ch3 = build_int_cst (unsigned_char_type_node, 3);
4239 tree ch128 = build_int_cst (unsigned_char_type_node, 128);
4240 tree ch129 = build_int_cst (unsigned_char_type_node, 129);
4241 tree ch254 = build_int_cst (unsigned_char_type_node, 254);
4242 tree ch255 = build_int_cst (unsigned_char_type_node, 255);
4244 const bounded_ranges *empty = mgr.get_or_create_empty ();
4245 ASSERT_DUMP_BOUNDED_RANGES_EQ (empty, "{}");
4247 const bounded_ranges *point0 = mgr.get_or_create_point (ch0);
4248 ASSERT_DUMP_BOUNDED_RANGES_EQ (point0, "{0}");
4250 const bounded_ranges *point1 = mgr.get_or_create_point (ch1);
4251 ASSERT_DUMP_BOUNDED_RANGES_EQ (point1, "{1}");
4253 const bounded_ranges *point2 = mgr.get_or_create_point (ch2);
4254 ASSERT_DUMP_BOUNDED_RANGES_EQ (point2, "{2}");
4256 const bounded_ranges *range0_128 = mgr.get_or_create_range (ch0, ch128);
4257 ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_128, "{[0, 128]}");
4259 const bounded_ranges *range0_255 = mgr.get_or_create_range (ch0, ch255);
4260 ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_255, "{[0, 255]}");
4262 ASSERT_FALSE (empty->contain_p (ch0));
4263 ASSERT_FALSE (empty->contain_p (ch1));
4264 ASSERT_FALSE (empty->contain_p (ch255));
4266 ASSERT_TRUE (point0->contain_p (ch0));
4267 ASSERT_FALSE (point0->contain_p (ch1));
4268 ASSERT_FALSE (point0->contain_p (ch255));
4270 ASSERT_FALSE (point1->contain_p (ch0));
4271 ASSERT_TRUE (point1->contain_p (ch1));
4272 ASSERT_FALSE (point0->contain_p (ch255));
4274 ASSERT_TRUE (range0_128->contain_p (ch0));
4275 ASSERT_TRUE (range0_128->contain_p (ch1));
4276 ASSERT_TRUE (range0_128->contain_p (ch128));
4277 ASSERT_FALSE (range0_128->contain_p (ch129));
4278 ASSERT_FALSE (range0_128->contain_p (ch254));
4279 ASSERT_FALSE (range0_128->contain_p (ch255));
4281 const bounded_ranges *inv0_128
4282 = mgr.get_or_create_inverse (range0_128, unsigned_char_type_node);
4283 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv0_128, "{[129, 255]}");
4285 const bounded_ranges *range128_129 = mgr.get_or_create_range (ch128, ch129);
4286 ASSERT_DUMP_BOUNDED_RANGES_EQ (range128_129, "{[128, 129]}");
4288 const bounded_ranges *inv128_129
4289 = mgr.get_or_create_inverse (range128_129, unsigned_char_type_node);
4290 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv128_129, "{[0, 127], [130, 255]}");
4292 /* Intersection. */
4294 /* Intersection of disjoint ranges should be empty set. */
4295 const bounded_ranges *intersect0_1
4296 = mgr.get_or_create_intersection (point0, point1);
4297 ASSERT_DUMP_BOUNDED_RANGES_EQ (intersect0_1, "{}");
4300 /* Various tests of "union of ranges". */
4303 /* Touching points should be merged into a range. */
4304 auto_vec <const bounded_ranges *> v;
4305 v.safe_push (point0);
4306 v.safe_push (point1);
4307 const bounded_ranges *union_0_and_1 = mgr.get_or_create_union (v);
4308 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_0_and_1, "{[0, 1]}");
4312 /* Overlapping and out-of-order. */
4313 auto_vec <const bounded_ranges *> v;
4314 v.safe_push (inv0_128); // {[129, 255]}
4315 v.safe_push (range128_129);
4316 const bounded_ranges *union_129_255_and_128_129
4317 = mgr.get_or_create_union (v);
4318 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_129_255_and_128_129, "{[128, 255]}");
4322 /* Union of R and inverse(R) should be full range of type. */
4323 auto_vec <const bounded_ranges *> v;
4324 v.safe_push (range128_129);
4325 v.safe_push (inv128_129);
4326 const bounded_ranges *union_ = mgr.get_or_create_union (v);
4327 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{[0, 255]}");
4330 /* Union with an endpoint. */
4332 const bounded_ranges *range2_to_255
4333 = mgr.get_or_create_range (ch2, ch255);
4334 ASSERT_DUMP_BOUNDED_RANGES_EQ (range2_to_255, "{[2, 255]}");
4335 auto_vec <const bounded_ranges *> v;
4336 v.safe_push (point0);
4337 v.safe_push (point2);
4338 v.safe_push (range2_to_255);
4339 const bounded_ranges *union_ = mgr.get_or_create_union (v);
4340 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{0, [2, 255]}");
4343 /* Construct from vector of bounded_range. */
4345 auto_vec<bounded_range> v;
4346 v.safe_push (bounded_range (ch2, ch2));
4347 v.safe_push (bounded_range (ch0, ch0));
4348 v.safe_push (bounded_range (ch2, ch255));
4349 bounded_ranges br (v);
4350 ASSERT_DUMP_BOUNDED_RANGES_EQ (&br, "{0, [2, 255]}");
4354 /* Various tests of "inverse". */
4357 const bounded_ranges *range_1_to_3 = mgr.get_or_create_range (ch1, ch3);
4358 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_3, "{[1, 3]}");
4359 const bounded_ranges *inv
4360 = mgr.get_or_create_inverse (range_1_to_3, unsigned_char_type_node);
4361 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0, [4, 255]}");
4364 const bounded_ranges *range_1_to_255
4365 = mgr.get_or_create_range (ch1, ch255);
4366 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_255, "{[1, 255]}");
4367 const bounded_ranges *inv
4368 = mgr.get_or_create_inverse (range_1_to_255, unsigned_char_type_node);
4369 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0}");
4372 const bounded_ranges *range_0_to_254
4373 = mgr.get_or_create_range (ch0, ch254);
4374 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_0_to_254, "{[0, 254]}");
4375 const bounded_ranges *inv
4376 = mgr.get_or_create_inverse (range_0_to_254, unsigned_char_type_node);
4377 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{255}");
4381 /* "case 'a'-'z': case 'A-Z':" vs "default:", for ASCII. */
4383 tree ch65 = build_int_cst (unsigned_char_type_node, 65);
4384 tree ch90 = build_int_cst (unsigned_char_type_node, 90);
4386 tree ch97 = build_int_cst (unsigned_char_type_node, 97);
4387 tree ch122 = build_int_cst (unsigned_char_type_node, 122);
4389 const bounded_ranges *A_to_Z = mgr.get_or_create_range (ch65, ch90);
4390 ASSERT_DUMP_BOUNDED_RANGES_EQ (A_to_Z, "{[65, 90]}");
4391 const bounded_ranges *a_to_z = mgr.get_or_create_range (ch97, ch122);
4392 ASSERT_DUMP_BOUNDED_RANGES_EQ (a_to_z, "{[97, 122]}");
4393 auto_vec <const bounded_ranges *> v;
4394 v.safe_push (A_to_Z);
4395 v.safe_push (a_to_z);
4396 const bounded_ranges *label_ranges = mgr.get_or_create_union (v);
4397 ASSERT_DUMP_BOUNDED_RANGES_EQ (label_ranges, "{[65, 90], [97, 122]}");
4398 const bounded_ranges *default_ranges
4399 = mgr.get_or_create_inverse (label_ranges, unsigned_char_type_node);
4400 ASSERT_DUMP_BOUNDED_RANGES_EQ (default_ranges,
4401 "{[0, 64], [91, 96], [123, 255]}");
4404 /* Verify ranges from ops. */
4405 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (EQ_EXPR, ch128),
4406 "{128}");
4407 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch128),
4408 "{[0, 127], [129, 255]}");
4409 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch128),
4410 "{[0, 127]}");
4411 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch128),
4412 "{[0, 128]}");
4413 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch128),
4414 "{[128, 255]}");
4415 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch128),
4416 "{[129, 255]}");
4417 /* Ops at endpoints of type ranges. */
4418 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch0),
4419 "{0}");
4420 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch0),
4421 "{}");
4422 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch0),
4423 "{[1, 255]}");
4424 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch255),
4425 "{255}");
4426 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch255),
4427 "{}");
4428 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch255),
4429 "{[0, 254]}");
4431 /* Verify that instances are consolidated by mgr. */
4432 ASSERT_EQ (mgr.get_or_create_point (ch0),
4433 mgr.get_or_create_point (ch0));
4434 ASSERT_NE (mgr.get_or_create_point (ch0),
4435 mgr.get_or_create_point (ch1));
4438 /* Run the selftests in this file, temporarily overriding
4439 flag_analyzer_transitivity with TRANSITIVITY. */
4441 static void
4442 run_constraint_manager_tests (bool transitivity)
4444 int saved_flag_analyzer_transitivity = flag_analyzer_transitivity;
4445 flag_analyzer_transitivity = transitivity;
4447 test_range ();
4448 test_constraint_conditions ();
4449 if (flag_analyzer_transitivity)
4451 /* These selftests assume transitivity. */
4452 test_transitivity ();
4454 test_constant_comparisons ();
4455 test_constraint_impl ();
4456 test_equality ();
4457 test_many_constants ();
4458 test_purging ();
4459 test_bounded_range ();
4460 test_bounded_ranges ();
4462 flag_analyzer_transitivity = saved_flag_analyzer_transitivity;
4465 /* Run all of the selftests within this file. */
4467 void
4468 analyzer_constraint_manager_cc_tests ()
4470 /* Run the tests twice: with and without transitivity. */
4471 run_constraint_manager_tests (true);
4472 run_constraint_manager_tests (false);
4475 } // namespace selftest
4477 #endif /* CHECKING_P */
4479 } // namespace ana
4481 #endif /* #if ENABLE_ANALYZER */