1*38fd1498Szrj /* ET-trees data structure implementation.
2*38fd1498Szrj Contributed by Pavel Nejedly
3*38fd1498Szrj Copyright (C) 2002-2018 Free Software Foundation, Inc.
4*38fd1498Szrj
5*38fd1498Szrj This file is part of the libiberty library.
6*38fd1498Szrj Libiberty is free software; you can redistribute it and/or
7*38fd1498Szrj modify it under the terms of the GNU Library General Public
8*38fd1498Szrj License as published by the Free Software Foundation; either
9*38fd1498Szrj version 3 of the License, or (at your option) any later version.
10*38fd1498Szrj
11*38fd1498Szrj Libiberty is distributed in the hope that it will be useful,
12*38fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14*38fd1498Szrj Library General Public License for more details.
15*38fd1498Szrj
16*38fd1498Szrj You should have received a copy of the GNU Library General Public
17*38fd1498Szrj License along with libiberty; see the file COPYING3. If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.
19*38fd1498Szrj
20*38fd1498Szrj The ET-forest structure is described in:
21*38fd1498Szrj D. D. Sleator and R. E. Tarjan. A data structure for dynamic trees.
22*38fd1498Szrj J. G'omput. System Sci., 26(3):362 381, 1983.
23*38fd1498Szrj */
24*38fd1498Szrj
25*38fd1498Szrj #include "config.h"
26*38fd1498Szrj #include "system.h"
27*38fd1498Szrj #include "coretypes.h"
28*38fd1498Szrj #include "alloc-pool.h"
29*38fd1498Szrj #include "et-forest.h"
30*38fd1498Szrj #include "selftest.h"
31*38fd1498Szrj
32*38fd1498Szrj /* We do not enable this with CHECKING_P, since it is awfully slow. */
33*38fd1498Szrj #undef DEBUG_ET
34*38fd1498Szrj
35*38fd1498Szrj #ifdef DEBUG_ET
36*38fd1498Szrj #include "backend.h"
37*38fd1498Szrj #include "hard-reg-set.h"
38*38fd1498Szrj #endif
39*38fd1498Szrj
40*38fd1498Szrj /* The occurrence of a node in the et tree. */
41*38fd1498Szrj struct et_occ
42*38fd1498Szrj {
43*38fd1498Szrj struct et_node *of; /* The node. */
44*38fd1498Szrj
45*38fd1498Szrj struct et_occ *parent; /* Parent in the splay-tree. */
46*38fd1498Szrj struct et_occ *prev; /* Left son in the splay-tree. */
47*38fd1498Szrj struct et_occ *next; /* Right son in the splay-tree. */
48*38fd1498Szrj
49*38fd1498Szrj int depth; /* The depth of the node is the sum of depth
50*38fd1498Szrj fields on the path to the root. */
51*38fd1498Szrj int min; /* The minimum value of the depth in the subtree
52*38fd1498Szrj is obtained by adding sum of depth fields
53*38fd1498Szrj on the path to the root. */
54*38fd1498Szrj struct et_occ *min_occ; /* The occurrence in the subtree with the minimal
55*38fd1498Szrj depth. */
56*38fd1498Szrj };
57*38fd1498Szrj
58*38fd1498Szrj static object_allocator<et_node> et_nodes ("et_nodes pool");
59*38fd1498Szrj static object_allocator<et_occ> et_occurrences ("et_occ pool");
60*38fd1498Szrj
61*38fd1498Szrj /* Changes depth of OCC to D. */
62*38fd1498Szrj
63*38fd1498Szrj static inline void
set_depth(struct et_occ * occ,int d)64*38fd1498Szrj set_depth (struct et_occ *occ, int d)
65*38fd1498Szrj {
66*38fd1498Szrj if (!occ)
67*38fd1498Szrj return;
68*38fd1498Szrj
69*38fd1498Szrj occ->min += d - occ->depth;
70*38fd1498Szrj occ->depth = d;
71*38fd1498Szrj }
72*38fd1498Szrj
73*38fd1498Szrj /* Adds D to the depth of OCC. */
74*38fd1498Szrj
75*38fd1498Szrj static inline void
set_depth_add(struct et_occ * occ,int d)76*38fd1498Szrj set_depth_add (struct et_occ *occ, int d)
77*38fd1498Szrj {
78*38fd1498Szrj if (!occ)
79*38fd1498Szrj return;
80*38fd1498Szrj
81*38fd1498Szrj occ->min += d;
82*38fd1498Szrj occ->depth += d;
83*38fd1498Szrj }
84*38fd1498Szrj
85*38fd1498Szrj /* Sets prev field of OCC to P. */
86*38fd1498Szrj
87*38fd1498Szrj static inline void
set_prev(struct et_occ * occ,struct et_occ * t)88*38fd1498Szrj set_prev (struct et_occ *occ, struct et_occ *t)
89*38fd1498Szrj {
90*38fd1498Szrj #ifdef DEBUG_ET
91*38fd1498Szrj gcc_assert (occ != t);
92*38fd1498Szrj #endif
93*38fd1498Szrj
94*38fd1498Szrj occ->prev = t;
95*38fd1498Szrj if (t)
96*38fd1498Szrj t->parent = occ;
97*38fd1498Szrj }
98*38fd1498Szrj
99*38fd1498Szrj /* Sets next field of OCC to P. */
100*38fd1498Szrj
101*38fd1498Szrj static inline void
set_next(struct et_occ * occ,struct et_occ * t)102*38fd1498Szrj set_next (struct et_occ *occ, struct et_occ *t)
103*38fd1498Szrj {
104*38fd1498Szrj #ifdef DEBUG_ET
105*38fd1498Szrj gcc_assert (occ != t);
106*38fd1498Szrj #endif
107*38fd1498Szrj
108*38fd1498Szrj occ->next = t;
109*38fd1498Szrj if (t)
110*38fd1498Szrj t->parent = occ;
111*38fd1498Szrj }
112*38fd1498Szrj
113*38fd1498Szrj /* Recompute minimum for occurrence OCC. */
114*38fd1498Szrj
115*38fd1498Szrj static inline void
et_recomp_min(struct et_occ * occ)116*38fd1498Szrj et_recomp_min (struct et_occ *occ)
117*38fd1498Szrj {
118*38fd1498Szrj struct et_occ *mson = occ->prev;
119*38fd1498Szrj
120*38fd1498Szrj if (!mson
121*38fd1498Szrj || (occ->next
122*38fd1498Szrj && mson->min > occ->next->min))
123*38fd1498Szrj mson = occ->next;
124*38fd1498Szrj
125*38fd1498Szrj if (mson && mson->min < 0)
126*38fd1498Szrj {
127*38fd1498Szrj occ->min = mson->min + occ->depth;
128*38fd1498Szrj occ->min_occ = mson->min_occ;
129*38fd1498Szrj }
130*38fd1498Szrj else
131*38fd1498Szrj {
132*38fd1498Szrj occ->min = occ->depth;
133*38fd1498Szrj occ->min_occ = occ;
134*38fd1498Szrj }
135*38fd1498Szrj }
136*38fd1498Szrj
137*38fd1498Szrj #ifdef DEBUG_ET
138*38fd1498Szrj /* Checks whether neighborhood of OCC seems sane. */
139*38fd1498Szrj
140*38fd1498Szrj static void
et_check_occ_sanity(struct et_occ * occ)141*38fd1498Szrj et_check_occ_sanity (struct et_occ *occ)
142*38fd1498Szrj {
143*38fd1498Szrj if (!occ)
144*38fd1498Szrj return;
145*38fd1498Szrj
146*38fd1498Szrj gcc_assert (occ->parent != occ);
147*38fd1498Szrj gcc_assert (occ->prev != occ);
148*38fd1498Szrj gcc_assert (occ->next != occ);
149*38fd1498Szrj gcc_assert (!occ->next || occ->next != occ->prev);
150*38fd1498Szrj
151*38fd1498Szrj if (occ->next)
152*38fd1498Szrj {
153*38fd1498Szrj gcc_assert (occ->next != occ->parent);
154*38fd1498Szrj gcc_assert (occ->next->parent == occ);
155*38fd1498Szrj }
156*38fd1498Szrj
157*38fd1498Szrj if (occ->prev)
158*38fd1498Szrj {
159*38fd1498Szrj gcc_assert (occ->prev != occ->parent);
160*38fd1498Szrj gcc_assert (occ->prev->parent == occ);
161*38fd1498Szrj }
162*38fd1498Szrj
163*38fd1498Szrj gcc_assert (!occ->parent
164*38fd1498Szrj || occ->parent->prev == occ
165*38fd1498Szrj || occ->parent->next == occ);
166*38fd1498Szrj }
167*38fd1498Szrj
168*38fd1498Szrj /* Checks whether tree rooted at OCC is sane. */
169*38fd1498Szrj
170*38fd1498Szrj static void
et_check_sanity(struct et_occ * occ)171*38fd1498Szrj et_check_sanity (struct et_occ *occ)
172*38fd1498Szrj {
173*38fd1498Szrj et_check_occ_sanity (occ);
174*38fd1498Szrj if (occ->prev)
175*38fd1498Szrj et_check_sanity (occ->prev);
176*38fd1498Szrj if (occ->next)
177*38fd1498Szrj et_check_sanity (occ->next);
178*38fd1498Szrj }
179*38fd1498Szrj
180*38fd1498Szrj /* Checks whether tree containing OCC is sane. */
181*38fd1498Szrj
182*38fd1498Szrj static void
et_check_tree_sanity(struct et_occ * occ)183*38fd1498Szrj et_check_tree_sanity (struct et_occ *occ)
184*38fd1498Szrj {
185*38fd1498Szrj while (occ->parent)
186*38fd1498Szrj occ = occ->parent;
187*38fd1498Szrj
188*38fd1498Szrj et_check_sanity (occ);
189*38fd1498Szrj }
190*38fd1498Szrj
191*38fd1498Szrj /* For recording the paths. */
192*38fd1498Szrj
193*38fd1498Szrj /* An ad-hoc constant; if the function has more blocks, this won't work,
194*38fd1498Szrj but since it is used for debugging only, it does not matter. */
195*38fd1498Szrj #define MAX_NODES 100000
196*38fd1498Szrj
197*38fd1498Szrj static int len;
198*38fd1498Szrj static void *datas[MAX_NODES];
199*38fd1498Szrj static int depths[MAX_NODES];
200*38fd1498Szrj
201*38fd1498Szrj /* Records the path represented by OCC, with depth incremented by DEPTH. */
202*38fd1498Szrj
203*38fd1498Szrj static int
record_path_before_1(struct et_occ * occ,int depth)204*38fd1498Szrj record_path_before_1 (struct et_occ *occ, int depth)
205*38fd1498Szrj {
206*38fd1498Szrj int mn, m;
207*38fd1498Szrj
208*38fd1498Szrj depth += occ->depth;
209*38fd1498Szrj mn = depth;
210*38fd1498Szrj
211*38fd1498Szrj if (occ->prev)
212*38fd1498Szrj {
213*38fd1498Szrj m = record_path_before_1 (occ->prev, depth);
214*38fd1498Szrj if (m < mn)
215*38fd1498Szrj mn = m;
216*38fd1498Szrj }
217*38fd1498Szrj
218*38fd1498Szrj fprintf (stderr, "%d (%d); ", ((basic_block) occ->of->data)->index, depth);
219*38fd1498Szrj
220*38fd1498Szrj gcc_assert (len < MAX_NODES);
221*38fd1498Szrj
222*38fd1498Szrj depths[len] = depth;
223*38fd1498Szrj datas[len] = occ->of;
224*38fd1498Szrj len++;
225*38fd1498Szrj
226*38fd1498Szrj if (occ->next)
227*38fd1498Szrj {
228*38fd1498Szrj m = record_path_before_1 (occ->next, depth);
229*38fd1498Szrj if (m < mn)
230*38fd1498Szrj mn = m;
231*38fd1498Szrj }
232*38fd1498Szrj
233*38fd1498Szrj gcc_assert (mn == occ->min + depth - occ->depth);
234*38fd1498Szrj
235*38fd1498Szrj return mn;
236*38fd1498Szrj }
237*38fd1498Szrj
238*38fd1498Szrj /* Records the path represented by a tree containing OCC. */
239*38fd1498Szrj
240*38fd1498Szrj static void
record_path_before(struct et_occ * occ)241*38fd1498Szrj record_path_before (struct et_occ *occ)
242*38fd1498Szrj {
243*38fd1498Szrj while (occ->parent)
244*38fd1498Szrj occ = occ->parent;
245*38fd1498Szrj
246*38fd1498Szrj len = 0;
247*38fd1498Szrj record_path_before_1 (occ, 0);
248*38fd1498Szrj fprintf (stderr, "\n");
249*38fd1498Szrj }
250*38fd1498Szrj
251*38fd1498Szrj /* Checks whether the path represented by OCC, with depth incremented by DEPTH,
252*38fd1498Szrj was not changed since the last recording. */
253*38fd1498Szrj
254*38fd1498Szrj static int
check_path_after_1(struct et_occ * occ,int depth)255*38fd1498Szrj check_path_after_1 (struct et_occ *occ, int depth)
256*38fd1498Szrj {
257*38fd1498Szrj int mn, m;
258*38fd1498Szrj
259*38fd1498Szrj depth += occ->depth;
260*38fd1498Szrj mn = depth;
261*38fd1498Szrj
262*38fd1498Szrj if (occ->next)
263*38fd1498Szrj {
264*38fd1498Szrj m = check_path_after_1 (occ->next, depth);
265*38fd1498Szrj if (m < mn)
266*38fd1498Szrj mn = m;
267*38fd1498Szrj }
268*38fd1498Szrj
269*38fd1498Szrj len--;
270*38fd1498Szrj gcc_assert (depths[len] == depth && datas[len] == occ->of);
271*38fd1498Szrj
272*38fd1498Szrj if (occ->prev)
273*38fd1498Szrj {
274*38fd1498Szrj m = check_path_after_1 (occ->prev, depth);
275*38fd1498Szrj if (m < mn)
276*38fd1498Szrj mn = m;
277*38fd1498Szrj }
278*38fd1498Szrj
279*38fd1498Szrj gcc_assert (mn == occ->min + depth - occ->depth);
280*38fd1498Szrj
281*38fd1498Szrj return mn;
282*38fd1498Szrj }
283*38fd1498Szrj
284*38fd1498Szrj /* Checks whether the path represented by a tree containing OCC was
285*38fd1498Szrj not changed since the last recording. */
286*38fd1498Szrj
287*38fd1498Szrj static void
check_path_after(struct et_occ * occ)288*38fd1498Szrj check_path_after (struct et_occ *occ)
289*38fd1498Szrj {
290*38fd1498Szrj while (occ->parent)
291*38fd1498Szrj occ = occ->parent;
292*38fd1498Szrj
293*38fd1498Szrj check_path_after_1 (occ, 0);
294*38fd1498Szrj gcc_assert (!len);
295*38fd1498Szrj }
296*38fd1498Szrj
297*38fd1498Szrj #endif
298*38fd1498Szrj
299*38fd1498Szrj /* Splay the occurrence OCC to the root of the tree. */
300*38fd1498Szrj
301*38fd1498Szrj static void
et_splay(struct et_occ * occ)302*38fd1498Szrj et_splay (struct et_occ *occ)
303*38fd1498Szrj {
304*38fd1498Szrj struct et_occ *f, *gf, *ggf;
305*38fd1498Szrj int occ_depth, f_depth, gf_depth;
306*38fd1498Szrj
307*38fd1498Szrj #ifdef DEBUG_ET
308*38fd1498Szrj record_path_before (occ);
309*38fd1498Szrj et_check_tree_sanity (occ);
310*38fd1498Szrj #endif
311*38fd1498Szrj
312*38fd1498Szrj while (occ->parent)
313*38fd1498Szrj {
314*38fd1498Szrj occ_depth = occ->depth;
315*38fd1498Szrj
316*38fd1498Szrj f = occ->parent;
317*38fd1498Szrj f_depth = f->depth;
318*38fd1498Szrj
319*38fd1498Szrj gf = f->parent;
320*38fd1498Szrj
321*38fd1498Szrj if (!gf)
322*38fd1498Szrj {
323*38fd1498Szrj set_depth_add (occ, f_depth);
324*38fd1498Szrj occ->min_occ = f->min_occ;
325*38fd1498Szrj occ->min = f->min;
326*38fd1498Szrj
327*38fd1498Szrj if (f->prev == occ)
328*38fd1498Szrj {
329*38fd1498Szrj /* zig */
330*38fd1498Szrj set_prev (f, occ->next);
331*38fd1498Szrj set_next (occ, f);
332*38fd1498Szrj set_depth_add (f->prev, occ_depth);
333*38fd1498Szrj }
334*38fd1498Szrj else
335*38fd1498Szrj {
336*38fd1498Szrj /* zag */
337*38fd1498Szrj set_next (f, occ->prev);
338*38fd1498Szrj set_prev (occ, f);
339*38fd1498Szrj set_depth_add (f->next, occ_depth);
340*38fd1498Szrj }
341*38fd1498Szrj set_depth (f, -occ_depth);
342*38fd1498Szrj occ->parent = NULL;
343*38fd1498Szrj
344*38fd1498Szrj et_recomp_min (f);
345*38fd1498Szrj #ifdef DEBUG_ET
346*38fd1498Szrj et_check_tree_sanity (occ);
347*38fd1498Szrj check_path_after (occ);
348*38fd1498Szrj #endif
349*38fd1498Szrj return;
350*38fd1498Szrj }
351*38fd1498Szrj
352*38fd1498Szrj gf_depth = gf->depth;
353*38fd1498Szrj
354*38fd1498Szrj set_depth_add (occ, f_depth + gf_depth);
355*38fd1498Szrj occ->min_occ = gf->min_occ;
356*38fd1498Szrj occ->min = gf->min;
357*38fd1498Szrj
358*38fd1498Szrj ggf = gf->parent;
359*38fd1498Szrj
360*38fd1498Szrj if (gf->prev == f)
361*38fd1498Szrj {
362*38fd1498Szrj if (f->prev == occ)
363*38fd1498Szrj {
364*38fd1498Szrj /* zig zig */
365*38fd1498Szrj set_prev (gf, f->next);
366*38fd1498Szrj set_prev (f, occ->next);
367*38fd1498Szrj set_next (occ, f);
368*38fd1498Szrj set_next (f, gf);
369*38fd1498Szrj
370*38fd1498Szrj set_depth (f, -occ_depth);
371*38fd1498Szrj set_depth_add (f->prev, occ_depth);
372*38fd1498Szrj set_depth (gf, -f_depth);
373*38fd1498Szrj set_depth_add (gf->prev, f_depth);
374*38fd1498Szrj }
375*38fd1498Szrj else
376*38fd1498Szrj {
377*38fd1498Szrj /* zag zig */
378*38fd1498Szrj set_prev (gf, occ->next);
379*38fd1498Szrj set_next (f, occ->prev);
380*38fd1498Szrj set_prev (occ, f);
381*38fd1498Szrj set_next (occ, gf);
382*38fd1498Szrj
383*38fd1498Szrj set_depth (f, -occ_depth);
384*38fd1498Szrj set_depth_add (f->next, occ_depth);
385*38fd1498Szrj set_depth (gf, -occ_depth - f_depth);
386*38fd1498Szrj set_depth_add (gf->prev, occ_depth + f_depth);
387*38fd1498Szrj }
388*38fd1498Szrj }
389*38fd1498Szrj else
390*38fd1498Szrj {
391*38fd1498Szrj if (f->prev == occ)
392*38fd1498Szrj {
393*38fd1498Szrj /* zig zag */
394*38fd1498Szrj set_next (gf, occ->prev);
395*38fd1498Szrj set_prev (f, occ->next);
396*38fd1498Szrj set_prev (occ, gf);
397*38fd1498Szrj set_next (occ, f);
398*38fd1498Szrj
399*38fd1498Szrj set_depth (f, -occ_depth);
400*38fd1498Szrj set_depth_add (f->prev, occ_depth);
401*38fd1498Szrj set_depth (gf, -occ_depth - f_depth);
402*38fd1498Szrj set_depth_add (gf->next, occ_depth + f_depth);
403*38fd1498Szrj }
404*38fd1498Szrj else
405*38fd1498Szrj {
406*38fd1498Szrj /* zag zag */
407*38fd1498Szrj set_next (gf, f->prev);
408*38fd1498Szrj set_next (f, occ->prev);
409*38fd1498Szrj set_prev (occ, f);
410*38fd1498Szrj set_prev (f, gf);
411*38fd1498Szrj
412*38fd1498Szrj set_depth (f, -occ_depth);
413*38fd1498Szrj set_depth_add (f->next, occ_depth);
414*38fd1498Szrj set_depth (gf, -f_depth);
415*38fd1498Szrj set_depth_add (gf->next, f_depth);
416*38fd1498Szrj }
417*38fd1498Szrj }
418*38fd1498Szrj
419*38fd1498Szrj occ->parent = ggf;
420*38fd1498Szrj if (ggf)
421*38fd1498Szrj {
422*38fd1498Szrj if (ggf->prev == gf)
423*38fd1498Szrj ggf->prev = occ;
424*38fd1498Szrj else
425*38fd1498Szrj ggf->next = occ;
426*38fd1498Szrj }
427*38fd1498Szrj
428*38fd1498Szrj et_recomp_min (gf);
429*38fd1498Szrj et_recomp_min (f);
430*38fd1498Szrj #ifdef DEBUG_ET
431*38fd1498Szrj et_check_tree_sanity (occ);
432*38fd1498Szrj #endif
433*38fd1498Szrj }
434*38fd1498Szrj
435*38fd1498Szrj #ifdef DEBUG_ET
436*38fd1498Szrj et_check_sanity (occ);
437*38fd1498Szrj check_path_after (occ);
438*38fd1498Szrj #endif
439*38fd1498Szrj }
440*38fd1498Szrj
441*38fd1498Szrj /* Create a new et tree occurrence of NODE. */
442*38fd1498Szrj
443*38fd1498Szrj static struct et_occ *
et_new_occ(struct et_node * node)444*38fd1498Szrj et_new_occ (struct et_node *node)
445*38fd1498Szrj {
446*38fd1498Szrj et_occ *nw = et_occurrences.allocate ();
447*38fd1498Szrj
448*38fd1498Szrj nw->of = node;
449*38fd1498Szrj nw->parent = NULL;
450*38fd1498Szrj nw->prev = NULL;
451*38fd1498Szrj nw->next = NULL;
452*38fd1498Szrj
453*38fd1498Szrj nw->depth = 0;
454*38fd1498Szrj nw->min_occ = nw;
455*38fd1498Szrj nw->min = 0;
456*38fd1498Szrj
457*38fd1498Szrj return nw;
458*38fd1498Szrj }
459*38fd1498Szrj
460*38fd1498Szrj /* Create a new et tree containing DATA. */
461*38fd1498Szrj
462*38fd1498Szrj struct et_node *
et_new_tree(void * data)463*38fd1498Szrj et_new_tree (void *data)
464*38fd1498Szrj {
465*38fd1498Szrj et_node *nw = et_nodes.allocate ();
466*38fd1498Szrj
467*38fd1498Szrj nw->data = data;
468*38fd1498Szrj nw->father = NULL;
469*38fd1498Szrj nw->left = NULL;
470*38fd1498Szrj nw->right = NULL;
471*38fd1498Szrj nw->son = NULL;
472*38fd1498Szrj
473*38fd1498Szrj nw->rightmost_occ = et_new_occ (nw);
474*38fd1498Szrj nw->parent_occ = NULL;
475*38fd1498Szrj
476*38fd1498Szrj return nw;
477*38fd1498Szrj }
478*38fd1498Szrj
479*38fd1498Szrj /* Releases et tree T. */
480*38fd1498Szrj
481*38fd1498Szrj void
et_free_tree(struct et_node * t)482*38fd1498Szrj et_free_tree (struct et_node *t)
483*38fd1498Szrj {
484*38fd1498Szrj while (t->son)
485*38fd1498Szrj et_split (t->son);
486*38fd1498Szrj
487*38fd1498Szrj if (t->father)
488*38fd1498Szrj et_split (t);
489*38fd1498Szrj
490*38fd1498Szrj et_occurrences.remove (t->rightmost_occ);
491*38fd1498Szrj et_nodes.remove (t);
492*38fd1498Szrj }
493*38fd1498Szrj
494*38fd1498Szrj /* Releases et tree T without maintaining other nodes. */
495*38fd1498Szrj
496*38fd1498Szrj void
et_free_tree_force(struct et_node * t)497*38fd1498Szrj et_free_tree_force (struct et_node *t)
498*38fd1498Szrj {
499*38fd1498Szrj et_occurrences.remove (t->rightmost_occ);
500*38fd1498Szrj if (t->parent_occ)
501*38fd1498Szrj et_occurrences.remove (t->parent_occ);
502*38fd1498Szrj et_nodes.remove (t);
503*38fd1498Szrj }
504*38fd1498Szrj
505*38fd1498Szrj /* Release the alloc pools, if they are empty. */
506*38fd1498Szrj
507*38fd1498Szrj void
et_free_pools(void)508*38fd1498Szrj et_free_pools (void)
509*38fd1498Szrj {
510*38fd1498Szrj et_occurrences.release_if_empty ();
511*38fd1498Szrj et_nodes.release_if_empty ();
512*38fd1498Szrj }
513*38fd1498Szrj
514*38fd1498Szrj /* Sets father of et tree T to FATHER. */
515*38fd1498Szrj
516*38fd1498Szrj void
et_set_father(struct et_node * t,struct et_node * father)517*38fd1498Szrj et_set_father (struct et_node *t, struct et_node *father)
518*38fd1498Szrj {
519*38fd1498Szrj struct et_node *left, *right;
520*38fd1498Szrj struct et_occ *rmost, *left_part, *new_f_occ, *p;
521*38fd1498Szrj
522*38fd1498Szrj /* Update the path represented in the splay tree. */
523*38fd1498Szrj new_f_occ = et_new_occ (father);
524*38fd1498Szrj
525*38fd1498Szrj rmost = father->rightmost_occ;
526*38fd1498Szrj et_splay (rmost);
527*38fd1498Szrj
528*38fd1498Szrj left_part = rmost->prev;
529*38fd1498Szrj
530*38fd1498Szrj p = t->rightmost_occ;
531*38fd1498Szrj et_splay (p);
532*38fd1498Szrj
533*38fd1498Szrj set_prev (new_f_occ, left_part);
534*38fd1498Szrj set_next (new_f_occ, p);
535*38fd1498Szrj
536*38fd1498Szrj p->depth++;
537*38fd1498Szrj p->min++;
538*38fd1498Szrj et_recomp_min (new_f_occ);
539*38fd1498Szrj
540*38fd1498Szrj set_prev (rmost, new_f_occ);
541*38fd1498Szrj
542*38fd1498Szrj if (new_f_occ->min + rmost->depth < rmost->min)
543*38fd1498Szrj {
544*38fd1498Szrj rmost->min = new_f_occ->min + rmost->depth;
545*38fd1498Szrj rmost->min_occ = new_f_occ->min_occ;
546*38fd1498Szrj }
547*38fd1498Szrj
548*38fd1498Szrj t->parent_occ = new_f_occ;
549*38fd1498Szrj
550*38fd1498Szrj /* Update the tree. */
551*38fd1498Szrj t->father = father;
552*38fd1498Szrj right = father->son;
553*38fd1498Szrj if (right)
554*38fd1498Szrj left = right->left;
555*38fd1498Szrj else
556*38fd1498Szrj left = right = t;
557*38fd1498Szrj
558*38fd1498Szrj left->right = t;
559*38fd1498Szrj right->left = t;
560*38fd1498Szrj t->left = left;
561*38fd1498Szrj t->right = right;
562*38fd1498Szrj
563*38fd1498Szrj father->son = t;
564*38fd1498Szrj
565*38fd1498Szrj #ifdef DEBUG_ET
566*38fd1498Szrj et_check_tree_sanity (rmost);
567*38fd1498Szrj record_path_before (rmost);
568*38fd1498Szrj #endif
569*38fd1498Szrj }
570*38fd1498Szrj
571*38fd1498Szrj /* Splits the edge from T to its father. */
572*38fd1498Szrj
573*38fd1498Szrj void
et_split(struct et_node * t)574*38fd1498Szrj et_split (struct et_node *t)
575*38fd1498Szrj {
576*38fd1498Szrj struct et_node *father = t->father;
577*38fd1498Szrj struct et_occ *r, *l, *rmost, *p_occ;
578*38fd1498Szrj
579*38fd1498Szrj /* Update the path represented by the splay tree. */
580*38fd1498Szrj rmost = t->rightmost_occ;
581*38fd1498Szrj et_splay (rmost);
582*38fd1498Szrj
583*38fd1498Szrj for (r = rmost->next; r->prev; r = r->prev)
584*38fd1498Szrj continue;
585*38fd1498Szrj et_splay (r);
586*38fd1498Szrj
587*38fd1498Szrj r->prev->parent = NULL;
588*38fd1498Szrj p_occ = t->parent_occ;
589*38fd1498Szrj et_splay (p_occ);
590*38fd1498Szrj t->parent_occ = NULL;
591*38fd1498Szrj
592*38fd1498Szrj l = p_occ->prev;
593*38fd1498Szrj p_occ->next->parent = NULL;
594*38fd1498Szrj
595*38fd1498Szrj set_prev (r, l);
596*38fd1498Szrj
597*38fd1498Szrj et_recomp_min (r);
598*38fd1498Szrj
599*38fd1498Szrj et_splay (rmost);
600*38fd1498Szrj rmost->depth = 0;
601*38fd1498Szrj rmost->min = 0;
602*38fd1498Szrj
603*38fd1498Szrj et_occurrences.remove (p_occ);
604*38fd1498Szrj
605*38fd1498Szrj /* Update the tree. */
606*38fd1498Szrj if (father->son == t)
607*38fd1498Szrj father->son = t->right;
608*38fd1498Szrj if (father->son == t)
609*38fd1498Szrj father->son = NULL;
610*38fd1498Szrj else
611*38fd1498Szrj {
612*38fd1498Szrj t->left->right = t->right;
613*38fd1498Szrj t->right->left = t->left;
614*38fd1498Szrj }
615*38fd1498Szrj t->left = t->right = NULL;
616*38fd1498Szrj t->father = NULL;
617*38fd1498Szrj
618*38fd1498Szrj #ifdef DEBUG_ET
619*38fd1498Szrj et_check_tree_sanity (rmost);
620*38fd1498Szrj record_path_before (rmost);
621*38fd1498Szrj
622*38fd1498Szrj et_check_tree_sanity (r);
623*38fd1498Szrj record_path_before (r);
624*38fd1498Szrj #endif
625*38fd1498Szrj }
626*38fd1498Szrj
627*38fd1498Szrj /* Finds the nearest common ancestor of the nodes N1 and N2. */
628*38fd1498Szrj
629*38fd1498Szrj struct et_node *
et_nca(struct et_node * n1,struct et_node * n2)630*38fd1498Szrj et_nca (struct et_node *n1, struct et_node *n2)
631*38fd1498Szrj {
632*38fd1498Szrj struct et_occ *o1 = n1->rightmost_occ, *o2 = n2->rightmost_occ, *om;
633*38fd1498Szrj struct et_occ *l, *r, *ret;
634*38fd1498Szrj int mn;
635*38fd1498Szrj
636*38fd1498Szrj if (n1 == n2)
637*38fd1498Szrj return n1;
638*38fd1498Szrj
639*38fd1498Szrj et_splay (o1);
640*38fd1498Szrj l = o1->prev;
641*38fd1498Szrj r = o1->next;
642*38fd1498Szrj if (l)
643*38fd1498Szrj l->parent = NULL;
644*38fd1498Szrj if (r)
645*38fd1498Szrj r->parent = NULL;
646*38fd1498Szrj et_splay (o2);
647*38fd1498Szrj
648*38fd1498Szrj if (l == o2 || (l && l->parent != NULL))
649*38fd1498Szrj {
650*38fd1498Szrj ret = o2->next;
651*38fd1498Szrj
652*38fd1498Szrj set_prev (o1, o2);
653*38fd1498Szrj if (r)
654*38fd1498Szrj r->parent = o1;
655*38fd1498Szrj }
656*38fd1498Szrj else if (r == o2 || (r && r->parent != NULL))
657*38fd1498Szrj {
658*38fd1498Szrj ret = o2->prev;
659*38fd1498Szrj
660*38fd1498Szrj set_next (o1, o2);
661*38fd1498Szrj if (l)
662*38fd1498Szrj l->parent = o1;
663*38fd1498Szrj }
664*38fd1498Szrj else
665*38fd1498Szrj {
666*38fd1498Szrj /* O1 and O2 are in different components of the forest. */
667*38fd1498Szrj if (l)
668*38fd1498Szrj l->parent = o1;
669*38fd1498Szrj if (r)
670*38fd1498Szrj r->parent = o1;
671*38fd1498Szrj return NULL;
672*38fd1498Szrj }
673*38fd1498Szrj
674*38fd1498Szrj if (o2->depth > 0)
675*38fd1498Szrj {
676*38fd1498Szrj om = o1;
677*38fd1498Szrj mn = o1->depth;
678*38fd1498Szrj }
679*38fd1498Szrj else
680*38fd1498Szrj {
681*38fd1498Szrj om = o2;
682*38fd1498Szrj mn = o2->depth + o1->depth;
683*38fd1498Szrj }
684*38fd1498Szrj
685*38fd1498Szrj #ifdef DEBUG_ET
686*38fd1498Szrj et_check_tree_sanity (o2);
687*38fd1498Szrj #endif
688*38fd1498Szrj
689*38fd1498Szrj if (ret && ret->min + o1->depth + o2->depth < mn)
690*38fd1498Szrj return ret->min_occ->of;
691*38fd1498Szrj else
692*38fd1498Szrj return om->of;
693*38fd1498Szrj }
694*38fd1498Szrj
695*38fd1498Szrj /* Checks whether the node UP is an ancestor of the node DOWN. */
696*38fd1498Szrj
697*38fd1498Szrj bool
et_below(struct et_node * down,struct et_node * up)698*38fd1498Szrj et_below (struct et_node *down, struct et_node *up)
699*38fd1498Szrj {
700*38fd1498Szrj struct et_occ *u = up->rightmost_occ, *d = down->rightmost_occ;
701*38fd1498Szrj struct et_occ *l, *r;
702*38fd1498Szrj
703*38fd1498Szrj if (up == down)
704*38fd1498Szrj return true;
705*38fd1498Szrj
706*38fd1498Szrj et_splay (u);
707*38fd1498Szrj l = u->prev;
708*38fd1498Szrj r = u->next;
709*38fd1498Szrj
710*38fd1498Szrj if (!l)
711*38fd1498Szrj return false;
712*38fd1498Szrj
713*38fd1498Szrj l->parent = NULL;
714*38fd1498Szrj
715*38fd1498Szrj if (r)
716*38fd1498Szrj r->parent = NULL;
717*38fd1498Szrj
718*38fd1498Szrj et_splay (d);
719*38fd1498Szrj
720*38fd1498Szrj if (l == d || l->parent != NULL)
721*38fd1498Szrj {
722*38fd1498Szrj if (r)
723*38fd1498Szrj r->parent = u;
724*38fd1498Szrj set_prev (u, d);
725*38fd1498Szrj #ifdef DEBUG_ET
726*38fd1498Szrj et_check_tree_sanity (u);
727*38fd1498Szrj #endif
728*38fd1498Szrj }
729*38fd1498Szrj else
730*38fd1498Szrj {
731*38fd1498Szrj l->parent = u;
732*38fd1498Szrj
733*38fd1498Szrj /* In case O1 and O2 are in two different trees, we must just restore the
734*38fd1498Szrj original state. */
735*38fd1498Szrj if (r && r->parent != NULL)
736*38fd1498Szrj set_next (u, d);
737*38fd1498Szrj else
738*38fd1498Szrj set_next (u, r);
739*38fd1498Szrj
740*38fd1498Szrj #ifdef DEBUG_ET
741*38fd1498Szrj et_check_tree_sanity (u);
742*38fd1498Szrj #endif
743*38fd1498Szrj return false;
744*38fd1498Szrj }
745*38fd1498Szrj
746*38fd1498Szrj if (d->depth <= 0)
747*38fd1498Szrj return false;
748*38fd1498Szrj
749*38fd1498Szrj return !d->next || d->next->min + d->depth >= 0;
750*38fd1498Szrj }
751*38fd1498Szrj
752*38fd1498Szrj /* Returns the root of the tree that contains NODE. */
753*38fd1498Szrj
754*38fd1498Szrj struct et_node *
et_root(struct et_node * node)755*38fd1498Szrj et_root (struct et_node *node)
756*38fd1498Szrj {
757*38fd1498Szrj struct et_occ *occ = node->rightmost_occ, *r;
758*38fd1498Szrj
759*38fd1498Szrj /* The root of the tree corresponds to the rightmost occurrence in the
760*38fd1498Szrj represented path. */
761*38fd1498Szrj et_splay (occ);
762*38fd1498Szrj for (r = occ; r->next; r = r->next)
763*38fd1498Szrj continue;
764*38fd1498Szrj et_splay (r);
765*38fd1498Szrj
766*38fd1498Szrj return r->of;
767*38fd1498Szrj }
768*38fd1498Szrj
769*38fd1498Szrj #if CHECKING_P
770*38fd1498Szrj
771*38fd1498Szrj namespace selftest {
772*38fd1498Szrj
773*38fd1498Szrj /* Selftests for et-forest.c. */
774*38fd1498Szrj
775*38fd1498Szrj /* Perform sanity checks for a tree consisting of a single node. */
776*38fd1498Szrj
777*38fd1498Szrj static void
test_single_node()778*38fd1498Szrj test_single_node ()
779*38fd1498Szrj {
780*38fd1498Szrj void *test_data = (void *)0xcafebabe;
781*38fd1498Szrj
782*38fd1498Szrj et_node *n = et_new_tree (test_data);
783*38fd1498Szrj ASSERT_EQ (n->data, test_data);
784*38fd1498Szrj ASSERT_EQ (n, et_root (n));
785*38fd1498Szrj et_free_tree (n);
786*38fd1498Szrj }
787*38fd1498Szrj
788*38fd1498Szrj /* Test of this tree:
789*38fd1498Szrj a
790*38fd1498Szrj / \
791*38fd1498Szrj / \
792*38fd1498Szrj b c
793*38fd1498Szrj / \ |
794*38fd1498Szrj d e f. */
795*38fd1498Szrj
796*38fd1498Szrj static void
test_simple_tree()797*38fd1498Szrj test_simple_tree ()
798*38fd1498Szrj {
799*38fd1498Szrj et_node *a = et_new_tree (NULL);
800*38fd1498Szrj et_node *b = et_new_tree (NULL);
801*38fd1498Szrj et_node *c = et_new_tree (NULL);
802*38fd1498Szrj et_node *d = et_new_tree (NULL);
803*38fd1498Szrj et_node *e = et_new_tree (NULL);
804*38fd1498Szrj et_node *f = et_new_tree (NULL);
805*38fd1498Szrj
806*38fd1498Szrj et_set_father (b, a);
807*38fd1498Szrj et_set_father (c, a);
808*38fd1498Szrj et_set_father (d, b);
809*38fd1498Szrj et_set_father (e, b);
810*38fd1498Szrj et_set_father (f, c);
811*38fd1498Szrj
812*38fd1498Szrj ASSERT_TRUE (et_below (a, a));
813*38fd1498Szrj ASSERT_TRUE (et_below (b, a));
814*38fd1498Szrj ASSERT_TRUE (et_below (c, a));
815*38fd1498Szrj ASSERT_TRUE (et_below (d, a));
816*38fd1498Szrj ASSERT_TRUE (et_below (e, a));
817*38fd1498Szrj ASSERT_TRUE (et_below (f, a));
818*38fd1498Szrj
819*38fd1498Szrj ASSERT_FALSE (et_below (a, b));
820*38fd1498Szrj ASSERT_TRUE (et_below (b, b));
821*38fd1498Szrj ASSERT_FALSE (et_below (c, b));
822*38fd1498Szrj ASSERT_TRUE (et_below (d, b));
823*38fd1498Szrj ASSERT_TRUE (et_below (e, b));
824*38fd1498Szrj ASSERT_FALSE (et_below (f, b));
825*38fd1498Szrj
826*38fd1498Szrj ASSERT_FALSE (et_below (a, c));
827*38fd1498Szrj ASSERT_FALSE (et_below (b, c));
828*38fd1498Szrj ASSERT_TRUE (et_below (c, c));
829*38fd1498Szrj ASSERT_FALSE (et_below (d, c));
830*38fd1498Szrj ASSERT_FALSE (et_below (e, c));
831*38fd1498Szrj ASSERT_TRUE (et_below (f, c));
832*38fd1498Szrj
833*38fd1498Szrj ASSERT_FALSE (et_below (a, d));
834*38fd1498Szrj ASSERT_FALSE (et_below (b, d));
835*38fd1498Szrj ASSERT_FALSE (et_below (c, d));
836*38fd1498Szrj ASSERT_TRUE (et_below (d, d));
837*38fd1498Szrj ASSERT_FALSE (et_below (e, d));
838*38fd1498Szrj ASSERT_FALSE (et_below (f, d));
839*38fd1498Szrj
840*38fd1498Szrj ASSERT_FALSE (et_below (a, e));
841*38fd1498Szrj ASSERT_FALSE (et_below (b, e));
842*38fd1498Szrj ASSERT_FALSE (et_below (c, e));
843*38fd1498Szrj ASSERT_FALSE (et_below (d, e));
844*38fd1498Szrj ASSERT_TRUE (et_below (e, e));
845*38fd1498Szrj ASSERT_FALSE (et_below (f, e));
846*38fd1498Szrj
847*38fd1498Szrj ASSERT_FALSE (et_below (a, f));
848*38fd1498Szrj ASSERT_FALSE (et_below (b, f));
849*38fd1498Szrj ASSERT_FALSE (et_below (c, f));
850*38fd1498Szrj ASSERT_FALSE (et_below (d, f));
851*38fd1498Szrj ASSERT_FALSE (et_below (e, f));
852*38fd1498Szrj ASSERT_TRUE (et_below (f, f));
853*38fd1498Szrj
854*38fd1498Szrj et_free_tree_force (a);
855*38fd1498Szrj }
856*38fd1498Szrj
857*38fd1498Szrj /* Verify that two disconnected nodes are unrelated. */
858*38fd1498Szrj
859*38fd1498Szrj static void
test_disconnected_nodes()860*38fd1498Szrj test_disconnected_nodes ()
861*38fd1498Szrj {
862*38fd1498Szrj et_node *a = et_new_tree (NULL);
863*38fd1498Szrj et_node *b = et_new_tree (NULL);
864*38fd1498Szrj
865*38fd1498Szrj ASSERT_FALSE (et_below (a, b));
866*38fd1498Szrj ASSERT_FALSE (et_below (b, a));
867*38fd1498Szrj
868*38fd1498Szrj et_free_tree (a);
869*38fd1498Szrj et_free_tree (b);
870*38fd1498Szrj }
871*38fd1498Szrj
872*38fd1498Szrj /* Run all of the selftests within this file. */
873*38fd1498Szrj
874*38fd1498Szrj void
et_forest_c_tests()875*38fd1498Szrj et_forest_c_tests ()
876*38fd1498Szrj {
877*38fd1498Szrj test_single_node ();
878*38fd1498Szrj test_simple_tree ();
879*38fd1498Szrj test_disconnected_nodes ();
880*38fd1498Szrj }
881*38fd1498Szrj
882*38fd1498Szrj } // namespace selftest
883*38fd1498Szrj
884*38fd1498Szrj #endif /* CHECKING_P */
885