08b2bef2fe220408e5b84fe6c62f075815da6766
[libfirm] / ir / ana / structure.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ana/structure.c
4  * Purpose:     Structure Analysis
5  * Author:      Michael Beck
6  * Modified by:
7  * Created:     5.4.2007
8  * CVS-ID:      $Id: $
9  * Copyright:   (c) 2007 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include "firm_common.h"
17 #include "irnode_t.h"
18 #include "structure.h"
19 #include "irdom.h"
20 #include "irouts.h"
21 #include "irtools.h"
22 #include "irgwalk.h"
23 #include "array.h"
24 #include "irphase_t.h"
25
26 #include "debug.h"
27
28 typedef union ir_reg_or_blk ir_reg_or_blk;
29
30 /* The structure tree. */
31 struct ir_reg_tree {
32         struct obstack obst;   /**< The obstack where the data is allocated. */
33         ir_region *top;        /**< The top region. */
34         ir_graph *irg;         /**< Associated graph. */
35 };
36
37 /* A region. */
38 struct ir_region {
39         firm_kind      kind;    /**< Must be k_ir_region. */
40         ir_region_kind type;    /**< The type of this region. */
41         ir_region      *parent; /**< points to the parent. */
42         ir_reg_or_blk  *parts;  /**< The list of all region parts. */
43         ir_region      **pred;  /**< The predecessor (control flow) regions of this region. */
44         ir_region      **succ;  /**< The successor (control flow) regions of this region. */
45         unsigned       prenum;  /**< DFS pre-oder number */
46         unsigned       postnum; /**< DFS post-oder number */
47         void           *link;   /**< A link field. */
48         unsigned long  nr;      /**< for debugging */
49         char           visited; /**< The visited flag. */
50 };
51
52 /* A helper type for unioning blocks and regions. */
53 union ir_reg_or_blk {
54         firm_kind *kind;    /**< For easier check. */
55         ir_node   *blk;     /**< A node */
56         ir_region *region;  /**< A region. */
57 };
58
59 /* The debug handle. */
60 DEBUG_ONLY(firm_dbg_module_t *dbg;)
61
62 /**
63  * Returns the link of a region.
64  */
65 void *get_region_link(const ir_region *reg) {
66         return reg->link;
67 }
68
69 /**
70  * Sets the link of a region.
71  */
72 void set_region_link(ir_region *reg, void *data) {
73         reg->link = data;
74 }
75
76 /**
77  * Get the immediate region of a block.
78  */
79 ir_region *get_block_region(const ir_node *block) {
80         assert(is_Block(block));
81         return block->attr.block.region;
82 }
83
84 /**
85  * Sets the immediate region of a block.
86  */
87 void set_block_region(ir_node *block, ir_region *reg) {
88         assert(is_Block(block));
89         block->attr.block.region = reg;
90 }
91
92 /**
93  * Get the immediate region of a node.
94  */
95 ir_region *get_irn_region(ir_node *n) {
96         if (is_no_Block(n))
97                 n = get_nodes_block(n);
98         return get_block_region(n);
99 }
100
101 /**
102  * Return non-if a given firm thing is a region.
103  */
104 int is_region(const void *thing) {
105         const firm_kind *kind = thing;
106         return *kind == k_ir_region;
107 }
108
109 /**
110  * Return the number of predecessors in a region.
111  */
112 int get_region_n_preds(const ir_region *reg) {
113         return ARR_LEN(reg->pred);
114 }
115
116 /**
117  * Return the predecessor region at position pos.
118  */
119 ir_region *get_region_pred(const ir_region *reg, int pos) {
120         assert(0 <= pos && pos <= get_region_n_preds(reg));
121         return reg->pred[pos];
122 }
123
124 /**
125  * Set the predecessor region at position pos.
126  */
127 void set_region_pred(ir_region *reg, int pos, ir_region *n) {
128         assert(0 <= pos && pos <= get_region_n_preds(reg));
129         reg->pred[pos] = n;
130 }
131
132 /**
133  * Return the number of successors in a region.
134  */
135 int get_region_n_succs(const ir_region *reg) {
136         return ARR_LEN(reg->succ);
137 }
138
139 /**
140  * Return the successor region at position pos.
141  */
142 ir_region *get_region_succ(const ir_region *reg, int pos) {
143         assert(0 <= pos && pos <= get_region_n_succs(reg));
144         return reg->succ[pos];
145 }
146
147 /**
148  * Set the successor region at position pos.
149  */
150 void set_region_succ(ir_region *reg, int pos, ir_region *n) {
151         assert(0 <= pos && pos <= get_region_n_succs(reg));
152         reg->succ[pos] = n;
153 }
154
155 /* ----------------------- construction -------------------------- */
156
157 /** Walker environment. */
158 typedef struct walk_env {
159         struct obstack *obst;  /**< an obstack to allocate from. */
160         ir_region **post;      /**< The list of all currently existent top regions. */
161         unsigned l_post;       /**< length of the allocated regions array. */
162         unsigned premax;       /**< maximum pre counter */
163         unsigned postmax;      /**< maximum post counter */
164         ir_node *start_block;  /**< the start block of the graph. */
165         ir_node *end_block;    /**< the end block of the graph. */
166 } walk_env;
167
168 /**
169  * Do a DFS search on the initial regions, assign a prenum and a postnum to every
170  * node and store the region nodes into the post array.
171  */
172 static void dfs_walk2(ir_region *reg, walk_env *env) {
173         int i, n;
174
175         if (reg->visited == 0) {
176                 reg->visited = 1;
177
178                 reg->prenum = env->premax++;
179                 for (i = 0, n = get_region_n_succs(reg); i < n; ++i) {
180                         /* recursion */
181                         ir_region *succ = get_region_succ(reg, i);
182                         dfs_walk2(succ, env);
183                 }
184
185                 env->post[env->postmax] = reg;
186                 reg->postnum = env->postmax++;
187         }
188 }
189
190 /**
191  * Do a DFS search on the initial regions, assign a prenum and a postnum to every
192  * node and store the region nodes into the post array.
193  */
194 static void dfs_walk(ir_graph *irg, walk_env *env) {
195         ir_graph *rem = current_ir_graph;
196         ir_region *reg;
197
198         current_ir_graph = irg;
199         reg              = get_irn_link(get_irg_start_block(irg));
200
201         env->premax  = 0;
202         env->postmax = 0;
203         dfs_walk2(reg, env);
204         current_ir_graph = rem;
205 }
206
207 /**
208  * Post-walker: wrap all blocks with a BasicBlock region
209  * and count them
210  */
211 static void wrap_BasicBlocks(ir_node *block, void *ctx) {
212         walk_env *env = ctx;
213         ir_region *reg;
214
215         /* Allocate a Block wrapper */
216         reg          = obstack_alloc(env->obst, sizeof(*reg));
217         reg->kind    = k_ir_region;
218         reg->type    = ir_rk_BasicBlock;
219         reg->parent  = NULL;
220         reg->prenum  = 0;
221         reg->postnum = 0;
222         reg->visited = 0;
223         reg->link    = NULL;
224         reg->nr      = get_irn_node_nr(block);
225         reg->parts   = NEW_ARR_D(ir_reg_or_blk, env->obst, 1);
226
227         reg->parts[0].blk = block;
228         set_irn_link(block, reg);
229
230         ++env->l_post;
231 }  /* wrap_BasicBlocks */
232
233 /**
234  * Create the pred and succ edges for Block wrapper.
235  * Kill edges to the Start and End blocks.
236  */
237 static void update_BasicBlock_regions(ir_node *blk, void *ctx) {
238         walk_env *env = ctx;
239         ir_region *reg = get_irn_link(blk);
240         int i, j, len;
241
242         if (blk == env->start_block) {
243                 /* handle Firm's self loop */
244                 reg->pred = NEW_ARR_D(ir_region *, env->obst, 0);
245         } else {
246                 len = get_Block_n_cfgpreds(blk);
247                 reg->pred = NEW_ARR_D(ir_region *, env->obst, len);
248                 for (i = j = 0; i < len; ++i) {
249                         ir_node *pred = get_Block_cfgpred_block(blk, i);
250                         reg->pred[j++] = get_irn_link(pred);
251                 }
252                 ARR_SHRINKLEN(reg->pred, j);
253         }
254
255         len = get_Block_n_cfg_outs(blk);
256         reg->succ = NEW_ARR_D(ir_region *, env->obst, len);
257         for (i = j = 0; i < len; ++i) {
258                 ir_node *succ = get_Block_cfg_out(blk, i);
259                 reg->succ[j++] = get_irn_link(succ);
260         }
261         ARR_SHRINKLEN(reg->succ, j);
262 }  /* update_BasicBlock_regions */
263
264 /** Allocate a new region of a obstack */
265 #define ALLOC_REG(obst, reg, tp) \
266         do { \
267                 (reg)          = obstack_alloc((obst), sizeof(*(reg))); \
268                 (reg)->kind    = k_ir_region; \
269                 (reg)->type    = tp; \
270                 (reg)->parent  = NULL; \
271                 (reg)->prenum  = 0; \
272                 (reg)->postnum = 0; \
273                 (reg)->visited = 0; \
274                 (reg)->link    = NULL; \
275         } while (0)
276
277 /**
278  * Creates a new Sequence region.
279  */
280 static ir_region *new_Sequence(struct obstack *obst, ir_region *nset, int nset_len) {
281         ir_region *reg;
282         int i;
283
284         ALLOC_REG(obst, reg, ir_rk_Sequence);
285
286         reg->parts = NEW_ARR_D(ir_reg_or_blk, obst, nset_len);
287
288         /* beware: list is in reverse order, reverse */
289         for (i = nset_len - 1; i >= 0; --i) {
290                 reg->parts[i].region = nset;
291                 nset->parent = reg;
292                 nset = nset->link;
293         }
294
295         reg->nr   = reg->parts[0].region->nr;
296         reg->pred = DUP_ARR_D(ir_region *, obst, reg->parts[0].region->pred);
297         reg->succ = DUP_ARR_D(ir_region *, obst, reg->parts[nset_len - 1].region->succ);
298
299         DEBUG_ONLY(
300                 DB((dbg, LEVEL_2, " Created Sequence "));
301                 for (i = 0; i < nset_len; ++i) {
302                         DB((dbg, LEVEL_2, "(%u)", reg->parts[i].region->nr));
303                 }
304                 DB((dbg, LEVEL_2, "\n"));
305         )
306         return reg;
307 }  /* new_Sequence */
308
309 /**
310  * Create a new IfThenElse region.
311  */
312 static ir_region *new_IfThenElse(struct obstack *obst, ir_region *if_b, ir_region *then_b, ir_region *else_b) {
313         ir_region *reg;
314
315         ALLOC_REG(obst, reg, ir_rk_IfThenElse);
316
317         reg->nr    = if_b->nr;
318         reg->parts = NEW_ARR_D(ir_reg_or_blk, obst, 3);
319
320         reg->parts[0].region = if_b;   if_b->parent   = reg;
321         reg->parts[1].region = then_b; then_b->parent = reg;
322         reg->parts[2].region = else_b; else_b->parent = reg;
323
324         reg->pred = DUP_ARR_D(ir_region *, obst, if_b->pred);
325         reg->succ = DUP_ARR_D(ir_region *, obst, then_b->succ);
326
327         DB((dbg, LEVEL_2, " Created If(%u)Then(%u)Else(%u)\n", reg->nr, then_b->nr, else_b->nr));
328
329         return reg;
330 }  /* new_IfThenElse */
331
332 /**
333  * Create a new IfThen region.
334  */
335 static ir_region *new_IfThen(struct obstack *obst, ir_region *if_b, ir_region *then_b) {
336         ir_region *reg;
337
338         ALLOC_REG(obst, reg, ir_rk_IfThen);
339
340         reg->nr    = if_b->nr;
341         reg->parts = NEW_ARR_D(ir_reg_or_blk, obst, 2);
342
343         reg->parts[0].region = if_b;   if_b->parent   = reg;
344         reg->parts[1].region = then_b; then_b->parent = reg;
345
346         reg->pred = DUP_ARR_D(ir_region *, obst, if_b->pred);
347         reg->succ = DUP_ARR_D(ir_region *, obst, then_b->succ);
348
349         DB((dbg, LEVEL_2, " Created If(%u)Then(%u)\n", reg->nr, then_b->nr));
350
351         return reg;
352 }  /* new_IfThenElse */
353
354 /**
355  * Create a new Switch/case region.
356  */
357 static ir_region *new_SwitchCase(struct obstack *obst, ir_region_kind type, ir_region *head, ir_region *exit,
358                                  ir_region *cases, int cases_len) {
359         ir_region *reg, *c, *n;
360         int i;
361         int add = 1;
362
363         /* check, if the exit block is in the list */
364         for (c = cases; c != NULL; c = c->link) {
365                 if (c == exit) {
366                         add = 0;
367                         break;
368                 }
369         }
370
371         ALLOC_REG(obst, reg, type);
372
373         reg->nr    = head->nr;
374         reg->parts = NEW_ARR_D(ir_reg_or_blk, obst, cases_len + add);
375
376         reg->parts[0].region = head; head->parent = reg;
377         i = 1;
378         for (c = cases; c != NULL; c = n) {
379                 n = c->link;
380                 if (c != exit) {
381                         reg->parts[i++].region = c;
382                         c->parent = reg;
383                 }
384                 c->link = NULL;
385         }
386
387         reg->pred = DUP_ARR_D(ir_region *, obst, head->pred);
388         reg->succ = NEW_ARR_D(ir_region *, obst, 1);
389         reg->succ[0] = exit;
390
391         DEBUG_ONLY(
392                 DB((dbg, LEVEL_2, " Created %s(%u)\n", reg->type == ir_rk_Switch ? "Switch" : "Case", reg->nr));
393                 for (i = 1; i < ARR_LEN(reg->parts); ++i) {
394                         DB((dbg, LEVEL_2, "  Case(%u)\n", reg->parts[i].region->nr));
395                 }
396                 DB((dbg, LEVEL_2, "  Exit(%u)\n", exit->nr));
397         )
398         return reg;
399 }  /* new_SwitchCase */
400
401 /**
402  * Create a new SelfLoop region.
403  */
404 static ir_region *new_SelfLoop(struct obstack *obst, ir_region *head) {
405         ir_region *reg, *succ;
406         int i, j, len;
407
408         ALLOC_REG(obst, reg, ir_rk_SelfLoop);
409
410         reg->nr      = head->nr;
411         reg->parts   = NEW_ARR_D(ir_reg_or_blk, obst, 1);
412
413         reg->parts[0].region = head; head->parent = reg;
414
415         len = ARR_LEN(head->pred);
416         reg->pred = NEW_ARR_D(ir_region *, obst, len - 1);
417         for (i = j = 0; i < len; ++i) {
418                 ir_region *pred = get_region_pred(head, i);
419                 if (pred != head)
420                         reg->pred[j++] = pred;
421         }
422         assert(j == len - 1);
423
424         reg->succ = NEW_ARR_D(ir_region *, obst, 1);
425         assert(ARR_LEN(head->succ) == 2);
426
427         succ = get_region_succ(head, 0);
428         if (succ != head)
429                 reg->succ[0] = succ;
430         else
431                 reg->succ[0] = get_region_succ(head, 1);
432
433         DB((dbg, LEVEL_2, " Created SelfLoop(%u)\n", reg->nr));
434
435         return reg;
436 }  /* new_SelfLoop */
437
438 /**
439  * Create a new RepeatLoop region.
440  */
441 static ir_region *new_RepeatLoop(struct obstack *obst, ir_region *head, ir_region *body) {
442         ir_region *reg, *succ;
443
444         ALLOC_REG(obst, reg, ir_rk_RepeatLoop);
445
446         reg->nr      = head->nr;
447         reg->parts   = NEW_ARR_D(ir_reg_or_blk, obst, 2);
448
449         reg->parts[0].region = head; head->parent = reg;
450         reg->parts[1].region = body; body->parent = reg;
451
452         reg->pred = DUP_ARR_D(ir_region *, obst, head->pred);
453         reg->succ = NEW_ARR_D(ir_region *, obst, 1);
454         assert(ARR_LEN(body->succ) == 2);
455
456         succ = get_region_succ(body, 0);
457         if (succ != head)
458                 reg->succ[0] = succ;
459         else
460                 reg->succ[0] = get_region_succ(body, 1);
461
462         DB((dbg, LEVEL_2, " Created RepeatLoop(%u)Body(%u)\n", reg->nr, body->nr));
463
464         return reg;
465 }  /* new_RepeatLoop */
466
467 /**
468  * Create a new WhileLoop region.
469  */
470 static ir_region *new_WhileLoop(struct obstack *obst, ir_region *head) {
471         ir_region *reg, *succ;
472         ir_region *body = head->link;
473         int i, j, len;
474
475         head->link = NULL;
476
477         ALLOC_REG(obst, reg, ir_rk_WhileLoop);
478
479         reg->nr      = head->nr;
480         reg->parts   = NEW_ARR_D(ir_reg_or_blk, obst, 2);
481
482         reg->parts[0].region = head; head->parent = reg;
483         reg->parts[1].region = body; body->parent = reg;
484
485         len = ARR_LEN(head->pred);
486         reg->pred = NEW_ARR_D(ir_region *, obst, len - 1);
487         for (i = j = 0; i < len; ++i) {
488                 ir_region *pred = get_region_pred(head, i);
489                 if (pred != body)
490                         reg->pred[j++] = pred;
491         }
492         assert(j == len - 1);
493
494         reg->succ = NEW_ARR_D(ir_region *, obst, 1);
495         assert(ARR_LEN(head->succ) == 2);
496
497         succ = get_region_succ(head, 0);
498         if (succ != body)
499                 reg->succ[0] = succ;
500         else
501                 reg->succ[0] = get_region_succ(head, 1);
502
503         DB((dbg, LEVEL_2, " Created WhileLoop(%u)Body(%u)\n", reg->nr, body->nr));
504
505         return reg;
506 }  /* new_WhileLoop */
507
508 /**
509  * Return true if a is an ancestor of b in DFS search.
510  */
511 static int is_ancestor(const ir_region *a, const ir_region *b) {
512         return (a->prenum <= b->prenum && a->postnum > b->postnum);
513 }
514
515 /**
516  *  Return true if region pred is a predecessor of region n.
517  */
518 static int pred_of(const ir_region *pred, const ir_region *n) {
519         int i;
520         for (i = get_region_n_preds(n) - 1; i >= 0; --i) {
521                 if (get_region_pred(n, i) == pred)
522                         return 1;
523         }
524         return 0;
525 }
526
527 /**
528  *  Return true if region succ is a successor of region n.
529  */
530 static int succ_of(const ir_region *succ, const ir_region *n) {
531         int i;
532         for (i = get_region_n_succs(n) - 1; i >= 0; --i) {
533                 if (get_region_succ(n, i) == succ)
534                         return 1;
535         }
536         return 0;
537 }
538
539 /**
540  *  Reverse linked list.
541  */
542 static struct ir_region *reverse_list(ir_region *n) {
543         ir_region *prev = NULL, *next;
544
545         for (; n; n = next) {
546                 next = n->link;
547                 n->link = prev;
548                 prev = n;
549         }
550         return prev;
551 }
552
553 /**
554  * Find the cyclic region in the subgraph entered by node.
555  */
556 static ir_region *find_cyclic_region(ir_region *node) {
557         int i;
558         ir_region *last = node;
559         int improper = 0;
560
561         for (i = get_region_n_preds(node) - 1; i >= 0; --i) {
562                 ir_region *pred = get_region_pred(node, i);
563
564                 /* search backedges */
565                 if (!pred->link && pred != last && is_ancestor(node, pred)) {
566                         ir_region *rem = last;
567                         int j;
568
569                         last->link = pred;
570                         last       = pred;
571                         for (j = get_region_n_preds(pred) - 1; j >= 0; --j) {
572                                 ir_region *p = get_region_pred(pred, j);
573
574                                 /* Search regions we didn't visited yet and
575                                    link them into the list. */
576                                 if (!p->link && p != last) {
577                                         if (is_ancestor(node, p)) {
578                                                 last->link = p;
579                                                 last       = p;
580                                         } else {
581                                                 improper = 1;
582                                         }
583                                 }
584                         }
585                         /* reverse the list. */
586                         last = rem->link;
587                         rem->link = reverse_list(rem->link);
588                 }
589         }
590
591         if (node->link && improper) {
592                 /* found an improper region */
593         }
594         return node;
595 }
596
597 #define LINK(list) ((ir_region *)list->link)
598
599 /**
600  * Detect a cyclic region.
601  */
602 static ir_region *cyclic_region_type(struct obstack *obst, ir_region *node) {
603         ir_region *list;
604
605         /* simple cases first */
606         if (succ_of(node, node)) {
607                 return new_SelfLoop(obst, node);
608         }
609         if (get_region_n_succs(node) == 1) {
610                 ir_region *succ = get_region_succ(node, 0);
611                 if (get_region_n_preds(succ) == 1 && succ_of(node, succ)) {
612                         return new_RepeatLoop(obst, node, succ);
613                 }
614         }
615         list = find_cyclic_region(node);
616
617         if (list->link && !LINK(list)->link && get_region_n_succs(list->link) == 1) {
618                 return new_WhileLoop(obst, list);
619         }
620
621         return NULL;
622 }
623
624 /**
625  * Clear all links on a list. Needed, because we expect cleared links-
626  */
627 static void clear_list(ir_region *list) {
628         ir_region *next;
629
630         for (next = list; next; list = next) {
631                 next = list->link;
632                 list->link = NULL;
633         }
634 }
635
636 #define ADD_LIST(list, n) do { n->link = list; list = n; ++list##_len; } while(0)
637
638 /**
639  * Detect an acyclic region.
640  */
641 static ir_region *acyclic_region_type(struct obstack *obst, ir_region *node) {
642         ir_region *n, *m;
643         int p, s, i, k;
644         ir_region *nset = NULL;
645         int nset_len = 0;
646         ir_region *res;
647
648         /* check for a block containing node */
649         n = node;
650         p = get_region_n_preds(n) == 1;
651         s = 1;
652         while (p & s) {
653                 n = get_region_pred(n, 0);
654                 p = get_region_n_preds(n) == 1;
655                 s = get_region_n_succs(n) == 1;
656         }
657         p = 1;
658         s = get_region_n_succs(n) == 1;
659         while (p & s) {
660                 ADD_LIST(nset, n);
661                 n = get_region_succ(n, 0);
662                 p = get_region_n_preds(n) == 1;
663                 s = get_region_n_succs(n) == 1;
664         }
665         if (p) {
666                 ADD_LIST(nset, n);
667         }
668         if (nset_len > 1) {
669                 /* node --> .. --> .. */
670                 res = new_Sequence(obst, nset, nset_len);
671                 return res;
672         }
673         node = n;
674
675         /* check for IfThenElse */
676         k = get_region_n_succs(node);
677         if (k == 2) {
678                 int n_succs, m_succs, n_preds, m_preds;
679
680                 n = get_region_succ(node, 0);
681                 m = get_region_succ(node, 1);
682
683                 n_succs = get_region_n_succs(n);
684                 m_succs = get_region_n_succs(m);
685                 n_preds = get_region_n_preds(n);
686                 m_preds = get_region_n_preds(m);
687                 if (n_succs == 1 && n_succs == m_succs && n_preds == m_preds &&
688                     get_region_succ(n, 0) == get_region_succ(m, 0)) {
689                         /*
690                          *    /-->n---\
691                          * node      ...
692                          *    \-->m---/
693                          */
694                         return new_IfThenElse(obst, node, n, m);
695                 }
696                 if (n_succs == 1 &&
697                     get_region_succ(n, 0) == m &&
698                     pred_of(node, m)) {
699                         /*
700                          * node -->n-->m
701                          *    \-------/
702                          */
703                         return new_IfThen(obst, node, n);
704                 }
705                 if (m_succs == 1 &&
706                     get_region_succ(m, 0) == m &&
707                     pred_of(node, n)) {
708                         /*
709                          * node -->m-->n
710                          *    \-------/
711                          */
712                         return new_IfThen(obst, node, m);
713                 }
714         }
715         /* check for Switch, case */
716         if (k > 0) {
717                 ir_region *exit = NULL;
718                 nset = NULL; nset_len = 0;
719                 p = 0;
720                 for (i = k - 1; i >= 0; --i) {
721                         n = get_region_succ(node, i);
722                         ADD_LIST(nset, n);
723                         if (get_region_n_succs(n) != 1) {
724                                 /* must be the exit */
725                                 exit = n;
726                                 ++p;
727                                 if (p > 1)
728                                         break;
729                         }
730                 }
731                 if (p <= 1) {
732                         ir_region_kind kind = ir_rk_Case;
733                         ir_region *pos_exit_1 = NULL;
734                         ir_region *pos_exit_2 = NULL;
735
736                         /* find the exit */
737                         for (m = nset; m != NULL; m = m->link) {
738                                 if (get_region_n_succs(m) != 1) {
739                                         /* must be the exit block */
740                                         if (exit == NULL) {
741                                                 exit = m;
742                                         } else if (exit != m) {
743                                                 /* two exits */
744                                                 exit = NULL;
745                                                 break;
746                                         }
747                                 } else {
748                                         ir_region *succ = get_region_succ(m, 0);
749
750                                         if (succ->link == NULL) {
751                                                 if (exit == NULL) {
752                                                         if (succ == pos_exit_1)
753                                                                 exit = succ;
754                                                         else if (succ == pos_exit_2)
755                                                                 exit = succ;
756                                                         else if (pos_exit_1 == NULL)
757                                                                 pos_exit_1 = succ;
758                                                         else if (pos_exit_2 == NULL)
759                                                                 pos_exit_2 = succ;
760                                                         else {
761                                                                 /* more than two possible exits */
762                                                                 break;
763                                                         }
764                                                 } else if (exit != succ) {
765                                                         /* two exits */
766                                                         exit = NULL;
767                                                         break;
768                                                 }
769                                         }
770                                 }
771                         }
772                         if (exit != NULL) {
773                                 /* do the checks */
774                                 for (n = nset; n != NULL; n = n->link) {
775                                         ir_region *succ;
776                                         if (n == exit) {
777                                                 /* good, default fall through */
778                                                 continue;
779                                         }
780                                         succ = get_region_succ(n, 0);
781                                         if (succ == exit) {
782                                                 /* good, switch to exit */
783                                                 continue;
784                                         }
785                                         if (succ->link == NULL) {
786                                                 /* another exit */
787                                                 break;
788                                         } else {
789                                                 /* a fall through */
790                                                 kind = ir_rk_Switch;
791                                         }
792                                 }
793
794                                 if (n == NULL) {
795                                         /* detected */
796                                         return new_SwitchCase(obst, kind, node, exit, nset, nset_len);
797                                 }
798                         }
799                 }
800                 clear_list(nset);
801         }
802         return NULL;
803 }
804
805 /**
806  * replace all pred edges from region pred that points to any of the set set
807  * to ONE edge to reg.
808  */
809 static void replace_pred(ir_region *succ, ir_region *reg) {
810         int i, len = get_region_n_preds(succ);
811         int have_one = 0;
812
813         for (i = 0; i < len; ++i) {
814                 ir_region *pred = get_region_pred(succ, i);
815
816                 if (pred->parent == reg) {
817                         ir_region *r;
818
819                         if (have_one) {
820                                 /* kill it */
821                                 r = get_region_pred(succ, --len);
822                         } else {
823                                 /* replace it */
824                                 have_one = 1;
825                                 r = reg;
826                         }
827                         set_region_pred(succ, i, r);
828                 }
829         }
830         ARR_SHRINKLEN(succ->pred, len);
831 }
832
833 /**
834  * replace all succ edges from region pred that points to any of the set set
835  * to ONE edge to reg.
836  */
837 static void replace_succ(ir_region *pred, ir_region *reg) {
838         int i, len = get_region_n_succs(pred);
839         int have_one = 0;
840
841         for (i = 0; i < len; ++i) {
842                 ir_region *succ = get_region_succ(pred, i);
843
844                 if (succ->parent == reg) {
845                         ir_region *r;
846
847                         if (have_one) {
848                                 /* kill it */
849                                 r = get_region_succ(pred, --len);
850                         } else {
851                                 /* replace it */
852                                 have_one = 1;
853                                 r = reg;
854                         }
855                         set_region_succ(pred, i, r);
856                 }
857         }
858         ARR_SHRINKLEN(pred->succ, len);
859 }
860
861 /**
862  * Reduce the graph by the node reg.
863  */
864 static void reduce(walk_env *env, ir_region *reg) {
865         int i;
866         ir_region *head = reg->parts[0].region;
867         unsigned maxorder = head->postnum;
868         unsigned minorder = head->prenum;
869
870         /* second step: replace all preds in successors */
871         for (i = get_region_n_succs(reg) - 1; i >= 0; --i) {
872                 ir_region *succ = get_region_succ(reg, i);
873
874                 replace_pred(succ, reg);
875         }
876
877         /* second third: replace all succs in predessors */
878         for (i = get_region_n_preds(reg) - 1; i >= 0; --i) {
879                 ir_region *pred = get_region_pred(reg, i);
880
881                 replace_succ(pred, reg);
882         }
883
884         reg->prenum  = minorder;
885         reg->postnum = maxorder;
886         env->post[maxorder] = reg;
887 }
888
889 /**
890  * Construct the region tree of a graph by doing
891  * structural analysis.
892  *
893  * Uses link fields of nodes.
894  *
895  * @param irg  the graph
896  */
897 ir_reg_tree *construct_region_tree(ir_graph *irg) {
898         walk_env env;
899         ir_graph *rem = current_ir_graph;
900         ir_reg_tree *res = xmalloc(sizeof(*res));
901
902         obstack_init(&res->obst);
903
904         current_ir_graph = irg;
905
906         FIRM_DBG_REGISTER(dbg, "firm.ana.structure");
907         firm_dbg_set_mask(dbg, SET_LEVEL_5);
908
909         DB((dbg, LEVEL_1, "Structural analysis on %+F starts...\n", irg));
910
911         dump_ir_block_graph(irg, "-structure_start");
912
913         /* we need dominance info */
914         assure_doms(irg);
915         /* and out edges */
916         assure_irg_outs(irg);
917
918         env.start_block = get_irg_start_block(irg);
919         env.end_block   = get_irg_end_block(irg);
920
921         /* create the Block wrapper and count them */
922         env.l_post = 0;
923         env.obst   = &res->obst;
924         irg_block_walk_graph(irg, NULL, wrap_BasicBlocks, &env);
925         irg_block_walk_graph(irg, NULL, update_BasicBlock_regions, &env);
926
927         env.post = NEW_ARR_F(ir_region *, env.l_post);
928
929         /* do the DFS walk */
930         dfs_walk(irg, &env);
931
932         DB((dbg, LEVEL_1, "%d regions left\n", env.postmax));
933         if (env.postmax > 1) {
934                 unsigned postctr = 0;
935                 do {
936                         ir_region *reg, *n = env.post[postctr];
937                         do {
938                                 if (n->parent) {
939                                         /* already folded */
940                                         break;
941                                 }
942                                 /* locate an acyclic region if present */
943                                 reg = acyclic_region_type(env.obst, n);
944                                 if (reg == NULL) {
945                                         /* locate a cyclic region */
946                                         reg = cyclic_region_type(env.obst, n);
947                                 }
948                                 if (reg != NULL) {
949                                         /* found a new region */
950                                         reduce(&env, reg);
951                                         n = reg;
952                                 }
953                         } while (reg != NULL);
954                         ++postctr;
955                 } while (postctr < env.postmax);
956         }
957         DB((dbg, LEVEL_1, "Structural analysis finished.\n"));
958
959         DEL_ARR_F(env.post);
960         current_ir_graph = rem;
961
962         res->top = env.post[0];
963         res->irg = irg;
964         return res;
965 }
966
967 /**
968  * Walk over the region tree.
969  *
970  * @param reg   a region node
971  * @param pre   walker function, executed before the children of a tree node are visited
972  * @param post  walker function, executed after the children of a tree node are visited
973  * @param env   environment, passed to pre and post
974  */
975 static void region_tree_walk2(ir_region *reg, irg_reg_walk_func *pre, irg_reg_walk_func *post, void *env) {
976         int i, n;
977
978         if (pre)
979                 pre(reg, env);
980         if (reg->type != ir_rk_BasicBlock) {
981                 for (i = 0, n = ARR_LEN(reg->parts); i < n; ++i)
982                         region_tree_walk2(reg->parts[i].region, pre, post, env);
983         }
984         if (post)
985                 post(reg, env);
986 }
987
988 /**
989  * Walk over the region tree.
990  *
991  * @param tree  the tree
992  * @param pre   walker function, executed before the children of a tree node are visited
993  * @param post  walker function, executed after the children of a tree node are visited
994  * @param env   environment, passed to pre and post
995  */
996 void region_tree_walk(ir_reg_tree *tree, irg_reg_walk_func *pre, irg_reg_walk_func *post, void *env) {
997         region_tree_walk2(tree->top, pre, post, env);
998 }