make libfirm faster
[libfirm] / ir / ana / irbackedge.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ana/irbackedge.c
4  * Purpose:     Access function for backedges.
5  * Author:      Goetz Lindenmaier
6  * Modified by:
7  * Created:     7.2002
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 2002-2003 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #include "irnode_t.h"
14 #include "array.h"
15 #include "irbackedge_t.h"
16
17 /*--------------------------------------------------------------------*/
18 /* Backedge information.                                              */
19 /*--------------------------------------------------------------------*/
20
21
22 /**
23  * Returns backarray if the node can have backedges, else returns
24  * NULL.
25  *
26  * Does not assert whether the backarray is correct -- use
27  * very careful!
28  */
29 static INLINE int *mere_get_backarray(ir_node *n) {
30   switch(intern_get_irn_opcode(n)) {
31   case iro_Block:
32     if (!get_Block_matured(n)) return NULL;
33     if (interprocedural_view && n->attr.block.in_cg) {
34       assert(n->attr.block.cg_backedge && "backedge array not allocated!");
35       return n->attr.block.cg_backedge;
36     } else {
37       assert(n->attr.block.backedge && "backedge array not allocated!");
38       return n->attr.block.backedge;
39     }
40     break;
41   case iro_Phi:
42       assert(n->attr.phi_backedge && "backedge array not allocated!");
43     return n->attr.phi_backedge;
44     break;
45   case iro_Filter:
46     if (interprocedural_view) {
47       assert(n->attr.filter.backedge && "backedge array not allocated!");
48       return n->attr.filter.backedge;
49     }
50     break;
51   default: ;
52   }
53   return NULL;
54 }
55
56 /**
57  * Returns backarray if the node can have backedges, else returns
58  * NULL.
59  */
60 static INLINE int *get_backarray(ir_node *n) {
61   int *ba = mere_get_backarray(n);
62
63   if (ba) {
64     int bal = ARR_LEN(ba);  /* avoid makro expansion in assertion. */
65     int inl = ARR_LEN(get_irn_in(n)) -1;  /* Use get_irn_in -- sensitive to view! */
66     assert(bal == inl && "backedge array with faulty length");
67   }
68
69   return ba;
70 }
71
72 /**
73  * Returns true if node has no backarray, or
74  *              if size of backarray == size of in array.
75  */
76 static INLINE bool legal_backarray (ir_node *n) {
77   int *ba = mere_get_backarray(n);
78   if (ba && (ARR_LEN(ba) != ARR_LEN(get_irn_in(n))-1))  /* Use get_irn_in -- sensitive to view! */
79     return false;
80   return true;
81 }
82
83
84 INLINE void fix_backedges(struct obstack *obst, ir_node *n) {
85   opcode opc = intern_get_irn_opcode(n);
86   int *arr = mere_get_backarray(n);
87   if (ARR_LEN(arr) == ARR_LEN(get_irn_in(n))-1)
88     return;
89   if (ARR_LEN(arr) != ARR_LEN(get_irn_in(n))-1) {
90     arr = new_backedge_arr(obst, ARR_LEN(get_irn_in(n))-1);
91     if (opc == iro_Phi)    n->attr.phi_backedge = arr;
92     if ((opc == iro_Block) && !interprocedural_view)
93       n->attr.block.backedge = arr;
94     if ((opc == iro_Block) && interprocedural_view)
95       n->attr.block.cg_backedge = arr;
96     if (opc == iro_Filter) n->attr.filter.backedge = arr;
97     return;
98   }
99   assert(legal_backarray(n));
100   /* @@@ more efficient in memory consumption, not possible with
101    array implementation.
102   if (ARR_LEN(arr) < ARR_LEN(get_irn_in(n))-1) {
103     ARR_SETLEN(int, arr, ARR_LEN(get_irn_in(n))-1);
104   }*/
105 }
106
107 /** Returns true if the predesessor pos is a backedge. */
108 bool is_backedge (ir_node *n, int pos) {
109   int *ba = get_backarray (n);
110   if (ba) return ba[pos];
111   return false;
112 }
113
114 /** Remarks that edge pos is a backedge. */
115 void set_backedge (ir_node *n, int pos) {
116   int *ba = get_backarray (n);
117   assert(ba && "can only set backedges at Phi, Filter, Block nodes.");
118   ba[pos] = 1;
119 }
120
121 /** Remarks that edge pos is a backedge. */
122 void set_not_backedge (ir_node *n, int pos) {
123   int *ba = get_backarray (n);
124   assert(ba && "can only set backedges at Phi, Filter, Block nodes.");
125   ba[pos] = 0;
126 }
127
128 /** Returns true if n has backedges. */
129 bool has_backedges (ir_node *n) {
130   int i;
131   int *ba = get_backarray (n);
132   if (ba)
133     for (i = 0; i < intern_get_irn_arity(n); i++)
134       if (ba[i]) return true;
135   return false;
136 }
137
138 /** Sets all backedge information to zero. */
139 void clear_backedges (ir_node *n) {
140   int i, rem = interprocedural_view;
141   int *ba;
142   interprocedural_view = 0;
143   ba = get_backarray (n);
144   if (ba)
145     for (i = 0; i < intern_get_irn_arity(n); i++)
146       ba[i] = 0;
147   interprocedural_view = 1;
148   ba = get_backarray (n);
149   if (ba)
150     for (i = 0; i < intern_get_irn_arity(n); i++)
151       ba[i] = 0;
152   interprocedural_view = rem;
153 }