xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/cp/logic.cc (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Derivation and subsumption rules for constraints.
2    Copyright (C) 2013-2020 Free Software Foundation, Inc.
3    Contributed by Andrew Sutton (andrew.n.sutton@gmail.com)
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it 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,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU 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 #define INCLUDE_LIST
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "timevar.h"
27 #include "hash-set.h"
28 #include "machmode.h"
29 #include "vec.h"
30 #include "double-int.h"
31 #include "input.h"
32 #include "alias.h"
33 #include "symtab.h"
34 #include "wide-int.h"
35 #include "inchash.h"
36 #include "tree.h"
37 #include "stringpool.h"
38 #include "attribs.h"
39 #include "intl.h"
40 #include "flags.h"
41 #include "cp-tree.h"
42 #include "c-family/c-common.h"
43 #include "c-family/c-objc.h"
44 #include "cp-objcp-common.h"
45 #include "tree-inline.h"
46 #include "decl.h"
47 #include "toplev.h"
48 #include "type-utils.h"
49 
50 /* Hash functions for atomic constrains.  */
51 
52 struct constraint_hash : default_hash_traits<tree>
53 {
hashconstraint_hash54   static hashval_t hash (tree t)
55   {
56     return hash_atomic_constraint (t);
57   }
58 
equalconstraint_hash59   static bool equal (tree t1, tree t2)
60   {
61     return atomic_constraints_identical_p (t1, t2);
62   }
63 };
64 
65 /* A conjunctive or disjunctive clause.
66 
67    Each clause maintains an iterator that refers to the current
68    term, which is used in the linear decomposition of a formula
69    into CNF or DNF.  */
70 
71 struct clause
72 {
73   typedef std::list<tree>::iterator iterator;
74   typedef std::list<tree>::const_iterator const_iterator;
75 
76   /* Initialize a clause with an initial term.  */
77 
clauseclause78   clause (tree t)
79   {
80     m_terms.push_back (t);
81     if (TREE_CODE (t) == ATOMIC_CONSTR)
82       m_set.add (t);
83 
84     m_current = m_terms.begin ();
85   }
86 
87   /* Create a copy of the current term. The current
88      iterator is set to point to the same position in the
89      copied list of terms.  */
90 
clauseclause91   clause (clause const& c)
92     : m_terms (c.m_terms), m_set (c.m_set), m_current (m_terms.begin ())
93   {
94     std::advance (m_current, std::distance (c.begin (), c.current ()));
95   }
96 
97   /* Returns true when all terms are atoms.  */
98 
doneclause99   bool done () const
100   {
101     return m_current == end ();
102   }
103 
104   /* Advance to the next term.  */
105 
advanceclause106   void advance ()
107   {
108     gcc_assert (!done ());
109     ++m_current;
110   }
111 
112   /* Replaces the current term at position ITER with T.  If
113      T is an atomic constraint that already appears in the
114      clause, remove but do not replace ITER. Returns a pair
115      containing an iterator to the replace object or past
116      the erased object and a boolean value which is true if
117      an object was erased.  */
118 
replaceclause119   std::pair<iterator, bool> replace (iterator iter, tree t)
120   {
121     gcc_assert (TREE_CODE (*iter) != ATOMIC_CONSTR);
122     if (TREE_CODE (t) == ATOMIC_CONSTR)
123       {
124 	if (m_set.add (t))
125 	  return std::make_pair (m_terms.erase (iter), true);
126       }
127     *iter = t;
128     return std::make_pair (iter, false);
129   }
130 
131   /* Inserts T before ITER in the list of terms.  If T has
132      already is an atomic constraint that already appears in
133      the clause, no action is taken, and the current iterator
134      is returned. Returns a pair of an iterator to the inserted
135      object or ITER if no insertion occurred and a boolean
136      value which is true if an object was inserted.  */
137 
insertclause138   std::pair<iterator, bool> insert (iterator iter, tree t)
139   {
140     if (TREE_CODE (t) == ATOMIC_CONSTR)
141     {
142       if (m_set.add (t))
143 	return std::make_pair (iter, false);
144     }
145     return std::make_pair (m_terms.insert (iter, t), true);
146   }
147 
148   /* Replaces the current term with T. In the case where the
149      current term is erased (because T is redundant), update
150      the position of the current term to the next term.  */
151 
replaceclause152   void replace (tree t)
153   {
154     m_current = replace (m_current, t).first;
155   }
156 
157   /* Replace the current term with T1 and T2, in that order.  */
158 
replaceclause159   void replace (tree t1, tree t2)
160   {
161     /* Replace the current term with t1. Ensure that iter points
162        to the term before which t2 will be inserted.  Update the
163        current term as needed.  */
164     std::pair<iterator, bool> rep = replace (m_current, t1);
165     if (rep.second)
166       m_current = rep.first;
167     else
168       ++rep.first;
169 
170     /* Insert the t2. Make this the current term if we erased
171        the prior term.  */
172     std::pair<iterator, bool> ins = insert (rep.first, t2);
173     if (rep.second && ins.second)
174       m_current = ins.first;
175   }
176 
177   /* Returns true if the clause contains the term T.  */
178 
containsclause179   bool contains (tree t)
180   {
181     gcc_assert (TREE_CODE (t) == ATOMIC_CONSTR);
182     return m_set.contains (t);
183   }
184 
185 
186   /* Returns an iterator to the first clause in the formula.  */
187 
beginclause188   iterator begin ()
189   {
190     return m_terms.begin ();
191   }
192 
193   /* Returns an iterator to the first clause in the formula.  */
194 
beginclause195   const_iterator begin () const
196   {
197     return m_terms.begin ();
198   }
199 
200   /* Returns an iterator past the last clause in the formula.  */
201 
endclause202   iterator end ()
203   {
204     return m_terms.end ();
205   }
206 
207   /* Returns an iterator past the last clause in the formula.  */
208 
endclause209   const_iterator end () const
210   {
211     return m_terms.end ();
212   }
213 
214   /* Returns the current iterator.  */
215 
currentclause216   const_iterator current () const
217   {
218     return m_current;
219   }
220 
221   std::list<tree> m_terms; /* The list of terms.  */
222   hash_set<tree, false, constraint_hash> m_set; /* The set of atomic constraints.  */
223   iterator m_current; /* The current term.  */
224 };
225 
226 
227 /* A proof state owns a list of goals and tracks the
228    current sub-goal. The class also provides facilities
229    for managing subgoals and constructing term lists. */
230 
231 struct formula
232 {
233   typedef std::list<clause>::iterator iterator;
234   typedef std::list<clause>::const_iterator const_iterator;
235 
236   /* Construct a formula with an initial formula in a
237      single clause.  */
238 
formulaformula239   formula (tree t)
240   {
241     /* This should call emplace_back(). There's an extra copy being
242        invoked by using push_back().  */
243     m_clauses.push_back (t);
244     m_current = m_clauses.begin ();
245   }
246 
247   /* Returns true when all clauses are atomic.  */
doneformula248   bool done () const
249   {
250     return m_current == end ();
251   }
252 
253   /* Advance to the next term.  */
advanceformula254   void advance ()
255   {
256     gcc_assert (!done ());
257     ++m_current;
258   }
259 
260   /* Insert a copy of clause into the formula. This corresponds
261      to a distribution of one logical operation over the other.  */
262 
branchformula263   clause& branch ()
264   {
265     gcc_assert (!done ());
266     m_clauses.push_back (*m_current);
267     return m_clauses.back ();
268   }
269 
270   /* Returns the position of the current clause.  */
271 
currentformula272   iterator current ()
273   {
274     return m_current;
275   }
276 
277   /* Returns an iterator to the first clause in the formula.  */
278 
beginformula279   iterator begin ()
280   {
281     return m_clauses.begin ();
282   }
283 
284   /* Returns an iterator to the first clause in the formula.  */
285 
beginformula286   const_iterator begin () const
287   {
288     return m_clauses.begin ();
289   }
290 
291   /* Returns an iterator past the last clause in the formula.  */
292 
endformula293   iterator end ()
294   {
295     return m_clauses.end ();
296   }
297 
298   /* Returns an iterator past the last clause in the formula.  */
299 
endformula300   const_iterator end () const
301   {
302     return m_clauses.end ();
303   }
304 
305   std::list<clause> m_clauses; /* The list of clauses.  */
306   iterator m_current; /* The current clause.  */
307 };
308 
309 void
debug(clause & c)310 debug (clause& c)
311 {
312   for (clause::iterator i = c.begin(); i != c.end(); ++i)
313     verbatim ("  # %E", *i);
314 }
315 
316 void
debug(formula & f)317 debug (formula& f)
318 {
319   for (formula::iterator i = f.begin(); i != f.end(); ++i)
320     {
321       verbatim ("(((");
322       debug (*i);
323       verbatim (")))");
324     }
325 }
326 
327 /* The logical rules used to analyze a logical formula. The
328    "left" and "right" refer to the position of formula in a
329    sequent (as in sequent calculus).  */
330 
331 enum rules
332 {
333   left, right
334 };
335 
336 /* Distribution counting.  */
337 
338 static inline bool
disjunction_p(tree t)339 disjunction_p (tree t)
340 {
341   return TREE_CODE (t) == DISJ_CONSTR;
342 }
343 
344 static inline bool
conjunction_p(tree t)345 conjunction_p (tree t)
346 {
347   return TREE_CODE (t) == CONJ_CONSTR;
348 }
349 
350 static inline bool
atomic_p(tree t)351 atomic_p (tree t)
352 {
353   return TREE_CODE (t) == ATOMIC_CONSTR;
354 }
355 
356 /* Recursively count the number of clauses produced when converting T
357    to DNF. Returns a pair containing the number of clauses and a bool
358    value signifying that the tree would be rewritten as a result of
359    distributing. In general, a conjunction for which this flag is set
360    is considered a disjunction for the purpose of counting.  */
361 
362 static std::pair<int, bool>
dnf_size_r(tree t)363 dnf_size_r (tree t)
364 {
365   if (atomic_p (t))
366     /* Atomic constraints produce no clauses.  */
367     return std::make_pair (0, false);
368 
369   /* For compound constraints, recursively count clauses and unpack
370      the results.  */
371   tree lhs = TREE_OPERAND (t, 0);
372   tree rhs = TREE_OPERAND (t, 1);
373   std::pair<int, bool> p1 = dnf_size_r (lhs);
374   std::pair<int, bool> p2 = dnf_size_r (rhs);
375   int n1 = p1.first, n2 = p2.first;
376   bool d1 = p1.second, d2 = p2.second;
377 
378   if (disjunction_p (t))
379     {
380       /* Matches constraints of the form P \/ Q. Disjunctions contribute
381 	 linearly to the number of constraints.  When both P and Q are
382 	 disjunctions, clauses are added. When only one of P and Q
383 	 is a disjunction, an additional clause is produced. When neither
384 	 P nor Q are disjunctions, two clauses are produced.  */
385       if (disjunction_p (lhs))
386 	{
387 	  if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
388 	    /* Both P and Q are disjunctions.  */
389 	    return std::make_pair (n1 + n2, d1 | d2);
390 	  else
391 	    /* Only LHS is a disjunction.  */
392 	    return std::make_pair (1 + n1 + n2, d1 | d2);
393 	  gcc_unreachable ();
394 	}
395       if (conjunction_p (lhs))
396 	{
397 	  if ((disjunction_p (rhs) && d1) || (conjunction_p (rhs) && d1 && d2))
398 	    /* Both P and Q are disjunctions.  */
399 	    return std::make_pair (n1 + n2, d1 | d2);
400 	  if (disjunction_p (rhs)
401 	      || (conjunction_p (rhs) && d1 != d2)
402 	      || (atomic_p (rhs) && d1))
403 	    /* Either LHS or RHS is a disjunction.  */
404 	    return std::make_pair (1 + n1 + n2, d1 | d2);
405 	  else
406 	    /* Neither LHS nor RHS is a disjunction.  */
407 	    return std::make_pair (2, false);
408 	}
409       if (atomic_p (lhs))
410 	{
411 	  if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
412 	    /* Only RHS is a disjunction.  */
413 	    return std::make_pair (1 + n1 + n2, d1 | d2);
414 	  else
415 	    /* Neither LHS nor RHS is a disjunction.  */
416 	    return std::make_pair (2, false);
417 	}
418     }
419   else /* conjunction_p (t)  */
420     {
421       /* Matches constraints of the form P /\ Q, possibly resulting
422          in the distribution of one side over the other. When both
423          P and Q are disjunctions, the number of clauses are multiplied.
424 	 When only one of P and Q is a disjunction, the number of
425          clauses are added. Otherwise, neither side is a disjunction and
426          no clauses are created.  */
427       if (disjunction_p (lhs))
428 	{
429 	  if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
430 	    /* Both P and Q are disjunctions.  */
431 	    return std::make_pair (n1 * n2, true);
432 	  else
433 	    /* Only LHS is a disjunction.  */
434 	    return std::make_pair (n1 + n2, true);
435 	  gcc_unreachable ();
436 	}
437       if (conjunction_p (lhs))
438 	{
439 	  if ((disjunction_p (rhs) && d1) || (conjunction_p (rhs) && d1 && d2))
440 	    /* Both P and Q are disjunctions.  */
441 	    return std::make_pair (n1 * n2, true);
442 	  if (disjunction_p (rhs)
443 	      || (conjunction_p (rhs) && d1 != d2)
444 	      || (atomic_p (rhs) && d1))
445 	    /* Either LHS or RHS is a disjunction.  */
446 	    return std::make_pair (n1 + n2, true);
447 	  else
448 	    /* Neither LHS nor RHS is a disjunction.  */
449 	    return std::make_pair (0, false);
450 	}
451       if (atomic_p (lhs))
452 	{
453 	  if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
454 	    /* Only RHS is a disjunction.  */
455 	    return std::make_pair (n1 + n2, true);
456 	  else
457 	    /* Neither LHS nor RHS is a disjunction.  */
458 	    return std::make_pair (0, false);
459 	}
460     }
461   gcc_unreachable ();
462 }
463 
464 /* Recursively count the number of clauses produced when converting T
465    to CNF. Returns a pair containing the number of clauses and a bool
466    value signifying that the tree would be rewritten as a result of
467    distributing. In general, a disjunction for which this flag is set
468    is considered a conjunction for the purpose of counting.  */
469 
470 static std::pair<int, bool>
cnf_size_r(tree t)471 cnf_size_r (tree t)
472 {
473   if (atomic_p (t))
474     /* Atomic constraints produce no clauses.  */
475     return std::make_pair (0, false);
476 
477   /* For compound constraints, recursively count clauses and unpack
478      the results.  */
479   tree lhs = TREE_OPERAND (t, 0);
480   tree rhs = TREE_OPERAND (t, 1);
481   std::pair<int, bool> p1 = cnf_size_r (lhs);
482   std::pair<int, bool> p2 = cnf_size_r (rhs);
483   int n1 = p1.first, n2 = p2.first;
484   bool d1 = p1.second, d2 = p2.second;
485 
486   if (disjunction_p (t))
487     {
488       /* Matches constraints of the form P \/ Q, possibly resulting
489          in the distribution of one side over the other. When both
490          P and Q are conjunctions, the number of clauses are multiplied.
491 	 When only one of P and Q is a conjunction, the number of
492          clauses are added. Otherwise, neither side is a conjunction and
493          no clauses are created.  */
494       if (disjunction_p (lhs))
495 	{
496 	  if ((disjunction_p (rhs) && d1 && d2) || (conjunction_p (rhs) && d1))
497 	    /* Both P and Q are conjunctions.  */
498 	    return std::make_pair (n1 * n2, true);
499 	  if ((disjunction_p (rhs) && d1 != d2)
500 	      || conjunction_p (rhs)
501 	      || (atomic_p (rhs) && d1))
502 	    /* Either LHS or RHS is a conjunction.  */
503 	    return std::make_pair (n1 + n2, true);
504 	  else
505 	    /* Neither LHS nor RHS is a conjunction.  */
506 	    return std::make_pair (0, false);
507 	  gcc_unreachable ();
508 	}
509       if (conjunction_p (lhs))
510 	{
511 	  if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
512 	    /* Both LHS and RHS are conjunctions.  */
513 	    return std::make_pair (n1 * n2, true);
514 	  else
515 	    /* Only LHS is a conjunction.  */
516 	    return std::make_pair (n1 + n2, true);
517 	}
518       if (atomic_p (lhs))
519 	{
520 	  if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
521 	    /* Only RHS is a disjunction.  */
522 	    return std::make_pair (n1 + n2, true);
523 	  else
524 	    /* Neither LHS nor RHS is a disjunction.  */
525 	    return std::make_pair (0, false);
526 	}
527     }
528   else /* conjunction_p (t)  */
529     {
530       /* Matches constraints of the form P /\ Q. Conjunctions contribute
531 	 linearly to the number of constraints.  When both P and Q are
532 	 conjunctions, clauses are added. When only one of P and Q
533 	 is a conjunction, an additional clause is produced. When neither
534 	 P nor Q are conjunctions, two clauses are produced.  */
535       if (disjunction_p (lhs))
536 	{
537 	  if ((disjunction_p (rhs) && d1 && d2) || (conjunction_p (rhs) && d1))
538 	    /* Both P and Q are conjunctions.  */
539 	    return std::make_pair (n1 + n2, d1 | d2);
540 	  if ((disjunction_p (rhs) && d1 != d2)
541 	      || conjunction_p (rhs)
542 	      || (atomic_p (rhs) && d1))
543 	    /* Either LHS or RHS is a conjunction.  */
544 	    return std::make_pair (1 + n1 + n2, d1 | d2);
545 	  else
546 	    /* Neither LHS nor RHS is a conjunction.  */
547 	    return std::make_pair (2, false);
548 	  gcc_unreachable ();
549 	}
550       if (conjunction_p (lhs))
551 	{
552 	  if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
553 	    /* Both LHS and RHS are conjunctions.  */
554 	    return std::make_pair (n1 + n2, d1 | d2);
555 	  else
556 	    /* Only LHS is a conjunction.  */
557 	    return std::make_pair (1 + n1 + n2, d1 | d2);
558 	}
559       if (atomic_p (lhs))
560 	{
561 	  if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
562 	    /* Only RHS is a disjunction.  */
563 	    return std::make_pair (1 + n1 + n2, d1 | d2);
564 	  else
565 	    /* Neither LHS nor RHS is a disjunction.  */
566 	    return std::make_pair (2, false);
567 	}
568     }
569   gcc_unreachable ();
570 }
571 
572 /* Count the number conjunctive clauses that would be created
573    when rewriting T to DNF. */
574 
575 static int
dnf_size(tree t)576 dnf_size (tree t)
577 {
578   std::pair<int, bool> result = dnf_size_r (t);
579   return result.first == 0 ? 1 : result.first;
580 }
581 
582 
583 /* Count the number disjunctive clauses that would be created
584    when rewriting T to CNF. */
585 
586 static int
cnf_size(tree t)587 cnf_size (tree t)
588 {
589   std::pair<int, bool> result = cnf_size_r (t);
590   return result.first == 0 ? 1 : result.first;
591 }
592 
593 
594 /* A left-conjunction is replaced by its operands.  */
595 
596 void
replace_term(clause & c,tree t)597 replace_term (clause& c, tree t)
598 {
599   tree t1 = TREE_OPERAND (t, 0);
600   tree t2 = TREE_OPERAND (t, 1);
601   return c.replace (t1, t2);
602 }
603 
604 /* Create a new clause in the formula by copying the current
605    clause. In the current clause, the term at CI is replaced
606    by the first operand, and in the new clause, it is replaced
607    by the second.  */
608 
609 void
branch_clause(formula & f,clause & c1,tree t)610 branch_clause (formula& f, clause& c1, tree t)
611 {
612   tree t1 = TREE_OPERAND (t, 0);
613   tree t2 = TREE_OPERAND (t, 1);
614   clause& c2 = f.branch ();
615   c1.replace (t1);
616   c2.replace (t2);
617 }
618 
619 /* Decompose t1 /\ t2 according to the rules R.  */
620 
621 inline void
decompose_conjuntion(formula & f,clause & c,tree t,rules r)622 decompose_conjuntion (formula& f, clause& c, tree t, rules r)
623 {
624   if (r == left)
625     replace_term (c, t);
626   else
627     branch_clause (f, c, t);
628 }
629 
630 /* Decompose t1 \/ t2 according to the rules R.  */
631 
632 inline void
decompose_disjunction(formula & f,clause & c,tree t,rules r)633 decompose_disjunction (formula& f, clause& c, tree t, rules r)
634 {
635   if (r == right)
636     replace_term (c, t);
637   else
638     branch_clause (f, c, t);
639 }
640 
641 /* An atomic constraint is already decomposed.  */
642 inline void
decompose_atom(clause & c)643 decompose_atom (clause& c)
644 {
645   c.advance ();
646 }
647 
648 /* Decompose a term of clause C (in formula F) according to the
649    logical rules R. */
650 
651 void
decompose_term(formula & f,clause & c,tree t,rules r)652 decompose_term (formula& f, clause& c, tree t, rules r)
653 {
654   switch (TREE_CODE (t))
655     {
656       case CONJ_CONSTR:
657         return decompose_conjuntion (f, c, t, r);
658       case DISJ_CONSTR:
659 	return decompose_disjunction (f, c, t, r);
660       default:
661 	return decompose_atom (c);
662     }
663 }
664 
665 /* Decompose C (in F) using the logical rules R until it
666    is comprised of only atomic constraints.  */
667 
668 void
decompose_clause(formula & f,clause & c,rules r)669 decompose_clause (formula& f, clause& c, rules r)
670 {
671   while (!c.done ())
672     decompose_term (f, c, *c.current (), r);
673   f.advance ();
674 }
675 
676 /* Decompose the logical formula F according to the logical
677    rules determined by R.  The result is a formula containing
678    clauses that contain only atomic terms.  */
679 
680 void
decompose_formula(formula & f,rules r)681 decompose_formula (formula& f, rules r)
682 {
683   while (!f.done ())
684     decompose_clause (f, *f.current (), r);
685 }
686 
687 /* Fully decomposing T into a list of sequents, each comprised of
688    a list of atomic constraints, as if T were an antecedent.  */
689 
690 static formula
decompose_antecedents(tree t)691 decompose_antecedents (tree t)
692 {
693   formula f (t);
694   decompose_formula (f, left);
695   return f;
696 }
697 
698 /* Fully decomposing T into a list of sequents, each comprised of
699    a list of atomic constraints, as if T were a consequent.  */
700 
701 static formula
decompose_consequents(tree t)702 decompose_consequents (tree t)
703 {
704   formula f (t);
705   decompose_formula (f, right);
706   return f;
707 }
708 
709 static bool derive_proof (clause&, tree, rules);
710 
711 /* Derive a proof of both operands of T.  */
712 
713 static bool
derive_proof_for_both_operands(clause & c,tree t,rules r)714 derive_proof_for_both_operands (clause& c, tree t, rules r)
715 {
716   if (!derive_proof (c, TREE_OPERAND (t, 0), r))
717     return false;
718   return derive_proof (c, TREE_OPERAND (t, 1), r);
719 }
720 
721 /* Derive a proof of either operand of T.  */
722 
723 static bool
derive_proof_for_either_operand(clause & c,tree t,rules r)724 derive_proof_for_either_operand (clause& c, tree t, rules r)
725 {
726   if (derive_proof (c, TREE_OPERAND (t, 0), r))
727     return true;
728   return derive_proof (c, TREE_OPERAND (t, 1), r);
729 }
730 
731 /* Derive a proof of the atomic constraint T in clause C.  */
732 
733 static bool
derive_atomic_proof(clause & c,tree t)734 derive_atomic_proof (clause& c, tree t)
735 {
736   return c.contains (t);
737 }
738 
739 /* Derive a proof of T from the terms in C.  */
740 
741 static bool
derive_proof(clause & c,tree t,rules r)742 derive_proof (clause& c, tree t, rules r)
743 {
744   switch (TREE_CODE (t))
745   {
746     case CONJ_CONSTR:
747       if (r == left)
748         return derive_proof_for_both_operands (c, t, r);
749       else
750 	return derive_proof_for_either_operand (c, t, r);
751     case DISJ_CONSTR:
752       if (r == left)
753         return derive_proof_for_either_operand (c, t, r);
754       else
755 	return derive_proof_for_both_operands (c, t, r);
756     default:
757       return derive_atomic_proof (c, t);
758   }
759 }
760 
761 /* Derive a proof of T from disjunctive clauses in F.  */
762 
763 static bool
derive_proofs(formula & f,tree t,rules r)764 derive_proofs (formula& f, tree t, rules r)
765 {
766   for (formula::iterator i = f.begin(); i != f.end(); ++i)
767     if (!derive_proof (*i, t, r))
768       return false;
769   return true;
770 }
771 
772 /* The largest number of clauses in CNF or DNF we accept as input
773    for subsumption. This an upper bound of 2^16 expressions.  */
774 static int max_problem_size = 16;
775 
776 static inline bool
diagnose_constraint_size(tree t)777 diagnose_constraint_size (tree t)
778 {
779   error_at (input_location, "%qE exceeds the maximum constraint complexity", t);
780   return false;
781 }
782 
783 /* Key/value pair for caching subsumption results. This associates a pair of
784    constraints with a boolean value indicating the result.  */
785 
786 struct GTY((for_user)) subsumption_entry
787 {
788   tree lhs;
789   tree rhs;
790   bool result;
791 };
792 
793 /* Hashing function and equality for constraint entries.  */
794 
795 struct subsumption_hasher : ggc_ptr_hash<subsumption_entry>
796 {
hashsubsumption_hasher797   static hashval_t hash (subsumption_entry *e)
798   {
799     hashval_t val = 0;
800     val = iterative_hash_constraint (e->lhs, val);
801     val = iterative_hash_constraint (e->rhs, val);
802     return val;
803   }
804 
equalsubsumption_hasher805   static bool equal (subsumption_entry *e1, subsumption_entry *e2)
806   {
807     if (!constraints_equivalent_p (e1->lhs, e2->lhs))
808       return false;
809     if (!constraints_equivalent_p (e1->rhs, e2->rhs))
810       return false;
811     return true;
812   }
813 };
814 
815 /* Caches the results of subsumes_non_null(t1, t1).  */
816 
817 static GTY ((deletable)) hash_table<subsumption_hasher> *subsumption_cache;
818 
819 /* Search for a previously cached subsumption result. */
820 
821 static bool*
lookup_subsumption(tree t1,tree t2)822 lookup_subsumption (tree t1, tree t2)
823 {
824   if (!subsumption_cache)
825     return NULL;
826   subsumption_entry elt = { t1, t2, false };
827   subsumption_entry* found = subsumption_cache->find (&elt);
828   if (found)
829     return &found->result;
830   else
831     return 0;
832 }
833 
834 /* Save a subsumption result. */
835 
836 static bool
save_subsumption(tree t1,tree t2,bool result)837 save_subsumption (tree t1, tree t2, bool result)
838 {
839   if (!subsumption_cache)
840     subsumption_cache = hash_table<subsumption_hasher>::create_ggc(31);
841   subsumption_entry elt = {t1, t2, result};
842   subsumption_entry** slot = subsumption_cache->find_slot (&elt, INSERT);
843   subsumption_entry* entry = ggc_alloc<subsumption_entry> ();
844   *entry = elt;
845   *slot = entry;
846   return result;
847 }
848 
849 
850 /* Returns true if the LEFT constraint subsume the RIGHT constraints.
851    This is done by deriving a proof of the conclusions on the RIGHT
852    from the assumptions on the LEFT assumptions.  */
853 
854 static bool
subsumes_constraints_nonnull(tree lhs,tree rhs)855 subsumes_constraints_nonnull (tree lhs, tree rhs)
856 {
857   auto_timevar time (TV_CONSTRAINT_SUB);
858 
859   if (bool *b = lookup_subsumption(lhs, rhs))
860     return *b;
861 
862   int n1 = dnf_size (lhs);
863   int n2 = cnf_size (rhs);
864 
865   /* Make sure we haven't exceeded the largest acceptable problem.  */
866   if (std::min (n1, n2) >= max_problem_size)
867     {
868       if (n1 < n2)
869         diagnose_constraint_size (lhs);
870       else
871 	diagnose_constraint_size (rhs);
872       return false;
873     }
874 
875   /* Decompose the smaller of the two formulas, and recursively
876      check for implication of the larger.  */
877   bool result;
878   if (n1 <= n2)
879     {
880       formula dnf = decompose_antecedents (lhs);
881       result = derive_proofs (dnf, rhs, left);
882     }
883   else
884     {
885       formula cnf = decompose_consequents (rhs);
886       result = derive_proofs (cnf, lhs, right);
887     }
888 
889   return save_subsumption (lhs, rhs, result);
890 }
891 
892 /* Returns true if the LEFT constraints subsume the RIGHT
893    constraints.  */
894 
895 bool
subsumes(tree lhs,tree rhs)896 subsumes (tree lhs, tree rhs)
897 {
898   if (lhs == rhs)
899     return true;
900   if (!lhs || lhs == error_mark_node)
901     return false;
902   if (!rhs || rhs == error_mark_node)
903     return true;
904   return subsumes_constraints_nonnull (lhs, rhs);
905 }
906 
907 #include "gt-cp-logic.h"
908