1 /* Tracking equivalence classes and constraints at a point on an execution path.
2    Copyright (C) 2019-2020 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 "analyzer/analyzer.h"
35 #include "ordered-hash-map.h"
36 #include "options.h"
37 #include "cgraph.h"
38 #include "cfg.h"
39 #include "digraph.h"
40 #include "analyzer/supergraph.h"
41 #include "sbitmap.h"
42 #include "bitmap.h"
43 #include "tristate.h"
44 #include "analyzer/region-model.h"
45 #include "analyzer/constraint-manager.h"
46 #include "analyzer/analyzer-selftests.h"
47 
48 #if ENABLE_ANALYZER
49 
50 namespace ana {
51 
52 /* One of the end-points of a range.  */
53 
54 struct bound
55 {
boundana::bound56   bound () : m_constant (NULL_TREE), m_closed (false) {}
boundana::bound57   bound (tree constant, bool closed)
58   : m_constant (constant), m_closed (closed) {}
59 
60   void ensure_closed (bool is_upper);
61 
62   const char * get_relation_as_str () const;
63 
64   tree m_constant;
65   bool m_closed;
66 };
67 
68 /* A range of values, used for determining if a value has been
69    constrained to just one possible constant value.  */
70 
71 struct range
72 {
rangeana::range73   range () : m_lower_bound (), m_upper_bound () {}
rangeana::range74   range (const bound &lower, const bound &upper)
75   : m_lower_bound (lower), m_upper_bound (upper) {}
76 
77   void dump (pretty_printer *pp) const;
78 
79   bool constrained_to_single_element (tree *out);
80 
81   bound m_lower_bound;
82   bound m_upper_bound;
83 };
84 
85 /* struct bound.  */
86 
87 /* Ensure that this bound is closed by converting an open bound to a
88    closed one.  */
89 
90 void
ensure_closed(bool is_upper)91 bound::ensure_closed (bool is_upper)
92 {
93   if (!m_closed)
94     {
95       /* Offset by 1 in the appropriate direction.
96 	 For example, convert 3 < x into 4 <= x,
97 	 and convert x < 5 into x <= 4.  */
98       gcc_assert (CONSTANT_CLASS_P (m_constant));
99       m_constant = fold_build2 (is_upper ? MINUS_EXPR : PLUS_EXPR,
100 				TREE_TYPE (m_constant),
101 				m_constant, integer_one_node);
102       gcc_assert (CONSTANT_CLASS_P (m_constant));
103       m_closed = true;
104     }
105 }
106 
107 /* Get "<=" vs "<" for this bound.  */
108 
109 const char *
get_relation_as_str() const110 bound::get_relation_as_str () const
111 {
112   if (m_closed)
113     return "<=";
114   else
115     return "<";
116 }
117 
118 /* struct range.  */
119 
120 /* Dump this range to PP, which must support %E for tree.  */
121 
122 void
dump(pretty_printer * pp) const123 range::dump (pretty_printer *pp) const
124 {
125   pp_printf (pp, "%qE %s x %s %qE",
126 	     m_lower_bound.m_constant,
127 	     m_lower_bound.get_relation_as_str (),
128 	     m_upper_bound.get_relation_as_str (),
129 	     m_upper_bound.m_constant);
130 }
131 
132 /* Determine if there is only one possible value for this range.
133    If so, return true and write the constant to *OUT.
134    Otherwise, return false.  */
135 
136 bool
constrained_to_single_element(tree * out)137 range::constrained_to_single_element (tree *out)
138 {
139   if (!INTEGRAL_TYPE_P (TREE_TYPE (m_lower_bound.m_constant)))
140     return false;
141   if (!INTEGRAL_TYPE_P (TREE_TYPE (m_upper_bound.m_constant)))
142     return false;
143 
144   /* Convert any open bounds to closed bounds.  */
145   m_lower_bound.ensure_closed (false);
146   m_upper_bound.ensure_closed (true);
147 
148   // Are they equal?
149   tree comparison = fold_binary (EQ_EXPR, boolean_type_node,
150 				 m_lower_bound.m_constant,
151 				 m_upper_bound.m_constant);
152   if (comparison == boolean_true_node)
153     {
154       *out = m_lower_bound.m_constant;
155       return true;
156     }
157   else
158     return false;
159 }
160 
161 /* class equiv_class.  */
162 
163 /* equiv_class's default ctor.  */
164 
equiv_class()165 equiv_class::equiv_class ()
166 : m_constant (NULL_TREE), m_cst_sid (svalue_id::null ()),
167   m_vars ()
168 {
169 }
170 
171 /* equiv_class's copy ctor.  */
172 
equiv_class(const equiv_class & other)173 equiv_class::equiv_class (const equiv_class &other)
174 : m_constant (other.m_constant), m_cst_sid (other.m_cst_sid),
175   m_vars (other.m_vars.length ())
176 {
177   int i;
178   svalue_id *sid;
179   FOR_EACH_VEC_ELT (other.m_vars, i, sid)
180     m_vars.quick_push (*sid);
181 }
182 
183 /* Print an all-on-one-line representation of this equiv_class to PP,
184    which must support %E for trees.  */
185 
186 void
print(pretty_printer * pp) const187 equiv_class::print (pretty_printer *pp) const
188 {
189   pp_character (pp, '{');
190   int i;
191   svalue_id *sid;
192   FOR_EACH_VEC_ELT (m_vars, i, sid)
193     {
194       if (i > 0)
195 	pp_string (pp, " == ");
196       sid->print (pp);
197     }
198   if (m_constant)
199     {
200       if (i > 0)
201 	pp_string (pp, " == ");
202       pp_printf (pp, "%qE", m_constant);
203     }
204   pp_character (pp, '}');
205 }
206 
207 /* Generate a hash value for this equiv_class.  */
208 
209 hashval_t
hash() const210 equiv_class::hash () const
211 {
212   inchash::hash hstate;
213   int i;
214   svalue_id *sid;
215 
216   inchash::add_expr (m_constant, hstate);
217   FOR_EACH_VEC_ELT (m_vars, i, sid)
218     inchash::add (*sid, hstate);
219   return hstate.end ();
220 }
221 
222 /* Equality operator for equiv_class.  */
223 
224 bool
operator ==(const equiv_class & other)225 equiv_class::operator== (const equiv_class &other)
226 {
227   if (m_constant != other.m_constant)
228     return false; // TODO: use tree equality here?
229 
230   /* FIXME: should we compare m_cst_sid?  */
231 
232   if (m_vars.length () != other.m_vars.length ())
233     return false;
234 
235   int i;
236   svalue_id *sid;
237   FOR_EACH_VEC_ELT (m_vars, i, sid)
238     if (! (*sid == other.m_vars[i]))
239       return false;
240 
241   return true;
242 }
243 
244 /* Add SID to this equiv_class, using CM to check if it's a constant.  */
245 
246 void
add(svalue_id sid,const constraint_manager & cm)247 equiv_class::add (svalue_id sid, const constraint_manager &cm)
248 {
249   gcc_assert (!sid.null_p ());
250   if (tree cst = cm.maybe_get_constant (sid))
251     {
252       gcc_assert (CONSTANT_CLASS_P (cst));
253       /* FIXME: should we canonicalize which svalue is the constant
254 	 when there are multiple equal constants?  */
255       m_constant = cst;
256       m_cst_sid = sid;
257     }
258   m_vars.safe_push (sid);
259 }
260 
261 /* Remove SID from this equivalence class.
262    Return true if SID was the last var in the equivalence class (suggesting
263    a possible leak).  */
264 
265 bool
del(svalue_id sid)266 equiv_class::del (svalue_id sid)
267 {
268   gcc_assert (!sid.null_p ());
269   gcc_assert (sid != m_cst_sid);
270 
271   int i;
272   svalue_id *iv;
273   FOR_EACH_VEC_ELT (m_vars, i, iv)
274     {
275       if (*iv == sid)
276 	{
277 	  m_vars[i] = m_vars[m_vars.length () - 1];
278 	  m_vars.pop ();
279 	  return m_vars.length () == 0;
280 	}
281     }
282 
283   /* SID must be in the class.  */
284   gcc_unreachable ();
285   return false;
286 }
287 
288 /* Get a representative member of this class, for handling cases
289    where the IDs can change mid-traversal.  */
290 
291 svalue_id
get_representative() const292 equiv_class::get_representative () const
293 {
294   if (!m_cst_sid.null_p ())
295     return m_cst_sid;
296   else
297     {
298       gcc_assert (m_vars.length () > 0);
299       return m_vars[0];
300     }
301 }
302 
303 /* Remap all svalue_ids within this equiv_class using MAP.  */
304 
305 void
remap_svalue_ids(const svalue_id_map & map)306 equiv_class::remap_svalue_ids (const svalue_id_map &map)
307 {
308   int i;
309   svalue_id *iv;
310   FOR_EACH_VEC_ELT (m_vars, i, iv)
311     map.update (iv);
312   map.update (&m_cst_sid);
313 }
314 
315 /* Comparator for use by equiv_class::canonicalize.  */
316 
317 static int
svalue_id_cmp_by_id(const void * p1,const void * p2)318 svalue_id_cmp_by_id (const void *p1, const void *p2)
319 {
320   const svalue_id *sid1 = (const svalue_id *)p1;
321   const svalue_id *sid2 = (const svalue_id *)p2;
322   return sid1->as_int () - sid2->as_int ();
323 }
324 
325 /* Sort the svalues_ids within this equiv_class.  */
326 
327 void
canonicalize()328 equiv_class::canonicalize ()
329 {
330   m_vars.qsort (svalue_id_cmp_by_id);
331 }
332 
333 /* Get a debug string for C_OP.  */
334 
335 const char *
constraint_op_code(enum constraint_op c_op)336 constraint_op_code (enum constraint_op c_op)
337 {
338   switch (c_op)
339     {
340     default:
341       gcc_unreachable ();
342     case CONSTRAINT_NE: return "!=";
343     case CONSTRAINT_LT: return "<";
344     case CONSTRAINT_LE: return "<=";
345     }
346 }
347 
348 /* Convert C_OP to an enum tree_code.  */
349 
350 enum tree_code
constraint_tree_code(enum constraint_op c_op)351 constraint_tree_code (enum constraint_op c_op)
352 {
353   switch (c_op)
354     {
355     default:
356       gcc_unreachable ();
357     case CONSTRAINT_NE: return NE_EXPR;
358     case CONSTRAINT_LT: return LT_EXPR;
359     case CONSTRAINT_LE: return LE_EXPR;
360     }
361 }
362 
363 /* Given "lhs C_OP rhs", determine "lhs T_OP rhs".
364 
365    For example, given "x < y", then "x > y" is false.  */
366 
367 static tristate
eval_constraint_op_for_op(enum constraint_op c_op,enum tree_code t_op)368 eval_constraint_op_for_op (enum constraint_op c_op, enum tree_code t_op)
369 {
370   switch (c_op)
371     {
372     default:
373       gcc_unreachable ();
374     case CONSTRAINT_NE:
375       if (t_op == EQ_EXPR)
376 	return tristate (tristate::TS_FALSE);
377       if (t_op == NE_EXPR)
378 	return tristate (tristate::TS_TRUE);
379       break;
380     case CONSTRAINT_LT:
381       if (t_op == LT_EXPR || t_op == LE_EXPR || t_op == NE_EXPR)
382 	return tristate (tristate::TS_TRUE);
383       if (t_op == EQ_EXPR || t_op == GT_EXPR || t_op == GE_EXPR)
384 	return tristate (tristate::TS_FALSE);
385       break;
386     case CONSTRAINT_LE:
387       if (t_op == LE_EXPR)
388 	return tristate (tristate::TS_TRUE);
389       if (t_op == GT_EXPR)
390 	return tristate (tristate::TS_FALSE);
391       break;
392     }
393   return tristate (tristate::TS_UNKNOWN);
394 }
395 
396 /* class constraint.  */
397 
398 /* Print this constraint to PP (which must support %E for trees),
399    using CM to look up equiv_class instances from ids.  */
400 
401 void
print(pretty_printer * pp,const constraint_manager & cm) const402 constraint::print (pretty_printer *pp, const constraint_manager &cm) const
403 {
404   m_lhs.print (pp);
405   pp_string (pp, ": ");
406   m_lhs.get_obj (cm).print (pp);
407   pp_string (pp, " ");
408   pp_string (pp, constraint_op_code (m_op));
409   pp_string (pp, " ");
410   m_rhs.print (pp);
411   pp_string (pp, ": ");
412   m_rhs.get_obj (cm).print (pp);
413 }
414 
415 /* Generate a hash value for this constraint.  */
416 
417 hashval_t
hash() const418 constraint::hash () const
419 {
420   inchash::hash hstate;
421   hstate.add_int (m_lhs.m_idx);
422   hstate.add_int (m_op);
423   hstate.add_int (m_rhs.m_idx);
424   return hstate.end ();
425 }
426 
427 /* Equality operator for constraints.  */
428 
429 bool
operator ==(const constraint & other) const430 constraint::operator== (const constraint &other) const
431 {
432   if (m_lhs != other.m_lhs)
433     return false;
434   if (m_op != other.m_op)
435     return false;
436   if (m_rhs != other.m_rhs)
437     return false;
438   return true;
439 }
440 
441 /* class equiv_class_id.  */
442 
443 /* Get the underlying equiv_class for this ID from CM.  */
444 
445 const equiv_class &
get_obj(const constraint_manager & cm) const446 equiv_class_id::get_obj (const constraint_manager &cm) const
447 {
448   return cm.get_equiv_class_by_index (m_idx);
449 }
450 
451 /* Access the underlying equiv_class for this ID from CM.  */
452 
453 equiv_class &
get_obj(constraint_manager & cm) const454 equiv_class_id::get_obj (constraint_manager &cm) const
455 {
456   return cm.get_equiv_class_by_index (m_idx);
457 }
458 
459 /* Print this equiv_class_id to PP.  */
460 
461 void
print(pretty_printer * pp) const462 equiv_class_id::print (pretty_printer *pp) const
463 {
464   if (null_p ())
465     pp_printf (pp, "null");
466   else
467     pp_printf (pp, "ec%i", m_idx);
468 }
469 
470 /* class constraint_manager.  */
471 
472 /* constraint_manager's copy ctor.  */
473 
constraint_manager(const constraint_manager & other)474 constraint_manager::constraint_manager (const constraint_manager &other)
475 : m_equiv_classes (other.m_equiv_classes.length ()),
476   m_constraints (other.m_constraints.length ())
477 {
478   int i;
479   equiv_class *ec;
480   FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
481     m_equiv_classes.quick_push (new equiv_class (*ec));
482   constraint *c;
483   FOR_EACH_VEC_ELT (other.m_constraints, i, c)
484     m_constraints.quick_push (*c);
485 }
486 
487 /* constraint_manager's assignment operator.  */
488 
489 constraint_manager&
operator =(const constraint_manager & other)490 constraint_manager::operator= (const constraint_manager &other)
491 {
492   gcc_assert (m_equiv_classes.length () == 0);
493   gcc_assert (m_constraints.length () == 0);
494 
495   int i;
496   equiv_class *ec;
497   m_equiv_classes.reserve (other.m_equiv_classes.length ());
498   FOR_EACH_VEC_ELT (other.m_equiv_classes, i, ec)
499     m_equiv_classes.quick_push (new equiv_class (*ec));
500   constraint *c;
501   m_constraints.reserve (other.m_constraints.length ());
502   FOR_EACH_VEC_ELT (other.m_constraints, i, c)
503     m_constraints.quick_push (*c);
504 
505   return *this;
506 }
507 
508 /* Generate a hash value for this constraint_manager.  */
509 
510 hashval_t
hash() const511 constraint_manager::hash () const
512 {
513   inchash::hash hstate;
514   int i;
515   equiv_class *ec;
516   constraint *c;
517 
518   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
519     hstate.merge_hash (ec->hash ());
520   FOR_EACH_VEC_ELT (m_constraints, i, c)
521     hstate.merge_hash (c->hash ());
522   return hstate.end ();
523 }
524 
525 /* Equality operator for constraint_manager.  */
526 
527 bool
operator ==(const constraint_manager & other) const528 constraint_manager::operator== (const constraint_manager &other) const
529 {
530   if (m_equiv_classes.length () != other.m_equiv_classes.length ())
531     return false;
532   if (m_constraints.length () != other.m_constraints.length ())
533     return false;
534 
535   int i;
536   equiv_class *ec;
537 
538   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
539     if (!(*ec == *other.m_equiv_classes[i]))
540       return false;
541 
542   constraint *c;
543 
544   FOR_EACH_VEC_ELT (m_constraints, i, c)
545     if (!(*c == other.m_constraints[i]))
546       return false;
547 
548   return true;
549 }
550 
551 /* Print this constraint_manager to PP (which must support %E for trees).  */
552 
553 void
print(pretty_printer * pp) const554 constraint_manager::print (pretty_printer *pp) const
555 {
556   pp_string (pp, "{");
557   int i;
558   equiv_class *ec;
559   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
560     {
561       if (i > 0)
562 	pp_string (pp, ", ");
563       equiv_class_id (i).print (pp);
564       pp_string (pp, ": ");
565       ec->print (pp);
566     }
567   pp_string (pp, "  |  ");
568   constraint *c;
569   FOR_EACH_VEC_ELT (m_constraints, i, c)
570     {
571       if (i > 0)
572 	pp_string (pp, " && ");
573       c->print (pp, *this);
574     }
575   pp_printf (pp, "}");
576 }
577 
578 /* Dump a multiline representation of this constraint_manager to PP
579    (which must support %E for trees).  */
580 
581 void
dump_to_pp(pretty_printer * pp) const582 constraint_manager::dump_to_pp (pretty_printer *pp) const
583 {
584   // TODO
585   pp_string (pp, "  equiv classes:");
586   pp_newline (pp);
587   int i;
588   equiv_class *ec;
589   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
590     {
591       pp_string (pp, "    ");
592       equiv_class_id (i).print (pp);
593       pp_string (pp, ": ");
594       ec->print (pp);
595       pp_newline (pp);
596     }
597   pp_string (pp, "  constraints:");
598   pp_newline (pp);
599   constraint *c;
600   FOR_EACH_VEC_ELT (m_constraints, i, c)
601     {
602       pp_printf (pp, "    %i: ", i);
603       c->print (pp, *this);
604       pp_newline (pp);
605     }
606 }
607 
608 /* Dump a multiline representation of this constraint_manager to FP.  */
609 
610 void
dump(FILE * fp) const611 constraint_manager::dump (FILE *fp) const
612 {
613   pretty_printer pp;
614   pp_format_decoder (&pp) = default_tree_printer;
615   pp_show_color (&pp) = pp_show_color (global_dc->printer);
616   pp.buffer->stream = fp;
617   dump_to_pp (&pp);
618   pp_flush (&pp);
619 }
620 
621 /* Dump a multiline representation of this constraint_manager to stderr.  */
622 
623 DEBUG_FUNCTION void
dump() const624 constraint_manager::dump () const
625 {
626   dump (stderr);
627 }
628 
629 /* Dump a multiline representation of CM to stderr.  */
630 
631 DEBUG_FUNCTION void
debug(const constraint_manager & cm)632 debug (const constraint_manager &cm)
633 {
634   cm.dump ();
635 }
636 
637 /* Attempt to add the constraint LHS OP RHS to this constraint_manager.
638    Return true if the constraint could be added (or is already true).
639    Return false if the constraint contradicts existing knowledge.  */
640 
641 bool
add_constraint(svalue_id lhs,enum tree_code op,svalue_id rhs)642 constraint_manager::add_constraint (svalue_id lhs,
643 				    enum tree_code op,
644 				    svalue_id rhs)
645 {
646   equiv_class_id lhs_ec_id = get_or_add_equiv_class (lhs);
647   equiv_class_id rhs_ec_id = get_or_add_equiv_class (rhs);
648   return add_constraint (lhs_ec_id, op,rhs_ec_id);
649 }
650 
651 /* Attempt to add the constraint LHS_EC_ID OP RHS_EC_ID to this
652    constraint_manager.
653    Return true if the constraint could be added (or is already true).
654    Return false if the constraint contradicts existing knowledge.  */
655 
656 bool
add_constraint(equiv_class_id lhs_ec_id,enum tree_code op,equiv_class_id rhs_ec_id)657 constraint_manager::add_constraint (equiv_class_id lhs_ec_id,
658 				    enum tree_code op,
659 				    equiv_class_id rhs_ec_id)
660 {
661   tristate t = eval_condition (lhs_ec_id, op, rhs_ec_id);
662 
663   /* Discard constraints that are already known.  */
664   if (t.is_true ())
665     return true;
666 
667   /* Reject unsatisfiable constraints.  */
668   if (t.is_false ())
669     return false;
670 
671   gcc_assert (lhs_ec_id != rhs_ec_id);
672 
673   /* For now, simply accumulate constraints, without attempting any further
674      optimization.  */
675   switch (op)
676     {
677     case EQ_EXPR:
678       {
679 	/* Merge rhs_ec into lhs_ec.  */
680 	equiv_class &lhs_ec_obj = lhs_ec_id.get_obj (*this);
681 	const equiv_class &rhs_ec_obj = rhs_ec_id.get_obj (*this);
682 
683 	int i;
684 	svalue_id *sid;
685 	FOR_EACH_VEC_ELT (rhs_ec_obj.m_vars, i, sid)
686 	  lhs_ec_obj.add (*sid, *this);
687 
688 	if (rhs_ec_obj.m_constant)
689 	  {
690 	    lhs_ec_obj.m_constant = rhs_ec_obj.m_constant;
691 	    lhs_ec_obj.m_cst_sid = rhs_ec_obj.m_cst_sid;
692 	  }
693 
694 	/* Drop rhs equivalence class, overwriting it with the
695 	   final ec (which might be the same one).  */
696 	equiv_class_id final_ec_id = m_equiv_classes.length () - 1;
697 	equiv_class *old_ec = m_equiv_classes[rhs_ec_id.m_idx];
698 	equiv_class *final_ec = m_equiv_classes.pop ();
699 	if (final_ec != old_ec)
700 	  m_equiv_classes[rhs_ec_id.m_idx] = final_ec;
701 	delete old_ec;
702 
703 	/* Update the constraints.  */
704 	constraint *c;
705 	FOR_EACH_VEC_ELT (m_constraints, i, c)
706 	  {
707 	    /* Update references to the rhs_ec so that
708 	       they refer to the lhs_ec.  */
709 	    if (c->m_lhs == rhs_ec_id)
710 	      c->m_lhs = lhs_ec_id;
711 	    if (c->m_rhs == rhs_ec_id)
712 	      c->m_rhs = lhs_ec_id;
713 
714 	    /* Renumber all constraints that refer to the final rhs_ec
715 	       to the old rhs_ec, where the old final_ec now lives.  */
716 	    if (c->m_lhs == final_ec_id)
717 	      c->m_lhs = rhs_ec_id;
718 	    if (c->m_rhs == final_ec_id)
719 	      c->m_rhs = rhs_ec_id;
720 	  }
721       }
722       break;
723     case GE_EXPR:
724       add_constraint_internal (rhs_ec_id, CONSTRAINT_LE, lhs_ec_id);
725       break;
726     case LE_EXPR:
727       add_constraint_internal (lhs_ec_id, CONSTRAINT_LE, rhs_ec_id);
728       break;
729     case NE_EXPR:
730       add_constraint_internal (lhs_ec_id, CONSTRAINT_NE, rhs_ec_id);
731       break;
732     case GT_EXPR:
733       add_constraint_internal (rhs_ec_id, CONSTRAINT_LT, lhs_ec_id);
734       break;
735     case LT_EXPR:
736       add_constraint_internal (lhs_ec_id, CONSTRAINT_LT, rhs_ec_id);
737       break;
738     default:
739       /* do nothing.  */
740       break;
741     }
742   validate ();
743   return true;
744 }
745 
746 /* Subroutine of constraint_manager::add_constraint, for handling all
747    operations other than equality (for which equiv classes are merged).  */
748 
749 void
add_constraint_internal(equiv_class_id lhs_id,enum constraint_op c_op,equiv_class_id rhs_id)750 constraint_manager::add_constraint_internal (equiv_class_id lhs_id,
751 					     enum constraint_op c_op,
752 					     equiv_class_id rhs_id)
753 {
754   /* Add the constraint.  */
755   m_constraints.safe_push (constraint (lhs_id, c_op, rhs_id));
756 
757   if (!flag_analyzer_transitivity)
758     return;
759 
760   if (c_op != CONSTRAINT_NE)
761     {
762       /* The following can potentially add EQ_EXPR facts, which could lead
763 	 to ECs being merged, which would change the meaning of the EC IDs.
764 	 Hence we need to do this via representatives.  */
765       svalue_id lhs = lhs_id.get_obj (*this).get_representative ();
766       svalue_id rhs = rhs_id.get_obj (*this).get_representative ();
767 
768       /* We have LHS </<= RHS */
769 
770       /* Handle transitivity of ordering by adding additional constraints
771 	 based on what we already knew.
772 
773 	 So if we have already have:
774 	   (a < b)
775 	   (c < d)
776 	 Then adding:
777 	   (b < c)
778 	 will also add:
779 	   (a < c)
780 	   (b < d)
781 	 We need to recurse to ensure we also add:
782 	   (a < d).
783 	 We call the checked add_constraint to avoid adding constraints
784 	 that are already present.  Doing so also ensures termination
785 	 in the case of cycles.
786 
787 	 We also check for single-element ranges, adding EQ_EXPR facts
788 	 where we discover them.  For example 3 < x < 5 implies
789 	 that x == 4 (if x is an integer).  */
790       for (unsigned i = 0; i < m_constraints.length (); i++)
791 	{
792 	  const constraint *other = &m_constraints[i];
793 	  if (other->is_ordering_p ())
794 	    {
795 	      /* Refresh the EC IDs, in case any mergers have happened.  */
796 	      lhs_id = get_or_add_equiv_class (lhs);
797 	      rhs_id = get_or_add_equiv_class (rhs);
798 
799 	      tree lhs_const = lhs_id.get_obj (*this).m_constant;
800 	      tree rhs_const = rhs_id.get_obj (*this).m_constant;
801 	      tree other_lhs_const
802 		= other->m_lhs.get_obj (*this).m_constant;
803 	      tree other_rhs_const
804 		= other->m_rhs.get_obj (*this).m_constant;
805 
806 	      /* We have "LHS </<= RHS" and "other.lhs </<= other.rhs".  */
807 
808 	      /* If we have LHS </<= RHS and RHS </<= LHS, then we have a
809 		 cycle.  */
810 	      if (rhs_id == other->m_lhs
811 		  && other->m_rhs == lhs_id)
812 		{
813 		  /* We must have equality for this to be possible.  */
814 		  gcc_assert (c_op == CONSTRAINT_LE
815 			      && other->m_op == CONSTRAINT_LE);
816 		  add_constraint (lhs_id, EQ_EXPR, rhs_id);
817 		  /* Adding an equality will merge the two ECs and potentially
818 		     reorganize the constraints.  Stop iterating.  */
819 		  return;
820 		}
821 	      /* Otherwise, check for transitivity.  */
822 	      if (rhs_id == other->m_lhs)
823 		{
824 		  /* With RHS == other.lhs, we have:
825 		     "LHS </<= (RHS, other.lhs) </<= other.rhs"
826 		     and thus this implies "LHS </<= other.rhs".  */
827 
828 		  /* Do we have a tightly-constrained range?  */
829 		  if (lhs_const
830 		      && !rhs_const
831 		      && other_rhs_const)
832 		    {
833 		      range r (bound (lhs_const, c_op == CONSTRAINT_LE),
834 			       bound (other_rhs_const,
835 				      other->m_op == CONSTRAINT_LE));
836 		      tree constant;
837 		      if (r.constrained_to_single_element (&constant))
838 			{
839 			  svalue_id cst_sid = get_sid_for_constant (constant);
840 			  add_constraint
841 			    (rhs_id, EQ_EXPR,
842 			     get_or_add_equiv_class (cst_sid));
843 			  return;
844 			}
845 		    }
846 
847 		  /* Otherwise, add the constraint implied by transitivity.  */
848 		  enum tree_code new_op
849 		    = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
850 		       ? LE_EXPR : LT_EXPR);
851 		  add_constraint (lhs_id, new_op, other->m_rhs);
852 		}
853 	      else if (other->m_rhs == lhs_id)
854 		{
855 		  /* With other.rhs == LHS, we have:
856 		     "other.lhs </<= (other.rhs, LHS) </<= RHS"
857 		     and thus this implies "other.lhs </<= RHS".  */
858 
859 		  /* Do we have a tightly-constrained range?  */
860 		  if (other_lhs_const
861 		      && !lhs_const
862 		      && rhs_const)
863 		    {
864 		      range r (bound (other_lhs_const,
865 				      other->m_op == CONSTRAINT_LE),
866 			       bound (rhs_const,
867 				      c_op == CONSTRAINT_LE));
868 		      tree constant;
869 		      if (r.constrained_to_single_element (&constant))
870 			{
871 			  svalue_id cst_sid = get_sid_for_constant (constant);
872 			  add_constraint
873 			    (lhs_id, EQ_EXPR,
874 			     get_or_add_equiv_class (cst_sid));
875 			  return;
876 			}
877 		    }
878 
879 		  /* Otherwise, add the constraint implied by transitivity.  */
880 		  enum tree_code new_op
881 		    = ((c_op == CONSTRAINT_LE && other->m_op == CONSTRAINT_LE)
882 		       ? LE_EXPR : LT_EXPR);
883 		  add_constraint (other->m_lhs, new_op, rhs_id);
884 		}
885 	    }
886 	}
887     }
888 }
889 
890 /* Look for SID within the equivalence classes of this constraint_manager;
891    if found, write the id to *OUT and return true, otherwise return false.  */
892 
893 bool
get_equiv_class_by_sid(svalue_id sid,equiv_class_id * out) const894 constraint_manager::get_equiv_class_by_sid (svalue_id sid, equiv_class_id *out) const
895 {
896   /* TODO: should we have a map, rather than these searches?  */
897   int i;
898   equiv_class *ec;
899   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
900     {
901       int j;
902       svalue_id *iv;
903       FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
904 	if (*iv == sid)
905 	  {
906 	    *out = equiv_class_id (i);
907 	    return true;
908 	  }
909     }
910   return false;
911 }
912 
913 /* Ensure that SID has an equivalence class within this constraint_manager;
914    return the ID of the class.  */
915 
916 equiv_class_id
get_or_add_equiv_class(svalue_id sid)917 constraint_manager::get_or_add_equiv_class (svalue_id sid)
918 {
919   equiv_class_id result (-1);
920 
921   /* Try svalue_id match.  */
922   if (get_equiv_class_by_sid (sid, &result))
923     return result;
924 
925   /* Try equality of constants.  */
926   if (tree cst = maybe_get_constant (sid))
927     {
928       int i;
929       equiv_class *ec;
930       FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
931 	if (ec->m_constant
932 	    && types_compatible_p (TREE_TYPE (cst),
933 				   TREE_TYPE (ec->m_constant)))
934 	  {
935 	    tree eq = fold_binary (EQ_EXPR, boolean_type_node,
936 				   cst, ec->m_constant);
937 	    if (eq == boolean_true_node)
938 	      {
939 		ec->add (sid, *this);
940 		return equiv_class_id (i);
941 	      }
942 	  }
943     }
944 
945 
946   /* Not found.  */
947   equiv_class *new_ec = new equiv_class ();
948   new_ec->add (sid, *this);
949   m_equiv_classes.safe_push (new_ec);
950 
951   equiv_class_id new_id (m_equiv_classes.length () - 1);
952 
953   if (maybe_get_constant (sid))
954     {
955       /* If we have a new EC for a constant, add constraints comparing this
956 	 to other constants we may have (so that we accumulate the transitive
957 	 closure of all constraints on constants as the constants are
958 	 added).  */
959       for (equiv_class_id other_id (0); other_id.m_idx < new_id.m_idx;
960 	   other_id.m_idx++)
961 	{
962 	  const equiv_class &other_ec = other_id.get_obj (*this);
963 	  if (other_ec.m_constant
964 	      && types_compatible_p (TREE_TYPE (new_ec->m_constant),
965 				     TREE_TYPE (other_ec.m_constant)))
966 	    {
967 	      /* If we have two ECs, both with constants, the constants must be
968 		 non-equal (or they would be in the same EC).
969 		 Determine the direction of the inequality, and record that
970 		 fact.  */
971 	      tree lt
972 		= fold_binary (LT_EXPR, boolean_type_node,
973 			       new_ec->m_constant, other_ec.m_constant);
974 	      if (lt == boolean_true_node)
975 		add_constraint_internal (new_id, CONSTRAINT_LT, other_id);
976 	      else if (lt == boolean_false_node)
977 		add_constraint_internal (other_id, CONSTRAINT_LT, new_id);
978 	      /* Refresh new_id, in case ECs were merged.  SID should always
979 		 be present by now, so this should never lead to a
980 		 recursion.  */
981 	      new_id = get_or_add_equiv_class (sid);
982 	    }
983 	}
984     }
985 
986   return new_id;
987 }
988 
989 /* Evaluate the condition LHS_EC OP RHS_EC.  */
990 
991 tristate
eval_condition(equiv_class_id lhs_ec,enum tree_code op,equiv_class_id rhs_ec)992 constraint_manager::eval_condition (equiv_class_id lhs_ec,
993 				    enum tree_code op,
994 				    equiv_class_id rhs_ec)
995 {
996   if (lhs_ec == rhs_ec)
997     {
998       switch (op)
999 	{
1000 	case EQ_EXPR:
1001 	case GE_EXPR:
1002 	case LE_EXPR:
1003 	  return tristate (tristate::TS_TRUE);
1004 
1005 	case NE_EXPR:
1006 	case GT_EXPR:
1007 	case LT_EXPR:
1008 	  return tristate (tristate::TS_FALSE);
1009 	default:
1010 	  break;
1011 	}
1012     }
1013 
1014   tree lhs_const = lhs_ec.get_obj (*this).get_any_constant ();
1015   tree rhs_const = rhs_ec.get_obj (*this).get_any_constant ();
1016   if (lhs_const && rhs_const)
1017     {
1018       tree comparison
1019 	= fold_binary (op, boolean_type_node, lhs_const, rhs_const);
1020       if (comparison == boolean_true_node)
1021 	return tristate (tristate::TS_TRUE);
1022       if (comparison == boolean_false_node)
1023 	return tristate (tristate::TS_FALSE);
1024     }
1025 
1026   enum tree_code swapped_op = swap_tree_comparison (op);
1027 
1028   int i;
1029   constraint *c;
1030   FOR_EACH_VEC_ELT (m_constraints, i, c)
1031     {
1032       if (c->m_lhs == lhs_ec
1033 	  && c->m_rhs == rhs_ec)
1034 	{
1035 	  tristate result_for_constraint
1036 	    = eval_constraint_op_for_op (c->m_op, op);
1037 	  if (result_for_constraint.is_known ())
1038 	    return result_for_constraint;
1039 	}
1040       /* Swapped operands.  */
1041       if (c->m_lhs == rhs_ec
1042 	  && c->m_rhs == lhs_ec)
1043 	{
1044 	  tristate result_for_constraint
1045 	    = eval_constraint_op_for_op (c->m_op, swapped_op);
1046 	  if (result_for_constraint.is_known ())
1047 	    return result_for_constraint;
1048 	}
1049     }
1050 
1051   return tristate (tristate::TS_UNKNOWN);
1052 }
1053 
1054 /* Evaluate the condition LHS OP RHS, creating equiv_class instances for
1055    LHS and RHS if they aren't already in equiv_classes.  */
1056 
1057 tristate
eval_condition(svalue_id lhs,enum tree_code op,svalue_id rhs)1058 constraint_manager::eval_condition (svalue_id lhs,
1059 				    enum tree_code op,
1060 				    svalue_id rhs)
1061 {
1062   return eval_condition (get_or_add_equiv_class (lhs),
1063 			 op,
1064 			 get_or_add_equiv_class (rhs));
1065 }
1066 
1067 /* Delete any information about svalue_id instances identified by P.
1068    Such instances are removed from equivalence classes, and any
1069    redundant ECs and constraints are also removed.
1070    Accumulate stats into STATS.  */
1071 
1072 void
purge(const purge_criteria & p,purge_stats * stats)1073 constraint_manager::purge (const purge_criteria &p, purge_stats *stats)
1074 {
1075   /* Delete any svalue_ids identified by P within the various equivalence
1076      classes.  */
1077   for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
1078     {
1079       equiv_class *ec = m_equiv_classes[ec_idx];
1080 
1081       int i;
1082       svalue_id *pv;
1083       bool delete_ec = false;
1084       FOR_EACH_VEC_ELT (ec->m_vars, i, pv)
1085 	{
1086 	  if (*pv == ec->m_cst_sid)
1087 	    continue;
1088 	  if (p.should_purge_p (*pv))
1089 	    {
1090 	      if (ec->del (*pv))
1091 		if (!ec->m_constant)
1092 		  delete_ec = true;
1093 	    }
1094 	}
1095 
1096       if (delete_ec)
1097 	{
1098 	  delete ec;
1099 	  m_equiv_classes.ordered_remove (ec_idx);
1100 	  if (stats)
1101 	    stats->m_num_equiv_classes++;
1102 
1103 	  /* Update the constraints, potentially removing some.  */
1104 	  for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
1105 	    {
1106 	      constraint *c = &m_constraints[con_idx];
1107 
1108 	      /* Remove constraints that refer to the deleted EC.  */
1109 	      if (c->m_lhs == ec_idx
1110 		  || c->m_rhs == ec_idx)
1111 		{
1112 		  m_constraints.ordered_remove (con_idx);
1113 		  if (stats)
1114 		    stats->m_num_constraints++;
1115 		}
1116 	      else
1117 		{
1118 		  /* Renumber constraints that refer to ECs that have
1119 		     had their idx changed.  */
1120 		  c->m_lhs.update_for_removal (ec_idx);
1121 		  c->m_rhs.update_for_removal (ec_idx);
1122 
1123 		  con_idx++;
1124 		}
1125 	    }
1126 	}
1127       else
1128 	ec_idx++;
1129     }
1130 
1131   /* Now delete any constraints that are purely between constants.  */
1132   for (unsigned con_idx = 0; con_idx < m_constraints.length (); )
1133     {
1134       constraint *c = &m_constraints[con_idx];
1135       if (m_equiv_classes[c->m_lhs.m_idx]->m_vars.length () == 0
1136 	  && m_equiv_classes[c->m_rhs.m_idx]->m_vars.length () == 0)
1137 	{
1138 	  m_constraints.ordered_remove (con_idx);
1139 	  if (stats)
1140 	    stats->m_num_constraints++;
1141 	}
1142       else
1143 	{
1144 	  con_idx++;
1145 	}
1146     }
1147 
1148   /* Finally, delete any ECs that purely contain constants and aren't
1149      referenced by any constraints.  */
1150   for (unsigned ec_idx = 0; ec_idx < m_equiv_classes.length (); )
1151     {
1152       equiv_class *ec = m_equiv_classes[ec_idx];
1153       if (ec->m_vars.length () == 0)
1154 	{
1155 	  equiv_class_id ec_id (ec_idx);
1156 	  bool has_constraint = false;
1157 	  for (unsigned con_idx = 0; con_idx < m_constraints.length ();
1158 	       con_idx++)
1159 	    {
1160 	      constraint *c = &m_constraints[con_idx];
1161 	      if (c->m_lhs == ec_id
1162 		  || c->m_rhs == ec_id)
1163 		{
1164 		  has_constraint = true;
1165 		  break;
1166 		}
1167 	    }
1168 	  if (!has_constraint)
1169 	    {
1170 	      delete ec;
1171 	      m_equiv_classes.ordered_remove (ec_idx);
1172 	      if (stats)
1173 		stats->m_num_equiv_classes++;
1174 
1175 	      /* Renumber constraints that refer to ECs that have
1176 		 had their idx changed.  */
1177 	      for (unsigned con_idx = 0; con_idx < m_constraints.length ();
1178 		   con_idx++)
1179 		{
1180 		  constraint *c = &m_constraints[con_idx];
1181 		  c->m_lhs.update_for_removal (ec_idx);
1182 		  c->m_rhs.update_for_removal (ec_idx);
1183 		}
1184 	      continue;
1185 	    }
1186 	}
1187       ec_idx++;
1188     }
1189 
1190   validate ();
1191 }
1192 
1193 /* Remap all svalue_ids within this constraint_manager using MAP.  */
1194 
1195 void
remap_svalue_ids(const svalue_id_map & map)1196 constraint_manager::remap_svalue_ids (const svalue_id_map &map)
1197 {
1198   int i;
1199   equiv_class *ec;
1200   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1201     ec->remap_svalue_ids (map);
1202 }
1203 
1204 /* Comparator for use by constraint_manager::canonicalize.
1205    Sort a pair of equiv_class instances, using the representative
1206    svalue_id as a sort key.  */
1207 
1208 static int
equiv_class_cmp(const void * p1,const void * p2)1209 equiv_class_cmp (const void *p1, const void *p2)
1210 {
1211   const equiv_class *ec1 = *(const equiv_class * const *)p1;
1212   const equiv_class *ec2 = *(const equiv_class * const *)p2;
1213 
1214   svalue_id rep1 = ec1->get_representative ();
1215   svalue_id rep2 = ec2->get_representative ();
1216 
1217   return rep1.as_int () - rep2.as_int ();
1218 }
1219 
1220 /* Comparator for use by constraint_manager::canonicalize.
1221    Sort a pair of constraint instances.  */
1222 
1223 static int
constraint_cmp(const void * p1,const void * p2)1224 constraint_cmp (const void *p1, const void *p2)
1225 {
1226   const constraint *c1 = (const constraint *)p1;
1227   const constraint *c2 = (const constraint *)p2;
1228   int lhs_cmp = c1->m_lhs.as_int () - c2->m_lhs.as_int ();
1229   if (lhs_cmp)
1230     return lhs_cmp;
1231   int rhs_cmp = c1->m_rhs.as_int () - c2->m_rhs.as_int ();
1232   if (rhs_cmp)
1233     return rhs_cmp;
1234   return c1->m_op - c2->m_op;
1235 }
1236 
1237 /* Reorder the equivalence classes and constraints within this
1238    constraint_manager into a canonical order, to increase the
1239    chances of finding equality with another instance.  */
1240 
1241 void
canonicalize(unsigned num_svalue_ids)1242 constraint_manager::canonicalize (unsigned num_svalue_ids)
1243 {
1244   /* First, sort svalue_ids within the ECs.  */
1245   unsigned i;
1246   equiv_class *ec;
1247   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1248     ec->canonicalize ();
1249 
1250   /* Next, sort the ECs into a canonical order.  */
1251 
1252   /* We will need to remap the equiv_class_ids in the constraints,
1253      so we need to store the original index of each EC.
1254      Build a lookup table, mapping from representative svalue_id
1255      to the original equiv_class_id of that svalue_id.  */
1256   auto_vec<equiv_class_id> original_ec_id (num_svalue_ids);
1257   for (i = 0; i < num_svalue_ids; i++)
1258     original_ec_id.quick_push (equiv_class_id::null ());
1259   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1260     {
1261       svalue_id rep = ec->get_representative ();
1262       gcc_assert (!rep.null_p ());
1263       original_ec_id[rep.as_int ()] = i;
1264     }
1265 
1266   /* Sort the equivalence classes.  */
1267   m_equiv_classes.qsort (equiv_class_cmp);
1268 
1269   /* Populate ec_id_map based on the old vs new EC ids.  */
1270   one_way_id_map<equiv_class_id> ec_id_map (m_equiv_classes.length ());
1271   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1272     {
1273       svalue_id rep = ec->get_representative ();
1274       ec_id_map.put (original_ec_id[rep.as_int ()], i);
1275     }
1276 
1277   /* Update the EC ids within the constraints.  */
1278   constraint *c;
1279   FOR_EACH_VEC_ELT (m_constraints, i, c)
1280     {
1281       ec_id_map.update (&c->m_lhs);
1282       ec_id_map.update (&c->m_rhs);
1283     }
1284 
1285   /* Finally, sort the constraints. */
1286   m_constraints.qsort (constraint_cmp);
1287 }
1288 
1289 /* A concrete subclass of constraint_manager for use when
1290    merging two constraint_manager into a third constraint_manager,
1291    each of which has its own region_model.
1292    Calls are delegated to the constraint_manager for the merged model,
1293    and thus affect its region_model.  */
1294 
1295 class cleaned_constraint_manager : public constraint_manager
1296 {
1297 public:
cleaned_constraint_manager(constraint_manager * merged)1298   cleaned_constraint_manager (constraint_manager *merged) : m_merged (merged) {}
1299 
clone(region_model *) const1300   constraint_manager *clone (region_model *) const FINAL OVERRIDE
1301   {
1302     gcc_unreachable ();
1303   }
maybe_get_constant(svalue_id sid) const1304   tree maybe_get_constant (svalue_id sid) const FINAL OVERRIDE
1305   {
1306     return m_merged->maybe_get_constant (sid);
1307   }
get_sid_for_constant(tree cst) const1308   svalue_id get_sid_for_constant (tree cst) const FINAL OVERRIDE
1309   {
1310     return m_merged->get_sid_for_constant (cst);
1311   }
get_num_svalues() const1312   virtual int get_num_svalues () const FINAL OVERRIDE
1313   {
1314     return m_merged->get_num_svalues ();
1315   }
1316 private:
1317   constraint_manager *m_merged;
1318 };
1319 
1320 /* Concrete subclass of fact_visitor for use by constraint_manager::merge.
1321    For every fact in CM_A, see if it is also true in *CM_B.  Add such
1322    facts to *OUT.  */
1323 
1324 class merger_fact_visitor : public fact_visitor
1325 {
1326 public:
merger_fact_visitor(constraint_manager * cm_b,constraint_manager * out)1327   merger_fact_visitor (constraint_manager *cm_b,
1328 		       constraint_manager *out)
1329   : m_cm_b (cm_b), m_out (out)
1330   {}
1331 
on_fact(svalue_id lhs,enum tree_code code,svalue_id rhs)1332   void on_fact (svalue_id lhs, enum tree_code code, svalue_id rhs)
1333     FINAL OVERRIDE
1334   {
1335     if (m_cm_b->eval_condition (lhs, code, rhs).is_true ())
1336       {
1337 	bool sat = m_out->add_constraint (lhs, code, rhs);
1338 	gcc_assert (sat);
1339       }
1340   }
1341 
1342 private:
1343   constraint_manager *m_cm_b;
1344   constraint_manager *m_out;
1345 };
1346 
1347 /* Use MERGER to merge CM_A and CM_B into *OUT.
1348    If one thinks of a constraint_manager as a subset of N-dimensional
1349    space, this takes the union of the points of CM_A and CM_B, and
1350    expresses that into *OUT.  Alternatively, it can be thought of
1351    as the intersection of the constraints.  */
1352 
1353 void
merge(const constraint_manager & cm_a,const constraint_manager & cm_b,constraint_manager * out,const model_merger & merger)1354 constraint_manager::merge (const constraint_manager &cm_a,
1355 			   const constraint_manager &cm_b,
1356 			   constraint_manager *out,
1357 			   const model_merger &merger)
1358 {
1359   gcc_assert (merger.m_sid_mapping);
1360 
1361   /* Map svalue_ids in each equiv class from both sources
1362      to the merged region_model, dropping ids that don't survive merger,
1363      and potentially creating svalues in *OUT for constants.  */
1364   cleaned_constraint_manager cleaned_cm_a (out);
1365   const one_way_svalue_id_map &map_a_to_m
1366     = merger.m_sid_mapping->m_map_from_a_to_m;
1367   clean_merger_input (cm_a, map_a_to_m, &cleaned_cm_a);
1368 
1369   cleaned_constraint_manager cleaned_cm_b (out);
1370   const one_way_svalue_id_map &map_b_to_m
1371     = merger.m_sid_mapping->m_map_from_b_to_m;
1372   clean_merger_input (cm_b, map_b_to_m, &cleaned_cm_b);
1373 
1374   /* At this point, the two cleaned CMs have ECs and constraints referring
1375      to svalues in the merged region model, but both of them have separate
1376      ECs.  */
1377 
1378   /* Merge the equivalence classes and constraints.
1379      The easiest way to do this seems to be to enumerate all of the facts
1380      in cleaned_cm_a, see which are also true in cleaned_cm_b,
1381      and add those to *OUT.  */
1382   merger_fact_visitor v (&cleaned_cm_b, out);
1383   cleaned_cm_a.for_each_fact (&v);
1384 }
1385 
1386 /* A subroutine of constraint_manager::merge.
1387    Use MAP_SID_TO_M to map equivalence classes and constraints from
1388    SM_IN to *OUT.  Purge any non-constant svalue_id that don't appear
1389    in the result of MAP_SID_TO_M, purging any ECs and their constraints
1390    that become empty as a result.  Potentially create svalues in
1391    the merged region_model for constants that weren't already in use there.  */
1392 
1393 void
1394 constraint_manager::
clean_merger_input(const constraint_manager & cm_in,const one_way_svalue_id_map & map_sid_to_m,constraint_manager * out)1395 clean_merger_input (const constraint_manager &cm_in,
1396 		    const one_way_svalue_id_map &map_sid_to_m,
1397 		    constraint_manager *out)
1398 {
1399   one_way_id_map<equiv_class_id> map_ec_to_m
1400     (cm_in.m_equiv_classes.length ());
1401   unsigned ec_idx;
1402   equiv_class *ec;
1403   FOR_EACH_VEC_ELT (cm_in.m_equiv_classes, ec_idx, ec)
1404     {
1405       equiv_class cleaned_ec;
1406       if (tree cst = ec->get_any_constant ())
1407 	{
1408 	  cleaned_ec.m_constant = cst;
1409 	  /* Lazily create the constant in the out region_model.  */
1410 	  cleaned_ec.m_cst_sid = out->get_sid_for_constant (cst);
1411 	}
1412       unsigned var_idx;
1413       svalue_id *var_in_sid;
1414       FOR_EACH_VEC_ELT (ec->m_vars, var_idx, var_in_sid)
1415 	{
1416 	  svalue_id var_m_sid = map_sid_to_m.get_dst_for_src (*var_in_sid);
1417 	  if (!var_m_sid.null_p ())
1418 	    cleaned_ec.m_vars.safe_push (var_m_sid);
1419 	}
1420       if (cleaned_ec.get_any_constant () || !cleaned_ec.m_vars.is_empty ())
1421 	{
1422 	  map_ec_to_m.put (ec_idx, out->m_equiv_classes.length ());
1423 	  out->m_equiv_classes.safe_push (new equiv_class (cleaned_ec));
1424 	}
1425     }
1426 
1427   /* Write out to *OUT any constraints for which both sides survived
1428      cleaning, using the new EC IDs.  */
1429   unsigned con_idx;
1430   constraint *c;
1431   FOR_EACH_VEC_ELT (cm_in.m_constraints, con_idx, c)
1432     {
1433       equiv_class_id new_lhs = map_ec_to_m.get_dst_for_src (c->m_lhs);
1434       if (new_lhs.null_p ())
1435 	continue;
1436       equiv_class_id new_rhs = map_ec_to_m.get_dst_for_src (c->m_rhs);
1437       if (new_rhs.null_p ())
1438 	continue;
1439       out->m_constraints.safe_push (constraint (new_lhs,
1440 						c->m_op,
1441 						new_rhs));
1442     }
1443 }
1444 
1445 /* Call VISITOR's on_fact vfunc repeatedly to express the various
1446    equivalence classes and constraints.
1447    This is used by constraint_manager::merge to find the common
1448    facts between two input constraint_managers.  */
1449 
1450 void
for_each_fact(fact_visitor * visitor) const1451 constraint_manager::for_each_fact (fact_visitor *visitor) const
1452 {
1453   /* First, call EQ_EXPR within the various equivalence classes.  */
1454   unsigned ec_idx;
1455   equiv_class *ec;
1456   FOR_EACH_VEC_ELT (m_equiv_classes, ec_idx, ec)
1457     {
1458       if (!ec->m_cst_sid.null_p ())
1459 	{
1460 	  unsigned i;
1461 	  svalue_id *sid;
1462 	  FOR_EACH_VEC_ELT (ec->m_vars, i, sid)
1463 	    visitor->on_fact (ec->m_cst_sid, EQ_EXPR, *sid);
1464 	}
1465       for (unsigned i = 0; i < ec->m_vars.length (); i++)
1466 	for (unsigned j = i + 1; j < ec->m_vars.length (); j++)
1467 	  visitor->on_fact (ec->m_vars[i], EQ_EXPR, ec->m_vars[j]);
1468     }
1469 
1470   /* Now, express the various constraints.  */
1471   unsigned con_idx;
1472   constraint *c;
1473   FOR_EACH_VEC_ELT (m_constraints, con_idx, c)
1474     {
1475       const equiv_class &ec_lhs = c->m_lhs.get_obj (*this);
1476       const equiv_class &ec_rhs = c->m_rhs.get_obj (*this);
1477       enum tree_code code = constraint_tree_code (c->m_op);
1478 
1479       if (!ec_lhs.m_cst_sid.null_p ())
1480 	{
1481 	  for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
1482 	    {
1483 	      visitor->on_fact (ec_lhs.m_cst_sid, code, ec_rhs.m_vars[j]);
1484 	    }
1485 	}
1486       for (unsigned i = 0; i < ec_lhs.m_vars.length (); i++)
1487 	{
1488 	  if (!ec_rhs.m_cst_sid.null_p ())
1489 	    visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_cst_sid);
1490 	  for (unsigned j = 0; j < ec_rhs.m_vars.length (); j++)
1491 	    visitor->on_fact (ec_lhs.m_vars[i], code, ec_rhs.m_vars[j]);
1492 	}
1493     }
1494 }
1495 
1496 /* Assert that this object is valid.  */
1497 
1498 void
validate() const1499 constraint_manager::validate () const
1500 {
1501   /* Skip this in a release build.  */
1502 #if !CHECKING_P
1503   return;
1504 #endif
1505 
1506   int i;
1507   equiv_class *ec;
1508   FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
1509     {
1510       gcc_assert (ec);
1511 
1512       int j;
1513       svalue_id *sid;
1514       FOR_EACH_VEC_ELT (ec->m_vars, j, sid)
1515 	{
1516 	  gcc_assert (!sid->null_p ());
1517 	  gcc_assert (sid->as_int () < get_num_svalues ());
1518 	}
1519       if (ec->m_constant)
1520 	{
1521 	  gcc_assert (CONSTANT_CLASS_P (ec->m_constant));
1522 	  gcc_assert (!ec->m_cst_sid.null_p ());
1523 	  gcc_assert (ec->m_cst_sid.as_int () < get_num_svalues ());
1524 	}
1525 #if 0
1526       else
1527 	gcc_assert (ec->m_vars.length () > 0);
1528 #endif
1529     }
1530 
1531   constraint *c;
1532   FOR_EACH_VEC_ELT (m_constraints, i, c)
1533     {
1534       gcc_assert (!c->m_lhs.null_p ());
1535       gcc_assert (c->m_lhs.as_int () <= (int)m_equiv_classes.length ());
1536       gcc_assert (!c->m_rhs.null_p ());
1537       gcc_assert (c->m_rhs.as_int () <= (int)m_equiv_classes.length ());
1538     }
1539 }
1540 
1541 #if CHECKING_P
1542 
1543 namespace selftest {
1544 
1545 /* Various constraint_manager selftests.
1546    These have to be written in terms of a region_model, since
1547    the latter is responsible for managing svalue and svalue_id
1548    instances.  */
1549 
1550 /* Verify that setting and getting simple conditions within a region_model
1551    work (thus exercising the underlying constraint_manager).  */
1552 
1553 static void
test_constraint_conditions()1554 test_constraint_conditions ()
1555 {
1556   tree int_42 = build_int_cst (integer_type_node, 42);
1557   tree int_0 = build_int_cst (integer_type_node, 0);
1558 
1559   tree x = build_global_decl ("x", integer_type_node);
1560   tree y = build_global_decl ("y", integer_type_node);
1561   tree z = build_global_decl ("z", integer_type_node);
1562 
1563   /* Self-comparisons.  */
1564   {
1565     region_model model;
1566     ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, x);
1567     ASSERT_CONDITION_TRUE (model, x, LE_EXPR, x);
1568     ASSERT_CONDITION_TRUE (model, x, GE_EXPR, x);
1569     ASSERT_CONDITION_FALSE (model, x, NE_EXPR, x);
1570     ASSERT_CONDITION_FALSE (model, x, LT_EXPR, x);
1571     ASSERT_CONDITION_FALSE (model, x, GT_EXPR, x);
1572   }
1573 
1574   /* x == y.  */
1575   {
1576     region_model model;
1577     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
1578 
1579     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
1580 
1581     ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, y);
1582     ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
1583     ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
1584     ASSERT_CONDITION_FALSE (model, x, NE_EXPR, y);
1585     ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
1586     ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
1587 
1588     /* Swapped operands.  */
1589     ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x);
1590     ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
1591     ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
1592     ASSERT_CONDITION_FALSE (model, y, NE_EXPR, x);
1593     ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
1594     ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
1595 
1596     /* Comparison with other var.  */
1597     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
1598     ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
1599     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
1600     ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
1601     ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
1602     ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
1603   }
1604 
1605   /* x == y, then y == z  */
1606   {
1607     region_model model;
1608     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
1609 
1610     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
1611     ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, z);
1612 
1613     ASSERT_CONDITION_TRUE (model, x, EQ_EXPR, z);
1614     ASSERT_CONDITION_TRUE (model, x, LE_EXPR, z);
1615     ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
1616     ASSERT_CONDITION_FALSE (model, x, NE_EXPR, z);
1617     ASSERT_CONDITION_FALSE (model, x, LT_EXPR, z);
1618     ASSERT_CONDITION_FALSE (model, x, GT_EXPR, z);
1619   }
1620 
1621   /* x != y.  */
1622   {
1623     region_model model;
1624 
1625     ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
1626 
1627     ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
1628     ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
1629     ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
1630     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
1631     ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
1632     ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
1633 
1634     /* Swapped operands.  */
1635     ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
1636     ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
1637     ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
1638     ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
1639     ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
1640     ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
1641 
1642     /* Comparison with other var.  */
1643     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, z);
1644     ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, z);
1645     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
1646     ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, z);
1647     ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, z);
1648     ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, z);
1649   }
1650 
1651   /* x < y.  */
1652   {
1653     region_model model;
1654 
1655     ADD_SAT_CONSTRAINT (model, x, LT_EXPR, y);
1656 
1657     ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
1658     ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
1659     ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
1660     ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
1661     ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
1662     ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
1663 
1664     /* Swapped operands.  */
1665     ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
1666     ASSERT_CONDITION_FALSE (model, y, LE_EXPR, x);
1667     ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
1668     ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
1669     ASSERT_CONDITION_TRUE (model, y, GT_EXPR, x);
1670     ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
1671   }
1672 
1673   /* x <= y.  */
1674   {
1675     region_model model;
1676 
1677     ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
1678 
1679     ASSERT_CONDITION_UNKNOWN (model, x, LT_EXPR, y);
1680     ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
1681     ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
1682     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
1683     ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
1684     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, y);
1685 
1686     /* Swapped operands.  */
1687     ASSERT_CONDITION_FALSE (model, y, LT_EXPR, x);
1688     ASSERT_CONDITION_UNKNOWN (model, y, LE_EXPR, x);
1689     ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
1690     ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
1691     ASSERT_CONDITION_UNKNOWN (model, y, GT_EXPR, x);
1692     ASSERT_CONDITION_TRUE (model, y, GE_EXPR, x);
1693   }
1694 
1695   /* x > y.  */
1696   {
1697     region_model model;
1698 
1699     ADD_SAT_CONSTRAINT (model, x, GT_EXPR, y);
1700 
1701     ASSERT_CONDITION_TRUE (model, x, GT_EXPR, y);
1702     ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
1703     ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
1704     ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
1705     ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
1706     ASSERT_CONDITION_FALSE (model, x, LE_EXPR, y);
1707 
1708     /* Swapped operands.  */
1709     ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
1710     ASSERT_CONDITION_FALSE (model, y, GE_EXPR, x);
1711     ASSERT_CONDITION_TRUE (model, y, NE_EXPR, x);
1712     ASSERT_CONDITION_FALSE (model, y, EQ_EXPR, x);
1713     ASSERT_CONDITION_TRUE (model, y, LT_EXPR, x);
1714     ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
1715   }
1716 
1717   /* x >= y.  */
1718   {
1719     region_model model;
1720 
1721     ADD_SAT_CONSTRAINT (model, x, GE_EXPR, y);
1722 
1723     ASSERT_CONDITION_UNKNOWN (model, x, GT_EXPR, y);
1724     ASSERT_CONDITION_TRUE (model, x, GE_EXPR, y);
1725     ASSERT_CONDITION_UNKNOWN (model, x, NE_EXPR, y);
1726     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
1727     ASSERT_CONDITION_FALSE (model, x, LT_EXPR, y);
1728     ASSERT_CONDITION_UNKNOWN (model, x, LE_EXPR, y);
1729 
1730     /* Swapped operands.  */
1731     ASSERT_CONDITION_FALSE (model, y, GT_EXPR, x);
1732     ASSERT_CONDITION_UNKNOWN (model, y, GE_EXPR, x);
1733     ASSERT_CONDITION_UNKNOWN (model, y, NE_EXPR, x);
1734     ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, x);
1735     ASSERT_CONDITION_UNKNOWN (model, y, LT_EXPR, x);
1736     ASSERT_CONDITION_TRUE (model, y, LE_EXPR, x);
1737   }
1738 
1739   // TODO: implied orderings
1740 
1741   /* Constants.  */
1742   {
1743     region_model model;
1744     ASSERT_CONDITION_FALSE (model, int_0, EQ_EXPR, int_42);
1745     ASSERT_CONDITION_TRUE (model, int_0, NE_EXPR, int_42);
1746     ASSERT_CONDITION_TRUE (model, int_0, LT_EXPR, int_42);
1747     ASSERT_CONDITION_TRUE (model, int_0, LE_EXPR, int_42);
1748     ASSERT_CONDITION_FALSE (model, int_0, GT_EXPR, int_42);
1749     ASSERT_CONDITION_FALSE (model, int_0, GE_EXPR, int_42);
1750   }
1751 
1752   /* x == 0, y == 42.  */
1753   {
1754     region_model model;
1755     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
1756     ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, int_42);
1757 
1758     ASSERT_CONDITION_TRUE (model, x, NE_EXPR, y);
1759     ASSERT_CONDITION_FALSE (model, x, EQ_EXPR, y);
1760     ASSERT_CONDITION_TRUE (model, x, LE_EXPR, y);
1761     ASSERT_CONDITION_FALSE (model, x, GE_EXPR, y);
1762     ASSERT_CONDITION_TRUE (model, x, LT_EXPR, y);
1763     ASSERT_CONDITION_FALSE (model, x, GT_EXPR, y);
1764   }
1765 
1766   /* Unsatisfiable combinations.  */
1767 
1768   /* x == y && x != y.  */
1769   {
1770     region_model model;
1771     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
1772     ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, y);
1773   }
1774 
1775   /* x == 0 then x == 42.  */
1776   {
1777     region_model model;
1778     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
1779     ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, int_42);
1780   }
1781 
1782   /* x == 0 then x != 0.  */
1783   {
1784     region_model model;
1785     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
1786     ADD_UNSAT_CONSTRAINT (model, x, NE_EXPR, int_0);
1787   }
1788 
1789   /* x == 0 then x > 0.  */
1790   {
1791     region_model model;
1792     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
1793     ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, int_0);
1794   }
1795 
1796   /* x != y && x == y.  */
1797   {
1798     region_model model;
1799     ADD_SAT_CONSTRAINT (model, x, NE_EXPR, y);
1800     ADD_UNSAT_CONSTRAINT (model, x, EQ_EXPR, y);
1801   }
1802 
1803   /* x <= y && x > y.  */
1804   {
1805     region_model model;
1806     ADD_SAT_CONSTRAINT (model, x, LE_EXPR, y);
1807     ADD_UNSAT_CONSTRAINT (model, x, GT_EXPR, y);
1808   }
1809 
1810   // etc
1811 }
1812 
1813 /* Test transitivity of conditions.  */
1814 
1815 static void
test_transitivity()1816 test_transitivity ()
1817 {
1818   tree a = build_global_decl ("a", integer_type_node);
1819   tree b = build_global_decl ("b", integer_type_node);
1820   tree c = build_global_decl ("c", integer_type_node);
1821   tree d = build_global_decl ("d", integer_type_node);
1822 
1823   /* a == b, then c == d, then c == b.  */
1824   {
1825     region_model model;
1826     ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, b);
1827     ASSERT_CONDITION_UNKNOWN (model, b, EQ_EXPR, c);
1828     ASSERT_CONDITION_UNKNOWN (model, c, EQ_EXPR, d);
1829     ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
1830 
1831     ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, b);
1832     ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
1833 
1834     ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, d);
1835     ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, d);
1836     ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, d);
1837 
1838     ADD_SAT_CONSTRAINT (model, c, EQ_EXPR, b);
1839     ASSERT_CONDITION_TRUE (model, c, EQ_EXPR, b);
1840     ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, d);
1841   }
1842 
1843   /* Transitivity: "a < b", "b < c" should imply "a < c".  */
1844   {
1845     region_model model;
1846     ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
1847     ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
1848 
1849     ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
1850     ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
1851   }
1852 
1853   /* Transitivity: "a <= b", "b < c" should imply "a < c".  */
1854   {
1855     region_model model;
1856     ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
1857     ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
1858 
1859     ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
1860     ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
1861   }
1862 
1863   /* Transitivity: "a <= b", "b <= c" should imply "a <= c".  */
1864   {
1865     region_model model;
1866     ADD_SAT_CONSTRAINT (model, a, LE_EXPR, b);
1867     ADD_SAT_CONSTRAINT (model, b, LE_EXPR, c);
1868 
1869     ASSERT_CONDITION_TRUE (model, a, LE_EXPR, c);
1870     ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
1871   }
1872 
1873   /* Transitivity: "a > b", "b > c" should imply "a > c".  */
1874   {
1875     region_model model;
1876     ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
1877     ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
1878 
1879     ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
1880     ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
1881   }
1882 
1883   /* Transitivity: "a >= b", "b > c" should imply " a > c".  */
1884   {
1885     region_model model;
1886     ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
1887     ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
1888 
1889     ASSERT_CONDITION_TRUE (model, a, GT_EXPR, c);
1890     ASSERT_CONDITION_FALSE (model, a, EQ_EXPR, c);
1891   }
1892 
1893   /* Transitivity: "a >= b", "b >= c" should imply "a >= c".  */
1894   {
1895     region_model model;
1896     ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
1897     ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c);
1898 
1899     ASSERT_CONDITION_TRUE (model, a, GE_EXPR, c);
1900     ASSERT_CONDITION_UNKNOWN (model, a, EQ_EXPR, c);
1901   }
1902 
1903   /* Transitivity: "(a < b)", "(c < d)", "(b < c)" should
1904      imply the easy cases:
1905        (a < c)
1906        (b < d)
1907      but also that:
1908        (a < d).  */
1909   {
1910     region_model model;
1911     ADD_SAT_CONSTRAINT (model, a, LT_EXPR, b);
1912     ADD_SAT_CONSTRAINT (model, c, LT_EXPR, d);
1913     ADD_SAT_CONSTRAINT (model, b, LT_EXPR, c);
1914 
1915     ASSERT_CONDITION_TRUE (model, a, LT_EXPR, c);
1916     ASSERT_CONDITION_TRUE (model, b, LT_EXPR, d);
1917     ASSERT_CONDITION_TRUE (model, a, LT_EXPR, d);
1918   }
1919 
1920   /* Transitivity: "a >= b", "b >= a" should imply that a == b.  */
1921   {
1922     region_model model;
1923     ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
1924     ADD_SAT_CONSTRAINT (model, b, GE_EXPR, a);
1925 
1926     // TODO:
1927     ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, b);
1928   }
1929 
1930   /* Transitivity: "a >= b", "b > a" should be impossible.  */
1931   {
1932     region_model model;
1933     ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
1934     ADD_UNSAT_CONSTRAINT (model, b, GT_EXPR, a);
1935   }
1936 
1937   /* Transitivity: "a >= b", "b >= c", "c >= a" should imply
1938      that a == b == c.  */
1939   {
1940     region_model model;
1941     ADD_SAT_CONSTRAINT (model, a, GE_EXPR, b);
1942     ADD_SAT_CONSTRAINT (model, b, GE_EXPR, c);
1943     ADD_SAT_CONSTRAINT (model, c, GE_EXPR, a);
1944 
1945     ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, c);
1946   }
1947 
1948   /* Transitivity: "a > b", "b > c", "c > a"
1949      should be impossible.  */
1950   {
1951     region_model model;
1952     ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
1953     ADD_SAT_CONSTRAINT (model, b, GT_EXPR, c);
1954     ADD_UNSAT_CONSTRAINT (model, c, GT_EXPR, a);
1955   }
1956 
1957 }
1958 
1959 /* Test various conditionals involving constants where the results
1960    ought to be implied based on the values of the constants.  */
1961 
1962 static void
test_constant_comparisons()1963 test_constant_comparisons ()
1964 {
1965   tree int_3 = build_int_cst (integer_type_node, 3);
1966   tree int_4 = build_int_cst (integer_type_node, 4);
1967   tree int_5 = build_int_cst (integer_type_node, 5);
1968 
1969   tree int_1023 = build_int_cst (integer_type_node, 1023);
1970   tree int_1024 = build_int_cst (integer_type_node, 1024);
1971 
1972   tree a = build_global_decl ("a", integer_type_node);
1973   tree b = build_global_decl ("b", integer_type_node);
1974 
1975   /* Given a >= 1024, then a <= 1023 should be impossible.  */
1976   {
1977     region_model model;
1978     ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_1024);
1979     ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_1023);
1980   }
1981 
1982   /* a > 4.  */
1983   {
1984     region_model model;
1985     ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_4);
1986     ASSERT_CONDITION_TRUE (model, a, GT_EXPR, int_4);
1987     ASSERT_CONDITION_TRUE (model, a, NE_EXPR, int_3);
1988     ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_5);
1989   }
1990 
1991   /* a <= 4.  */
1992   {
1993     region_model model;
1994     ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
1995     ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_4);
1996     ASSERT_CONDITION_FALSE (model, a, GT_EXPR, int_5);
1997     ASSERT_CONDITION_UNKNOWN (model, a, NE_EXPR, int_3);
1998   }
1999 
2000   /* If "a > b" and "a == 3", then "b == 4" ought to be unsatisfiable.  */
2001   {
2002     region_model model;
2003     ADD_SAT_CONSTRAINT (model, a, GT_EXPR, b);
2004     ADD_SAT_CONSTRAINT (model, a, EQ_EXPR, int_3);
2005     ADD_UNSAT_CONSTRAINT (model, b, EQ_EXPR, int_4);
2006   }
2007 
2008   /* Various tests of int ranges where there is only one possible candidate.  */
2009   {
2010     /* If "a <= 4" && "a > 3", then "a == 4",
2011        assuming a is of integral type.  */
2012     {
2013       region_model model;
2014       ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
2015       ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
2016       ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
2017     }
2018 
2019     /* If "a > 3" && "a <= 4", then "a == 4",
2020        assuming a is of integral type.  */
2021     {
2022       region_model model;
2023       ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
2024       ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
2025       ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
2026     }
2027     /* If "a > 3" && "a < 5", then "a == 4",
2028        assuming a is of integral type.  */
2029     {
2030       region_model model;
2031       ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3);
2032       ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
2033       ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
2034     }
2035     /* If "a >= 4" && "a < 5", then "a == 4",
2036        assuming a is of integral type.  */
2037     {
2038       region_model model;
2039       ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
2040       ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5);
2041       ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
2042     }
2043     /* If "a >= 4" && "a <= 4", then "a == 4".  */
2044     {
2045       region_model model;
2046       ADD_SAT_CONSTRAINT (model, a, GE_EXPR, int_4);
2047       ADD_SAT_CONSTRAINT (model, a, LE_EXPR, int_4);
2048       ASSERT_CONDITION_TRUE (model, a, EQ_EXPR, int_4);
2049     }
2050   }
2051 
2052   /* As above, but for floating-point:
2053      if "f > 3" && "f <= 4" we don't know that f == 4.  */
2054   {
2055     tree f = build_global_decl ("f", double_type_node);
2056     tree float_3 = build_real_from_int_cst (double_type_node, int_3);
2057     tree float_4 = build_real_from_int_cst (double_type_node, int_4);
2058 
2059     region_model model;
2060     ADD_SAT_CONSTRAINT (model, f, GT_EXPR, float_3);
2061     ADD_SAT_CONSTRAINT (model, f, LE_EXPR, float_4);
2062     ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, float_4);
2063     ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, int_4);
2064   }
2065 }
2066 
2067 /* Verify various lower-level implementation details about
2068    constraint_manager.  */
2069 
2070 static void
test_constraint_impl()2071 test_constraint_impl ()
2072 {
2073   tree int_42 = build_int_cst (integer_type_node, 42);
2074   tree int_0 = build_int_cst (integer_type_node, 0);
2075 
2076   tree x = build_global_decl ("x", integer_type_node);
2077   tree y = build_global_decl ("y", integer_type_node);
2078   tree z = build_global_decl ("z", integer_type_node);
2079 
2080   /* x == y.  */
2081   {
2082     region_model model;
2083 
2084     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
2085 
2086     /* Assert various things about the insides of model.  */
2087     constraint_manager *cm = model.get_constraints ();
2088     ASSERT_EQ (cm->m_constraints.length (), 0);
2089     ASSERT_EQ (cm->m_equiv_classes.length (), 1);
2090   }
2091 
2092   /* y <= z; x == y.  */
2093   {
2094     region_model model;
2095     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
2096     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
2097 
2098     ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
2099     ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
2100     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
2101 
2102     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, y);
2103 
2104     /* Assert various things about the insides of model.  */
2105     constraint_manager *cm = model.get_constraints ();
2106     ASSERT_EQ (cm->m_constraints.length (), 1);
2107     ASSERT_EQ (cm->m_equiv_classes.length (), 2);
2108 
2109     /* Ensure that we merged the constraints.  */
2110     ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
2111   }
2112 
2113   /* y <= z; y == x.  */
2114   {
2115     region_model model;
2116     ASSERT_CONDITION_UNKNOWN (model, x, EQ_EXPR, y);
2117     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
2118 
2119     ADD_SAT_CONSTRAINT (model, y, GE_EXPR, z);
2120     ASSERT_CONDITION_TRUE (model, y, GE_EXPR, z);
2121     ASSERT_CONDITION_UNKNOWN (model, x, GE_EXPR, z);
2122 
2123     ADD_SAT_CONSTRAINT (model, y, EQ_EXPR, x);
2124 
2125     /* Assert various things about the insides of model.  */
2126     constraint_manager *cm = model.get_constraints ();
2127     ASSERT_EQ (cm->m_constraints.length (), 1);
2128     ASSERT_EQ (cm->m_equiv_classes.length (), 2);
2129 
2130     /* Ensure that we merged the constraints.  */
2131     ASSERT_CONDITION_TRUE (model, x, GE_EXPR, z);
2132   }
2133 
2134   /* x == 0, then x != 42.  */
2135   {
2136     region_model model;
2137 
2138     ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
2139     ADD_SAT_CONSTRAINT (model, x, NE_EXPR, int_42);
2140 
2141     /* Assert various things about the insides of model.  */
2142     constraint_manager *cm = model.get_constraints ();
2143     ASSERT_EQ (cm->m_constraints.length (), 1);
2144     ASSERT_EQ (cm->m_equiv_classes.length (), 2);
2145     ASSERT_EQ (cm->m_constraints[0].m_lhs,
2146 	       cm->get_or_add_equiv_class (model.get_rvalue (int_0, NULL)));
2147     ASSERT_EQ (cm->m_constraints[0].m_rhs,
2148 	       cm->get_or_add_equiv_class (model.get_rvalue (int_42, NULL)));
2149     ASSERT_EQ (cm->m_constraints[0].m_op, CONSTRAINT_LT);
2150   }
2151 
2152   // TODO: selftest for merging ecs "in the middle"
2153   // where a non-final one gets overwritten
2154 
2155   // TODO: selftest where there are pre-existing constraints
2156 }
2157 
2158 /* Check that operator== and hashing works as expected for the
2159    various types.  */
2160 
2161 static void
test_equality()2162 test_equality ()
2163 {
2164   tree x = build_global_decl ("x", integer_type_node);
2165   tree y = build_global_decl ("y", integer_type_node);
2166 
2167   {
2168     region_model model0;
2169     region_model model1;
2170 
2171     constraint_manager *cm0 = model0.get_constraints ();
2172     constraint_manager *cm1 = model1.get_constraints ();
2173 
2174     ASSERT_EQ (cm0->hash (), cm1->hash ());
2175     ASSERT_EQ (*cm0, *cm1);
2176 
2177     ASSERT_EQ (model0.hash (), model1.hash ());
2178     ASSERT_EQ (model0, model1);
2179 
2180     ADD_SAT_CONSTRAINT (model1, x, EQ_EXPR, y);
2181     ASSERT_NE (cm0->hash (), cm1->hash ());
2182     ASSERT_NE (*cm0, *cm1);
2183 
2184     ASSERT_NE (model0.hash (), model1.hash ());
2185     ASSERT_NE (model0, model1);
2186 
2187     region_model model2;
2188     constraint_manager *cm2 = model2.get_constraints ();
2189     /* Make the same change to cm2.  */
2190     ADD_SAT_CONSTRAINT (model2, x, EQ_EXPR, y);
2191     ASSERT_EQ (cm1->hash (), cm2->hash ());
2192     ASSERT_EQ (*cm1, *cm2);
2193 
2194     ASSERT_EQ (model1.hash (), model2.hash ());
2195     ASSERT_EQ (model1, model2);
2196   }
2197 }
2198 
2199 /* Verify tracking inequality of a variable against many constants.  */
2200 
2201 static void
test_many_constants()2202 test_many_constants ()
2203 {
2204   tree a = build_global_decl ("a", integer_type_node);
2205 
2206   region_model model;
2207   auto_vec<tree> constants;
2208   for (int i = 0; i < 20; i++)
2209     {
2210       tree constant = build_int_cst (integer_type_node, i);
2211       constants.safe_push (constant);
2212       ADD_SAT_CONSTRAINT (model, a, NE_EXPR, constant);
2213 
2214       /* Merge, and check the result.  */
2215       region_model other (model);
2216 
2217       region_model merged;
2218       ASSERT_TRUE (model.can_merge_with_p (other, &merged));
2219       model.canonicalize (NULL);
2220       merged.canonicalize (NULL);
2221       ASSERT_EQ (model, merged);
2222 
2223       for (int j = 0; j <= i; j++)
2224 	ASSERT_CONDITION_TRUE (model, a, NE_EXPR, constants[j]);
2225     }
2226 }
2227 
2228 /* Run the selftests in this file, temporarily overriding
2229    flag_analyzer_transitivity with TRANSITIVITY.  */
2230 
2231 static void
run_constraint_manager_tests(bool transitivity)2232 run_constraint_manager_tests (bool transitivity)
2233 {
2234   int saved_flag_analyzer_transitivity = flag_analyzer_transitivity;
2235   flag_analyzer_transitivity = transitivity;
2236 
2237   test_constraint_conditions ();
2238   if (flag_analyzer_transitivity)
2239     {
2240       /* These selftests assume transitivity.  */
2241       test_transitivity ();
2242       test_constant_comparisons ();
2243     }
2244   test_constraint_impl ();
2245   test_equality ();
2246   test_many_constants ();
2247 
2248   flag_analyzer_transitivity = saved_flag_analyzer_transitivity;
2249 }
2250 
2251 /* Run all of the selftests within this file.  */
2252 
2253 void
analyzer_constraint_manager_cc_tests()2254 analyzer_constraint_manager_cc_tests ()
2255 {
2256   /* Run the tests twice: with and without transitivity.  */
2257   run_constraint_manager_tests (true);
2258   run_constraint_manager_tests (false);
2259 }
2260 
2261 } // namespace selftest
2262 
2263 #endif /* CHECKING_P */
2264 
2265 } // namespace ana
2266 
2267 #endif /* #if ENABLE_ANALYZER */
2268