PIPS
hierarchize.c
Go to the documentation of this file.
1 /*
2 
3  $Id: hierarchize.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /*
28  Hierarchize the control graph of a module.
29 
30  Replace unstructured by unstructured of unstructured and so on if
31  possible by using interval graphs.
32 
33  Ronan.Keryell@cri.ensmp.fr
34  */
35 
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 
40 #include "linear.h"
41 
42 #include "genC.h"
43 #include "ri.h"
44 
45 #include "interval_graph.h"
46 
47 /* Instantiation of the interval graph: */
49 /* Since the arc are not used, just put a dummy type for arc_label. It
50  will be initialized to interval_vertex_label_undefined anyway: */
52 
53 #include "graph.h"
54 #include "ri-util.h"
55 #include "misc.h"
56 #include "control.h"
57 
58 
59 /* *** Warning ***
60 
61  We use the NewGen graph structure in reverse order since we need
62  predecessor graph and not successor graph. Furthermore, we do not
63  use the arc_label.
64 
65  Let us lay down this cpp and type lies for programmer's sake...
66 */
67 #define vertex_predecessors vertex_successors
68 #define predecessor_vertex successor_vertex
69 #define make_predecessor make_successor
70 #define free_predecessor free_successor
71 #define PREDECESSOR SUCCESSOR
72 #define PREDECESSOR_TYPE SUCCESSOR_TYPE
73 #undef PREDECESSOR_NEWGEN_DOMAIN
74 #define PREDECESSOR_NEWGEN_DOMAIN (-1)
75 #undef SUCCESSOR_NEWGEN_DOMAIN
76 #define SUCCESSOR_NEWGEN_DOMAIN (-1)
77 #undef gen_SUCCESSOR_cons
78 #define gen_SUCCESSOR_cons gen_cons
79 #define gen_PREDECESSOR_cons gen_cons
80 #define gen_successor_cons gen_cons
81 #define gen_predecessor_cons gen_cons
83 
84 
85 /* Remove all the predecessors of an interval: */
86 static void
88 {
89  /* Detach the predecessor vertex: */
90  MAP(PREDECESSOR, p, {
92  }, vertex_predecessors(interval));
93  /* And remove all the predecessors: */
95  vertex_predecessors(interval) = NIL;
96 }
97 
98 
99 /* Remove all the instances of a predecessor pred of an interval.
100 
101  Return true if pred was really in the predecessor list: */
102 static bool
104  vertex pred)
105 {
106  bool pred_has_been_found_p = false;
107  list predecessors_to_remove = NIL;
108  /* Detach the predecessor vertex: */
109  MAP(PREDECESSOR, p, {
110  if (predecessor_vertex(p) == pred) {
112  predecessors_to_remove = CONS(PREDECESSOR, p, predecessors_to_remove);
113  pred_has_been_found_p = true;
114  }
115  }, vertex_predecessors(interval));
116  /* And now remove the predecessors than own pred: */
117  MAP(PREDECESSOR, p, {
118  gen_remove(&vertex_predecessors(interval), p);
119  free_predecessor(p);
120  }, predecessors_to_remove);
121 
122  return pred_has_been_found_p;
123 }
124 
125 
126 /* Add an interval node to an interval and remove the node. */
127 static void
129  vertex interval,
130  vertex node)
131 {
132  /* Replace every allusion to node by interval in the interval
133  graph.
134 
135  The main issue is that the interval graph must remain a graph, that
136  is it cannot have more than one edge from a vertex to another one: */
137  MAP(VERTEX, v, {
138  list predecessors_to_change = NIL;
139  bool interval_already_in_predecessors = false;
140  MAPL(ip, {
141  if (predecessor_vertex(PREDECESSOR(CAR(ip))) == node)
142  predecessors_to_change = CONS(PREDECESSOR,
143  PREDECESSOR(CAR(ip)),
144  predecessors_to_change);
145  if (predecessor_vertex(PREDECESSOR(CAR(ip))) == interval)
146  interval_already_in_predecessors = true;
147  }, vertex_predecessors(v));
148  if (predecessors_to_change != NIL) {
149  /* There is at least an interval that must appear ONLY ONCE in
150  the predecessors. Thus it is easier to delete any reference
151  an create an unique instance of it: */
152  /* I guess there is memory leak here... */
153  gen_list_and_not(&vertex_predecessors(v), predecessors_to_change);
154  if (! interval_already_in_predecessors)
155  /* Add the lacking interval in the predecessors: */
159  }
160  }, graph_vertices(intervals));
161 
162  /* Concatenate the control nodes to the interval and preserve the
163  order to keep the entry node first: */
167  /* Protect the control nodes from later deletion (useless to free
168  the list since it is still lived via gen_nconc. Thanks to
169  Purify... :-) */
171  /* Detach the node: */
173  /* Clean up the useless old node: */
174  gen_remove(&graph_vertices(intervals), node);
175  free_vertex(node);
176 }
177 
178 
179 /* Add the interval from (node, intervals) to interval graph
180  intervals and update selected_nodes accordingly if : */
181 static void __attribute__ ((unused))
182 add_to_interval_or_create_new_interval(vertex node,
183  graph intervals,
184  set selected_nodes)
185 {
186  bool a_node_has_been_added;
187  /* Since we modify in place the current interval graph, do not
188  perturbate the do/MAP loop on intervals below. Just keep the
189  list of interval to be removed later. */
190  list intervals_to_be_removed = NIL;
191  /* The new interval will be the node itself, begin of the new
192  interval. Just select it and keep it: */
193  set_add_element(selected_nodes, selected_nodes, (char *) node);
194 
195  do {
196  a_node_has_been_added = false;
197  /* Find a candidate through all the intervals: */
198  MAP(VERTEX, candidate, {
199  if (!set_belong_p(selected_nodes, (char *) candidate)) {
200  bool all_predecessors_are_in_current_interval = true;
201  /* Test that the candidate has all its predecessors in
202  the interval we are building: */
205  all_predecessors_are_in_current_interval = false;
206  break;
207  }
208  }, vertex_predecessors(candidate));
209  if (all_predecessors_are_in_current_interval) {
210  /* Ok, this node belong to the new interval: */
211  /* add_node_to_interval(candidate,
212  node,
213  intervals,
214  selected_nodes,
215  &intervals_to_be_removed);*/
216  /* Look for the next appliant: */
217  a_node_has_been_added = true;
218  break;
219  }
220  }
221  }, graph_vertices(intervals));
222  } while(a_node_has_been_added);
223 
224  gen_full_free_list(intervals_to_be_removed);
225 }
226 
227 
228 static void
230 {
231  MAP(VERTEX, node, {
232  pips_debug(0, "Interval %p, control nodes:\n", node);
234  pips_debug(0, "Interval predecessors:\n");
235  MAP(SUCCESSOR, p, {
236  pips_debug(0, "\t%p\n", predecessor_vertex(p));
238  }, graph_vertices(intervals));
239 }
240 
241 
242 /* Build an interval graph from an older interval graph and put it in the
243  older one. An interval is a subgraph whose header dominate all its
244  nodes. It can be seen as a natural loop plus an acyclic structure that
245  dangles from the nodes of that loop.
246 
247  Algorithm use the T1/T2 analysis that can be found from pages 665
248  to 670 of:
249 
250 @book{dragon-1986,
251  author = {Alfred V. Aho and Ravi Sethi and Jeffrey D. Ullman},
252  title = {Compilers Principles, Techniques and Tools},
253  publisher = {Addison-Wesley Publishing Company},
254  year = 1986
255  }
256 
257  It looks like it is from Hecht and Ullman according to Zahira
258  Ammarguellat.
259 */
260 static bool
262 {
263  bool a_node_has_been_fused;
264  bool the_interval_graph_has_been_modified = false;
265  vertex entry_interval = VERTEX(CAR(graph_vertices(intervals)));
266 
267  /* Apply the T2 transformation, that is equivalent to my
268  fuse_sequences_in_unstructured elsewhere. Just use a less
269  optimized algorithm here: */
270  do {
271  a_node_has_been_fused = false;
272  MAP(VERTEX, node, {
273  pips_debug(8, "vertex %p.\n", node);
274  if (node != entry_interval
275  /* The entry interval is kept untouched */
276  && gen_length(vertex_predecessors(node)) == 1) {
277  /* Fuse a node with its only predecessor: */
279  pips_debug(8, "\tonly one vertex predecessor %p.\n", p_v);
280  add_node_to_interval(intervals, p_v, node);
281  /* Let's go to find a new interval to fuse: */
282  a_node_has_been_fused = true;
283  break;
284  }
285  }, graph_vertices(intervals));
286  the_interval_graph_has_been_modified |= a_node_has_been_fused;
287  } while (a_node_has_been_fused);
288 
289  /* T1 transformation on page 668: Remove the eventual arcs to
290  itself: */
291  MAP(VERTEX, node, {
292  /* If a loop around a interval node is removed, it considered
293  as a graph modification: */
294  the_interval_graph_has_been_modified
296  }, graph_vertices(intervals));
297 
298  return the_interval_graph_has_been_modified;
299 }
300 
301 
302 /* Get the interval node of a control or create it if it does not
303  exist and add it to the interval graph. */
304 static vertex
306  graph intervals,
307  hash_table control_to_interval_node)
308 {
309  vertex interval;
310  if (!hash_defined_p(control_to_interval_node, (char *) c)) {
311  /* This control has never been seen before: allocate the
312  peering interval node with no successor: */
313  interval =
315  NIL);
316  /* Use gen_nconc since the entry interval must be the first
317  one: */
318  graph_vertices(intervals) = gen_nconc(graph_vertices(intervals),
319  CONS(VERTEX, interval, NIL));
320  hash_put(control_to_interval_node, (char *) c, (char *) interval);
321  }
322  else
323  interval = (vertex) hash_get(control_to_interval_node, (char *) c);
324 
325  return interval;
326 }
327 
328 
329 /* Duplicate the control graph in a format suitable to deal with
330  intervals later.
331 
332  The interval graph format is the predecessor control graph in
333  fact. */
334 static graph
336 {
337  list blocs = NIL;
338  graph intervals = make_graph(NIL);
339 
340  hash_table control_to_interval_node = hash_table_make(hash_pointer, 0);
341  pips_debug(5, "Control entry node %p:\n", entry_node);
342  CONTROL_MAP(c, {
343  vertex interval =
345  intervals,
346  control_to_interval_node);
347  pips_debug(6, "\tControl %p -> interval %p\n", c, interval);
348  MAP(CONTROL, p, {
349  bool interval_already_in_predecessors = false;
350  vertex vertex_predecessor =
352  intervals,
353  control_to_interval_node);
354  /* Add the predeccessor only if it is not already in the
355  predecessor list: */
356  MAPL(ip, {
357  if (predecessor_vertex(PREDECESSOR(CAR(ip))) == vertex_predecessor) {
358  interval_already_in_predecessors = true;
359  break;
360  }
361  }, vertex_predecessors(interval));
362  if (! interval_already_in_predecessors) {
364  vertex_predecessor);
365  vertex_predecessors(interval) =
366  CONS(PREDECESSOR, v_p, vertex_predecessors(interval));
367  }
368  pips_debug(7, "\t\tControl predecessor %p -> interval %p\n",
369  p, vertex_predecessor);
370  }, control_predecessors(c));
371  }, entry_node, blocs);
372  gen_free_list(blocs);
373 
374  hash_table_free(control_to_interval_node);
375 
376  return intervals;
377 }
378 
379 
380 /* Return the list of control nodes exiting an interval. Note that if a
381  node of the control list is in fact the exit_node of an unstructured, it
382  is really an exit node at an upper level. */
383 static list
384 interval_exit_nodes(vertex interval, control exit_node)
385 {
386  list exit_controls = NIL;
387 
388  pips_debug(6, "Interval %p with controls ", interval);
389  ifdebug(6)
391  MAP(CONTROL, c, {
392  pips_debug(7, "\n\tControl %p:\n", c);
393  MAP(CONTROL, successor, {
394  pips_debug(7, "\t\tControl successor %p:\n", successor);
397  /* A successor that is not in the interval is an exit
398  node... Add it to the exit nodes list if not
399  already in it: */
400  if (!gen_in_list_p(successor, exit_controls))
401  exit_controls = CONS(CONTROL, successor, exit_controls);
402  }
403  }, control_successors(c));
404 
405  if (c == exit_node)
406  /* The current exit_node of the unstructured is clearly an
407  exit node even if it does not have any successor: */
408  exit_controls = CONS(CONTROL, c, exit_controls);
410 
411  ifdebug(6) {
412  pips_debug(6, "Interval exit node list: ");
413  display_address_of_control_nodes(exit_controls);
414  pips_debug(6, "\n");
415  }
416 
417  return exit_controls;
418 }
419 
420 
421 /* Put all the controls in their own unstructured to hierarchize the
422  graph and link the unstructured to the outer unstructured.
423 
424  The exit_node is the exit control node, either control_undefined if
425  it there is no exit : it is a true endless loop (assume it is not
426  the exit node). */
427 static void
429  list controls,
430  control exit_node)
431 {
432  /* The list of all reachable controls of the new unstructured: */
433  list new_controls = gen_copy_seq(controls);
434 
435  control entry_node = CONTROL(CAR(controls));
436  /* Create the new control nodes with the new unstructured: */
437  control new_entry_node = make_control(control_statement(entry_node),
438  NIL, NIL);
439  control new_exit_node = make_control(make_nop_statement(),
440  NIL, NIL);
441  unstructured new_unstructured = make_unstructured(new_entry_node,
442  new_exit_node);
443  control_statement(entry_node) =
445  new_unstructured));
446  ifdebug(6) {
447  pips_debug(6, "List of controls: ");
449  if (exit_node != control_undefined) {
450  pips_debug(6, "\nExit node %p\n", exit_node);
451  }
452  pips_debug(6, "New unstructured %p: new_entry_node = %p, new_exit_node = %p\n",
453  new_unstructured, new_entry_node, new_exit_node);
454  }
455  /* Now the hard work: replace carefully the old control nodes by
456  new one in the spaghetti plate... */
457 
458  /* First clone the graph structure: */
459  control_successors(new_entry_node) =
460  gen_copy_seq(control_successors(entry_node));
461  control_predecessors(new_entry_node) =
462  gen_copy_seq(control_predecessors(entry_node));
463  control_list_patch(new_controls, entry_node, new_entry_node);
464  if (exit_node != control_undefined) {
465  control_successors(new_exit_node) =
466  gen_copy_seq(control_successors(exit_node));
467  control_predecessors(new_exit_node) =
469  /* Add the new_exit_node in the new_controls list: */
470  new_controls = CONS(CONTROL, new_exit_node, new_controls);
471  }
472  ifdebug(6) {
473  pips_debug(6, "new_controls list: ");
474  display_address_of_control_nodes(new_controls);
475  }
476 
477  /* Correct the nodes to reflect the new nodes: */
478  MAP(CONTROL, c, {
479  control_list_patch(control_successors(c), entry_node, new_entry_node);
480  control_list_patch(control_predecessors(c), entry_node, new_entry_node);
481  if (exit_node != control_undefined) {
482  control_list_patch(control_successors(c), exit_node, new_exit_node);
483  control_list_patch(control_predecessors(c), exit_node, new_exit_node);
484  }
485  }, new_controls);
486 
487  /* Detach the new unstructured from the old one: */
488  MAP(CONTROL, c, {
489  gen_list_and(&control_successors(c), new_controls);
490  gen_list_and(&control_predecessors(c), new_controls);
491  }, new_controls);
492 
493  /* If there was a goto from exit_node to entry_node, there is an
494  artefact one between new_exit_node and new_entry_node. Remove
495  it: */
496  unlink_2_control_nodes(new_exit_node, new_entry_node);
497 
498  /* Detach the old unstructured from the new one: */
499  gen_list_and_not(&control_successors(entry_node), new_controls);
500  gen_list_and_not(&control_predecessors(entry_node), new_controls);
501 
502  /* Unlink an eventual loop around entry_node that has been
503  captured anyway in the new unstructured: */
504  unlink_2_control_nodes(entry_node, entry_node);
505 
506  if (exit_node != control_undefined) {
507  gen_list_and_not(&control_successors(exit_node), new_controls);
508  gen_list_and_not(&control_predecessors(exit_node), new_controls);
509  }
510 
511  if (exit_node != control_undefined
512  && control_successors(entry_node) == NIL /* When a single node
513  loop has been hierarchize, this link already exist */
514  ) {
515  /* Now the exit_node becomes a successor of the entry_node: */
516  link_2_control_nodes(entry_node, exit_node);
517  }
518 
519  /* Update the control list of the interval that owns only
520  entry_node after hierarchization: */
523  CONS(CONTROL, entry_node, NIL);
524 
525  gen_free_list(new_controls);
526 
527  ifdebug(5) {
528  pips_debug(6, "Nodes from entry_node: ");
529  display_linked_control_nodes(entry_node);
530  if (exit_node != control_undefined) {
531  pips_debug(6, "\nNodes from exit_node: ");
532  display_linked_control_nodes(exit_node);
533  }
534  pips_debug(6, "\nNodes from new_entry_node: ");
535  display_linked_control_nodes(new_entry_node);
536  pips_debug(6, "\nNodes from new_exit_node: ");
537  display_linked_control_nodes(new_exit_node);
538  }
539  ifdebug(1) {
540  check_control_coherency(new_entry_node);
541  check_control_coherency(new_exit_node);
542  check_control_coherency(entry_node);
543  if (exit_node != control_undefined)
544  check_control_coherency(exit_node);
545  pips_assert("Control should be consistent from entry_node)...",
546  control_consistent_p(entry_node));
547  }
548  pips_assert("new_exit_node cannot have a successor.",
549  control_successors(new_exit_node) == NIL);
550  /* ifdebug(7) */
551  /* print_statement(control_statement(entry_node)); */
552 }
553 
554 
555 /* Use an interval graph partitionning method to recursively
556  decompose the control graph.
557 
558  Have a look to paper "A Control-Flow Normalization Algorithm and Its
559  Complexity" (1994) from Zahira Ammarguellat for a bibliography of the
560  domain.
561  */
562 void
564 {
565  /* An interval graph is represented by a graph with
566  interval_vertex_label decorations embedding control nodes. The
567  first interval of the graph is the entry interval of the
568  interval graph and the first control node of an interval is the
569  entry control node of the interval: */
570  bool modified;
571  control entry_node, exit_node;
572  graph intervals;
573 
574  debug_on("RECURSIVE_DECOMPOSITION_DEBUG_LEVEL");
575 
576  entry_node = unstructured_control(u);
577  exit_node = unstructured_exit(u);
578 
579  /* The seed interval graph is indeed the control graph itself: */
580  intervals = control_graph_to_interval_graph_format(entry_node);
581 
582  pips_debug(3, "Entering with unstructured %p (%p, %p)\n",
583  u, entry_node, exit_node);
584  ifdebug(5) {
585  pips_debug(5, "Nodes from entry_node: ");
586  display_linked_control_nodes(entry_node);
587  pips_debug(5, "\nNodes from exit_node: ");
588  display_linked_control_nodes(exit_node);
589  }
590  ifdebug(6)
591  display_interval_graph(intervals);
592 
593  /* Apply recursively interval graph decomposition: */
594  do {
595  /* For all intervals of the graph: */
596  MAP(VERTEX, interval, {
598  control interval_entry = CONTROL(CAR(controls));
599  list interval_exits = interval_exit_nodes(interval, exit_node);
600  if (/* If this interval has at most one exit it should be put
601  in its own unstructured: */
602  gen_length(interval_exits) <= 1
603  && /* Useless to restructure the exit node... */
604  interval_entry != exit_node
605  && /* If a single node, only useful if there is a loop
606  inside (in order to detect these loops,
607  hierarchize_control_list() is called before
608  interval_graph() but then we need to add more
609  guards...): */
610  (gen_length(controls) > 1
611  || (gen_length(control_successors(interval_entry)) == 2
612  && (CONTROL(CAR(control_successors(interval_entry))) == interval_entry
613  || CONTROL(CAR(CDR(control_successors(interval_entry)))) == interval_entry)))
614  ) {
615  /* If an interval has at most one exit, the
616  underlaying control graph can be hierachized by an
617  unstructured. */
618  /* Put all the controls in their own unstructured
619  to hierarchize the graph: */
620  hierarchize_control_list(interval,
621  controls,
622  interval_exits == NIL ? control_undefined : CONTROL(CAR(interval_exits)));
623 
624  gen_free_list(interval_exits);
625  }
626  }, CDR(graph_vertices(intervals)) /* Skip the entry interval */);
627  /* Stop if the interval graph does no longer change : it is
628  only one node or an irreductible graph: */
629  /* Construct the interval graph from the previous one: */
630  modified = interval_graph(intervals);
631  pips_debug(6, "Modified = %d\n", modified);
632  ifdebug(6)
633  display_interval_graph(intervals);
634  } while (modified);
635 
636 
637  /* Do not forget to detach control nodes from interval before
638  sweeping: */
639  MAP(VERTEX, v, {
642  }, graph_vertices(intervals));
643  free_graph(intervals);
644 
645  pips_debug(3, "Exiting.\n");
646  ifdebug(5) {
647  pips_debug(5, "Nodes from entry_node: ");
648  display_linked_control_nodes(entry_node);
649  pips_debug(5, "\nNodes from exit_node: ");
650  display_linked_control_nodes(exit_node);
651  }
652  ifdebug(1)
653  pips_assert("Unstructured should be consistent here...",
655  debug_off();
656 }
static void node(FILE *out, string name)
Build for module name a node and link to its successors.
Definition: graph.c:56
graph make_graph(list a)
Definition: graph.c:56
void free_vertex(vertex p)
Definition: graph.c:107
vertex make_vertex(vertex_label a1, list a2)
Definition: graph.c:140
void free_graph(graph p)
Definition: graph.c:23
interval_vertex_label make_interval_vertex_label(list a)
unstructured make_unstructured(control a1, control a2)
Definition: ri.c:2778
bool unstructured_consistent_p(unstructured p)
Definition: ri.c:2751
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
bool control_consistent_p(control p)
Definition: ri.c:496
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
struct _newgen_struct_vertex_ * vertex
Definition: dg.h:28
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define vertex_undefined
Definition: graph.h:128
#define vertex_vertex_label(x)
Definition: graph.h:152
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
void unlink_2_control_nodes(control source, control target)
Remove all edged between 2 control nodes.
Definition: control.c:1276
void display_linked_control_nodes(control c)
Display all the control nodes reached or reachable from c for debugging purpose.
Definition: control.c:629
void display_address_of_control_nodes(list cs)
Display the adresses a list of control nodes.
Definition: control.c:612
void link_2_control_nodes(control source, control target)
Add an edge between 2 control nodes.
Definition: control.c:1193
void control_list_patch(list l, control c_old, control c_new)
Replace in a list of control nodes all the instance of a control node by another one.
Definition: control.c:336
void check_control_coherency(control c)
Test the coherency of a control node network from a control node.
Definition: control.c:487
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
void gen_list_and(list *a, const list b)
Compute A = A inter B: complexity in O(n2)
Definition: list.c:941
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
void gen_list_and_not(list *a, const list b)
Compute A = A inter non B:
Definition: list.c:963
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
interval_vertex_label arc_label
Since the arc are not used, just put a dummy type for arc_label.
Definition: hierarchize.c:51
static bool remove_interval_predecessor(vertex interval, vertex pred)
Remove all the instances of a predecessor pred of an interval.
Definition: hierarchize.c:103
static void remove_interval_predecessors(vertex interval)
Remove all the predecessors of an interval:
Definition: hierarchize.c:87
static vertex create_or_get_an_interval_node(control c, graph intervals, hash_table control_to_interval_node)
Get the interval node of a control or create it if it does not exist and add it to the interval graph...
Definition: hierarchize.c:305
static void hierarchize_control_list(vertex interval, list controls, control exit_node)
Put all the controls in their own unstructured to hierarchize the graph and link the unstructured to ...
Definition: hierarchize.c:428
static list interval_exit_nodes(vertex interval, control exit_node)
Return the list of control nodes exiting an interval.
Definition: hierarchize.c:384
static void __attribute__((unused))
Add the interval from (node, intervals) to interval graph intervals and update selected_nodes accordi...
Definition: hierarchize.c:181
#define PREDECESSOR
Definition: hierarchize.c:71
#define predecessor_vertex
Definition: hierarchize.c:68
#define make_predecessor
Definition: hierarchize.c:69
interval_vertex_label vertex_label
Instantiation of the interval graph:
Definition: hierarchize.c:48
successor predecessor
Definition: hierarchize.c:82
static void display_interval_graph(graph intervals)
Definition: hierarchize.c:229
void control_graph_recursive_decomposition(unstructured u)
Use an interval graph partitionning method to recursively decompose the control graph.
Definition: hierarchize.c:563
#define free_predecessor
Definition: hierarchize.c:70
static bool interval_graph(graph intervals)
Build an interval graph from an older interval graph and put it in the older one.
Definition: hierarchize.c:261
static graph control_graph_to_interval_graph_format(control entry_node)
Duplicate the control graph in a format suitable to deal with intervals later.
Definition: hierarchize.c:335
static void add_node_to_interval(graph intervals, vertex interval, vertex node)
Add an interval node to an interval and remove the node.
Definition: hierarchize.c:128
#define vertex_predecessors
Definition: hierarchize.c:67
#define interval_vertex_label_controls(x)
#define interval_vertex_label_undefined
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
@ hash_pointer
Definition: newgen_hash.h:32
bool set_belong_p(const set, const void *)
Definition: set.c:194
set set_add_element(set, const set, const void *)
Definition: set.c:152
#define make_nop_statement
An alias for make_empty_block_statement.
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define control_undefined
Definition: ri.h:916
#define control_predecessors(x)
Definition: ri.h:943
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_instruction_unstructured
Definition: ri.h:1475
#define control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
#define control_statement(x)
Definition: ri.h:941
#define ifdebug(n)
Definition: sg.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41