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