Line data Source code
1 : /* Derivation and subsumption rules for constraints.
2 : Copyright (C) 2013-2023 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 : /* A conjunctive or disjunctive clause.
51 :
52 : Each clause maintains an iterator that refers to the current
53 : term, which is used in the linear decomposition of a formula
54 : into CNF or DNF. */
55 :
56 1542 : struct clause
57 : {
58 : typedef std::list<tree>::iterator iterator;
59 : typedef std::list<tree>::const_iterator const_iterator;
60 :
61 : /* Initialize a clause with an initial term. */
62 :
63 1426 : clause (tree t)
64 1426 : {
65 1426 : m_terms.push_back (t);
66 1426 : if (TREE_CODE (t) == ATOMIC_CONSTR)
67 403 : m_set.add (t);
68 :
69 1426 : m_current = m_terms.begin ();
70 1426 : }
71 :
72 : /* Create a copy of the current term. The current
73 : iterator is set to point to the same position in the
74 : copied list of terms. */
75 :
76 116 : clause (clause const& c)
77 116 : : m_terms (c.m_terms), m_set (c.m_set), m_current (m_terms.begin ())
78 : {
79 116 : std::advance (m_current, std::distance (c.begin (), c.current ()));
80 116 : }
81 :
82 : /* Returns true when all terms are atoms. */
83 :
84 272564 : bool done () const
85 : {
86 272564 : return m_current == end ();
87 : }
88 :
89 : /* Advance to the next term. */
90 :
91 44454 : void advance ()
92 : {
93 0 : gcc_assert (!done ());
94 44454 : ++m_current;
95 44454 : }
96 :
97 : /* Replaces the current term at position ITER with T. If
98 : T is an atomic constraint that already appears in the
99 : clause, remove but do not replace ITER. Returns a pair
100 : containing an iterator to the replace object or past
101 : the erased object and a boolean value which is true if
102 : an object was erased. */
103 :
104 182231 : std::pair<iterator, bool> replace (iterator iter, tree t)
105 : {
106 182231 : gcc_assert (TREE_CODE (*iter) != ATOMIC_CONSTR);
107 182231 : if (TREE_CODE (t) == ATOMIC_CONSTR)
108 : {
109 88856 : if (m_set.add (t))
110 69790 : return std::make_pair (m_terms.erase (iter), true);
111 : }
112 112441 : *iter = t;
113 112441 : return std::make_pair (iter, false);
114 : }
115 :
116 : /* Inserts T before ITER in the list of terms. If T has
117 : already is an atomic constraint that already appears in
118 : the clause, no action is taken, and the current iterator
119 : is returned. Returns a pair of an iterator to the inserted
120 : object or ITER if no insertion occurred and a boolean
121 : value which is true if an object was inserted. */
122 :
123 181999 : std::pair<iterator, bool> insert (iterator iter, tree t)
124 : {
125 181999 : if (TREE_CODE (t) == ATOMIC_CONSTR)
126 : {
127 94281 : if (m_set.add (t))
128 69296 : return std::make_pair (iter, false);
129 : }
130 112703 : return std::make_pair (m_terms.insert (iter, t), true);
131 : }
132 :
133 : /* Replaces the current term with T. In the case where the
134 : current term is erased (because T is redundant), update
135 : the position of the current term to the next term. */
136 :
137 232 : void replace (tree t)
138 : {
139 232 : m_current = replace (m_current, t).first;
140 232 : }
141 :
142 : /* Replace the current term with T1 and T2, in that order. */
143 :
144 181999 : void replace (tree t1, tree t2)
145 : {
146 : /* Replace the current term with t1. Ensure that iter points
147 : to the term before which t2 will be inserted. Update the
148 : current term as needed. */
149 181999 : std::pair<iterator, bool> rep = replace (m_current, t1);
150 181999 : if (rep.second)
151 69790 : m_current = rep.first;
152 : else
153 112209 : ++rep.first;
154 :
155 : /* Insert the t2. Make this the current term if we erased
156 : the prior term. */
157 181999 : std::pair<iterator, bool> ins = insert (rep.first, t2);
158 181999 : if (rep.second && ins.second)
159 18361 : m_current = ins.first;
160 181999 : }
161 :
162 : /* Returns true if the clause contains the term T. */
163 :
164 65951 : bool contains (tree t)
165 : {
166 65951 : gcc_assert (TREE_CODE (t) == ATOMIC_CONSTR);
167 65951 : return m_set.contains (t);
168 : }
169 :
170 :
171 : /* Returns an iterator to the first clause in the formula. */
172 :
173 0 : iterator begin ()
174 : {
175 0 : return m_terms.begin ();
176 : }
177 :
178 : /* Returns an iterator to the first clause in the formula. */
179 :
180 116 : const_iterator begin () const
181 : {
182 116 : return m_terms.begin ();
183 : }
184 :
185 : /* Returns an iterator past the last clause in the formula. */
186 :
187 0 : iterator end ()
188 : {
189 0 : return m_terms.end ();
190 : }
191 :
192 : /* Returns an iterator past the last clause in the formula. */
193 :
194 272564 : const_iterator end () const
195 : {
196 44454 : return m_terms.end ();
197 : }
198 :
199 : /* Returns the current iterator. */
200 :
201 226685 : const_iterator current () const
202 : {
203 116 : return m_current;
204 : }
205 :
206 : std::list<tree> m_terms; /* The list of terms. */
207 : hash_set<tree, false, atom_hasher> m_set; /* The set of atomic constraints. */
208 : iterator m_current; /* The current term. */
209 : };
210 :
211 :
212 : /* A proof state owns a list of goals and tracks the
213 : current sub-goal. The class also provides facilities
214 : for managing subgoals and constructing term lists. */
215 :
216 1426 : struct formula
217 : {
218 : typedef std::list<clause>::iterator iterator;
219 : typedef std::list<clause>::const_iterator const_iterator;
220 :
221 : /* Construct a formula with an initial formula in a
222 : single clause. */
223 :
224 1426 : formula (tree t)
225 1426 : {
226 1426 : m_clauses.emplace_back (t);
227 1426 : m_current = m_clauses.begin ();
228 1426 : }
229 :
230 : /* Returns true when all clauses are atomic. */
231 3881 : bool done () const
232 : {
233 3881 : return m_current == end ();
234 : }
235 :
236 : /* Advance to the next term. */
237 1541 : void advance ()
238 : {
239 0 : gcc_assert (!done ());
240 1541 : ++m_current;
241 1541 : }
242 :
243 : /* Insert a copy of clause into the formula. This corresponds
244 : to a distribution of one logical operation over the other. */
245 :
246 116 : clause& branch ()
247 : {
248 0 : gcc_assert (!done ());
249 116 : return *m_clauses.insert (std::next (m_current), *m_current);
250 : }
251 :
252 : /* Returns the position of the current clause. */
253 :
254 : iterator current ()
255 : {
256 : return m_current;
257 : }
258 :
259 : /* Returns an iterator to the first clause in the formula. */
260 :
261 0 : iterator begin ()
262 : {
263 0 : return m_clauses.begin ();
264 : }
265 :
266 : /* Returns an iterator to the first clause in the formula. */
267 :
268 : const_iterator begin () const
269 : {
270 : return m_clauses.begin ();
271 : }
272 :
273 : /* Returns an iterator past the last clause in the formula. */
274 :
275 0 : iterator end ()
276 : {
277 0 : return m_clauses.end ();
278 : }
279 :
280 : /* Returns an iterator past the last clause in the formula. */
281 :
282 3881 : const_iterator end () const
283 : {
284 1657 : return m_clauses.end ();
285 : }
286 :
287 : /* Remove the specified clause from the formula. */
288 :
289 798 : void erase (iterator i)
290 : {
291 798 : gcc_assert (i != m_current);
292 798 : m_clauses.erase (i);
293 798 : }
294 :
295 : std::list<clause> m_clauses; /* The list of clauses. */
296 : iterator m_current; /* The current clause. */
297 : };
298 :
299 : void
300 0 : debug (clause& c)
301 : {
302 0 : for (clause::iterator i = c.begin(); i != c.end(); ++i)
303 0 : verbatim (" # %E", *i);
304 0 : }
305 :
306 : void
307 0 : debug (formula& f)
308 : {
309 0 : for (formula::iterator i = f.begin(); i != f.end(); ++i)
310 : {
311 : /* Format punctuators via %s to avoid -Wformat-diag. */
312 0 : verbatim ("%s", "(((");
313 0 : debug (*i);
314 0 : verbatim ("%s", ")))");
315 : }
316 0 : }
317 :
318 : /* The logical rules used to analyze a logical formula. The
319 : "left" and "right" refer to the position of formula in a
320 : sequent (as in sequent calculus). */
321 :
322 : enum rules
323 : {
324 : left, right
325 : };
326 :
327 : /* Distribution counting. */
328 :
329 : static inline bool
330 1092783 : disjunction_p (tree t)
331 : {
332 1092783 : return TREE_CODE (t) == DISJ_CONSTR;
333 : }
334 :
335 : static inline bool
336 : conjunction_p (tree t)
337 : {
338 : return TREE_CODE (t) == CONJ_CONSTR;
339 : }
340 :
341 : static inline bool
342 731374 : atomic_p (tree t)
343 : {
344 731374 : return TREE_CODE (t) == ATOMIC_CONSTR;
345 : }
346 :
347 : /* Recursively count the number of clauses produced when converting T
348 : to DNF. Returns a pair containing the number of clauses and a bool
349 : value signifying that the tree would be rewritten as a result of
350 : distributing. In general, a conjunction for which this flag is set
351 : is considered a disjunction for the purpose of counting. */
352 :
353 : static std::pair<int, bool>
354 365686 : dnf_size_r (tree t)
355 : {
356 365686 : if (atomic_p (t))
357 : /* Atomic constraints produce no clauses. */
358 183556 : return std::make_pair (0, false);
359 :
360 : /* For compound constraints, recursively count clauses and unpack
361 : the results. */
362 182130 : tree lhs = TREE_OPERAND (t, 0);
363 182130 : tree rhs = TREE_OPERAND (t, 1);
364 182130 : std::pair<int, bool> p1 = dnf_size_r (lhs);
365 182130 : std::pair<int, bool> p2 = dnf_size_r (rhs);
366 182130 : int n1 = p1.first, n2 = p2.first;
367 182130 : bool d1 = p1.second, d2 = p2.second;
368 :
369 182130 : if (disjunction_p (t))
370 : {
371 : /* Matches constraints of the form P \/ Q. Disjunctions contribute
372 : linearly to the number of constraints. When both P and Q are
373 : disjunctions, clauses are added. When only one of P and Q
374 : is a disjunction, an additional clause is produced. When neither
375 : P nor Q are disjunctions, two clauses are produced. */
376 116 : if (disjunction_p (lhs))
377 : {
378 0 : if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
379 : /* Both P and Q are disjunctions. */
380 0 : return std::make_pair (n1 + n2, d1 | d2);
381 : else
382 : /* Only LHS is a disjunction. */
383 0 : return std::make_pair (1 + n1 + n2, d1 | d2);
384 : gcc_unreachable ();
385 : }
386 116 : if (conjunction_p (lhs))
387 : {
388 116 : if ((disjunction_p (rhs) && d1) || (conjunction_p (rhs) && d1 && d2))
389 : /* Both P and Q are disjunctions. */
390 0 : return std::make_pair (n1 + n2, d1 | d2);
391 116 : if (disjunction_p (rhs)
392 116 : || (conjunction_p (rhs) && d1 != d2)
393 232 : || (atomic_p (rhs) && d1))
394 : /* Either LHS or RHS is a disjunction. */
395 0 : return std::make_pair (1 + n1 + n2, d1 | d2);
396 : else
397 : /* Neither LHS nor RHS is a disjunction. */
398 116 : return std::make_pair (2, false);
399 : }
400 0 : if (atomic_p (lhs))
401 : {
402 0 : if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
403 : /* Only RHS is a disjunction. */
404 0 : return std::make_pair (1 + n1 + n2, d1 | d2);
405 : else
406 : /* Neither LHS nor RHS is a disjunction. */
407 0 : return std::make_pair (2, false);
408 : }
409 : }
410 : else /* conjunction_p (t) */
411 : {
412 : /* Matches constraints of the form P /\ Q, possibly resulting
413 : in the distribution of one side over the other. When both
414 : P and Q are disjunctions, the number of clauses are multiplied.
415 : When only one of P and Q is a disjunction, the number of
416 : clauses are added. Otherwise, neither side is a disjunction and
417 : no clauses are created. */
418 182014 : if (disjunction_p (lhs))
419 : {
420 0 : if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
421 : /* Both P and Q are disjunctions. */
422 0 : return std::make_pair (n1 * n2, true);
423 : else
424 : /* Only LHS is a disjunction. */
425 0 : return std::make_pair (n1 + n2, true);
426 : gcc_unreachable ();
427 : }
428 182014 : if (conjunction_p (lhs))
429 : {
430 93150 : if ((disjunction_p (rhs) && d1) || (conjunction_p (rhs) && d1 && d2))
431 : /* Both P and Q are disjunctions. */
432 0 : return std::make_pair (n1 * n2, true);
433 93150 : if (disjunction_p (rhs)
434 93035 : || (conjunction_p (rhs) && d1 != d2)
435 186185 : || (atomic_p (rhs) && d1))
436 : /* Either LHS or RHS is a disjunction. */
437 115 : return std::make_pair (n1 + n2, true);
438 : else
439 : /* Neither LHS nor RHS is a disjunction. */
440 93035 : return std::make_pair (0, false);
441 : }
442 88864 : if (atomic_p (lhs))
443 : {
444 88864 : if (disjunction_p (rhs) || (conjunction_p (rhs) && d2))
445 : /* Only RHS is a disjunction. */
446 0 : return std::make_pair (n1 + n2, true);
447 : else
448 : /* Neither LHS nor RHS is a disjunction. */
449 88864 : return std::make_pair (0, false);
450 : }
451 : }
452 0 : gcc_unreachable ();
453 : }
454 :
455 : /* Recursively count the number of clauses produced when converting T
456 : to CNF. Returns a pair containing the number of clauses and a bool
457 : value signifying that the tree would be rewritten as a result of
458 : distributing. In general, a disjunction for which this flag is set
459 : is considered a conjunction for the purpose of counting. */
460 :
461 : static std::pair<int, bool>
462 365688 : cnf_size_r (tree t)
463 : {
464 365688 : if (atomic_p (t))
465 : /* Atomic constraints produce no clauses. */
466 183557 : return std::make_pair (0, false);
467 :
468 : /* For compound constraints, recursively count clauses and unpack
469 : the results. */
470 182131 : tree lhs = TREE_OPERAND (t, 0);
471 182131 : tree rhs = TREE_OPERAND (t, 1);
472 182131 : std::pair<int, bool> p1 = cnf_size_r (lhs);
473 182131 : std::pair<int, bool> p2 = cnf_size_r (rhs);
474 182131 : int n1 = p1.first, n2 = p2.first;
475 182131 : bool d1 = p1.second, d2 = p2.second;
476 :
477 182131 : if (disjunction_p (t))
478 : {
479 : /* Matches constraints of the form P \/ Q, possibly resulting
480 : in the distribution of one side over the other. When both
481 : P and Q are conjunctions, the number of clauses are multiplied.
482 : When only one of P and Q is a conjunction, the number of
483 : clauses are added. Otherwise, neither side is a conjunction and
484 : no clauses are created. */
485 116 : if (disjunction_p (lhs))
486 : {
487 0 : if ((disjunction_p (rhs) && d1 && d2) || (conjunction_p (rhs) && d1))
488 : /* Both P and Q are conjunctions. */
489 0 : return std::make_pair (n1 * n2, true);
490 0 : if ((disjunction_p (rhs) && d1 != d2)
491 0 : || conjunction_p (rhs)
492 0 : || (atomic_p (rhs) && d1))
493 : /* Either LHS or RHS is a conjunction. */
494 0 : return std::make_pair (n1 + n2, true);
495 : else
496 : /* Neither LHS nor RHS is a conjunction. */
497 0 : return std::make_pair (0, false);
498 : }
499 116 : if (conjunction_p (lhs))
500 : {
501 116 : if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
502 : /* Both LHS and RHS are conjunctions. */
503 116 : return std::make_pair (n1 * n2, true);
504 : else
505 : /* Only LHS is a conjunction. */
506 0 : return std::make_pair (n1 + n2, true);
507 : }
508 0 : if (atomic_p (lhs))
509 : {
510 0 : if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
511 : /* Only RHS is a disjunction. */
512 0 : return std::make_pair (n1 + n2, true);
513 : else
514 : /* Neither LHS nor RHS is a disjunction. */
515 0 : return std::make_pair (0, false);
516 : }
517 : }
518 : else /* conjunction_p (t) */
519 : {
520 : /* Matches constraints of the form P /\ Q. Conjunctions contribute
521 : linearly to the number of constraints. When both P and Q are
522 : conjunctions, clauses are added. When only one of P and Q
523 : is a conjunction, an additional clause is produced. When neither
524 : P nor Q are conjunctions, two clauses are produced. */
525 182015 : if (disjunction_p (lhs))
526 : {
527 0 : if ((disjunction_p (rhs) && d1 && d2) || (conjunction_p (rhs) && d1))
528 : /* Both P and Q are conjunctions. */
529 0 : return std::make_pair (n1 + n2, d1 | d2);
530 0 : if ((disjunction_p (rhs) && d1 != d2)
531 0 : || conjunction_p (rhs)
532 0 : || (atomic_p (rhs) && d1))
533 : /* Either LHS or RHS is a conjunction. */
534 0 : return std::make_pair (1 + n1 + n2, d1 | d2);
535 : else
536 : /* Neither LHS nor RHS is a conjunction. */
537 0 : return std::make_pair (2, false);
538 : }
539 182015 : if (conjunction_p (lhs))
540 : {
541 93150 : if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
542 : /* Both LHS and RHS are conjunctions. */
543 69242 : return std::make_pair (n1 + n2, d1 | d2);
544 : else
545 : /* Only LHS is a conjunction. */
546 23908 : return std::make_pair (1 + n1 + n2, d1 | d2);
547 : }
548 88865 : if (atomic_p (lhs))
549 : {
550 88865 : if ((disjunction_p (rhs) && d2) || conjunction_p (rhs))
551 : /* Only RHS is a disjunction. */
552 18483 : return std::make_pair (1 + n1 + n2, d1 | d2);
553 : else
554 : /* Neither LHS nor RHS is a disjunction. */
555 70382 : return std::make_pair (2, false);
556 : }
557 : }
558 0 : gcc_unreachable ();
559 : }
560 :
561 : /* Count the number conjunctive clauses that would be created
562 : when rewriting T to DNF. */
563 :
564 : static int
565 1426 : dnf_size (tree t)
566 : {
567 0 : std::pair<int, bool> result = dnf_size_r (t);
568 1426 : return result.first == 0 ? 1 : result.first;
569 : }
570 :
571 :
572 : /* Count the number disjunctive clauses that would be created
573 : when rewriting T to CNF. */
574 :
575 : static int
576 1426 : cnf_size (tree t)
577 : {
578 0 : std::pair<int, bool> result = cnf_size_r (t);
579 1426 : return result.first == 0 ? 1 : result.first;
580 : }
581 :
582 :
583 : /* A left-conjunction is replaced by its operands. */
584 :
585 : void
586 181999 : replace_term (clause& c, tree t)
587 : {
588 181999 : tree t1 = TREE_OPERAND (t, 0);
589 181999 : tree t2 = TREE_OPERAND (t, 1);
590 181999 : return c.replace (t1, t2);
591 : }
592 :
593 : /* Create a new clause in the formula by copying the current
594 : clause. In the current clause, the term at CI is replaced
595 : by the first operand, and in the new clause, it is replaced
596 : by the second. */
597 :
598 : void
599 116 : branch_clause (formula& f, clause& c1, tree t)
600 : {
601 116 : tree t1 = TREE_OPERAND (t, 0);
602 116 : tree t2 = TREE_OPERAND (t, 1);
603 116 : clause& c2 = f.branch ();
604 116 : c1.replace (t1);
605 116 : c2.replace (t2);
606 116 : }
607 :
608 : /* Decompose t1 /\ t2 according to the rules R. */
609 :
610 : inline void
611 181999 : decompose_conjuntion (formula& f, clause& c, tree t, rules r)
612 : {
613 181999 : if (r == left)
614 181999 : replace_term (c, t);
615 : else
616 0 : branch_clause (f, c, t);
617 181999 : }
618 :
619 : /* Decompose t1 \/ t2 according to the rules R. */
620 :
621 : inline void
622 116 : decompose_disjunction (formula& f, clause& c, tree t, rules r)
623 : {
624 116 : if (r == right)
625 0 : replace_term (c, t);
626 : else
627 116 : branch_clause (f, c, t);
628 116 : }
629 :
630 : /* An atomic constraint is already decomposed. */
631 : inline void
632 44454 : decompose_atom (clause& c)
633 : {
634 44454 : c.advance ();
635 44454 : }
636 :
637 : /* Decompose a term of clause C (in formula F) according to the
638 : logical rules R. */
639 :
640 : void
641 226569 : decompose_term (formula& f, clause& c, tree t, rules r)
642 : {
643 226569 : switch (TREE_CODE (t))
644 : {
645 181999 : case CONJ_CONSTR:
646 181999 : return decompose_conjuntion (f, c, t, r);
647 116 : case DISJ_CONSTR:
648 116 : return decompose_disjunction (f, c, t, r);
649 44454 : default:
650 44454 : return decompose_atom (c);
651 : }
652 : }
653 :
654 : /* Decompose C (in F) using the logical rules R until it
655 : is comprised of only atomic constraints. */
656 :
657 : void
658 1541 : decompose_clause (formula& f, clause& c, rules r)
659 : {
660 228110 : while (!c.done ())
661 226569 : decompose_term (f, c, *c.current (), r);
662 1541 : f.advance ();
663 1541 : }
664 :
665 : static bool derive_proof (clause&, tree, rules);
666 :
667 : /* Derive a proof of both operands of T. */
668 :
669 : static bool
670 67038 : derive_proof_for_both_operands (clause& c, tree t, rules r)
671 : {
672 67038 : if (!derive_proof (c, TREE_OPERAND (t, 0), r))
673 : return false;
674 64294 : return derive_proof (c, TREE_OPERAND (t, 1), r);
675 : }
676 :
677 : /* Derive a proof of either operand of T. */
678 :
679 : static bool
680 116 : derive_proof_for_either_operand (clause& c, tree t, rules r)
681 : {
682 116 : if (derive_proof (c, TREE_OPERAND (t, 0), r))
683 : return true;
684 116 : return derive_proof (c, TREE_OPERAND (t, 1), r);
685 : }
686 :
687 : /* Derive a proof of the atomic constraint T in clause C. */
688 :
689 : static bool
690 65951 : derive_atomic_proof (clause& c, tree t)
691 : {
692 0 : return c.contains (t);
693 : }
694 :
695 : /* Derive a proof of T from the terms in C. */
696 :
697 : static bool
698 133105 : derive_proof (clause& c, tree t, rules r)
699 : {
700 133105 : switch (TREE_CODE (t))
701 : {
702 67038 : case CONJ_CONSTR:
703 67038 : if (r == left)
704 67038 : return derive_proof_for_both_operands (c, t, r);
705 : else
706 0 : return derive_proof_for_either_operand (c, t, r);
707 116 : case DISJ_CONSTR:
708 116 : if (r == left)
709 116 : return derive_proof_for_either_operand (c, t, r);
710 : else
711 0 : return derive_proof_for_both_operands (c, t, r);
712 65951 : default:
713 65951 : return derive_atomic_proof (c, t);
714 : }
715 : }
716 :
717 : /* Key/value pair for caching subsumption results. This associates a pair of
718 : constraints with a boolean value indicating the result. */
719 :
720 : struct GTY((for_user)) subsumption_entry
721 : {
722 : tree lhs;
723 : tree rhs;
724 : bool result;
725 : };
726 :
727 : /* Hashing function and equality for constraint entries. */
728 :
729 : struct subsumption_hasher : ggc_ptr_hash<subsumption_entry>
730 : {
731 9392 : static hashval_t hash (subsumption_entry *e)
732 : {
733 9392 : hashval_t val = 0;
734 9392 : val = iterative_hash_constraint (e->lhs, val);
735 9392 : val = iterative_hash_constraint (e->rhs, val);
736 9392 : return val;
737 : }
738 :
739 6721 : static bool equal (subsumption_entry *e1, subsumption_entry *e2)
740 : {
741 6721 : if (!constraints_equivalent_p (e1->lhs, e2->lhs))
742 : return false;
743 2125 : if (!constraints_equivalent_p (e1->rhs, e2->rhs))
744 : return false;
745 : return true;
746 : }
747 : };
748 :
749 : /* Caches the results of subsumes_non_null(t1, t1). */
750 :
751 : static GTY ((deletable)) hash_table<subsumption_hasher> *subsumption_cache;
752 :
753 : /* Search for a previously cached subsumption result. */
754 :
755 : static bool*
756 3405 : lookup_subsumption (tree t1, tree t2)
757 : {
758 3405 : if (!subsumption_cache)
759 : return NULL;
760 3046 : subsumption_entry elt = { t1, t2, false };
761 3046 : subsumption_entry* found = subsumption_cache->find (&elt);
762 3046 : if (found)
763 1979 : return &found->result;
764 : else
765 : return 0;
766 : }
767 :
768 : /* Save a subsumption result. */
769 :
770 : static bool
771 1426 : save_subsumption (tree t1, tree t2, bool result)
772 : {
773 1426 : if (!subsumption_cache)
774 359 : subsumption_cache = hash_table<subsumption_hasher>::create_ggc(31);
775 1426 : subsumption_entry elt = {t1, t2, result};
776 1426 : subsumption_entry** slot = subsumption_cache->find_slot (&elt, INSERT);
777 1426 : subsumption_entry* entry = ggc_alloc<subsumption_entry> ();
778 1426 : *entry = elt;
779 1426 : *slot = entry;
780 1426 : return result;
781 : }
782 :
783 :
784 : /* Returns true if the LEFT constraint subsume the RIGHT constraints.
785 : This is done by deriving a proof of the conclusions on the RIGHT
786 : from the assumptions on the LEFT assumptions. */
787 :
788 : static bool
789 3405 : subsumes_constraints_nonnull (tree lhs, tree rhs)
790 : {
791 3405 : auto_timevar time (TV_CONSTRAINT_SUB);
792 :
793 3405 : if (bool *b = lookup_subsumption(lhs, rhs))
794 1979 : return *b;
795 :
796 1426 : tree x, y;
797 1426 : rules r;
798 4278 : if (dnf_size (lhs) <= cnf_size (rhs))
799 : /* When LHS looks simpler than RHS, we'll determine subsumption by
800 : decomposing LHS into its disjunctive normal form and checking that
801 : each (conjunctive) clause in the decomposed LHS implies RHS. */
802 : x = lhs, y = rhs, r = left;
803 : else
804 : /* Otherwise, we'll determine subsumption by decomposing RHS into its
805 : conjunctive normal form and checking that each (disjunctive) clause
806 : in the decomposed RHS implies LHS. */
807 0 : x = rhs, y = lhs, r = right;
808 :
809 : /* Decompose X into a list of sequents according to R, and recursively
810 : check for implication of Y. */
811 1426 : bool result = true;
812 1426 : formula f (x);
813 3650 : while (!f.done ())
814 : {
815 1541 : auto i = f.current ();
816 1541 : decompose_clause (f, *i, r);
817 1541 : if (!derive_proof (*i, y, r))
818 : {
819 : result = false;
820 1426 : break;
821 : }
822 798 : f.erase (i);
823 : }
824 :
825 1426 : return save_subsumption (lhs, rhs, result);
826 3405 : }
827 :
828 : /* Returns true if the LEFT constraints subsume the RIGHT
829 : constraints. */
830 :
831 : bool
832 246953 : subsumes (tree lhs, tree rhs)
833 : {
834 246953 : if (lhs == rhs)
835 : return true;
836 105619 : if (!lhs || lhs == error_mark_node)
837 : return false;
838 54512 : if (!rhs || rhs == error_mark_node)
839 : return true;
840 3405 : return subsumes_constraints_nonnull (lhs, rhs);
841 : }
842 :
843 : #include "gt-cp-logic.h"
|