xref: /dflybsd-src/contrib/gcc-8.0/gcc/et-forest.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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