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