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>.
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "function.h"
26 #include "basic-block.h"
27 #include "gimple.h"
28 #include "gimple-iterator.h"
29 #include "fold-const.h"
30 #include "selftest.h"
31 #include "diagnostic-core.h"
32 #include "graphviz.h"
33 #include "function.h"
34 #include "json.h"
35 #include "analyzer/analyzer.h"
36 #include "ordered-hash-map.h"
37 #include "options.h"
38 #include "cgraph.h"
39 #include "cfg.h"
40 #include "digraph.h"
41 #include "analyzer/supergraph.h"
42 #include "sbitmap.h"
43 #include "bitmap.h"
44 #include "tristate.h"
45 #include "analyzer/analyzer-logging.h"
46 #include "analyzer/call-string.h"
47 #include "analyzer/program-point.h"
48 #include "analyzer/store.h"
49 #include "analyzer/region-model.h"
50 #include "analyzer/constraint-manager.h"
51 #include "analyzer/analyzer-selftests.h"
52 #include "tree-pretty-print.h"
53
54 #if ENABLE_ANALYZER
55
56 namespace ana {
57
58 static tristate
compare_constants(tree lhs_const,enum tree_code op,tree rhs_const)59 compare_constants (tree lhs_const, enum tree_code op, tree rhs_const)
60 {
61 tree comparison
62 = fold_binary (op, boolean_type_node, lhs_const, rhs_const);
63 if (comparison == boolean_true_node)
64 return tristate (tristate::TS_TRUE);
65 if (comparison == boolean_false_node)
66 return tristate (tristate::TS_FALSE);
67 return tristate (tristate::TS_UNKNOWN);
68 }
69
70 /* Return true iff CST is below the maximum value for its type. */
71
72 static bool
can_plus_one_p(tree cst)73 can_plus_one_p (tree cst)
74 {
75 gcc_assert (CONSTANT_CLASS_P (cst));
76 return tree_int_cst_lt (cst, TYPE_MAX_VALUE (TREE_TYPE (cst)));
77 }
78
79 /* Return (CST + 1). */
80
81 static tree
plus_one(tree cst)82 plus_one (tree cst)
83 {
84 gcc_assert (CONSTANT_CLASS_P (cst));
85 gcc_assert (can_plus_one_p (cst));
86 tree result = fold_build2 (PLUS_EXPR, TREE_TYPE (cst),
87 cst, integer_one_node);
88 gcc_assert (CONSTANT_CLASS_P (result));
89 return result;
90 }
91
92 /* Return true iff CST is above the minimum value for its type. */
93
94 static bool
can_minus_one_p(tree cst)95 can_minus_one_p (tree cst)
96 {
97 gcc_assert (CONSTANT_CLASS_P (cst));
98 return tree_int_cst_lt (TYPE_MIN_VALUE (TREE_TYPE (cst)), cst);
99 }
100
101 /* Return (CST - 1). */
102
103 static tree
minus_one(tree cst)104 minus_one (tree cst)
105 {
106 gcc_assert (CONSTANT_CLASS_P (cst));
107 gcc_assert (can_minus_one_p (cst));
108 tree result = fold_build2 (MINUS_EXPR, TREE_TYPE (cst),
109 cst, integer_one_node);
110 gcc_assert (CONSTANT_CLASS_P (result));
111 return result;
112 }
113
114 /* struct bound. */
115
116 /* Ensure that this bound is closed by converting an open bound to a
117 closed one. */
118
119 void
ensure_closed(enum bound_kind bound_kind)120 bound::ensure_closed (enum bound_kind bound_kind)
121 {
122 if (!m_closed)
123 {
124 /* Offset by 1 in the appropriate direction.
125 For example, convert 3 < x into 4 <= x,
126 and convert x < 5 into x <= 4. */
127 gcc_assert (CONSTANT_CLASS_P (m_constant));
128 m_constant = fold_build2 (bound_kind == BK_UPPER ? MINUS_EXPR : PLUS_EXPR,
129 TREE_TYPE (m_constant),
130 m_constant, integer_one_node);
131 gcc_assert (CONSTANT_CLASS_P (m_constant));
132 m_closed = true;
133 }
134 }
135
136 /* Get "<=" vs "<" for this bound. */
137
138 const char *
get_relation_as_str() const139 bound::get_relation_as_str () const
140 {
141 if (m_closed)
142 return "<=";
143 else
144 return "<";
145 }
146
147 /* struct range. */
148
149 /* Dump this range to PP, which must support %E for tree. */
150
151 void
dump_to_pp(pretty_printer * pp) const152 range::dump_to_pp (pretty_printer *pp) const
153 {
154 if (m_lower_bound.m_constant)
155 {
156 if (m_upper_bound.m_constant)
157 pp_printf (pp, "%qE %s x %s %qE",
158 m_lower_bound.m_constant,
159 m_lower_bound.get_relation_as_str (),
160 m_upper_bound.get_relation_as_str (),
161 m_upper_bound.m_constant);
162 else
163 pp_printf (pp, "%qE %s x",
164 m_lower_bound.m_constant,
165 m_lower_bound.get_relation_as_str ());
166 }
167 else
168 {
169 if (m_upper_bound.m_constant)
170 pp_printf (pp, "x %s %qE",
171 m_upper_bound.get_relation_as_str (),
172 m_upper_bound.m_constant);
173 else
174 pp_string (pp, "x");
175 }
176 }
177
178 /* Dump this range to stderr. */
179
180 DEBUG_FUNCTION void
dump() const181 range::dump () const
182 {
183 pretty_printer pp;
184 pp_format_decoder (&pp) = default_tree_printer;
185 pp_show_color (&pp) = pp_show_color (global_dc->printer);
186 pp.buffer->stream = stderr;
187 dump_to_pp (&pp);
188 pp_newline (&pp);
189 pp_flush (&pp);
190 }
191
192 /* Determine if there is only one possible value for this range.
193 If so, return the constant; otherwise, return NULL_TREE. */
194
195 tree
constrained_to_single_element()196 range::constrained_to_single_element ()
197 {
198 if (m_lower_bound.m_constant == NULL_TREE
199 || m_upper_bound.m_constant == NULL_TREE)
200 return NULL_TREE;
201
202 if (!INTEGRAL_TYPE_P (TREE_TYPE (m_lower_bound.m_constant)))
203 return NULL_TREE;
204 if (!INTEGRAL_TYPE_P (TREE_TYPE (m_upper_bound.m_constant)))
205 return NULL_TREE;
206
207 /* Convert any open bounds to closed bounds. */
208 m_lower_bound.ensure_closed (BK_LOWER);
209 m_upper_bound.ensure_closed (BK_UPPER);
210
211 // Are they equal?
212 tree comparison = fold_binary (EQ_EXPR, boolean_type_node,
213 m_lower_bound.m_constant,
214 m_upper_bound.m_constant);
215 if (comparison == boolean_true_node)
216 return m_lower_bound.m_constant;
217 else
218 return NULL_TREE;
219 }
220
221 /* Eval the condition "X OP RHS_CONST" for X within the range. */
222
223 tristate
eval_condition(enum tree_code op,tree rhs_const) const224 range::eval_condition (enum tree_code op, tree rhs_const) const
225 {
226 range copy (*this);
227 if (tree single_element = copy.constrained_to_single_element ())
228 return compare_constants (single_element, op, rhs_const);
229
230 switch (op)
231 {
232 case EQ_EXPR:
233 if (below_lower_bound (rhs_const))
234 return tristate (tristate::TS_FALSE);
235 if (above_upper_bound (rhs_const))
236 return tristate (tristate::TS_FALSE);
237 break;
238
239 case LT_EXPR:
240 case LE_EXPR:
241 /* Qn: "X </<= RHS_CONST". */
242 /* If RHS_CONST > upper bound, then it's true.
243 If RHS_CONST < lower bound, then it's false.
244 Otherwise unknown. */
245 if (above_upper_bound (rhs_const))
246 return tristate (tristate::TS_TRUE);
247 if (below_lower_bound (rhs_const))
248 return tristate (tristate::TS_FALSE);
249 break;
250
251 case NE_EXPR:
252 /* Qn: "X != RHS_CONST". */
253 /* If RHS_CONST < lower bound, then it's true.
254 If RHS_CONST > upper bound, then it's false.
255 Otherwise unknown. */
256 if (below_lower_bound (rhs_const))
257 return tristate (tristate::TS_TRUE);
258 if (above_upper_bound (rhs_const))
259 return tristate (tristate::TS_TRUE);
260 break;
261
262 case GE_EXPR:
263 case GT_EXPR:
264 /* Qn: "X >=/> RHS_CONST". */
265 if (above_upper_bound (rhs_const))
266 return tristate (tristate::TS_FALSE);
267 if (below_lower_bound (rhs_const))
268 return tristate (tristate::TS_TRUE);
269 break;
270
271 default:
272 gcc_unreachable ();
273 break;
274 }
275 return tristate (tristate::TS_UNKNOWN);
276 }
277
278 /* Return true if RHS_CONST is below the lower bound of this range. */
279
280 bool
below_lower_bound(tree rhs_const) const281 range::below_lower_bound (tree rhs_const) const
282 {
283 if (!m_lower_bound.m_constant)
284 return false;
285
286 return compare_constants (rhs_const,
287 m_lower_bound.m_closed ? LT_EXPR : LE_EXPR,
288 m_lower_bound.m_constant).is_true ();
289 }
290
291 /* Return true if RHS_CONST is above the upper bound of this range. */
292
293 bool
above_upper_bound(tree rhs_const) const294 range::above_upper_bound (tree rhs_const) const
295 {
296 if (!m_upper_bound.m_constant)
297 return false;
298
299 return compare_constants (rhs_const,
300 m_upper_bound.m_closed ? GT_EXPR : GE_EXPR,
301 m_upper_bound.m_constant).is_true ();
302 }
303
304 /* Attempt to add B to the bound of the given kind of this range.
305 Return true if feasible; false if infeasible. */
306
307 bool
add_bound(bound b,enum bound_kind bound_kind)308 range::add_bound (bound b, enum bound_kind bound_kind)
309 {
310 b.ensure_closed (bound_kind);
311
312 switch (bound_kind)
313 {
314 default:
315 gcc_unreachable ();
316 case BK_LOWER:
317 /* Discard redundant bounds. */
318 if (m_lower_bound.m_constant)
319 {
320 m_lower_bound.ensure_closed (BK_LOWER);
321 if (tree_int_cst_le (b.m_constant,
322 m_lower_bound.m_constant))
323 return true;
324 }
325 if (m_upper_bound.m_constant)
326 {
327 m_upper_bound.ensure_closed (BK_UPPER);
328 /* Reject B <= V <= UPPER when B > UPPER. */
329 if (!tree_int_cst_le (b.m_constant,
330 m_upper_bound.m_constant))
331 return false;
332 }
333 m_lower_bound = b;
334 break;
335
336 case BK_UPPER:
337 /* Discard redundant bounds. */
338 if (m_upper_bound.m_constant)
339 {
340 m_upper_bound.ensure_closed (BK_UPPER);
341 if (!tree_int_cst_lt (b.m_constant,
342 m_upper_bound.m_constant))
343 return true;
344 }
345 if (m_lower_bound.m_constant)
346 {
347 m_lower_bound.ensure_closed (BK_LOWER);
348 /* Reject LOWER <= V <= B when LOWER > B. */
349 if (!tree_int_cst_le (m_lower_bound.m_constant,
350 b.m_constant))
351 return false;
352 }
353 m_upper_bound = b;
354 break;
355 }
356
357 return true;
358 }
359
360 /* Attempt to add (RANGE OP RHS_CONST) as a bound to this range.
361 Return true if feasible; false if infeasible. */
362
363 bool
add_bound(enum tree_code op,tree rhs_const)364 range::add_bound (enum tree_code op, tree rhs_const)
365 {
366 switch (op)
367 {
368 default:
369 return true;
370 case LT_EXPR:
371 /* "V < RHS_CONST" */
372 return add_bound (bound (rhs_const, false), BK_UPPER);
373 case LE_EXPR:
374 /* "V <= RHS_CONST" */
375 return add_bound (bound (rhs_const, true), BK_UPPER);
376 case GE_EXPR:
377 /* "V >= RHS_CONST" */
378 return add_bound (bound (rhs_const, true), BK_LOWER);
379 case GT_EXPR:
380 /* "V > RHS_CONST" */
381 return add_bound (bound (rhs_const, false), BK_LOWER);
382 }
383 }
384
385 /* struct bounded_range. */
386
bounded_range(const_tree lower,const_tree upper)387 bounded_range::bounded_range (const_tree lower, const_tree upper)
388 : m_lower (const_cast<tree> (lower)),
389 m_upper (const_cast<tree> (upper))
390 {
391 if (lower && upper)
392 {
393 gcc_assert (TREE_CODE (m_lower) == INTEGER_CST);
394 gcc_assert (TREE_CODE (m_upper) == INTEGER_CST);
395 /* We should have lower <= upper. */
396 gcc_assert (!tree_int_cst_lt (m_upper, m_lower));
397 }
398 else
399 {
400 /* Purely for pending on-stack values, for
401 writing back to. */
402 gcc_assert (m_lower == NULL_TREE);
403 gcc_assert (m_lower == NULL_TREE);
404 }
405 }
406
407 static void
dump_cst(pretty_printer * pp,tree cst,bool show_types)408 dump_cst (pretty_printer *pp, tree cst, bool show_types)
409 {
410 gcc_assert (cst);
411 if (show_types)
412 {
413 pp_character (pp, '(');
414 dump_generic_node (pp, TREE_TYPE (cst), 0, (dump_flags_t)0, false);
415 pp_character (pp, ')');
416 }
417 dump_generic_node (pp, cst, 0, (dump_flags_t)0, false);
418 }
419
420 /* Dump this object to PP. */
421
422 void
dump_to_pp(pretty_printer * pp,bool show_types) const423 bounded_range::dump_to_pp (pretty_printer *pp, bool show_types) const
424 {
425 if (tree_int_cst_equal (m_lower, m_upper))
426 dump_cst (pp, m_lower, show_types);
427 else
428 {
429 pp_character (pp, '[');
430 dump_cst (pp, m_lower, show_types);
431 pp_string (pp, ", ");
432 dump_cst (pp, m_upper, show_types);
433 pp_character (pp, ']');
434 }
435 }
436
437 /* Dump this object to stderr. */
438
439 void
dump(bool show_types) const440 bounded_range::dump (bool show_types) const
441 {
442 pretty_printer pp;
443 pp_format_decoder (&pp) = default_tree_printer;
444 pp_show_color (&pp) = pp_show_color (global_dc->printer);
445 pp.buffer->stream = stderr;
446 dump_to_pp (&pp, show_types);
447 pp_newline (&pp);
448 pp_flush (&pp);
449 }
450
451 json::object *
to_json() const452 bounded_range::to_json () const
453 {
454 json::object *range_obj = new json::object ();
455 set_json_attr (range_obj, "lower", m_lower);
456 set_json_attr (range_obj, "upper", m_upper);
457 return range_obj;
458 }
459
460 /* Subroutine of bounded_range::to_json. */
461
462 void
set_json_attr(json::object * obj,const char * name,tree value)463 bounded_range::set_json_attr (json::object *obj, const char *name, tree value)
464 {
465 pretty_printer pp;
466 pp_format_decoder (&pp) = default_tree_printer;
467 pp_printf (&pp, "%E", value);
468 obj->set (name, new json::string (pp_formatted_text (&pp)));
469 }
470
471
472 /* Return true iff CST is within this range. */
473
474 bool
contains_p(tree cst) const475 bounded_range::contains_p (tree cst) const
476 {
477 /* Reject if below lower bound. */
478 if (tree_int_cst_lt (cst, m_lower))
479 return false;
480 /* Reject if above lower bound. */
481 if (tree_int_cst_lt (m_upper, cst))
482 return false;
483 return true;
484 }
485
486 /* If this range intersects OTHER, return true, writing
487 the intersection to *OUT if OUT is non-NULL.
488 Return false if they do not intersect. */
489
490 bool
intersects_p(const bounded_range & other,bounded_range * out) const491 bounded_range::intersects_p (const bounded_range &other,
492 bounded_range *out) const
493 {
494 const tree max_lower
495 = (tree_int_cst_le (m_lower, other.m_lower)
496 ? other.m_lower : m_lower);
497 gcc_assert (TREE_CODE (max_lower) == INTEGER_CST);
498 const tree min_upper
499 = (tree_int_cst_le (m_upper, other.m_upper)
500 ? m_upper : other.m_upper);
501 gcc_assert (TREE_CODE (min_upper) == INTEGER_CST);
502
503 if (tree_int_cst_le (max_lower, min_upper))
504 {
505 if (out)
506 *out = bounded_range (max_lower, min_upper);
507 return true;
508 }
509 else
510 return false;
511 }
512
513 bool
operator ==(const bounded_range & other) const514 bounded_range::operator== (const bounded_range &other) const
515 {
516 return (TREE_TYPE (m_lower) == TREE_TYPE (other.m_lower)
517 && TREE_TYPE (m_upper) == TREE_TYPE (other.m_upper)
518 && tree_int_cst_equal (m_lower, other.m_lower)
519 && tree_int_cst_equal (m_upper, other.m_upper));
520 }
521
522 int
cmp(const bounded_range & br1,const bounded_range & br2)523 bounded_range::cmp (const bounded_range &br1, const bounded_range &br2)
524 {
525 if (int cmp_lower = tree_int_cst_compare (br1.m_lower,
526 br2.m_lower))
527 return cmp_lower;
528 return tree_int_cst_compare (br1.m_upper, br2.m_upper);
529 }
530
531 /* struct bounded_ranges. */
532
533 /* Construct a bounded_ranges instance from a single range. */
534
bounded_ranges(const bounded_range & range)535 bounded_ranges::bounded_ranges (const bounded_range &range)
536 : m_ranges (1)
537 {
538 m_ranges.quick_push (range);
539 canonicalize ();
540 validate ();
541 }
542
543 /* Construct a bounded_ranges instance from multiple ranges. */
544
bounded_ranges(const vec<bounded_range> & ranges)545 bounded_ranges::bounded_ranges (const vec<bounded_range> &ranges)
546 : m_ranges (ranges.length ())
547 {
548 m_ranges.safe_splice (ranges);
549 canonicalize ();
550 validate ();
551 }
552
553 /* Construct a bounded_ranges instance for values of LHS for which
554 (LHS OP RHS_CONST) is true (e.g. "(LHS > 3)". */
555
bounded_ranges(enum tree_code op,tree rhs_const)556 bounded_ranges::bounded_ranges (enum tree_code op, tree rhs_const)
557 : m_ranges ()
558 {
559 gcc_assert (TREE_CODE (rhs_const) == INTEGER_CST);
560 tree type = TREE_TYPE (rhs_const);
561 switch (op)
562 {
563 default:
564 gcc_unreachable ();
565 case EQ_EXPR:
566 m_ranges.safe_push (bounded_range (rhs_const, rhs_const));
567 break;
568
569 case GE_EXPR:
570 m_ranges.safe_push (bounded_range (rhs_const, TYPE_MAX_VALUE (type)));
571 break;
572
573 case LE_EXPR:
574 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type), rhs_const));
575 break;
576
577 case NE_EXPR:
578 if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const))
579 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type),
580 minus_one (rhs_const)));
581 if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type)))
582 m_ranges.safe_push (bounded_range (plus_one (rhs_const),
583 TYPE_MAX_VALUE (type)));
584 break;
585 case GT_EXPR:
586 if (tree_int_cst_lt (rhs_const, TYPE_MAX_VALUE (type)))
587 m_ranges.safe_push (bounded_range (plus_one (rhs_const),
588 TYPE_MAX_VALUE (type)));
589 break;
590 case LT_EXPR:
591 if (tree_int_cst_lt (TYPE_MIN_VALUE (type), rhs_const))
592 m_ranges.safe_push (bounded_range (TYPE_MIN_VALUE (type),
593 minus_one (rhs_const)));
594 break;
595 }
596 canonicalize ();
597 validate ();
598 }
599
600 /* Subroutine of ctors for fixing up m_ranges.
601 Also, initialize m_hash. */
602
603 void
canonicalize()604 bounded_ranges::canonicalize ()
605 {
606 /* Sort the ranges. */
607 m_ranges.qsort ([](const void *p1, const void *p2) -> int
608 {
609 const bounded_range &br1 = *(const bounded_range *)p1;
610 const bounded_range &br2 = *(const bounded_range *)p2;
611 return bounded_range::cmp (br1, br2);
612 });
613
614 /* Merge ranges that are touching or overlapping. */
615 for (unsigned i = 1; i < m_ranges.length (); )
616 {
617 bounded_range *prev = &m_ranges[i - 1];
618 const bounded_range *next = &m_ranges[i];
619 if (prev->intersects_p (*next, NULL)
620 || (can_plus_one_p (prev->m_upper)
621 && tree_int_cst_equal (plus_one (prev->m_upper),
622 next->m_lower)))
623 {
624 prev->m_upper = next->m_upper;
625 m_ranges.ordered_remove (i);
626 }
627 else
628 i++;
629 }
630
631 /* Initialize m_hash. */
632 inchash::hash hstate (0);
633 for (const auto &iter : m_ranges)
634 {
635 inchash::add_expr (iter.m_lower, hstate);
636 inchash::add_expr (iter.m_upper, hstate);
637 }
638 m_hash = hstate.end ();
639 }
640
641 /* Assert that this object is valid. */
642
643 void
validate() const644 bounded_ranges::validate () const
645 {
646 /* Skip this in a release build. */
647 #if !CHECKING_P
648 return;
649 #endif
650
651 for (unsigned i = 1; i < m_ranges.length (); i++)
652 {
653 const bounded_range &prev = m_ranges[i - 1];
654 const bounded_range &next = m_ranges[i];
655
656 /* Give up if we somehow have incompatible different types. */
657 if (!types_compatible_p (TREE_TYPE (prev.m_upper),
658 TREE_TYPE (next.m_lower)))
659 continue;
660
661 /* Verify sorted. */
662 gcc_assert (tree_int_cst_lt (prev.m_upper, next.m_lower));
663
664 gcc_assert (can_plus_one_p (prev.m_upper));
665 /* otherwise there's no room for "next". */
666
667 /* Verify no ranges touch each other. */
668 gcc_assert (tree_int_cst_lt (plus_one (prev.m_upper), next.m_lower));
669 }
670 }
671
672 /* bounded_ranges equality operator. */
673
674 bool
operator ==(const bounded_ranges & other) const675 bounded_ranges::operator== (const bounded_ranges &other) const
676 {
677 if (m_ranges.length () != other.m_ranges.length ())
678 return false;
679 for (unsigned i = 0; i < m_ranges.length (); i++)
680 {
681 if (m_ranges[i] != other.m_ranges[i])
682 return false;
683 }
684 return true;
685 }
686
687 /* Dump this object to PP. */
688
689 void
dump_to_pp(pretty_printer * pp,bool show_types) const690 bounded_ranges::dump_to_pp (pretty_printer *pp, bool show_types) const
691 {
692 pp_character (pp, '{');
693 for (unsigned i = 0; i < m_ranges.length (); ++i)
694 {
695 if (i > 0)
696 pp_string (pp, ", ");
697 m_ranges[i].dump_to_pp (pp, show_types);
698 }
699 pp_character (pp, '}');
700 }
701
702 /* Dump this object to stderr. */
703
704 DEBUG_FUNCTION void
dump(bool show_types) const705 bounded_ranges::dump (bool show_types) const
706 {
707 pretty_printer pp;
708 pp_format_decoder (&pp) = default_tree_printer;
709 pp_show_color (&pp) = pp_show_color (global_dc->printer);
710 pp.buffer->stream = stderr;
711 dump_to_pp (&pp, show_types);
712 pp_newline (&pp);
713 pp_flush (&pp);
714 }
715
716 json::value *
to_json() const717 bounded_ranges::to_json () const
718 {
719 json::array *arr_obj = new json::array ();
720
721 for (unsigned i = 0; i < m_ranges.length (); ++i)
722 arr_obj->append (m_ranges[i].to_json ());
723
724 return arr_obj;
725 }
726
727 /* Determine whether (X OP RHS_CONST) is known to be true or false
728 for all X in the ranges expressed by this object. */
729
730 tristate
eval_condition(enum tree_code op,tree rhs_const,bounded_ranges_manager * mgr) const731 bounded_ranges::eval_condition (enum tree_code op,
732 tree rhs_const,
733 bounded_ranges_manager *mgr) const
734 {
735 /* Convert (X OP RHS_CONST) to a bounded_ranges instance and find
736 the intersection of that with this object. */
737 bounded_ranges other (op, rhs_const);
738 const bounded_ranges *intersection
739 = mgr->get_or_create_intersection (this, &other);
740
741 if (intersection->m_ranges.length () > 0)
742 {
743 /* We can use pointer equality to check for equality,
744 due to instance consolidation. */
745 if (intersection == this)
746 return tristate (tristate::TS_TRUE);
747 else
748 return tristate (tristate::TS_UNKNOWN);
749 }
750 else
751 /* No intersection. */
752 return tristate (tristate::TS_FALSE);
753 }
754
755 /* Return true if CST is within any of the ranges. */
756
757 bool
contain_p(tree cst) const758 bounded_ranges::contain_p (tree cst) const
759 {
760 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
761 for (const auto &iter : m_ranges)
762 {
763 /* TODO: should we optimize this based on sorting? */
764 if (iter.contains_p (cst))
765 return true;
766 }
767 return false;
768 }
769
770 int
cmp(const bounded_ranges * a,const bounded_ranges * b)771 bounded_ranges::cmp (const bounded_ranges *a, const bounded_ranges *b)
772 {
773 if (int cmp_length = ((int)a->m_ranges.length ()
774 - (int)b->m_ranges.length ()))
775 return cmp_length;
776 for (unsigned i = 0; i < a->m_ranges.length (); i++)
777 {
778 if (int cmp_range = bounded_range::cmp (a->m_ranges[i], b->m_ranges[i]))
779 return cmp_range;
780 }
781 /* They are equal. They ought to have been consolidated, so we should
782 have two pointers to the same object. */
783 gcc_assert (a == b);
784 return 0;
785 }
786
787 /* class bounded_ranges_manager. */
788
789 /* bounded_ranges_manager's dtor. */
790
~bounded_ranges_manager()791 bounded_ranges_manager::~bounded_ranges_manager ()
792 {
793 /* Delete the managed objects. */
794 for (const auto &iter : m_map)
795 delete iter.second;
796 }
797
798 /* Get the bounded_ranges instance for the empty set, creating it if
799 necessary. */
800
801 const bounded_ranges *
get_or_create_empty()802 bounded_ranges_manager::get_or_create_empty ()
803 {
804 auto_vec<bounded_range> empty_vec;
805
806 return consolidate (new bounded_ranges (empty_vec));
807 }
808
809 /* Get the bounded_ranges instance for {CST}, creating it if necessary. */
810
811 const bounded_ranges *
get_or_create_point(const_tree cst)812 bounded_ranges_manager::get_or_create_point (const_tree cst)
813 {
814 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
815
816 return get_or_create_range (cst, cst);
817 }
818
819 /* Get the bounded_ranges instance for {[LOWER_BOUND..UPPER_BOUND]},
820 creating it if necessary. */
821
822 const bounded_ranges *
get_or_create_range(const_tree lower_bound,const_tree upper_bound)823 bounded_ranges_manager::get_or_create_range (const_tree lower_bound,
824 const_tree upper_bound)
825 {
826 gcc_assert (TREE_CODE (lower_bound) == INTEGER_CST);
827 gcc_assert (TREE_CODE (upper_bound) == INTEGER_CST);
828
829 return consolidate
830 (new bounded_ranges (bounded_range (lower_bound, upper_bound)));
831 }
832
833 /* Get the bounded_ranges instance for the union of OTHERS,
834 creating it if necessary. */
835
836 const bounded_ranges *
837 bounded_ranges_manager::
get_or_create_union(const vec<const bounded_ranges * > & others)838 get_or_create_union (const vec <const bounded_ranges *> &others)
839 {
840 auto_vec<bounded_range> ranges;
841 for (const auto &r : others)
842 ranges.safe_splice (r->m_ranges);
843 return consolidate (new bounded_ranges (ranges));
844 }
845
846 /* Get the bounded_ranges instance for the intersection of A and B,
847 creating it if necessary. */
848
849 const bounded_ranges *
get_or_create_intersection(const bounded_ranges * a,const bounded_ranges * b)850 bounded_ranges_manager::get_or_create_intersection (const bounded_ranges *a,
851 const bounded_ranges *b)
852 {
853 auto_vec<bounded_range> ranges;
854 unsigned a_idx = 0;
855 unsigned b_idx = 0;
856 while (a_idx < a->m_ranges.length ()
857 && b_idx < b->m_ranges.length ())
858 {
859 const bounded_range &r_a = a->m_ranges[a_idx];
860 const bounded_range &r_b = b->m_ranges[b_idx];
861
862 bounded_range intersection (NULL_TREE, NULL_TREE);
863 if (r_a.intersects_p (r_b, &intersection))
864 {
865 ranges.safe_push (intersection);
866 }
867 if (tree_int_cst_lt (r_a.m_lower, r_b.m_lower))
868 {
869 a_idx++;
870 }
871 else
872 {
873 if (tree_int_cst_lt (r_a.m_upper, r_b.m_upper))
874 a_idx++;
875 else
876 b_idx++;
877 }
878 }
879
880 return consolidate (new bounded_ranges (ranges));
881 }
882
883 /* Get the bounded_ranges instance for the inverse of OTHER relative
884 to TYPE, creating it if necessary.
885 This is for use when handling "default" in switch statements, where
886 OTHER represents all the other cases. */
887
888 const bounded_ranges *
get_or_create_inverse(const bounded_ranges * other,tree type)889 bounded_ranges_manager::get_or_create_inverse (const bounded_ranges *other,
890 tree type)
891 {
892 tree min_val = TYPE_MIN_VALUE (type);
893 tree max_val = TYPE_MAX_VALUE (type);
894 if (other->m_ranges.length () == 0)
895 return get_or_create_range (min_val, max_val);
896 auto_vec<bounded_range> ranges;
897 tree first_lb = other->m_ranges[0].m_lower;
898 if (tree_int_cst_lt (min_val, first_lb)
899 && can_minus_one_p (first_lb))
900 ranges.safe_push (bounded_range (min_val,
901 minus_one (first_lb)));
902 for (unsigned i = 1; i < other->m_ranges.length (); i++)
903 {
904 tree prev_ub = other->m_ranges[i - 1].m_upper;
905 tree iter_lb = other->m_ranges[i].m_lower;
906 gcc_assert (tree_int_cst_lt (prev_ub, iter_lb));
907 if (can_plus_one_p (prev_ub) && can_minus_one_p (iter_lb))
908 ranges.safe_push (bounded_range (plus_one (prev_ub),
909 minus_one (iter_lb)));
910 }
911 tree last_ub
912 = other->m_ranges[other->m_ranges.length () - 1].m_upper;
913 if (tree_int_cst_lt (last_ub, max_val)
914 && can_plus_one_p (last_ub))
915 ranges.safe_push (bounded_range (plus_one (last_ub), max_val));
916
917 return consolidate (new bounded_ranges (ranges));
918 }
919
920 /* If an object equal to INST is already present, delete INST and
921 return the existing object.
922 Otherwise add INST and return it. */
923
924 const bounded_ranges *
consolidate(bounded_ranges * inst)925 bounded_ranges_manager::consolidate (bounded_ranges *inst)
926 {
927 if (bounded_ranges **slot = m_map.get (inst))
928 {
929 delete inst;
930 return *slot;
931 }
932 m_map.put (inst, inst);
933 return inst;
934 }
935
936 /* Get the bounded_ranges instance for EDGE of SWITCH_STMT,
937 creating it if necessary, and caching it by edge. */
938
939 const bounded_ranges *
940 bounded_ranges_manager::
get_or_create_ranges_for_switch(const switch_cfg_superedge * edge,const gswitch * switch_stmt)941 get_or_create_ranges_for_switch (const switch_cfg_superedge *edge,
942 const gswitch *switch_stmt)
943 {
944 /* Look in per-edge cache. */
945 if (const bounded_ranges ** slot = m_edge_cache.get (edge))
946 return *slot;
947
948 /* Not yet in cache. */
949 const bounded_ranges *all_cases_ranges
950 = create_ranges_for_switch (*edge, switch_stmt);
951 m_edge_cache.put (edge, all_cases_ranges);
952 return all_cases_ranges;
953 }
954
955 /* Get the bounded_ranges instance for EDGE of SWITCH_STMT,
956 creating it if necessary, for edges for which the per-edge
957 cache has not yet been populated. */
958
959 const bounded_ranges *
960 bounded_ranges_manager::
create_ranges_for_switch(const switch_cfg_superedge & edge,const gswitch * switch_stmt)961 create_ranges_for_switch (const switch_cfg_superedge &edge,
962 const gswitch *switch_stmt)
963 {
964 /* Get the ranges for each case label. */
965 auto_vec <const bounded_ranges *> case_ranges_vec
966 (gimple_switch_num_labels (switch_stmt));
967
968 for (tree case_label : edge.get_case_labels ())
969 {
970 /* Get the ranges for this case label. */
971 const bounded_ranges *case_ranges
972 = make_case_label_ranges (switch_stmt, case_label);
973 case_ranges_vec.quick_push (case_ranges);
974 }
975
976 /* Combine all the ranges for each case label into a single collection
977 of ranges. */
978 const bounded_ranges *all_cases_ranges
979 = get_or_create_union (case_ranges_vec);
980 return all_cases_ranges;
981 }
982
983 /* Get the bounded_ranges instance for CASE_LABEL within
984 SWITCH_STMT. */
985
986 const bounded_ranges *
987 bounded_ranges_manager::
make_case_label_ranges(const gswitch * switch_stmt,tree case_label)988 make_case_label_ranges (const gswitch *switch_stmt,
989 tree case_label)
990 {
991 gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR);
992 tree lower_bound = CASE_LOW (case_label);
993 tree upper_bound = CASE_HIGH (case_label);
994 if (lower_bound)
995 {
996 if (upper_bound)
997 /* Range. */
998 return get_or_create_range (lower_bound, upper_bound);
999 else
1000 /* Single-value. */
1001 return get_or_create_point (lower_bound);
1002 }
1003 else
1004 {
1005 /* The default case.
1006 Add exclusions based on the other cases. */
1007 auto_vec <const bounded_ranges *> other_case_ranges
1008 (gimple_switch_num_labels (switch_stmt));
1009 for (unsigned other_idx = 1;
1010 other_idx < gimple_switch_num_labels (switch_stmt);
1011 other_idx++)
1012 {
1013 tree other_label = gimple_switch_label (switch_stmt,
1014 other_idx);
1015 const bounded_ranges *other_ranges
1016 = make_case_label_ranges (switch_stmt, other_label);
1017 other_case_ranges.quick_push (other_ranges);
1018 }
1019 const bounded_ranges *other_cases_ranges
1020 = get_or_create_union (other_case_ranges);
1021 tree type = TREE_TYPE (gimple_switch_index (switch_stmt));
1022 return get_or_create_inverse (other_cases_ranges, type);
1023 }
1024 }
1025
1026 /* Dump the number of objects of each class that were managed by this
1027 manager to LOGGER.
1028 If SHOW_OBJS is true, also dump the objects themselves. */
1029
1030 void
log_stats(logger * logger,bool show_objs) const1031 bounded_ranges_manager::log_stats (logger *logger, bool show_objs) const
1032 {
1033 LOG_SCOPE (logger);
1034 logger->log (" # %s: %li", "ranges", (long)m_map.elements ());
1035 if (!show_objs)
1036 return;
1037
1038 auto_vec<const bounded_ranges *> vec_objs (m_map.elements ());
1039 for (const auto &iter : m_map)
1040 vec_objs.quick_push (iter.second);
1041 vec_objs.qsort
1042 ([](const void *p1, const void *p2) -> int
1043 {
1044 const bounded_ranges *br1 = *(const bounded_ranges * const *)p1;
1045 const bounded_ranges *br2 = *(const bounded_ranges * const *)p2;
1046 return bounded_ranges::cmp (br1, br2);
1047 });
1048
1049 for (const auto &iter : vec_objs)
1050 {
1051 logger->start_log_line ();
1052 pretty_printer *pp = logger->get_printer ();
1053 pp_string (pp, " ");
1054 iter->dump_to_pp (pp, true);
1055 logger->end_log_line ();
1056 }
1057 }
1058
1059 /* class equiv_class. */
1060
1061 /* equiv_class's default ctor. */
1062
equiv_class()1063 equiv_class::equiv_class ()
1064 : m_constant (NULL_TREE), m_cst_sval (NULL), m_vars ()
1065 {
1066 }
1067
1068 /* equiv_class's copy ctor. */
1069
equiv_class(const equiv_class & other)1070 equiv_class::equiv_class (const equiv_class &other)
1071 : m_constant (other.m_constant), m_cst_sval (other.m_cst_sval),
1072 m_vars (other.m_vars.length ())
1073 {
1074 for (const svalue *sval : other.m_vars)
1075 m_vars.quick_push (sval);
1076 }
1077
1078 /* Print an all-on-one-line representation of this equiv_class to PP,
1079 which must support %E for trees. */
1080
1081 void
print(pretty_printer * pp) const1082 equiv_class::print (pretty_printer *pp) const
1083 {
1084 pp_character (pp, '{');
1085 int i;
1086 const svalue *sval;
1087 FOR_EACH_VEC_ELT (m_vars, i, sval)
1088 {
1089 if (i > 0)
1090 pp_string (pp, " == ");
1091 sval->dump_to_pp (pp, true);
1092 }
1093 if (m_constant)
1094 {
1095 if (i > 0)
1096 pp_string (pp, " == ");
1097 pp_printf (pp, "[m_constant]%qE", m_constant);
1098 }
1099 pp_character (pp, '}');
1100 }
1101
1102 /* Return a new json::object of the form
1103 {"svals" : [str],
1104 "constant" : optional str}. */
1105
1106 json::object *
to_json() const1107 equiv_class::to_json () const
1108 {
1109 json::object *ec_obj = new json::object ();
1110
1111 json::array *sval_arr = new json::array ();
1112 for (const svalue *sval : m_vars)
1113 sval_arr->append (sval->to_json ());
1114 ec_obj->set ("svals", sval_arr);
1115
1116 if (m_constant)
1117 {
1118 pretty_printer pp;
1119 pp_format_decoder (&pp) = default_tree_printer;
1120 pp_printf (&pp, "%qE", m_constant);
1121 ec_obj->set ("constant", new json::string (pp_formatted_text (&pp)));
1122 }
1123
1124 return ec_obj;
1125 }
1126
1127 /* Generate a hash value for this equiv_class.
1128 This relies on the ordering of m_vars, and so this object needs to
1129 have been canonicalized for this to be meaningful. */
1130
1131 hashval_t
hash() const1132 equiv_class::hash () const
1133 {
1134 inchash::hash hstate;
1135
1136 inchash::add_expr (m_constant, hstate);
1137 for (const svalue * sval : m_vars)
1138 hstate.add_ptr (sval);
1139 return hstate.end ();
1140 }
1141
1142 /* Equality operator for equiv_class.
1143 This relies on the ordering of m_vars, and so this object
1144 and OTHER need to have been canonicalized for this to be
1145 meaningful. */
1146
1147 bool
operator ==(const equiv_class & other)1148 equiv_class::operator== (const equiv_class &other)
1149 {
1150 if (m_constant != other.m_constant)
1151 return false; // TODO: use tree equality here?
1152
1153 /* FIXME: should we compare m_cst_sval? */
1154
1155 if (m_vars.length () != other.m_vars.length ())
1156 return false;
1157
1158 int i;
1159 const svalue *sval;
1160 FOR_EACH_VEC_ELT (m_vars, i, sval)
1161 if (sval != other.m_vars[i])
1162 return false;
1163
1164 return true;
1165 }
1166
1167 /* Add SID to this equiv_class, using CM to check if it's a constant. */
1168
1169 void
add(const svalue * sval)1170 equiv_class::add (const svalue *sval)
1171 {
1172 gcc_assert (sval);
1173 if (tree cst = sval->maybe_get_constant ())
1174 {
1175 gcc_assert (CONSTANT_CLASS_P (cst));
1176 /* FIXME: should we canonicalize which svalue is the constant
1177 when there are multiple equal constants? */
1178 m_constant = cst;
1179 m_cst_sval = sval;
1180 }
1181 m_vars.safe_push (sval);
1182 }
1183
1184 /* Remove SID from this equivalence class.
1185 Return true if SID was the last var in the equivalence class (suggesting
1186 a possible leak). */
1187
1188 bool
del(const svalue * sval)1189 equiv_class::del (const svalue *sval)
1190 {
1191 gcc_assert (sval);
1192 gcc_assert (sval != m_cst_sval);
1193
1194 int i;
1195 const svalue *iv;
1196 FOR_EACH_VEC_ELT (m_vars, i, iv)
1197 {
1198 if (iv == sval)
1199 {
1200 m_vars[i] = m_vars[m_vars.length () - 1];
1201 m_vars.pop ();
1202 return m_vars.length () == 0;
1203 }
1204 }
1205
1206 /* SVAL must be in the class. */
1207 gcc_unreachable ();
1208 return false;
1209 }
1210
1211 /* Get a representative member of this class, for handling cases
1212 where the IDs can change mid-traversal. */
1213
1214 const svalue *
get_representative() const1215 equiv_class::get_representative () const
1216 {
1217 gcc_assert (m_vars.length () > 0);
1218 return m_vars[0];
1219 }
1220
1221 /* Sort the svalues within this equiv_class. */
1222
1223 void
canonicalize()1224 equiv_class::canonicalize ()
1225 {
1226 m_vars.qsort (svalue::cmp_ptr_ptr);
1227 }
1228
1229 /* Return true if this EC contains a variable, false if it merely
1230 contains constants.
1231 Subroutine of constraint_manager::canonicalize, for removing
1232 redundant ECs. */
1233
1234 bool
contains_non_constant_p() const1235 equiv_class::contains_non_constant_p () const
1236 {
1237 if (m_constant)
1238 {
1239 for (auto iter : m_vars)
1240 if (iter->maybe_get_constant ())
1241 continue;
1242 else
1243 /* We have {non-constant == constant}. */
1244 return true;
1245 /* We only have constants. */
1246 return false;
1247 }
1248 else
1249 /* Return true if we have {non-constant == non-constant}. */
1250 return m_vars.length () > 1;
1251 }
1252
1253 /* Get a debug string for C_OP. */
1254
1255 const char *
constraint_op_code(enum constraint_op c_op)1256 constraint_op_code (enum constraint_op c_op)
1257 {
1258 switch (c_op)
1259 {
1260 default:
1261 gcc_unreachable ();
1262 case CONSTRAINT_NE: return "!=";
1263 case CONSTRAINT_LT: return "<";
1264 case CONSTRAINT_LE: return "<=";
1265 }
1266 }
1267
1268 /* Convert C_OP to an enum tree_code. */
1269
1270 enum tree_code
constraint_tree_code(enum constraint_op c_op)1271 constraint_tree_code (enum constraint_op c_op)
1272 {
1273 switch (c_op)
1274 {
1275 default:
1276 gcc_unreachable ();
1277 case CONSTRAINT_NE: return NE_EXPR;
1278 case CONSTRAINT_LT: return LT_EXPR;
1279 case CONSTRAINT_LE: return LE_EXPR;
1280 }
1281 }
1282
1283 /* Given "lhs C_OP rhs", determine "lhs T_OP rhs".
1284
1285 For example, given "x < y", then "x > y" is false. */
1286
1287 static tristate
eval_constraint_op_for_op(enum constraint_op c_op,enum tree_code t_op)1288 eval_constraint_op_for_op (enum constraint_op c_op, enum tree_code t_op)
1289 {
1290 switch (c_op)
1291 {
1292 default:
1293 gcc_unreachable ();
1294 case CONSTRAINT_NE:
1295 if (t_op == EQ_EXPR)
1296 return tristate (tristate::TS_FALSE);
1297 if (t_op == NE_EXPR)
1298 return tristate (tristate::TS_TRUE);
1299 break;
1300 case CONSTRAINT_LT:
1301 if (t_op == LT_EXPR || t_op == LE_EXPR || t_op == NE_EXPR)
1302 return tristate (tristate::TS_TRUE);
1303 if (t_op == EQ_EXPR || t_op == GT_EXPR || t_op == GE_EXPR)
1304 return tristate (tristate::TS_FALSE);
1305 break;
1306 case CONSTRAINT_LE:
1307 if (t_op == LE_EXPR)
1308 return tristate (tristate::TS_TRUE);
1309 if (t_op == GT_EXPR)
1310 return tristate (tristate::TS_FALSE);
1311 break;
1312 }
1313 return tristate (tristate::TS_UNKNOWN);
1314 }
1315
1316 /* class constraint. */
1317
1318 /* Print this constraint to PP (which must support %E for trees),
1319 using CM to look up equiv_class instances from ids. */
1320
1321 void
print(pretty_printer * pp,const constraint_manager & cm) const1322 constraint::print (pretty_printer *pp, const constraint_manager &cm) const
1323 {
1324 m_lhs.print (pp);
1325 pp_string (pp, ": ");
1326 m_lhs.get_obj (cm).print (pp);
1327 pp_string (pp, " ");
1328 pp_string (pp, constraint_op_code (m_op));
1329 pp_string (pp, " ");
1330 m_rhs.print (pp);
1331 pp_string (pp, ": ");
1332 m_rhs.get_obj (cm).print (pp);
1333 }
1334
1335 /* Return a new json::object of the form
1336 {"lhs" : int, the EC index
1337 "op" : str,
1338 "rhs" : int, the EC index}. */
1339
1340 json::object *
to_json() const1341 constraint::to_json () const
1342 {
1343 json::object *con_obj = new json::object ();
1344
1345 con_obj->set ("lhs", new json::integer_number (m_lhs.as_int ()));
1346 con_obj->set ("op", new json::string (constraint_op_code (m_op)));
1347 con_obj->set ("rhs", new json::integer_number (m_rhs.as_int ()));
1348
1349 return con_obj;
1350 }
1351
1352 /* Generate a hash value for this constraint. */
1353
1354 hashval_t
hash() const1355 constraint::hash () const
1356 {
1357 inchash::hash hstate;
1358 hstate.add_int (m_lhs.m_idx);
1359 hstate.add_int (m_op);
1360 hstate.add_int (m_rhs.m_idx);
1361 return hstate.end ();
1362 }
1363
1364 /* Equality operator for constraints. */
1365
1366 bool
operator ==(const constraint & other) const1367 constraint::operator== (const constraint &other) const
1368 {
1369 if (m_lhs != other.m_lhs)
1370 return false;
1371 if (m_op != other.m_op)
1372 return false;
1373 if (m_rhs != other.m_rhs)
1374 return false;
1375 return true;
1376 }
1377
1378 /* Return true if this constraint is implied by OTHER. */
1379
1380 bool
implied_by(const constraint & other,const constraint_manager & cm) const1381 constraint::implied_by (const constraint &other,
1382 const constraint_manager &cm) const
1383 {
1384 if (m_lhs == other.m_lhs)
1385 if (tree rhs_const = m_rhs.get_obj (cm).get_any_constant ())
1386 if (tree other_rhs_const = other.m_rhs.get_obj (cm).get_any_constant ())
1387 if (m_lhs.get_obj (cm).get_any_constant () == NULL_TREE)
1388 if (m_op == other.m_op)
1389 switch (m_op)
1390 {
1391 default:
1392 break;
1393 case CONSTRAINT_LE:
1394 case CONSTRAINT_LT:
1395 if (compare_constants (rhs_const,
1396 GE_EXPR,
1397 other_rhs_const).is_true ())
1398 return true;
1399 break;
1400 }
1401 return false;
1402 }
1403
1404 /* class bounded_ranges_constraint. */
1405
1406 void
print(pretty_printer * pp,const constraint_manager & cm) const1407 bounded_ranges_constraint::print (pretty_printer *pp,
1408 const constraint_manager &cm) const
1409 {
1410 m_ec_id.print (pp);
1411 pp_string (pp, ": ");
1412 m_ec_id.get_obj (cm).print (pp);
1413 pp_string (pp, ": ");
1414 m_ranges->dump_to_pp (pp, true);
1415 }
1416
1417 json::object *
to_json() const1418 bounded_ranges_constraint::to_json () const
1419 {
1420 json::object *con_obj = new json::object ();
1421
1422 con_obj->set ("ec", new json::integer_number (m_ec_id.as_int ()));
1423 con_obj->set ("ranges", m_ranges->to_json ());
1424
1425 return con_obj;
1426 }
1427
1428 bool
1429 bounded_ranges_constraint::
operator ==(const bounded_ranges_constraint & other) const1430 operator== (const bounded_ranges_constraint &other) const
1431 {
1432 if (m_ec_id != other.m_ec_id)
1433 return false;
1434
1435 /* We can compare by pointer, since the bounded_ranges_manager
1436 consolidates instances. */
1437 return m_ranges == other.m_ranges;
1438 }
1439
1440 void
add_to_hash(inchash::hash * hstate) const1441 bounded_ranges_constraint::add_to_hash (inchash::hash *hstate) const
1442 {
1443 hstate->add_int (m_ec_id.m_idx);
1444 hstate->merge_hash (m_ranges->get_hash ());
1445 }
1446
1447 /* class equiv_class_id. */
1448
1449 /* Get the underlying equiv_class for this ID from CM. */
1450
1451 const equiv_class &
get_obj(const constraint_manager & cm) const1452 equiv_class_id::get_obj (const constraint_manager &cm) const
1453 {
1454 return cm.get_equiv_class_by_index (m_idx);
1455 }
1456
1457 /* Access the underlying equiv_class for this ID from CM. */
1458
1459 equiv_class &
get_obj(constraint_manager & cm) const1460 equiv_class_id::get_obj (constraint_manager &cm) const
1461 {
1462 return cm.get_equiv_class_by_index (m_idx);
1463 }
1464
1465 /* Print this equiv_class_id to PP. */
1466
1467 void
print(pretty_printer * pp) const1468 equiv_class_id::print (pretty_printer *pp) const
1469 {
1470 if (null_p ())
1471 pp_printf (pp, "null");
1472 else
1473 pp_printf (pp, "ec%i", m_idx);
1474 }
1475
1476 /* class constraint_manager. */
1477
1478 /* constraint_manager's copy ctor. */
1479
constraint_manager(const constraint_manager & other)1480 constraint_manager::constraint_manager (const constraint_manager &other)
1481 : m_equiv_classes (other.m_equiv_classes.length ()),
1482 m_constraints (other.m_constraints.length ()),
1483 m_bounded_ranges_constraints (other.m_bounded_ranges_constraints.length ()),
1484 m_mgr (other.m_mgr)
1485 {
1486 int i;
1487 equiv_class *ec;
1488 FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
1489 m_equiv_classes.quick_push (new equiv_class (*ec));
1490 constraint *c;
1491 FOR_EACH_VEC_ELT (other.m_constraints, i, c)
1492 m_constraints.quick_push (*c);
1493 for (const auto &iter : other.m_bounded_ranges_constraints)
1494 m_bounded_ranges_constraints.quick_push (iter);
1495 }
1496
1497 /* constraint_manager's assignment operator. */
1498
1499 constraint_manager&
operator =(const constraint_manager & other)1500 constraint_manager::operator= (const constraint_manager &other)
1501 {
1502 gcc_assert (m_equiv_classes.length () == 0);
1503 gcc_assert (m_constraints.length () == 0);
1504 gcc_assert (m_bounded_ranges_constraints.length () == 0);
1505
1506 int i;
1507 equiv_class *ec;
1508 m_equiv_classes.reserve (other.m_equiv_classes.length ());
1509 FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
1510 m_equiv_classes.quick_push (new equiv_class (*ec));
1511 constraint *c;
1512 m_constraints.reserve (other.m_constraints.length ());
1513 FOR_EACH_VEC_ELT (other.m_constraints, i, c)
1514 m_constraints.quick_push (*c);
1515 for (const auto &iter : other.m_bounded_ranges_constraints)
1516 m_bounded_ranges_constraints.quick_push (iter);
1517
1518 return *this;
1519 }
1520
1521 /* Generate a hash value for this constraint_manager. */
1522
1523 hashval_t
hash() const1524 constraint_manager::hash () const
1525 {
1526 inchash::hash hstate;
1527 int i;
1528 equiv_class *ec;
1529 constraint *c;
1530
1531 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1532 hstate.merge_hash (ec->hash ());
1533 FOR_EACH_VEC_ELT (m_constraints, i, c)
1534 hstate.merge_hash (c->hash ());
1535 for (const auto &iter : m_bounded_ranges_constraints)
1536 iter.add_to_hash (&hstate);
1537 return hstate.end ();
1538 }
1539
1540 /* Equality operator for constraint_manager. */
1541
1542 bool
operator ==(const constraint_manager & other) const1543 constraint_manager::operator== (const constraint_manager &other) const
1544 {
1545 if (m_equiv_classes.length () != other.m_equiv_classes.length ())
1546 return false;
1547 if (m_constraints.length () != other.m_constraints.length ())
1548 return false;
1549 if (m_bounded_ranges_constraints.length ()
1550 != other.m_bounded_ranges_constraints.length ())
1551 return false;
1552
1553 int i;
1554 equiv_class *ec;
1555
1556 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1557 if (!(*ec == *other.m_equiv_classes[i]))
1558 return false;
1559
1560 constraint *c;
1561
1562 FOR_EACH_VEC_ELT (m_constraints, i, c)
1563 if (!(*c == other.m_constraints[i]))
1564 return false;
1565
1566 for (unsigned i = 0; i < m_bounded_ranges_constraints.length (); i++)
1567 {
1568 if (m_bounded_ranges_constraints[i]
1569 != other.m_bounded_ranges_constraints[i])
1570 return false;
1571 }
1572
1573 return true;
1574 }
1575
1576 /* Print this constraint_manager to PP (which must support %E for trees). */
1577
1578 void
print(pretty_printer * pp) const1579 constraint_manager::print (pretty_printer *pp) const
1580 {
1581 pp_string (pp, "{");
1582 int i;
1583 equiv_class *ec;
1584 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1585 {
1586 if (i > 0)
1587 pp_string (pp, ", ");
1588 equiv_class_id (i).print (pp);
1589 pp_string (pp, ": ");
1590 ec->print (pp);
1591 }
1592 pp_string (pp, " | ");
1593 constraint *c;
1594 FOR_EACH_VEC_ELT (m_constraints, i, c)
1595 {
1596 if (i > 0)
1597 pp_string (pp, " && ");
1598 c->print (pp, *this);
1599 }
1600 if (m_bounded_ranges_constraints.length ())
1601 {
1602 pp_string (pp, " | ");
1603 i = 0;
1604 for (const auto &iter : m_bounded_ranges_constraints)
1605 {
1606 if (i > 0)
1607 pp_string (pp, " && ");
1608 iter.print (pp, *this);
1609 i++;
1610 }
1611 }
1612 pp_printf (pp, "}");
1613 }
1614
1615 /* Dump a representation of this constraint_manager to PP
1616 (which must support %E for trees). */
1617
1618 void
dump_to_pp(pretty_printer * pp,bool multiline) const1619 constraint_manager::dump_to_pp (pretty_printer *pp, bool multiline) const
1620 {
1621 if (multiline)
1622 pp_string (pp, " ");
1623 pp_string (pp, "equiv classes:");
1624 if (multiline)
1625 pp_newline (pp);
1626 else
1627 pp_string (pp, " {");
1628 int i;
1629 equiv_class *ec;
1630 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1631 {
1632 if (multiline)
1633 pp_string (pp, " ");
1634 else if (i > 0)
1635 pp_string (pp, ", ");
1636 equiv_class_id (i).print (pp);
1637 pp_string (pp, ": ");
1638 ec->print (pp);
1639 if (multiline)
1640 pp_newline (pp);
1641 }
1642 if (multiline)
1643 pp_string (pp, " ");
1644 else
1645 pp_string (pp, "}");
1646 pp_string (pp, "constraints:");
1647 if (multiline)
1648 pp_newline (pp);
1649 else
1650 pp_string (pp, "{");
1651 constraint *c;
1652 FOR_EACH_VEC_ELT (m_constraints, i, c)
1653 {
1654 if (multiline)
1655 pp_string (pp, " ");
1656 pp_printf (pp, "%i: ", i);
1657 c->print (pp, *this);
1658 if (multiline)
1659 pp_newline (pp);
1660 }
1661 if (!multiline)
1662 pp_string (pp, "}");
1663 if (m_bounded_ranges_constraints.length ())
1664 {
1665 if (multiline)
1666 pp_string (pp, " ");
1667 pp_string (pp, "ranges:");
1668 if (multiline)
1669 pp_newline (pp);
1670 else
1671 pp_string (pp, "{");
1672 i = 0;
1673 for (const auto &iter : m_bounded_ranges_constraints)
1674 {
1675 if (multiline)
1676 pp_string (pp, " ");
1677 else if (i > 0)
1678 pp_string (pp, " && ");
1679 iter.print (pp, *this);
1680 if (multiline)
1681 pp_newline (pp);
1682 i++;
1683 }
1684 if (!multiline)
1685 pp_string (pp, "}");
1686 }
1687 }
1688
1689 /* Dump a multiline representation of this constraint_manager to FP. */
1690
1691 void
dump(FILE * fp) const1692 constraint_manager::dump (FILE *fp) const
1693 {
1694 pretty_printer pp;
1695 pp_format_decoder (&pp) = default_tree_printer;
1696 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1697 pp.buffer->stream = fp;
1698 dump_to_pp (&pp, true);
1699 pp_flush (&pp);
1700 }
1701
1702 /* Dump a multiline representation of this constraint_manager to stderr. */
1703
1704 DEBUG_FUNCTION void
dump() const1705 constraint_manager::dump () const
1706 {
1707 dump (stderr);
1708 }
1709
1710 /* Dump a multiline representation of CM to stderr. */
1711
1712 DEBUG_FUNCTION void
debug(const constraint_manager & cm)1713 debug (const constraint_manager &cm)
1714 {
1715 cm.dump ();
1716 }
1717
1718 /* Return a new json::object of the form
1719 {"ecs" : array of objects, one per equiv_class
1720 "constraints" : array of objects, one per constraint}. */
1721
1722 json::object *
to_json() const1723 constraint_manager::to_json () const
1724 {
1725 json::object *cm_obj = new json::object ();
1726
1727 /* Equivalence classes. */
1728 {
1729 json::array *ec_arr = new json::array ();
1730 for (const equiv_class *ec : m_equiv_classes)
1731 ec_arr->append (ec->to_json ());
1732 cm_obj->set ("ecs", ec_arr);
1733 }
1734
1735 /* Constraints. */
1736 {
1737 json::array *con_arr = new json::array ();
1738 for (const constraint &c : m_constraints)
1739 con_arr->append (c.to_json ());
1740 cm_obj->set ("constraints", con_arr);
1741 }
1742
1743 /* m_bounded_ranges_constraints. */
1744 {
1745 json::array *con_arr = new json::array ();
1746 for (const auto &c : m_bounded_ranges_constraints)
1747 con_arr->append (c.to_json ());
1748 cm_obj->set ("bounded_ranges_constraints", con_arr);
1749 }
1750
1751 return cm_obj;
1752 }
1753
1754 /* Attempt to add the constraint LHS OP RHS to this constraint_manager.
1755 Return true if the constraint could be added (or is already true).
1756 Return false if the constraint contradicts existing knowledge. */
1757
1758 bool
add_constraint(const svalue * lhs,enum tree_code op,const svalue * rhs)1759 constraint_manager::add_constraint (const svalue *lhs,
1760 enum tree_code op,
1761 const svalue *rhs)
1762 {
1763 lhs = lhs->unwrap_any_unmergeable ();
1764 rhs = rhs->unwrap_any_unmergeable ();
1765
1766 /* Nothing can be known about unknown/poisoned values. */
1767 if (!lhs->can_have_associated_state_p ()
1768 || !rhs->can_have_associated_state_p ())
1769 /* Not a contradiction. */
1770 return true;
1771
1772 /* Check the conditions on svalues. */
1773 {
1774 tristate t_cond = eval_condition (lhs, op, rhs);
1775
1776 /* If we already have the condition, do nothing. */
1777 if (t_cond.is_true ())
1778 return true;
1779
1780 /* Reject a constraint that would contradict existing knowledge, as
1781 unsatisfiable. */
1782 if (t_cond.is_false ())
1783 return false;
1784 }
1785
1786 equiv_class_id lhs_ec_id = get_or_add_equiv_class (lhs);
1787 equiv_class_id rhs_ec_id = get_or_add_equiv_class (rhs);
1788
1789 /* Check the stronger conditions on ECs. */
1790 {
1791 tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id);
1792
1793 /* Discard constraints that are already known. */
1794 if (t.is_true ())
1795 return true;
1796
1797 /* Reject unsatisfiable constraints. */
1798 if (t.is_false ())
1799 return false;
1800 }
1801
1802 /* If adding
1803 (SVAL + OFFSET) > CST,
1804 then that can imply:
1805 SVAL > (CST - OFFSET). */
1806 if (const binop_svalue *lhs_binop = lhs->dyn_cast_binop_svalue ())
1807 if (tree rhs_cst = rhs->maybe_get_constant ())
1808 if (tree offset = lhs_binop->get_arg1 ()->maybe_get_constant ())
1809 if ((op == GT_EXPR || op == LT_EXPR
1810 || op == GE_EXPR || op == LE_EXPR)
1811 && lhs_binop->get_op () == PLUS_EXPR)
1812 {
1813 tree offset_of_cst = fold_build2 (MINUS_EXPR, TREE_TYPE (rhs_cst),
1814 rhs_cst, offset);
1815 const svalue *implied_lhs = lhs_binop->get_arg0 ();
1816 enum tree_code implied_op = op;
1817 const svalue *implied_rhs
1818 = m_mgr->get_or_create_constant_svalue (offset_of_cst);
1819 if (!add_constraint (implied_lhs, implied_op, implied_rhs))
1820 return false;
1821 /* The above add_constraint could lead to EC merger, so we need
1822 to refresh the EC IDs. */
1823 lhs_ec_id = get_or_add_equiv_class (lhs);
1824 rhs_ec_id = get_or_add_equiv_class (rhs);
1825 }
1826
1827 add_unknown_constraint (lhs_ec_id, op, rhs_ec_id);
1828 return true;
1829 }
1830
1831 /* Attempt to add the constraint LHS_EC_ID OP RHS_EC_ID to this
1832 constraint_manager.
1833 Return true if the constraint could be added (or is already true).
1834 Return false if the constraint contradicts existing knowledge. */
1835
1836 bool
add_constraint(equiv_class_id lhs_ec_id,enum tree_code op,equiv_class_id rhs_ec_id)1837 constraint_manager::add_constraint (equiv_class_id lhs_ec_id,
1838 enum tree_code op,
1839 equiv_class_id rhs_ec_id)
1840 {
1841 tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id);
1842
1843 /* Discard constraints that are already known. */
1844 if (t.is_true ())
1845 return true;
1846
1847 /* Reject unsatisfiable constraints. */
1848 if (t.is_false ())
1849 return false;
1850
1851 add_unknown_constraint (lhs_ec_id, op, rhs_ec_id);
1852 return true;
1853 }
1854
1855 /* Add the constraint LHS_EC_ID OP RHS_EC_ID to this constraint_manager,
1856 where the constraint has already been checked for being "unknown". */
1857
1858 void
add_unknown_constraint(equiv_class_id lhs_ec_id,enum tree_code op,equiv_class_id rhs_ec_id)1859 constraint_manager::add_unknown_constraint (equiv_class_id lhs_ec_id,
1860 enum tree_code op,
1861 equiv_class_id rhs_ec_id)
1862 {
1863 gcc_assert (lhs_ec_id != rhs_ec_id);
1864
1865 /* For now, simply accumulate constraints, without attempting any further
1866 optimization. */
1867 switch (op)
1868 {
1869 case EQ_EXPR:
1870 {
1871 /* Merge rhs_ec into lhs_ec. */
1872 equiv_class &lhs_ec_obj = lhs_ec_id.get_obj (*this);
1873 const equiv_class &rhs_ec_obj = rhs_ec_id.get_obj (*this);
1874
1875 int i;
1876 const svalue *sval;
1877 FOR_EACH_VEC_ELT (rhs_ec_obj.m_vars, i, sval)
1878 lhs_ec_obj.add (sval);
1879
1880 if (rhs_ec_obj.m_constant)
1881 {
1882 lhs_ec_obj.m_constant = rhs_ec_obj.m_constant;
1883 lhs_ec_obj.m_cst_sval = rhs_ec_obj.m_cst_sval;
1884 }
1885
1886 /* Drop rhs equivalence class, overwriting it with the
1887 final ec (which might be the same one). */
1888 equiv_class_id final_ec_id = m_equiv_classes.length () - 1;
1889 equiv_class *old_ec = m_equiv_classes[rhs_ec_id.m_idx];
1890 equiv_class *final_ec = m_equiv_classes.pop ();
1891 if (final_ec != old_ec)
1892 m_equiv_classes[rhs_ec_id.m_idx] = final_ec;
1893 delete old_ec;
1894 if (lhs_ec_id == final_ec_id)
1895 lhs_ec_id = rhs_ec_id;
1896
1897 /* Update the constraints. */
1898 constraint *c;
1899 FOR_EACH_VEC_ELT (m_constraints, i, c)
1900 {
1901 /* Update references to the rhs_ec so that
1902 they refer to the lhs_ec. */
1903 if (c->m_lhs == rhs_ec_id)
1904 c->m_lhs = lhs_ec_id;
1905 if (c->m_rhs == rhs_ec_id)
1906 c->m_rhs = lhs_ec_id;
1907
1908 /* Renumber all constraints that refer to the final rhs_ec
1909 to the old rhs_ec, where the old final_ec now lives. */
1910 if (c->m_lhs == final_ec_id)
1911 c->m_lhs = rhs_ec_id;
1912 if (c->m_rhs == final_ec_id)
1913 c->m_rhs = rhs_ec_id;
1914 }
1915 bounded_ranges_constraint *brc;
1916 FOR_EACH_VEC_ELT (m_bounded_ranges_constraints, i, brc)
1917 {
1918 if (brc->m_ec_id == rhs_ec_id)
1919 brc->m_ec_id = lhs_ec_id;
1920 if (brc->m_ec_id == final_ec_id)
1921 brc->m_ec_id = rhs_ec_id;
1922 }
1923
1924 /* We may now have self-comparisons due to the merger; these
1925 constraints should be removed. */
1926 unsigned read_index, write_index;
1927 VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c,
1928 (c->m_lhs == c->m_rhs));
1929 }
1930 break;
1931 case GE_EXPR:
1932 add_constraint_internal (rhs_ec_id, CONSTRAINT_LE, lhs_ec_id);
1933 break;
1934 case LE_EXPR:
1935 add_constraint_internal (lhs_ec_id, CONSTRAINT_LE, rhs_ec_id);
1936 break;
1937 case NE_EXPR:
1938 add_constraint_internal (lhs_ec_id, CONSTRAINT_NE, rhs_ec_id);
1939 break;
1940 case GT_EXPR:
1941 add_constraint_internal (rhs_ec_id, CONSTRAINT_LT, lhs_ec_id);
1942 break;
1943 case LT_EXPR:
1944 add_constraint_internal (lhs_ec_id, CONSTRAINT_LT, rhs_ec_id);
1945 break;
1946 default:
1947 /* do nothing. */
1948 break;
1949 }
1950 validate ();
1951 }
1952
1953 /* Subroutine of constraint_manager::add_constraint, for handling all
1954 operations other than equality (for which equiv classes are merged). */
1955
1956 void
add_constraint_internal(equiv_class_id lhs_id,enum constraint_op c_op,equiv_class_id rhs_id)1957 constraint_manager::add_constraint_internal (equiv_class_id lhs_id,
1958 enum constraint_op c_op,
1959 equiv_class_id rhs_id)
1960 {
1961 if (m_constraints.length () >= (unsigned)param_analyzer_max_constraints)
1962 return;
1963
1964 constraint new_c (lhs_id, c_op, rhs_id);
1965
1966 /* Remove existing constraints that would be implied by the
1967 new constraint. */
1968 unsigned read_index, write_index;
1969 constraint *c;
1970 VEC_ORDERED_REMOVE_IF (m_constraints, read_index, write_index, c,
1971 (c->implied_by (new_c, *this)));
1972
1973 /* Add the constraint. */
1974 m_constraints.safe_push (new_c);
1975
1976 /* We don't yet update m_bounded_ranges_constraints here yet. */
1977
1978 if (!flag_analyzer_transitivity)
1979 return;
1980
1981 if (c_op != CONSTRAINT_NE)
1982 {
1983 /* The following can potentially add EQ_EXPR facts, which could lead
1984 to ECs being merged, which would change the meaning of the EC IDs.
1985 Hence we need to do this via representatives. */
1986 const svalue *lhs = lhs_id.get_obj (*this).get_representative ();
1987 const svalue *rhs = rhs_id.get_obj (*this).get_representative ();
1988
1989 /* We have LHS </<= RHS */
1990
1991 /* Handle transitivity of ordering by adding additional constraints
1992 based on what we already knew.
1993
1994 So if we have already have:
1995 (a < b)
1996 (c < d)
1997 Then adding:
1998 (b < c)
1999 will also add:
2000 (a < c)
2001 (b < d)
2002 We need to recurse to ensure we also add:
2003 (a < d).
2004 We call the checked add_constraint to avoid adding constraints
2005 that are already present. Doing so also ensures termination
2006 in the case of cycles.
2007
2008 We also check for single-element ranges, adding EQ_EXPR facts
2009 where we discover them. For example 3 < x < 5 implies
2010 that x == 4 (if x is an integer). */
2011 for (unsigned i = 0; i < m_constraints.length (); i++)
2012 {
2013 const constraint *other = &m_constraints[i];
2014 if (other->is_ordering_p ())
2015 {
2016 /* Refresh the EC IDs, in case any mergers have happened. */
2017 lhs_id = get_or_add_equiv_class (lhs);
2018 rhs_id = get_or_add_equiv_class (rhs);
2019
2020 tree lhs_const = lhs_id.get_obj (*this).m_constant;
2021 tree rhs_const = rhs_id.get_obj (*this).m_constant;
2022 tree other_lhs_const
2023 = other->m_lhs.get_obj (*this).m_constant;
2024 tree other_rhs_const
2025 = other->m_rhs.get_obj (*this).m_constant;
2026
2027 /* We have "LHS </<= RHS" and "other.lhs </<= other.rhs". */
2028
2029 /* If we have LHS </<= RHS and RHS </<= LHS, then we have a
2030 cycle. */
2031 if (rhs_id == other->m_lhs
2032 && other->m_rhs == lhs_id)
2033 {
2034 /* We must have equality for this to be possible. */
2035 gcc_assert (c_op == CONSTRAINT_LE
2036 && other->m_op == CONSTRAINT_LE);
2037 add_constraint (lhs_id, EQ_EXPR, rhs_id);
2038 /* Adding an equality will merge the two ECs and potentially
2039 reorganize the constraints. Stop iterating. */
2040 return;
2041 }
2042 /* Otherwise, check for transitivity. */
2043 if (rhs_id == other->m_lhs)
2044 {
2045 /* With RHS == other.lhs, we have:
2046 "LHS </<= (RHS, other.lhs) </<= other.rhs"
2047 and thus this implies "LHS </<= other.rhs". */
2048
2049 /* Do we have a tightly-constrained range? */
2050 if (lhs_const
2051 && !rhs_const
2052 && other_rhs_const)
2053 {
2054 range r (bound (lhs_const, c_op == CONSTRAINT_LE),
2055 bound (other_rhs_const,
2056 other->m_op == CONSTRAINT_LE));
2057 if (tree constant = r.constrained_to_single_element ())
2058 {
2059 const svalue *cst_sval
2060 = m_mgr->get_or_create_constant_svalue (constant);
2061 add_constraint
2062 (rhs_id, EQ_EXPR,
2063 get_or_add_equiv_class (cst_sval));
2064 return;
2065 }
2066 }
2067
2068 /* Otherwise, add the constraint implied by transitivity. */
2069 enum tree_code new_op
2070 = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
2071 ? LE_EXPR : LT_EXPR);
2072 add_constraint (lhs_id, new_op, other->m_rhs);
2073 }
2074 else if (other->m_rhs == lhs_id)
2075 {
2076 /* With other.rhs == LHS, we have:
2077 "other.lhs </<= (other.rhs, LHS) </<= RHS"
2078 and thus this implies "other.lhs </<= RHS". */
2079
2080 /* Do we have a tightly-constrained range? */
2081 if (other_lhs_const
2082 && !lhs_const
2083 && rhs_const)
2084 {
2085 range r (bound (other_lhs_const,
2086 other->m_op == CONSTRAINT_LE),
2087 bound (rhs_const,
2088 c_op == CONSTRAINT_LE));
2089 if (tree constant = r.constrained_to_single_element ())
2090 {
2091 const svalue *cst_sval
2092 = m_mgr->get_or_create_constant_svalue (constant);
2093 add_constraint
2094 (lhs_id, EQ_EXPR,
2095 get_or_add_equiv_class (cst_sval));
2096 return;
2097 }
2098 }
2099
2100 /* Otherwise, add the constraint implied by transitivity. */
2101 enum tree_code new_op
2102 = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
2103 ? LE_EXPR : LT_EXPR);
2104 add_constraint (other->m_lhs, new_op, rhs_id);
2105 }
2106 }
2107 }
2108 }
2109 }
2110
2111 /* Attempt to add the constraint that SVAL is within RANGES to this
2112 constraint_manager.
2113
2114 Return true if the constraint was successfully added (or is already
2115 known to be true).
2116 Return false if the constraint contradicts existing knowledge. */
2117
2118 bool
add_bounded_ranges(const svalue * sval,const bounded_ranges * ranges)2119 constraint_manager::add_bounded_ranges (const svalue *sval,
2120 const bounded_ranges *ranges)
2121 {
2122 sval = sval->unwrap_any_unmergeable ();
2123
2124 /* Nothing can be known about unknown/poisoned values. */
2125 if (!sval->can_have_associated_state_p ())
2126 /* Not a contradiction. */
2127 return true;
2128
2129 /* If SVAL is a constant, then we can look at RANGES directly. */
2130 if (tree cst = sval->maybe_get_constant ())
2131 {
2132 /* If the ranges contain CST, then it's a successful no-op;
2133 otherwise it's a contradiction. */
2134 return ranges->contain_p (cst);
2135 }
2136
2137 equiv_class_id ec_id = get_or_add_equiv_class (sval);
2138
2139 /* If the EC has a constant, it's either true or false. */
2140 const equiv_class &ec = ec_id.get_obj (*this);
2141 if (tree ec_cst = ec.get_any_constant ())
2142 {
2143 if (ranges->contain_p (ec_cst))
2144 /* We already have SVAL == EC_CST, within RANGES, so
2145 we can discard RANGES and succeed. */
2146 return true;
2147 else
2148 /* We already have SVAL == EC_CST, not within RANGES, so
2149 we can reject RANGES as a contradiction. */
2150 return false;
2151 }
2152
2153 /* We have at most one per ec_id. */
2154 /* Iterate through each range in RANGES. */
2155 for (auto iter : m_bounded_ranges_constraints)
2156 {
2157 if (iter.m_ec_id == ec_id)
2158 {
2159 /* Update with intersection, or fail if empty. */
2160 bounded_ranges_manager *mgr = get_range_manager ();
2161 const bounded_ranges *intersection
2162 = mgr->get_or_create_intersection (iter.m_ranges, ranges);
2163 if (intersection->empty_p ())
2164 {
2165 /* No intersection; fail. */
2166 return false;
2167 }
2168 else
2169 {
2170 /* Update with intersection; succeed. */
2171 iter.m_ranges = intersection;
2172 validate ();
2173 return true;
2174 }
2175 }
2176 }
2177 m_bounded_ranges_constraints.safe_push
2178 (bounded_ranges_constraint (ec_id, ranges));
2179
2180 validate ();
2181
2182 return true;
2183 }
2184
2185 /* Look for SVAL within the equivalence classes of this constraint_manager;
2186 if found, return true, writing the id to *OUT if OUT is non-NULL,
2187 otherwise return false. */
2188
2189 bool
get_equiv_class_by_svalue(const svalue * sval,equiv_class_id * out) const2190 constraint_manager::get_equiv_class_by_svalue (const svalue *sval,
2191 equiv_class_id *out) const
2192 {
2193 /* TODO: should we have a map, rather than these searches? */
2194 int i;
2195 equiv_class *ec;
2196 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2197 {
2198 int j;
2199 const svalue *iv;
2200 FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
2201 if (iv == sval)
2202 {
2203 if (out)
2204 *out = equiv_class_id (i);
2205 return true;
2206 }
2207 }
2208 return false;
2209 }
2210
2211 /* Ensure that SVAL has an equivalence class within this constraint_manager;
2212 return the ID of the class. */
2213
2214 equiv_class_id
get_or_add_equiv_class(const svalue * sval)2215 constraint_manager::get_or_add_equiv_class (const svalue *sval)
2216 {
2217 equiv_class_id result (-1);
2218
2219 gcc_assert (sval->can_have_associated_state_p ());
2220
2221 /* Convert all NULL pointers to (void *) to avoid state explosions
2222 involving all of the various (foo *)NULL vs (bar *)NULL. */
2223 if (sval->get_type ())
2224 if (POINTER_TYPE_P (sval->get_type ()))
2225 if (tree cst = sval->maybe_get_constant ())
2226 if (zerop (cst))
2227 sval = m_mgr->get_or_create_constant_svalue (null_pointer_node);
2228
2229 /* Try svalue match. */
2230 if (get_equiv_class_by_svalue (sval, &result))
2231 return result;
2232
2233 /* Try equality of constants. */
2234 if (tree cst = sval->maybe_get_constant ())
2235 {
2236 int i;
2237 equiv_class *ec;
2238 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2239 if (ec->m_constant
2240 && types_compatible_p (TREE_TYPE (cst),
2241 TREE_TYPE (ec->m_constant)))
2242 {
2243 tree eq = fold_binary (EQ_EXPR, boolean_type_node,
2244 cst, ec->m_constant);
2245 if (eq == boolean_true_node)
2246 {
2247 ec->add (sval);
2248 return equiv_class_id (i);
2249 }
2250 }
2251 }
2252
2253
2254 /* Not found. */
2255 equiv_class *new_ec = new equiv_class ();
2256 new_ec->add (sval);
2257 m_equiv_classes.safe_push (new_ec);
2258
2259 equiv_class_id new_id (m_equiv_classes.length () - 1);
2260
2261 return new_id;
2262 }
2263
2264 /* Evaluate the condition LHS_EC OP RHS_EC. */
2265
2266 tristate
eval_condition(equiv_class_id lhs_ec,enum tree_code op,equiv_class_id rhs_ec) const2267 constraint_manager::eval_condition (equiv_class_id lhs_ec,
2268 enum tree_code op,
2269 equiv_class_id rhs_ec) const
2270 {
2271 if (lhs_ec == rhs_ec)
2272 {
2273 switch (op)
2274 {
2275 case EQ_EXPR:
2276 case GE_EXPR:
2277 case LE_EXPR:
2278 return tristate (tristate::TS_TRUE);
2279
2280 case NE_EXPR:
2281 case GT_EXPR:
2282 case LT_EXPR:
2283 return tristate (tristate::TS_FALSE);
2284 default:
2285 break;
2286 }
2287 }
2288
2289 tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ();
2290 tree rhs_const = rhs_ec.get_obj (*this).get_any_constant ();
2291 if (lhs_const && rhs_const)
2292 {
2293 tristate result_for_constants
2294 = compare_constants (lhs_const, op, rhs_const);
2295 if (result_for_constants.is_known ())
2296 return result_for_constants;
2297 }
2298
2299 enum tree_code swapped_op = swap_tree_comparison (op);
2300
2301 int i;
2302 constraint *c;
2303 FOR_EACH_VEC_ELT (m_constraints, i, c)
2304 {
2305 if (c->m_lhs == lhs_ec
2306 && c->m_rhs == rhs_ec)
2307 {
2308 tristate result_for_constraint
2309 = eval_constraint_op_for_op (c->m_op, op);
2310 if (result_for_constraint.is_known ())
2311 return result_for_constraint;
2312 }
2313 /* Swapped operands. */
2314 if (c->m_lhs == rhs_ec
2315 && c->m_rhs == lhs_ec)
2316 {
2317 tristate result_for_constraint
2318 = eval_constraint_op_for_op (c->m_op, swapped_op);
2319 if (result_for_constraint.is_known ())
2320 return result_for_constraint;
2321 }
2322 }
2323
2324 /* We don't use m_bounded_ranges_constraints here yet. */
2325
2326 return tristate (tristate::TS_UNKNOWN);
2327 }
2328
2329 range
get_ec_bounds(equiv_class_id ec_id) const2330 constraint_manager::get_ec_bounds (equiv_class_id ec_id) const
2331 {
2332 range result;
2333
2334 int i;
2335 constraint *c;
2336 FOR_EACH_VEC_ELT (m_constraints, i, c)
2337 {
2338 if (c->m_lhs == ec_id)
2339 {
2340 if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ())
2341 switch (c->m_op)
2342 {
2343 default:
2344 gcc_unreachable ();
2345 case CONSTRAINT_NE:
2346 continue;
2347
2348 case CONSTRAINT_LT:
2349 /* We have "EC_ID < OTHER_CST". */
2350 result.add_bound (bound (other_cst, false), BK_UPPER);
2351 break;
2352
2353 case CONSTRAINT_LE:
2354 /* We have "EC_ID <= OTHER_CST". */
2355 result.add_bound (bound (other_cst, true), BK_UPPER);
2356 break;
2357 }
2358 }
2359 if (c->m_rhs == ec_id)
2360 {
2361 if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ())
2362 switch (c->m_op)
2363 {
2364 default:
2365 gcc_unreachable ();
2366 case CONSTRAINT_NE:
2367 continue;
2368
2369 case CONSTRAINT_LT:
2370 /* We have "OTHER_CST < EC_ID"
2371 i.e. "EC_ID > OTHER_CST". */
2372 result.add_bound (bound (other_cst, false), BK_LOWER);
2373 break;
2374
2375 case CONSTRAINT_LE:
2376 /* We have "OTHER_CST <= EC_ID"
2377 i.e. "EC_ID >= OTHER_CST". */
2378 result.add_bound (bound (other_cst, true), BK_LOWER);
2379 break;
2380 }
2381 }
2382 }
2383
2384 return result;
2385 }
2386
2387 /* Evaluate the condition LHS_EC OP RHS_CONST, avoiding the creation
2388 of equiv_class instances. */
2389
2390 tristate
eval_condition(equiv_class_id lhs_ec,enum tree_code op,tree rhs_const) const2391 constraint_manager::eval_condition (equiv_class_id lhs_ec,
2392 enum tree_code op,
2393 tree rhs_const) const
2394 {
2395 gcc_assert (!lhs_ec.null_p ());
2396 gcc_assert (CONSTANT_CLASS_P (rhs_const));
2397
2398 if (tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ())
2399 return compare_constants (lhs_const, op, rhs_const);
2400
2401 /* Check for known inequalities of the form
2402 (LHS_EC != OTHER_CST) or (OTHER_CST != LHS_EC).
2403 If RHS_CONST == OTHER_CST, then we also know that LHS_EC != OTHER_CST.
2404 For example, we might have the constraint
2405 ptr != (void *)0
2406 so we want the condition
2407 ptr == (foo *)0
2408 to be false. */
2409 int i;
2410 constraint *c;
2411 FOR_EACH_VEC_ELT (m_constraints, i, c)
2412 {
2413 if (c->m_op == CONSTRAINT_NE)
2414 {
2415 if (c->m_lhs == lhs_ec)
2416 {
2417 if (tree other_cst = c->m_rhs.get_obj (*this).get_any_constant ())
2418 if (compare_constants
2419 (rhs_const, EQ_EXPR, other_cst).is_true ())
2420 {
2421 switch (op)
2422 {
2423 case EQ_EXPR:
2424 return tristate (tristate::TS_FALSE);
2425 case NE_EXPR:
2426 return tristate (tristate::TS_TRUE);
2427 default:
2428 break;
2429 }
2430 }
2431 }
2432 if (c->m_rhs == lhs_ec)
2433 {
2434 if (tree other_cst = c->m_lhs.get_obj (*this).get_any_constant ())
2435 if (compare_constants
2436 (rhs_const, EQ_EXPR, other_cst).is_true ())
2437 {
2438 switch (op)
2439 {
2440 case EQ_EXPR:
2441 return tristate (tristate::TS_FALSE);
2442 case NE_EXPR:
2443 return tristate (tristate::TS_TRUE);
2444 default:
2445 break;
2446 }
2447 }
2448 }
2449 }
2450 }
2451
2452 bounded_ranges_manager *mgr = get_range_manager ();
2453 for (const auto &iter : m_bounded_ranges_constraints)
2454 if (iter.m_ec_id == lhs_ec)
2455 return iter.m_ranges->eval_condition (op, rhs_const, mgr);
2456
2457 /* Look at existing bounds on LHS_EC. */
2458 range lhs_bounds = get_ec_bounds (lhs_ec);
2459 tristate result = lhs_bounds.eval_condition (op, rhs_const);
2460 if (result.is_known ())
2461 return result;
2462
2463 /* Also reject if range::add_bound fails. */
2464 if (!lhs_bounds.add_bound (op, rhs_const))
2465 return tristate (false);
2466
2467 return tristate::unknown ();
2468 }
2469
2470 /* Evaluate the condition LHS OP RHS, without modifying this
2471 constraint_manager (avoiding the creation of equiv_class instances). */
2472
2473 tristate
eval_condition(const svalue * lhs,enum tree_code op,const svalue * rhs) const2474 constraint_manager::eval_condition (const svalue *lhs,
2475 enum tree_code op,
2476 const svalue *rhs) const
2477 {
2478 lhs = lhs->unwrap_any_unmergeable ();
2479 rhs = rhs->unwrap_any_unmergeable ();
2480
2481 /* Nothing can be known about unknown or poisoned values. */
2482 if (lhs->get_kind () == SK_UNKNOWN
2483 || lhs->get_kind () == SK_POISONED
2484 || rhs->get_kind () == SK_UNKNOWN
2485 || rhs->get_kind () == SK_POISONED)
2486 return tristate (tristate::TS_UNKNOWN);
2487
2488 if (lhs == rhs
2489 && !(FLOAT_TYPE_P (lhs->get_type ())
2490 || FLOAT_TYPE_P (rhs->get_type ())))
2491 {
2492 switch (op)
2493 {
2494 case EQ_EXPR:
2495 case GE_EXPR:
2496 case LE_EXPR:
2497 return tristate (tristate::TS_TRUE);
2498
2499 case NE_EXPR:
2500 case GT_EXPR:
2501 case LT_EXPR:
2502 return tristate (tristate::TS_FALSE);
2503 default:
2504 break;
2505 }
2506 }
2507
2508 equiv_class_id lhs_ec (-1);
2509 equiv_class_id rhs_ec (-1);
2510 get_equiv_class_by_svalue (lhs, &lhs_ec);
2511 get_equiv_class_by_svalue (rhs, &rhs_ec);
2512 if (!lhs_ec.null_p () && !rhs_ec.null_p ())
2513 {
2514 tristate result_for_ecs
2515 = eval_condition (lhs_ec, op, rhs_ec);
2516 if (result_for_ecs.is_known ())
2517 return result_for_ecs;
2518 }
2519
2520 /* If at least one is not in an EC, we have no constraints
2521 comparing LHS and RHS yet.
2522 They might still be comparable if one (or both) is a constant.
2523
2524 Alternatively, we can also get here if we had ECs but they weren't
2525 comparable. Again, constant comparisons might give an answer. */
2526 tree lhs_const = lhs->maybe_get_constant ();
2527 tree rhs_const = rhs->maybe_get_constant ();
2528 if (lhs_const && rhs_const)
2529 {
2530 tristate result_for_constants
2531 = compare_constants (lhs_const, op, rhs_const);
2532 if (result_for_constants.is_known ())
2533 return result_for_constants;
2534 }
2535
2536 if (!lhs_ec.null_p ())
2537 {
2538 if (rhs_const)
2539 return eval_condition (lhs_ec, op, rhs_const);
2540 }
2541 if (!rhs_ec.null_p ())
2542 {
2543 if (lhs_const)
2544 {
2545 enum tree_code swapped_op = swap_tree_comparison (op);
2546 return eval_condition (rhs_ec, swapped_op, lhs_const);
2547 }
2548 }
2549
2550 return tristate (tristate::TS_UNKNOWN);
2551 }
2552
2553 /* Delete any information about svalues identified by P.
2554 Such instances are removed from equivalence classes, and any
2555 redundant ECs and constraints are also removed.
2556 Accumulate stats into STATS. */
2557
2558 template <typename PurgeCriteria>
2559 void
purge(const PurgeCriteria & p,purge_stats * stats)2560 constraint_manager::purge (const PurgeCriteria &p, purge_stats *stats)
2561 {
2562 /* Delete any svalues identified by P within the various equivalence
2563 classes. */
2564 for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
2565 {
2566 equiv_class *ec = m_equiv_classes[ec_idx];
2567
2568 int i;
2569 const svalue *sval;
2570 bool delete_ec = false;
2571 FOR_EACH_VEC_ELT (ec->m_vars, i, sval)
2572 {
2573 if (sval == ec->m_cst_sval)
2574 continue;
2575 if (p.should_purge_p (sval))
2576 {
2577 if (ec->del (sval))
2578 if (!ec->m_constant)
2579 delete_ec = true;
2580 }
2581 }
2582
2583 if (delete_ec)
2584 {
2585 delete ec;
2586 m_equiv_classes.ordered_remove (ec_idx);
2587 if (stats)
2588 stats->m_num_equiv_classes++;
2589
2590 /* Update the constraints, potentially removing some. */
2591 for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
2592 {
2593 constraint *c = &m_constraints[con_idx];
2594
2595 /* Remove constraints that refer to the deleted EC. */
2596 if (c->m_lhs == ec_idx
2597 || c->m_rhs == ec_idx)
2598 {
2599 m_constraints.ordered_remove (con_idx);
2600 if (stats)
2601 stats->m_num_constraints++;
2602 }
2603 else
2604 {
2605 /* Renumber constraints that refer to ECs that have
2606 had their idx changed. */
2607 c->m_lhs.update_for_removal (ec_idx);
2608 c->m_rhs.update_for_removal (ec_idx);
2609
2610 con_idx++;
2611 }
2612 }
2613
2614 /* Update bounded_ranges_constraint instances. */
2615 for (unsigned r_idx = 0;
2616 r_idx < m_bounded_ranges_constraints.length (); )
2617 {
2618 bounded_ranges_constraint *brc
2619 = &m_bounded_ranges_constraints[r_idx];
2620
2621 /* Remove if it refers to the deleted EC. */
2622 if (brc->m_ec_id == ec_idx)
2623 {
2624 m_bounded_ranges_constraints.ordered_remove (r_idx);
2625 if (stats)
2626 stats->m_num_bounded_ranges_constraints++;
2627 }
2628 else
2629 {
2630 /* Renumber any EC ids that refer to ECs that have
2631 had their idx changed. */
2632 brc->m_ec_id.update_for_removal (ec_idx);
2633 r_idx++;
2634 }
2635 }
2636 }
2637 else
2638 ec_idx++;
2639 }
2640
2641 /* Now delete any constraints that are purely between constants. */
2642 for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
2643 {
2644 constraint *c = &m_constraints[con_idx];
2645 if (m_equiv_classes[c->m_lhs.m_idx]->m_vars.length () == 0
2646 && m_equiv_classes[c->m_rhs.m_idx]->m_vars.length () == 0)
2647 {
2648 m_constraints.ordered_remove (con_idx);
2649 if (stats)
2650 stats->m_num_constraints++;
2651 }
2652 else
2653 {
2654 con_idx++;
2655 }
2656 }
2657
2658 /* Finally, delete any ECs that purely contain constants and aren't
2659 referenced by any constraints. */
2660 for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
2661 {
2662 equiv_class *ec = m_equiv_classes[ec_idx];
2663 if (ec->m_vars.length () == 0)
2664 {
2665 equiv_class_id ec_id (ec_idx);
2666 bool has_constraint = false;
2667 for (unsigned con_idx = 0; con_idx < m_constraints.length ();
2668 con_idx++)
2669 {
2670 constraint *c = &m_constraints[con_idx];
2671 if (c->m_lhs == ec_id
2672 || c->m_rhs == ec_id)
2673 {
2674 has_constraint = true;
2675 break;
2676 }
2677 }
2678 if (!has_constraint)
2679 {
2680 delete ec;
2681 m_equiv_classes.ordered_remove (ec_idx);
2682 if (stats)
2683 stats->m_num_equiv_classes++;
2684
2685 /* Renumber constraints that refer to ECs that have
2686 had their idx changed. */
2687 for (unsigned con_idx = 0; con_idx < m_constraints.length ();
2688 con_idx++)
2689 {
2690 constraint *c = &m_constraints[con_idx];
2691 c->m_lhs.update_for_removal (ec_idx);
2692 c->m_rhs.update_for_removal (ec_idx);
2693 }
2694
2695 /* Likewise for m_bounded_ranges_constraints. */
2696 for (unsigned r_idx = 0;
2697 r_idx < m_bounded_ranges_constraints.length ();
2698 r_idx++)
2699 {
2700 bounded_ranges_constraint *brc
2701 = &m_bounded_ranges_constraints[r_idx];
2702 brc->m_ec_id.update_for_removal (ec_idx);
2703 }
2704
2705 continue;
2706 }
2707 }
2708 ec_idx++;
2709 }
2710
2711 validate ();
2712 }
2713
2714 /* Implementation of PurgeCriteria: purge svalues that are not live
2715 with respect to LIVE_SVALUES and MODEL. */
2716
2717 class dead_svalue_purger
2718 {
2719 public:
dead_svalue_purger(const svalue_set & live_svalues,const region_model * model)2720 dead_svalue_purger (const svalue_set &live_svalues,
2721 const region_model *model)
2722 : m_live_svalues (live_svalues), m_model (model)
2723 {
2724 }
2725
should_purge_p(const svalue * sval) const2726 bool should_purge_p (const svalue *sval) const
2727 {
2728 return !sval->live_p (&m_live_svalues, m_model);
2729 }
2730
2731 private:
2732 const svalue_set &m_live_svalues;
2733 const region_model *m_model;
2734 };
2735
2736 /* Purge dead svalues from equivalence classes and update constraints
2737 accordingly. */
2738
2739 void
2740 constraint_manager::
on_liveness_change(const svalue_set & live_svalues,const region_model * model)2741 on_liveness_change (const svalue_set &live_svalues,
2742 const region_model *model)
2743 {
2744 dead_svalue_purger p (live_svalues, model);
2745 purge (p, NULL);
2746 }
2747
2748 class svalue_purger
2749 {
2750 public:
svalue_purger(const svalue * sval)2751 svalue_purger (const svalue *sval) : m_sval (sval) {}
2752
should_purge_p(const svalue * sval) const2753 bool should_purge_p (const svalue *sval) const
2754 {
2755 return sval->involves_p (m_sval);
2756 }
2757
2758 private:
2759 const svalue *m_sval;
2760 };
2761
2762 /* Purge any state involving SVAL. */
2763
2764 void
purge_state_involving(const svalue * sval)2765 constraint_manager::purge_state_involving (const svalue *sval)
2766 {
2767 svalue_purger p (sval);
2768 purge (p, NULL);
2769 }
2770
2771 /* Comparator for use by constraint_manager::canonicalize.
2772 Sort a pair of equiv_class instances, using the representative
2773 svalue as a sort key. */
2774
2775 static int
equiv_class_cmp(const void * p1,const void * p2)2776 equiv_class_cmp (const void *p1, const void *p2)
2777 {
2778 const equiv_class *ec1 = *(const equiv_class * const *)p1;
2779 const equiv_class *ec2 = *(const equiv_class * const *)p2;
2780
2781 const svalue *rep1 = ec1->get_representative ();
2782 const svalue *rep2 = ec2->get_representative ();
2783
2784 gcc_assert (rep1);
2785 gcc_assert (rep2);
2786
2787 return svalue::cmp_ptr (rep1, rep2);
2788 }
2789
2790 /* Comparator for use by constraint_manager::canonicalize.
2791 Sort a pair of constraint instances. */
2792
2793 static int
constraint_cmp(const void * p1,const void * p2)2794 constraint_cmp (const void *p1, const void *p2)
2795 {
2796 const constraint *c1 = (const constraint *)p1;
2797 const constraint *c2 = (const constraint *)p2;
2798 int lhs_cmp = c1->m_lhs.as_int () - c2->m_lhs.as_int ();
2799 if (lhs_cmp)
2800 return lhs_cmp;
2801 int rhs_cmp = c1->m_rhs.as_int () - c2->m_rhs.as_int ();
2802 if (rhs_cmp)
2803 return rhs_cmp;
2804 return c1->m_op - c2->m_op;
2805 }
2806
2807 /* Purge redundant equivalence classes and constraints, and reorder them
2808 within this constraint_manager into a canonical order, to increase the
2809 chances of finding equality with another instance. */
2810
2811 void
canonicalize()2812 constraint_manager::canonicalize ()
2813 {
2814 /* First, sort svalues within the ECs. */
2815 unsigned i;
2816 equiv_class *ec;
2817 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2818 ec->canonicalize ();
2819
2820 /* TODO: remove constraints where both sides have a constant, and are
2821 thus implicit. But does this break transitivity? */
2822
2823 /* We will be purging and reordering ECs.
2824 We will need to remap the equiv_class_ids in the constraints,
2825 so we need to store the original index of each EC.
2826 Build a lookup table, mapping from the representative svalue
2827 to the original equiv_class_id of that svalue. */
2828 hash_map<const svalue *, equiv_class_id> original_ec_id;
2829 const unsigned orig_num_equiv_classes = m_equiv_classes.length ();
2830 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2831 {
2832 const svalue *rep = ec->get_representative ();
2833 gcc_assert (rep);
2834 original_ec_id.put (rep, i);
2835 }
2836
2837 /* Find ECs used by constraints. */
2838 hash_set<const equiv_class *> used_ecs;
2839 constraint *c;
2840 FOR_EACH_VEC_ELT (m_constraints, i, c)
2841 {
2842 used_ecs.add (m_equiv_classes[c->m_lhs.as_int ()]);
2843 used_ecs.add (m_equiv_classes[c->m_rhs.as_int ()]);
2844 }
2845
2846 for (const auto &iter : m_bounded_ranges_constraints)
2847 used_ecs.add (m_equiv_classes[iter.m_ec_id.as_int ()]);
2848
2849 /* Purge unused ECs: those that aren't used by constraints and
2850 that effectively have only one svalue (either in m_constant
2851 or in m_vars). */
2852 {
2853 /* "unordered remove if" from a vec. */
2854 unsigned i = 0;
2855 while (i < m_equiv_classes.length ())
2856 {
2857 equiv_class *ec = m_equiv_classes[i];
2858 if (!used_ecs.contains (ec)
2859 && !ec->contains_non_constant_p ())
2860 {
2861 m_equiv_classes.unordered_remove (i);
2862 delete ec;
2863 }
2864 else
2865 i++;
2866 }
2867 }
2868
2869 /* Next, sort the surviving ECs into a canonical order. */
2870 m_equiv_classes.qsort (equiv_class_cmp);
2871
2872 /* Populate ec_id_map based on the old vs new EC ids. */
2873 one_way_id_map<equiv_class_id> ec_id_map (orig_num_equiv_classes);
2874 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
2875 {
2876 const svalue *rep = ec->get_representative ();
2877 gcc_assert (rep);
2878 ec_id_map.put (*original_ec_id.get (rep), i);
2879 }
2880
2881 /* Use ec_id_map to update the EC ids within the constraints. */
2882 FOR_EACH_VEC_ELT (m_constraints, i, c)
2883 {
2884 ec_id_map.update (&c->m_lhs);
2885 ec_id_map.update (&c->m_rhs);
2886 }
2887
2888 for (auto &iter : m_bounded_ranges_constraints)
2889 ec_id_map.update (&iter.m_ec_id);
2890
2891 /* Finally, sort the constraints. */
2892 m_constraints.qsort (constraint_cmp);
2893 }
2894
2895 /* Concrete subclass of fact_visitor for use by constraint_manager::merge.
2896 For every fact in CM_A, see if it is also true in *CM_B. Add such
2897 facts to *OUT. */
2898
2899 class merger_fact_visitor : public fact_visitor
2900 {
2901 public:
merger_fact_visitor(const constraint_manager * cm_b,constraint_manager * out)2902 merger_fact_visitor (const constraint_manager *cm_b,
2903 constraint_manager *out)
2904 : m_cm_b (cm_b), m_out (out)
2905 {}
2906
on_fact(const svalue * lhs,enum tree_code code,const svalue * rhs)2907 void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs)
2908 FINAL OVERRIDE
2909 {
2910 /* Special-case for widening. */
2911 if (lhs->get_kind () == SK_WIDENING)
2912 if (!m_cm_b->get_equiv_class_by_svalue (lhs, NULL))
2913 {
2914 /* LHS isn't constrained within m_cm_b. */
2915 bool sat = m_out->add_constraint (lhs, code, rhs);
2916 gcc_assert (sat);
2917 return;
2918 }
2919
2920 if (m_cm_b->eval_condition (lhs, code, rhs).is_true ())
2921 {
2922 bool sat = m_out->add_constraint (lhs, code, rhs);
2923 if (!sat)
2924 {
2925 /* If -fanalyzer-transitivity is off, we can encounter cases
2926 where at least one of the two constraint_managers being merged
2927 is infeasible, but we only discover that infeasibility
2928 during merging (PR analyzer/96650).
2929 Silently drop such constraints. */
2930 gcc_assert (!flag_analyzer_transitivity);
2931 }
2932 }
2933 }
2934
on_ranges(const svalue * lhs_sval,const bounded_ranges * ranges)2935 void on_ranges (const svalue *lhs_sval,
2936 const bounded_ranges *ranges) FINAL OVERRIDE
2937 {
2938 for (const auto &iter : m_cm_b->m_bounded_ranges_constraints)
2939 {
2940 const equiv_class &ec_rhs = iter.m_ec_id.get_obj (*m_cm_b);
2941 for (unsigned i = 0; i < ec_rhs.m_vars.length (); i++)
2942 {
2943 const svalue *rhs_sval = ec_rhs.m_vars[i];
2944 if (lhs_sval == rhs_sval)
2945 {
2946 /* Union of the two ranges. */
2947 auto_vec <const bounded_ranges *> pair (2);
2948 pair.quick_push (ranges);
2949 pair.quick_push (iter.m_ranges);
2950 bounded_ranges_manager *ranges_mgr
2951 = m_cm_b->get_range_manager ();
2952 const bounded_ranges *union_
2953 = ranges_mgr->get_or_create_union (pair);
2954 bool sat = m_out->add_bounded_ranges (lhs_sval, union_);
2955 gcc_assert (sat);
2956 }
2957 }
2958 }
2959 }
2960
2961 private:
2962 const constraint_manager *m_cm_b;
2963 constraint_manager *m_out;
2964 };
2965
2966 /* Use MERGER to merge CM_A and CM_B into *OUT.
2967 If one thinks of a constraint_manager as a subset of N-dimensional
2968 space, this takes the union of the points of CM_A and CM_B, and
2969 expresses that into *OUT. Alternatively, it can be thought of
2970 as the intersection of the constraints. */
2971
2972 void
merge(const constraint_manager & cm_a,const constraint_manager & cm_b,constraint_manager * out)2973 constraint_manager::merge (const constraint_manager &cm_a,
2974 const constraint_manager &cm_b,
2975 constraint_manager *out)
2976 {
2977 /* Merge the equivalence classes and constraints.
2978 The easiest way to do this seems to be to enumerate all of the facts
2979 in cm_a, see which are also true in cm_b,
2980 and add those to *OUT. */
2981 merger_fact_visitor v (&cm_b, out);
2982 cm_a.for_each_fact (&v);
2983 }
2984
2985 /* Call VISITOR's on_fact vfunc repeatedly to express the various
2986 equivalence classes and constraints.
2987 This is used by constraint_manager::merge to find the common
2988 facts between two input constraint_managers. */
2989
2990 void
for_each_fact(fact_visitor * visitor) const2991 constraint_manager::for_each_fact (fact_visitor *visitor) const
2992 {
2993 /* First, call EQ_EXPR within the various equivalence classes. */
2994 unsigned ec_idx;
2995 equiv_class *ec;
2996 FOR_EACH_VEC_ELT (m_equiv_classes, ec_idx, ec)
2997 {
2998 if (ec->m_cst_sval)
2999 {
3000 unsigned i;
3001 const svalue *sval;
3002 FOR_EACH_VEC_ELT (ec->m_vars, i, sval)
3003 visitor->on_fact (ec->m_cst_sval, EQ_EXPR, sval);
3004 }
3005 for (unsigned i = 0; i < ec->m_vars.length (); i++)
3006 for (unsigned j = i + 1; j < ec->m_vars.length (); j++)
3007 visitor->on_fact (ec->m_vars[i], EQ_EXPR, ec->m_vars[j]);
3008 }
3009
3010 /* Now, express the various constraints. */
3011 unsigned con_idx;
3012 constraint *c;
3013 FOR_EACH_VEC_ELT (m_constraints, con_idx, c)
3014 {
3015 const equiv_class &ec_lhs = c->m_lhs.get_obj (*this);
3016 const equiv_class &ec_rhs = c->m_rhs.get_obj (*this);
3017 enum tree_code code = constraint_tree_code (c->m_op);
3018
3019 if (ec_lhs.m_cst_sval)
3020 {
3021 for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
3022 {
3023 visitor->on_fact (ec_lhs.m_cst_sval, code, ec_rhs.m_vars[j]);
3024 }
3025 }
3026 for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++)
3027 {
3028 if (ec_rhs.m_cst_sval)
3029 visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_cst_sval);
3030 for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
3031 visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_vars[j]);
3032 }
3033 }
3034
3035 for (const auto &iter : m_bounded_ranges_constraints)
3036 {
3037 const equiv_class &ec_lhs = iter.m_ec_id.get_obj (*this);
3038 for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++)
3039 {
3040 const svalue *lhs_sval = ec_lhs.m_vars[i];
3041 visitor->on_ranges (lhs_sval, iter.m_ranges);
3042 }
3043 }
3044 }
3045
3046 /* Assert that this object is valid. */
3047
3048 void
validate() const3049 constraint_manager::validate () const
3050 {
3051 /* Skip this in a release build. */
3052 #if !CHECKING_P
3053 return;
3054 #endif
3055
3056 int i;
3057 equiv_class *ec;
3058 FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
3059 {
3060 gcc_assert (ec);
3061
3062 int j;
3063 const svalue *sval;
3064 FOR_EACH_VEC_ELT (ec->m_vars, j, sval)
3065 gcc_assert (sval);
3066 if (ec->m_constant)
3067 {
3068 gcc_assert (CONSTANT_CLASS_P (ec->m_constant));
3069 gcc_assert (ec->m_cst_sval);
3070 }
3071 #if 0
3072 else
3073 gcc_assert (ec->m_vars.length () > 0);
3074 #endif
3075 }
3076
3077 constraint *c;
3078 FOR_EACH_VEC_ELT (m_constraints, i, c)
3079 {
3080 gcc_assert (!c->m_lhs.null_p ());
3081 gcc_assert (c->m_lhs.as_int () < (int)m_equiv_classes.length ());
3082 gcc_assert (!c->m_rhs.null_p ());
3083 gcc_assert (c->m_rhs.as_int () < (int)m_equiv_classes.length ());
3084 }
3085
3086 for (const auto &iter : m_bounded_ranges_constraints)
3087 {
3088 gcc_assert (!iter.m_ec_id.null_p ());
3089 gcc_assert (iter.m_ec_id.as_int () < (int)m_equiv_classes.length ());
3090 }
3091 }
3092
3093 bounded_ranges_manager *
get_range_manager() const3094 constraint_manager::get_range_manager () const
3095 {
3096 return m_mgr->get_range_manager ();
3097 }
3098
3099 #if CHECKING_P
3100
3101 namespace selftest {
3102
3103 /* Various constraint_manager selftests.
3104 These have to be written in terms of a region_model, since
3105 the latter is responsible for managing svalue instances. */
3106
3107 /* Verify that range::add_bound works as expected. */
3108
3109 static void
test_range()3110 test_range ()
3111 {
3112 tree int_0 = build_int_cst (integer_type_node, 0);
3113 tree int_1 = build_int_cst (integer_type_node, 1);
3114 tree int_2 = build_int_cst (integer_type_node, 2);
3115 tree int_5 = build_int_cst (integer_type_node, 5);
3116
3117 {
3118 range r;
3119 ASSERT_FALSE (r.constrained_to_single_element ());
3120
3121 /* (r >= 1). */
3122 ASSERT_TRUE (r.add_bound (GE_EXPR, int_1));
3123
3124 /* Redundant. */
3125 ASSERT_TRUE (r.add_bound (GE_EXPR, int_0));
3126 ASSERT_TRUE (r.add_bound (GT_EXPR, int_0));
3127
3128 ASSERT_FALSE (r.constrained_to_single_element ());
3129
3130 /* Contradiction. */
3131 ASSERT_FALSE (r.add_bound (LT_EXPR, int_1));
3132
3133 /* (r < 5). */
3134 ASSERT_TRUE (r.add_bound (LT_EXPR, int_5));
3135 ASSERT_FALSE (r.constrained_to_single_element ());
3136
3137 /* Contradiction. */
3138 ASSERT_FALSE (r.add_bound (GE_EXPR, int_5));
3139
3140 /* (r < 2). */
3141 ASSERT_TRUE (r.add_bound (LT_EXPR, int_2));
3142 ASSERT_TRUE (r.constrained_to_single_element ());
3143
3144 /* Redundant. */
3145 ASSERT_TRUE (r.add_bound (LE_EXPR, int_1));
3146 ASSERT_TRUE (r.constrained_to_single_element ());
3147 }
3148 }
3149
3150 /* Verify that setting and getting simple conditions within a region_model
3151 work (thus exercising the underlying constraint_manager). */
3152
3153 static void
test_constraint_conditions()3154 test_constraint_conditions ()
3155 {
3156 tree int_42 = build_int_cst (integer_type_node, 42);
3157 tree int_0 = build_int_cst (integer_type_node, 0);
3158
3159 tree x = build_global_decl ("x", integer_type_node);
3160 tree y = build_global_decl ("y", integer_type_node);
3161 tree z = build_global_decl ("z", integer_type_node);
3162
3163 /* Self-comparisons. */
3164 {
3165 region_model_manager mgr;
3166 region_model model (&mgr);
3167 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, x);
3168 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, x);
3169 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, x);
3170 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, x);
3171 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, x);
3172 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, x);
3173 }
3174
3175 /* Adding self-equality shouldn't add equiv classes. */
3176 {
3177 region_model_manager mgr;
3178 region_model model (&mgr);
3179 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, x);
3180 ADD_SAT_CONSTRAINT (model, int_42, EQ_EXPR, int_42);
3181 /* ...even when done directly via svalues: */
3182 const svalue *sval_int_42 = model.get_rvalue (int_42, NULL);
3183 bool sat = model.get_constraints ()->add_constraint (sval_int_42,
3184 EQ_EXPR,
3185 sval_int_42);
3186 ASSERT_TRUE (sat);
3187 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
3188 }
3189
3190 /* x == y. */
3191 {
3192 region_model_manager mgr;
3193 region_model model (&mgr);
3194 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3195
3196 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3197
3198 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, y);
3199 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3200 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3201 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, y);
3202 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3203 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3204
3205 /* Swapped operands. */
3206 ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x);
3207 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3208 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3209 ASSERT_CONDITION_FALSE (model, y, NE_EXPR, x);
3210 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3211 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3212
3213 /* Comparison with other var. */
3214 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
3215 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
3216 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3217 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
3218 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
3219 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
3220 }
3221
3222 /* x == y, then y == z */
3223 {
3224 region_model_manager mgr;
3225 region_model model (&mgr);
3226 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3227
3228 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3229 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, z);
3230
3231 ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, z);
3232 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, z);
3233 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
3234 ASSERT_CONDITION_FALSE (model, x, NE_EXPR, z);
3235 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, z);
3236 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, z);
3237 }
3238
3239 /* x != y. */
3240 {
3241 region_model_manager mgr;
3242 region_model model (&mgr);
3243
3244 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
3245
3246 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3247 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3248 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
3249 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
3250 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
3251 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
3252
3253 /* Swapped operands. */
3254 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3255 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3256 ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
3257 ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
3258 ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
3259 ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
3260
3261 /* Comparison with other var. */
3262 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
3263 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
3264 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3265 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
3266 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
3267 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
3268 }
3269
3270 /* x < y. */
3271 {
3272 region_model_manager mgr;
3273 region_model model (&mgr);
3274
3275 ADD_SAT_CONSTRAINT (model, x, LT_EXPR, y);
3276
3277 ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
3278 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3279 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3280 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3281 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3282 ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
3283
3284 /* Swapped operands. */
3285 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3286 ASSERT_CONDITION_FALSE (model, y, LE_EXPR, x);
3287 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3288 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3289 ASSERT_CONDITION_TRUE (model, y, GT_EXPR, x);
3290 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3291 }
3292
3293 /* x <= y. */
3294 {
3295 region_model_manager mgr;
3296 region_model model (&mgr);
3297
3298 ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
3299
3300 ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
3301 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3302 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
3303 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3304 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3305 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
3306
3307 /* Swapped operands. */
3308 ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
3309 ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
3310 ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
3311 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
3312 ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
3313 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
3314 }
3315
3316 /* x > y. */
3317 {
3318 region_model_manager mgr;
3319 region_model model (&mgr);
3320
3321 ADD_SAT_CONSTRAINT (model, x, GT_EXPR, y);
3322
3323 ASSERT_CONDITION_TRUE (model, x, GT_EXPR, y);
3324 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3325 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3326 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3327 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3328 ASSERT_CONDITION_FALSE (model, x, LE_EXPR, y);
3329
3330 /* Swapped operands. */
3331 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3332 ASSERT_CONDITION_FALSE (model, y, GE_EXPR, x);
3333 ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
3334 ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
3335 ASSERT_CONDITION_TRUE (model, y, LT_EXPR, x);
3336 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3337 }
3338
3339 /* x >= y. */
3340 {
3341 region_model_manager mgr;
3342 region_model model (&mgr);
3343
3344 ADD_SAT_CONSTRAINT (model, x, GE_EXPR, y);
3345
3346 ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
3347 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
3348 ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
3349 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3350 ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
3351 ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
3352
3353 /* Swapped operands. */
3354 ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
3355 ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
3356 ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
3357 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
3358 ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
3359 ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
3360 }
3361
3362 // TODO: implied orderings
3363
3364 /* Constants. */
3365 {
3366 region_model_manager mgr;
3367 region_model model (&mgr);
3368 ASSERT_CONDITION_FALSE (model, int_0, EQ_EXPR, int_42);
3369 ASSERT_CONDITION_TRUE (model, int_0, NE_EXPR, int_42);
3370 ASSERT_CONDITION_TRUE (model, int_0, LT_EXPR, int_42);
3371 ASSERT_CONDITION_TRUE (model, int_0, LE_EXPR, int_42);
3372 ASSERT_CONDITION_FALSE (model, int_0, GT_EXPR, int_42);
3373 ASSERT_CONDITION_FALSE (model, int_0, GE_EXPR, int_42);
3374 }
3375
3376 /* x == 0, y == 42. */
3377 {
3378 region_model_manager mgr;
3379 region_model model (&mgr);
3380 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3381 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, int_42);
3382
3383 ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
3384 ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
3385 ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
3386 ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
3387 ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
3388 ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
3389 }
3390
3391 /* Unsatisfiable combinations. */
3392
3393 /* x == y && x != y. */
3394 {
3395 region_model_manager mgr;
3396 region_model model (&mgr);
3397 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3398 ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, y);
3399 }
3400
3401 /* x == 0 then x == 42. */
3402 {
3403 region_model_manager mgr;
3404 region_model model (&mgr);
3405 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3406 ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, int_42);
3407 }
3408
3409 /* x == 0 then x != 0. */
3410 {
3411 region_model_manager mgr;
3412 region_model model (&mgr);
3413 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3414 ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, int_0);
3415 }
3416
3417 /* x == 0 then x > 0. */
3418 {
3419 region_model_manager mgr;
3420 region_model model (&mgr);
3421 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3422 ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, int_0);
3423 }
3424
3425 /* x != y && x == y. */
3426 {
3427 region_model_manager mgr;
3428 region_model model (&mgr);
3429 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
3430 ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, y);
3431 }
3432
3433 /* x <= y && x > y. */
3434 {
3435 region_model_manager mgr;
3436 region_model model (&mgr);
3437 ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
3438 ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, y);
3439 }
3440
3441 // etc
3442 }
3443
3444 /* Test transitivity of conditions. */
3445
3446 static void
test_transitivity()3447 test_transitivity ()
3448 {
3449 tree a = build_global_decl ("a", integer_type_node);
3450 tree b = build_global_decl ("b", integer_type_node);
3451 tree c = build_global_decl ("c", integer_type_node);
3452 tree d = build_global_decl ("d", integer_type_node);
3453
3454 /* a == b, then c == d, then c == b. */
3455 {
3456 region_model_manager mgr;
3457 region_model model (&mgr);
3458 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, b);
3459 ASSERT_CONDITION_UNKNOWN (model, b, EQ_EXPR, c);
3460 ASSERT_CONDITION_UNKNOWN (model, c, EQ_EXPR, d);
3461 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
3462
3463 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, b);
3464 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
3465
3466 ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, d);
3467 ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, d);
3468 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
3469
3470 ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, b);
3471 ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, b);
3472 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, d);
3473 }
3474
3475 /* Transitivity: "a < b", "b < c" should imply "a < c". */
3476 {
3477 region_model_manager mgr;
3478 region_model model (&mgr);
3479 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
3480 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3481
3482 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3483 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3484 }
3485
3486 /* Transitivity: "a <= b", "b < c" should imply "a < c". */
3487 {
3488 region_model_manager mgr;
3489 region_model model (&mgr);
3490 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
3491 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3492
3493 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3494 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3495 }
3496
3497 /* Transitivity: "a <= b", "b <= c" should imply "a <= c". */
3498 {
3499 region_model_manager mgr;
3500 region_model model (&mgr);
3501 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
3502 ADD_SAT_CONSTRAINT (model, b, LE_EXPR, c);
3503
3504 ASSERT_CONDITION_TRUE (model, a, LE_EXPR, c);
3505 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
3506 }
3507
3508 /* Transitivity: "a > b", "b > c" should imply "a > c". */
3509 {
3510 region_model_manager mgr;
3511 region_model model (&mgr);
3512 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3513 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3514
3515 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
3516 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3517 }
3518
3519 /* Transitivity: "a >= b", "b > c" should imply " a > c". */
3520 {
3521 region_model_manager mgr;
3522 region_model model (&mgr);
3523 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3524 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3525
3526 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
3527 ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
3528 }
3529
3530 /* Transitivity: "a >= b", "b >= c" should imply "a >= c". */
3531 {
3532 region_model_manager mgr;
3533 region_model model (&mgr);
3534 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3535 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c);
3536
3537 ASSERT_CONDITION_TRUE (model, a, GE_EXPR, c);
3538 ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
3539 }
3540
3541 /* Transitivity: "(a < b)", "(c < d)", "(b < c)" should
3542 imply the easy cases:
3543 (a < c)
3544 (b < d)
3545 but also that:
3546 (a < d). */
3547 {
3548 region_model_manager mgr;
3549 region_model model (&mgr);
3550 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
3551 ADD_SAT_CONSTRAINT (model, c, LT_EXPR, d);
3552 ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
3553
3554 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
3555 ASSERT_CONDITION_TRUE (model, b, LT_EXPR, d);
3556 ASSERT_CONDITION_TRUE (model, a, LT_EXPR, d);
3557 }
3558
3559 /* Transitivity: "a >= b", "b >= a" should imply that a == b. */
3560 {
3561 region_model_manager mgr;
3562 region_model model (&mgr);
3563 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3564 ADD_SAT_CONSTRAINT (model, b, GE_EXPR, a);
3565
3566 // TODO:
3567 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
3568
3569 /* The ECs for a and b should have merged, and any constraints removed. */
3570 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
3571 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
3572 }
3573
3574 /* Transitivity: "a >= b", "b > a" should be impossible. */
3575 {
3576 region_model_manager mgr;
3577 region_model model (&mgr);
3578 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
3579 ADD_UNSAT_CONSTRAINT (model, b, GT_EXPR, a);
3580 }
3581
3582 /* Transitivity: "a >= b", "b >= c", "c >= a" should imply
3583 that a == b == c. */
3584 {
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);
3589 ADD_SAT_CONSTRAINT (model, c, GE_EXPR, a);
3590
3591 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, c);
3592 }
3593
3594 /* Transitivity: "a > b", "b > c", "c > a"
3595 should be impossible. */
3596 {
3597 region_model_manager mgr;
3598 region_model model (&mgr);
3599 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3600 ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
3601 ADD_UNSAT_CONSTRAINT (model, c, GT_EXPR, a);
3602 }
3603
3604 }
3605
3606 /* Test various conditionals involving constants where the results
3607 ought to be implied based on the values of the constants. */
3608
3609 static void
test_constant_comparisons()3610 test_constant_comparisons ()
3611 {
3612 tree int_1 = build_int_cst (integer_type_node, 1);
3613 tree int_3 = build_int_cst (integer_type_node, 3);
3614 tree int_4 = build_int_cst (integer_type_node, 4);
3615 tree int_5 = build_int_cst (integer_type_node, 5);
3616
3617 tree int_1023 = build_int_cst (integer_type_node, 1023);
3618 tree int_1024 = build_int_cst (integer_type_node, 1024);
3619
3620 tree a = build_global_decl ("a", integer_type_node);
3621 tree b = build_global_decl ("b", integer_type_node);
3622
3623 tree a_plus_one = build2 (PLUS_EXPR, integer_type_node, a, int_1);
3624
3625 /* Given a >= 1024, then a <= 1023 should be impossible. */
3626 {
3627 region_model_manager mgr;
3628 region_model model (&mgr);
3629 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_1024);
3630 ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_1023);
3631 }
3632
3633 /* a > 4. */
3634 {
3635 region_model_manager mgr;
3636 region_model model (&mgr);
3637 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_4);
3638 ASSERT_CONDITION_TRUE (model, a, GT_EXPR, int_4);
3639 ASSERT_CONDITION_TRUE (model, a, NE_EXPR, int_3);
3640 ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_5);
3641 }
3642
3643 /* a <= 4. */
3644 {
3645 region_model_manager mgr;
3646 region_model model (&mgr);
3647 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3648 ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_4);
3649 ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_5);
3650 ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_3);
3651 }
3652
3653 /* If "a > b" and "a == 3", then "b == 4" ought to be unsatisfiable. */
3654 {
3655 region_model_manager mgr;
3656 region_model model (&mgr);
3657 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
3658 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_3);
3659 ADD_UNSAT_CONSTRAINT (model, b, EQ_EXPR, int_4);
3660 }
3661
3662 /* Various tests of int ranges where there is only one possible candidate. */
3663 {
3664 /* If "a <= 4" && "a > 3", then "a == 4",
3665 assuming a is of integral type. */
3666 {
3667 region_model_manager mgr;
3668 region_model model (&mgr);
3669 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3670 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3671 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3672 }
3673
3674 /* If "a > 3" && "a <= 4", then "a == 4",
3675 assuming a is of integral type. */
3676 {
3677 region_model_manager mgr;
3678 region_model model (&mgr);
3679 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3680 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3681 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3682 }
3683 /* If "a > 3" && "a < 5", then "a == 4",
3684 assuming a is of integral type. */
3685 {
3686 region_model_manager mgr;
3687 region_model model (&mgr);
3688 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3689 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3690 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3691 }
3692 /* If "a >= 4" && "a < 5", then "a == 4",
3693 assuming a is of integral type. */
3694 {
3695 region_model_manager mgr;
3696 region_model model (&mgr);
3697 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
3698 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3699 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3700 }
3701 /* If "a >= 4" && "a <= 4", then "a == 4". */
3702 {
3703 region_model_manager mgr;
3704 region_model model (&mgr);
3705 ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
3706 ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
3707 ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
3708 }
3709 }
3710
3711 /* As above, but for floating-point:
3712 if "f > 3" && "f <= 4" we don't know that f == 4. */
3713 {
3714 tree f = build_global_decl ("f", double_type_node);
3715 tree float_3 = build_real_from_int_cst (double_type_node, int_3);
3716 tree float_4 = build_real_from_int_cst (double_type_node, int_4);
3717
3718 region_model_manager mgr;
3719 region_model model (&mgr);
3720 ADD_SAT_CONSTRAINT (model, f, GT_EXPR, float_3);
3721 ADD_SAT_CONSTRAINT (model, f, LE_EXPR, float_4);
3722 ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, float_4);
3723 ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, int_4);
3724 }
3725
3726 /* "a > 3 && a <= 3" should be impossible. */
3727 {
3728 region_model_manager mgr;
3729 region_model model (&mgr);
3730 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3731 ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_3);
3732 }
3733
3734 /* "(a + 1) > 3 && a < 3" should be impossible. */
3735 {
3736 region_model_manager mgr;
3737 {
3738 region_model model (&mgr);
3739 ADD_SAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3);
3740 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_3);
3741 }
3742 {
3743 region_model model (&mgr);
3744 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_3);
3745 ADD_UNSAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3);
3746 }
3747 }
3748
3749 /* "3 < a < 4" should be impossible for integer a. */
3750 {
3751 region_model_manager mgr;
3752 {
3753 region_model model (&mgr);
3754 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3755 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3756 }
3757 {
3758 region_model model (&mgr);
3759 ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a);
3760 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3761 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3762 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3763 }
3764 {
3765 region_model model (&mgr);
3766 ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a);
3767 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
3768 ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3769 ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3770 }
3771 {
3772 region_model model (&mgr);
3773 ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_4);
3774 ADD_UNSAT_CONSTRAINT (model, int_3, LT_EXPR, a);
3775 }
3776 {
3777 region_model model (&mgr);
3778 ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3779 ADD_UNSAT_CONSTRAINT (model, int_4, GT_EXPR, a);
3780 }
3781 {
3782 region_model model (&mgr);
3783 ADD_SAT_CONSTRAINT (model, int_4, GT_EXPR, a);
3784 ADD_UNSAT_CONSTRAINT (model, a, GT_EXPR, int_3);
3785 }
3786 }
3787 }
3788
3789 /* Verify various lower-level implementation details about
3790 constraint_manager. */
3791
3792 static void
test_constraint_impl()3793 test_constraint_impl ()
3794 {
3795 tree int_42 = build_int_cst (integer_type_node, 42);
3796 tree int_0 = build_int_cst (integer_type_node, 0);
3797
3798 tree x = build_global_decl ("x", integer_type_node);
3799 tree y = build_global_decl ("y", integer_type_node);
3800 tree z = build_global_decl ("z", integer_type_node);
3801
3802 /* x == y. */
3803 {
3804 region_model_manager mgr;
3805 region_model model (&mgr);
3806
3807 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3808
3809 /* Assert various things about the insides of model. */
3810 constraint_manager *cm = model.get_constraints ();
3811 ASSERT_EQ (cm->m_constraints.length (), 0);
3812 ASSERT_EQ (cm->m_equiv_classes.length (), 1);
3813 }
3814
3815 /* y <= z; x == y. */
3816 {
3817 region_model_manager mgr;
3818 region_model model (&mgr);
3819 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3820 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3821
3822 ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
3823 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
3824 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3825
3826 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
3827
3828 /* Assert various things about the insides of model. */
3829 constraint_manager *cm = model.get_constraints ();
3830 ASSERT_EQ (cm->m_constraints.length (), 1);
3831 ASSERT_EQ (cm->m_equiv_classes.length (), 2);
3832
3833 /* Ensure that we merged the constraints. */
3834 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
3835 }
3836
3837 /* y <= z; y == x. */
3838 {
3839 region_model_manager mgr;
3840 region_model model (&mgr);
3841 ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
3842 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3843
3844 ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
3845 ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
3846 ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
3847
3848 ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, x);
3849
3850 /* Assert various things about the insides of model. */
3851 constraint_manager *cm = model.get_constraints ();
3852 ASSERT_EQ (cm->m_constraints.length (), 1);
3853 ASSERT_EQ (cm->m_equiv_classes.length (), 2);
3854
3855 /* Ensure that we merged the constraints. */
3856 ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
3857 }
3858
3859 /* x == 0, then x != 42. */
3860 {
3861 region_model_manager mgr;
3862 region_model model (&mgr);
3863
3864 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
3865 ADD_SAT_CONSTRAINT (model, x, NE_EXPR, int_42);
3866
3867 /* Assert various things about the insides of model. */
3868 constraint_manager *cm = model.get_constraints ();
3869 ASSERT_EQ (cm->m_constraints.length (), 0);
3870 ASSERT_EQ (cm->m_equiv_classes.length (), 1);
3871 }
3872
3873 // TODO: selftest for merging ecs "in the middle"
3874 // where a non-final one gets overwritten
3875
3876 // TODO: selftest where there are pre-existing constraints
3877 }
3878
3879 /* Check that operator== and hashing works as expected for the
3880 various types. */
3881
3882 static void
test_equality()3883 test_equality ()
3884 {
3885 tree x = build_global_decl ("x", integer_type_node);
3886 tree y = build_global_decl ("y", integer_type_node);
3887
3888 {
3889 region_model_manager mgr;
3890 region_model model0 (&mgr);
3891 region_model model1 (&mgr);
3892
3893 constraint_manager *cm0 = model0.get_constraints ();
3894 constraint_manager *cm1 = model1.get_constraints ();
3895
3896 ASSERT_EQ (cm0->hash (), cm1->hash ());
3897 ASSERT_EQ (*cm0, *cm1);
3898
3899 ASSERT_EQ (model0.hash (), model1.hash ());
3900 ASSERT_EQ (model0, model1);
3901
3902 ADD_SAT_CONSTRAINT (model1, x, EQ_EXPR, y);
3903 ASSERT_NE (cm0->hash (), cm1->hash ());
3904 ASSERT_NE (*cm0, *cm1);
3905
3906 ASSERT_NE (model0.hash (), model1.hash ());
3907 ASSERT_NE (model0, model1);
3908
3909 region_model model2 (&mgr);
3910 constraint_manager *cm2 = model2.get_constraints ();
3911 /* Make the same change to cm2. */
3912 ADD_SAT_CONSTRAINT (model2, x, EQ_EXPR, y);
3913 ASSERT_EQ (cm1->hash (), cm2->hash ());
3914 ASSERT_EQ (*cm1, *cm2);
3915
3916 ASSERT_EQ (model1.hash (), model2.hash ());
3917 ASSERT_EQ (model1, model2);
3918 }
3919 }
3920
3921 /* Verify tracking inequality of a variable against many constants. */
3922
3923 static void
test_many_constants()3924 test_many_constants ()
3925 {
3926 program_point point (program_point::origin ());
3927 tree a = build_global_decl ("a", integer_type_node);
3928
3929 region_model_manager mgr;
3930 region_model model (&mgr);
3931 auto_vec<tree> constants;
3932 for (int i = 0; i < 20; i++)
3933 {
3934 tree constant = build_int_cst (integer_type_node, i);
3935 constants.safe_push (constant);
3936 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, constant);
3937
3938 /* Merge, and check the result. */
3939 region_model other (model);
3940
3941 region_model merged (&mgr);
3942 ASSERT_TRUE (model.can_merge_with_p (other, point, &merged));
3943 model.canonicalize ();
3944 merged.canonicalize ();
3945 ASSERT_EQ (model, merged);
3946
3947 for (int j = 0; j <= i; j++)
3948 ASSERT_CONDITION_TRUE (model, a, NE_EXPR, constants[j]);
3949 }
3950 }
3951
3952 /* Verify that purging state relating to a variable doesn't leave stray
3953 equivalence classes (after canonicalization). */
3954
3955 static void
test_purging(void)3956 test_purging (void)
3957 {
3958 tree int_0 = build_int_cst (integer_type_node, 0);
3959 tree a = build_global_decl ("a", integer_type_node);
3960 tree b = build_global_decl ("b", integer_type_node);
3961
3962 /* "a != 0". */
3963 {
3964 region_model_manager mgr;
3965 region_model model (&mgr);
3966 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
3967 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
3968 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
3969
3970 /* Purge state for "a". */
3971 const svalue *sval_a = model.get_rvalue (a, NULL);
3972 model.purge_state_involving (sval_a, NULL);
3973 model.canonicalize ();
3974 /* We should have an empty constraint_manager. */
3975 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
3976 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
3977 }
3978
3979 /* "a != 0" && "b != 0". */
3980 {
3981 region_model_manager mgr;
3982 region_model model (&mgr);
3983 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
3984 ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
3985 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 3);
3986 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 2);
3987
3988 /* Purge state for "a". */
3989 const svalue *sval_a = model.get_rvalue (a, NULL);
3990 model.purge_state_involving (sval_a, NULL);
3991 model.canonicalize ();
3992 /* We should just have the constraint/ECs involving b != 0. */
3993 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
3994 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
3995 ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
3996 }
3997
3998 /* "a != 0" && "b == 0". */
3999 {
4000 region_model_manager mgr;
4001 region_model model (&mgr);
4002 ADD_SAT_CONSTRAINT (model, a, NE_EXPR, int_0);
4003 ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
4004 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4005 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4006
4007 /* Purge state for "a". */
4008 const svalue *sval_a = model.get_rvalue (a, NULL);
4009 model.purge_state_involving (sval_a, NULL);
4010 model.canonicalize ();
4011 /* We should just have the EC involving b == 0. */
4012 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4013 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4014 ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
4015 }
4016
4017 /* "a == 0". */
4018 {
4019 region_model_manager mgr;
4020 region_model model (&mgr);
4021 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4022 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4023 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4024
4025 /* Purge state for "a". */
4026 const svalue *sval_a = model.get_rvalue (a, NULL);
4027 model.purge_state_involving (sval_a, NULL);
4028 model.canonicalize ();
4029 /* We should have an empty constraint_manager. */
4030 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 0);
4031 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4032 }
4033
4034 /* "a == 0" && "b != 0". */
4035 {
4036 region_model_manager mgr;
4037 region_model model (&mgr);
4038 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4039 ADD_SAT_CONSTRAINT (model, b, NE_EXPR, int_0);
4040 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4041 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4042
4043 /* Purge state for "a". */
4044 const svalue *sval_a = model.get_rvalue (a, NULL);
4045 model.purge_state_involving (sval_a, NULL);
4046 model.canonicalize ();
4047 /* We should just have the constraint/ECs involving b != 0. */
4048 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 2);
4049 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 1);
4050 ASSERT_CONDITION_TRUE (model, b, NE_EXPR, int_0);
4051 }
4052
4053 /* "a == 0" && "b == 0". */
4054 {
4055 region_model_manager mgr;
4056 region_model model (&mgr);
4057 ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_0);
4058 ADD_SAT_CONSTRAINT (model, b, EQ_EXPR, int_0);
4059 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4060 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4061
4062 /* Purge state for "a". */
4063 const svalue *sval_a = model.get_rvalue (a, NULL);
4064 model.purge_state_involving (sval_a, NULL);
4065 model.canonicalize ();
4066 /* We should just have the EC involving b == 0. */
4067 ASSERT_EQ (model.get_constraints ()->m_equiv_classes.length (), 1);
4068 ASSERT_EQ (model.get_constraints ()->m_constraints.length (), 0);
4069 ASSERT_CONDITION_TRUE (model, b, EQ_EXPR, int_0);
4070 }
4071 }
4072
4073 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4074
4075 static void
assert_dump_bounded_range_eq(const location & loc,const bounded_range & range,const char * expected)4076 assert_dump_bounded_range_eq (const location &loc,
4077 const bounded_range &range,
4078 const char *expected)
4079 {
4080 auto_fix_quotes sentinel;
4081 pretty_printer pp;
4082 pp_format_decoder (&pp) = default_tree_printer;
4083 range.dump_to_pp (&pp, false);
4084 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4085 }
4086
4087 /* Assert that BR.dump (false) is EXPECTED. */
4088
4089 #define ASSERT_DUMP_BOUNDED_RANGE_EQ(BR, EXPECTED) \
4090 SELFTEST_BEGIN_STMT \
4091 assert_dump_bounded_range_eq ((SELFTEST_LOCATION), (BR), (EXPECTED)); \
4092 SELFTEST_END_STMT
4093
4094 /* Verify that bounded_range works as expected. */
4095
4096 static void
test_bounded_range()4097 test_bounded_range ()
4098 {
4099 tree u8_0 = build_int_cst (unsigned_char_type_node, 0);
4100 tree u8_1 = build_int_cst (unsigned_char_type_node, 1);
4101 tree u8_64 = build_int_cst (unsigned_char_type_node, 64);
4102 tree u8_128 = build_int_cst (unsigned_char_type_node, 128);
4103 tree u8_255 = build_int_cst (unsigned_char_type_node, 255);
4104
4105 tree s8_0 = build_int_cst (signed_char_type_node, 0);
4106 tree s8_1 = build_int_cst (signed_char_type_node, 1);
4107 tree s8_2 = build_int_cst (signed_char_type_node, 2);
4108
4109 bounded_range br_u8_0 (u8_0, u8_0);
4110 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0, "0");
4111 ASSERT_TRUE (br_u8_0.contains_p (u8_0));
4112 ASSERT_FALSE (br_u8_0.contains_p (u8_1));
4113 ASSERT_TRUE (br_u8_0.contains_p (s8_0));
4114 ASSERT_FALSE (br_u8_0.contains_p (s8_1));
4115
4116 bounded_range br_u8_0_1 (u8_0, u8_1);
4117 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_0_1, "[0, 1]");
4118
4119 bounded_range tmp (NULL_TREE, NULL_TREE);
4120 ASSERT_TRUE (br_u8_0.intersects_p (br_u8_0_1, &tmp));
4121 ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "0");
4122
4123 bounded_range br_u8_64_128 (u8_64, u8_128);
4124 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_64_128, "[64, 128]");
4125
4126 ASSERT_FALSE (br_u8_0.intersects_p (br_u8_64_128, NULL));
4127 ASSERT_FALSE (br_u8_64_128.intersects_p (br_u8_0, NULL));
4128
4129 bounded_range br_u8_128_255 (u8_128, u8_255);
4130 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_u8_128_255, "[128, 255]");
4131 ASSERT_TRUE (br_u8_128_255.intersects_p (br_u8_64_128, &tmp));
4132 ASSERT_DUMP_BOUNDED_RANGE_EQ (tmp, "128");
4133
4134 bounded_range br_s8_2 (s8_2, s8_2);
4135 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2, "2");
4136 bounded_range br_s8_2_u8_255 (s8_2, u8_255);
4137 ASSERT_DUMP_BOUNDED_RANGE_EQ (br_s8_2_u8_255, "[2, 255]");
4138 }
4139
4140 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4141
4142 static void
assert_dump_bounded_ranges_eq(const location & loc,const bounded_ranges * ranges,const char * expected)4143 assert_dump_bounded_ranges_eq (const location &loc,
4144 const bounded_ranges *ranges,
4145 const char *expected)
4146 {
4147 auto_fix_quotes sentinel;
4148 pretty_printer pp;
4149 pp_format_decoder (&pp) = default_tree_printer;
4150 ranges->dump_to_pp (&pp, false);
4151 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4152 }
4153
4154 /* Implementation detail of ASSERT_DUMP_BOUNDED_RANGES_EQ. */
4155
4156 static void
assert_dump_bounded_ranges_eq(const location & loc,const bounded_ranges & ranges,const char * expected)4157 assert_dump_bounded_ranges_eq (const location &loc,
4158 const bounded_ranges &ranges,
4159 const char *expected)
4160 {
4161 auto_fix_quotes sentinel;
4162 pretty_printer pp;
4163 pp_format_decoder (&pp) = default_tree_printer;
4164 ranges.dump_to_pp (&pp, false);
4165 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
4166 }
4167
4168 /* Assert that BRS.dump (false) is EXPECTED. */
4169
4170 #define ASSERT_DUMP_BOUNDED_RANGES_EQ(BRS, EXPECTED) \
4171 SELFTEST_BEGIN_STMT \
4172 assert_dump_bounded_ranges_eq ((SELFTEST_LOCATION), (BRS), (EXPECTED)); \
4173 SELFTEST_END_STMT
4174
4175 /* Verify that the bounded_ranges class works as expected. */
4176
4177 static void
test_bounded_ranges()4178 test_bounded_ranges ()
4179 {
4180 bounded_ranges_manager mgr;
4181
4182 tree ch0 = build_int_cst (unsigned_char_type_node, 0);
4183 tree ch1 = build_int_cst (unsigned_char_type_node, 1);
4184 tree ch2 = build_int_cst (unsigned_char_type_node, 2);
4185 tree ch3 = build_int_cst (unsigned_char_type_node, 3);
4186 tree ch128 = build_int_cst (unsigned_char_type_node, 128);
4187 tree ch129 = build_int_cst (unsigned_char_type_node, 129);
4188 tree ch254 = build_int_cst (unsigned_char_type_node, 254);
4189 tree ch255 = build_int_cst (unsigned_char_type_node, 255);
4190
4191 const bounded_ranges *empty = mgr.get_or_create_empty ();
4192 ASSERT_DUMP_BOUNDED_RANGES_EQ (empty, "{}");
4193
4194 const bounded_ranges *point0 = mgr.get_or_create_point (ch0);
4195 ASSERT_DUMP_BOUNDED_RANGES_EQ (point0, "{0}");
4196
4197 const bounded_ranges *point1 = mgr.get_or_create_point (ch1);
4198 ASSERT_DUMP_BOUNDED_RANGES_EQ (point1, "{1}");
4199
4200 const bounded_ranges *point2 = mgr.get_or_create_point (ch2);
4201 ASSERT_DUMP_BOUNDED_RANGES_EQ (point2, "{2}");
4202
4203 const bounded_ranges *range0_128 = mgr.get_or_create_range (ch0, ch128);
4204 ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_128, "{[0, 128]}");
4205
4206 const bounded_ranges *range0_255 = mgr.get_or_create_range (ch0, ch255);
4207 ASSERT_DUMP_BOUNDED_RANGES_EQ (range0_255, "{[0, 255]}");
4208
4209 ASSERT_FALSE (empty->contain_p (ch0));
4210 ASSERT_FALSE (empty->contain_p (ch1));
4211 ASSERT_FALSE (empty->contain_p (ch255));
4212
4213 ASSERT_TRUE (point0->contain_p (ch0));
4214 ASSERT_FALSE (point0->contain_p (ch1));
4215 ASSERT_FALSE (point0->contain_p (ch255));
4216
4217 ASSERT_FALSE (point1->contain_p (ch0));
4218 ASSERT_TRUE (point1->contain_p (ch1));
4219 ASSERT_FALSE (point0->contain_p (ch255));
4220
4221 ASSERT_TRUE (range0_128->contain_p (ch0));
4222 ASSERT_TRUE (range0_128->contain_p (ch1));
4223 ASSERT_TRUE (range0_128->contain_p (ch128));
4224 ASSERT_FALSE (range0_128->contain_p (ch129));
4225 ASSERT_FALSE (range0_128->contain_p (ch254));
4226 ASSERT_FALSE (range0_128->contain_p (ch255));
4227
4228 const bounded_ranges *inv0_128
4229 = mgr.get_or_create_inverse (range0_128, unsigned_char_type_node);
4230 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv0_128, "{[129, 255]}");
4231
4232 const bounded_ranges *range128_129 = mgr.get_or_create_range (ch128, ch129);
4233 ASSERT_DUMP_BOUNDED_RANGES_EQ (range128_129, "{[128, 129]}");
4234
4235 const bounded_ranges *inv128_129
4236 = mgr.get_or_create_inverse (range128_129, unsigned_char_type_node);
4237 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv128_129, "{[0, 127], [130, 255]}");
4238
4239 /* Intersection. */
4240 {
4241 /* Intersection of disjoint ranges should be empty set. */
4242 const bounded_ranges *intersect0_1
4243 = mgr.get_or_create_intersection (point0, point1);
4244 ASSERT_DUMP_BOUNDED_RANGES_EQ (intersect0_1, "{}");
4245 }
4246
4247 /* Various tests of "union of ranges". */
4248 {
4249 {
4250 /* Touching points should be merged into a range. */
4251 auto_vec <const bounded_ranges *> v;
4252 v.safe_push (point0);
4253 v.safe_push (point1);
4254 const bounded_ranges *union_0_and_1 = mgr.get_or_create_union (v);
4255 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_0_and_1, "{[0, 1]}");
4256 }
4257
4258 {
4259 /* Overlapping and out-of-order. */
4260 auto_vec <const bounded_ranges *> v;
4261 v.safe_push (inv0_128); // {[129, 255]}
4262 v.safe_push (range128_129);
4263 const bounded_ranges *union_129_255_and_128_129
4264 = mgr.get_or_create_union (v);
4265 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_129_255_and_128_129, "{[128, 255]}");
4266 }
4267
4268 {
4269 /* Union of R and inverse(R) should be full range of type. */
4270 auto_vec <const bounded_ranges *> v;
4271 v.safe_push (range128_129);
4272 v.safe_push (inv128_129);
4273 const bounded_ranges *union_ = mgr.get_or_create_union (v);
4274 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{[0, 255]}");
4275 }
4276
4277 /* Union with an endpoint. */
4278 {
4279 const bounded_ranges *range2_to_255
4280 = mgr.get_or_create_range (ch2, ch255);
4281 ASSERT_DUMP_BOUNDED_RANGES_EQ (range2_to_255, "{[2, 255]}");
4282 auto_vec <const bounded_ranges *> v;
4283 v.safe_push (point0);
4284 v.safe_push (point2);
4285 v.safe_push (range2_to_255);
4286 const bounded_ranges *union_ = mgr.get_or_create_union (v);
4287 ASSERT_DUMP_BOUNDED_RANGES_EQ (union_, "{0, [2, 255]}");
4288 }
4289
4290 /* Construct from vector of bounded_range. */
4291 {
4292 auto_vec<bounded_range> v;
4293 v.safe_push (bounded_range (ch2, ch2));
4294 v.safe_push (bounded_range (ch0, ch0));
4295 v.safe_push (bounded_range (ch2, ch255));
4296 bounded_ranges br (v);
4297 ASSERT_DUMP_BOUNDED_RANGES_EQ (&br, "{0, [2, 255]}");
4298 }
4299 }
4300
4301 /* Various tests of "inverse". */
4302 {
4303 {
4304 const bounded_ranges *range_1_to_3 = mgr.get_or_create_range (ch1, ch3);
4305 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_3, "{[1, 3]}");
4306 const bounded_ranges *inv
4307 = mgr.get_or_create_inverse (range_1_to_3, unsigned_char_type_node);
4308 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0, [4, 255]}");
4309 }
4310 {
4311 const bounded_ranges *range_1_to_255
4312 = mgr.get_or_create_range (ch1, ch255);
4313 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_1_to_255, "{[1, 255]}");
4314 const bounded_ranges *inv
4315 = mgr.get_or_create_inverse (range_1_to_255, unsigned_char_type_node);
4316 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{0}");
4317 }
4318 {
4319 const bounded_ranges *range_0_to_254
4320 = mgr.get_or_create_range (ch0, ch254);
4321 ASSERT_DUMP_BOUNDED_RANGES_EQ (range_0_to_254, "{[0, 254]}");
4322 const bounded_ranges *inv
4323 = mgr.get_or_create_inverse (range_0_to_254, unsigned_char_type_node);
4324 ASSERT_DUMP_BOUNDED_RANGES_EQ (inv, "{255}");
4325 }
4326 }
4327
4328 /* "case 'a'-'z': case 'A-Z':" vs "default:", for ASCII. */
4329 {
4330 tree ch65 = build_int_cst (unsigned_char_type_node, 65);
4331 tree ch90 = build_int_cst (unsigned_char_type_node, 90);
4332
4333 tree ch97 = build_int_cst (unsigned_char_type_node, 97);
4334 tree ch122 = build_int_cst (unsigned_char_type_node, 122);
4335
4336 const bounded_ranges *A_to_Z = mgr.get_or_create_range (ch65, ch90);
4337 ASSERT_DUMP_BOUNDED_RANGES_EQ (A_to_Z, "{[65, 90]}");
4338 const bounded_ranges *a_to_z = mgr.get_or_create_range (ch97, ch122);
4339 ASSERT_DUMP_BOUNDED_RANGES_EQ (a_to_z, "{[97, 122]}");
4340 auto_vec <const bounded_ranges *> v;
4341 v.safe_push (A_to_Z);
4342 v.safe_push (a_to_z);
4343 const bounded_ranges *label_ranges = mgr.get_or_create_union (v);
4344 ASSERT_DUMP_BOUNDED_RANGES_EQ (label_ranges, "{[65, 90], [97, 122]}");
4345 const bounded_ranges *default_ranges
4346 = mgr.get_or_create_inverse (label_ranges, unsigned_char_type_node);
4347 ASSERT_DUMP_BOUNDED_RANGES_EQ (default_ranges,
4348 "{[0, 64], [91, 96], [123, 255]}");
4349 }
4350
4351 /* Verify ranges from ops. */
4352 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (EQ_EXPR, ch128),
4353 "{128}");
4354 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch128),
4355 "{[0, 127], [129, 255]}");
4356 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch128),
4357 "{[0, 127]}");
4358 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch128),
4359 "{[0, 128]}");
4360 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch128),
4361 "{[128, 255]}");
4362 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch128),
4363 "{[129, 255]}");
4364 /* Ops at endpoints of type ranges. */
4365 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LE_EXPR, ch0),
4366 "{0}");
4367 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (LT_EXPR, ch0),
4368 "{}");
4369 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch0),
4370 "{[1, 255]}");
4371 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GE_EXPR, ch255),
4372 "{255}");
4373 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (GT_EXPR, ch255),
4374 "{}");
4375 ASSERT_DUMP_BOUNDED_RANGES_EQ (bounded_ranges (NE_EXPR, ch255),
4376 "{[0, 254]}");
4377
4378 /* Verify that instances are consolidated by mgr. */
4379 ASSERT_EQ (mgr.get_or_create_point (ch0),
4380 mgr.get_or_create_point (ch0));
4381 ASSERT_NE (mgr.get_or_create_point (ch0),
4382 mgr.get_or_create_point (ch1));
4383 }
4384
4385 /* Run the selftests in this file, temporarily overriding
4386 flag_analyzer_transitivity with TRANSITIVITY. */
4387
4388 static void
run_constraint_manager_tests(bool transitivity)4389 run_constraint_manager_tests (bool transitivity)
4390 {
4391 int saved_flag_analyzer_transitivity = flag_analyzer_transitivity;
4392 flag_analyzer_transitivity = transitivity;
4393
4394 test_range ();
4395 test_constraint_conditions ();
4396 if (flag_analyzer_transitivity)
4397 {
4398 /* These selftests assume transitivity. */
4399 test_transitivity ();
4400 }
4401 test_constant_comparisons ();
4402 test_constraint_impl ();
4403 test_equality ();
4404 test_many_constants ();
4405 test_purging ();
4406 test_bounded_range ();
4407 test_bounded_ranges ();
4408
4409 flag_analyzer_transitivity = saved_flag_analyzer_transitivity;
4410 }
4411
4412 /* Run all of the selftests within this file. */
4413
4414 void
analyzer_constraint_manager_cc_tests()4415 analyzer_constraint_manager_cc_tests ()
4416 {
4417 /* Run the tests twice: with and without transitivity. */
4418 run_constraint_manager_tests (true);
4419 run_constraint_manager_tests (false);
4420 }
4421
4422 } // namespace selftest
4423
4424 #endif /* CHECKING_P */
4425
4426 } // namespace ana
4427
4428 #endif /* #if ENABLE_ANALYZER */
4429