Added interference test function
[libfirm] / ir / be / bera.c
1 /**
2  * Base routines for register allocation.
3  * @author Sebastian Hack
4  * @date 22.11.2004
5  */
6
7 #include "pset.h"
8 #include "impl.h"
9
10 #include "irnode.h"
11 #include "irmode.h"
12 #include "irdom.h"
13
14 #include "bera_t.h"
15 #include "besched_t.h"
16 #include "belive_t.h"
17
18 FIRM_IMPL1(is_allocatable_irn, int, const ir_node *)
19
20 size_t ra_irn_data_offset = 0;
21 size_t ra_irg_data_offset = 0;
22
23 void be_ra_init(void)
24 {
25         ra_irn_data_offset = register_additional_node_data(sizeof(ra_info_t));
26         ra_irg_data_offset = register_additional_graph_data(sizeof(void *));
27 }
28
29 static INLINE int values_interfere_dom(const ir_node *a, const ir_node *b)
30 {
31         const ir_node *b1 = get_nodes_block(a);
32         const ir_node *b2 = get_nodes_block(b);
33         int lo_a, lo_b;
34
35         assert(block_dominates(b1, b2));
36
37         /*
38          * if the two blocks are not equal, a and b can only interfere if a is
39          * live in at b2.
40          */
41         if(b1 != b2 && !is_live_in(b2, a))
42                 return 0;
43
44         lo_a = is_live_end(b2, a);
45         lo_b = is_live_end(b2, b);
46
47         /*
48          * If the two blocks are the same and one value is live out and the
49          * definition of the other is after the definition ov the live out
50          * value, they interfere.
51          */
52         if(b1 == b2) {
53                 int pos_a = sched_get_time_step(a);
54                 int pos_b = sched_get_time_step(b);
55
56                 if((pos_a < pos_b && lo_a) || (pos_b < pos_a && lo_b))
57                         return 1;
58         }
59
60         /*
61          * Now it is left to check, if the sequence from the last use of 'b'
62          * (or the end of the block b2, if b is live out)
63          * to the def of 'b' contains a use and NOT the def of 'a'. Then they
64          * also interfere
65          */
66         {
67                 const ir_node *irn;
68
69                 /* Initialize the liveness. */
70                 int a_live = lo_a;
71                 int b_live = lo_b;
72
73                 /* Go from the end of block b2 and try to detect the liveness. */
74                 sched_foreach_reverse(b2, irn) {
75                         int i, n;
76
77                         /*
78                          * If the definition of 'a' was found 'a' and 'b' interfere, if
79                          * 'b' is live here.
80                          */
81                         if(irn == a)
82                                 return b_live;
83
84                         /* Same goes for 'b'. */
85                         if(irn == b)
86                                 return a_live;
87
88                         /* If 'a' is not yet live, search for a use. */
89                         if(!a_live) {
90                                 for(i = 0, n = get_irn_arity(irn); i < n; ++i)
91                                         if(get_irn_n(irn, i) == a) {
92                                                 a_live = 1;
93                                                 break;
94                                 }
95                         }
96
97                         /* Same for 'b' */
98                         if(!b_live) {
99                                 for(i = 0, n = get_irn_arity(irn); i < n; ++i)
100                                         if(get_irn_n(irn, i) == b) {
101                                                 b_live = 1;
102                                                 break;
103                                         }
104                         }
105
106                 }
107         }
108
109         assert(0 && "You may never reach this place");
110
111         /* This is never reached */
112         return 0;
113 }
114
115 int values_interfere(const ir_node *a, const ir_node *b)
116 {
117         const ir_node *b1 = get_nodes_block(a);
118         const ir_node *b2 = get_nodes_block(b);
119
120         if(block_dominates(b1, b2))
121                 return values_interfere_dom(a, b);
122         else if(block_dominates(b2, b1))
123                 return values_interfere_dom(b, a);
124         else
125                 return 0;
126 }