annotate gcc/cp/logic.cc @ 158:494b0b89df80 default tip

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