1 /* neatcc global register allocation */
6 #define IC_LLD(ic, i) (O_C((ic)[i].op) == (O_LD | O_LOC) ? (ic)[i].a1 : -1)
7 #define IC_LST(ic, i) (O_C((ic)[i].op) == (O_ST | O_LOC) ? (ic)[i].a2 : -1)
9 static int ic_loc(struct ic
*ic
, long iv
, long *loc
, long *off
)
11 long oc
= O_C(ic
[iv
].op
);
12 if (oc
== (O_LD
| O_LOC
) || oc
== (O_MOV
| O_LOC
)) {
17 if (oc
== (O_ST
| O_LOC
)) {
25 /* local live region */
27 long loc
; /* local number */
28 long beg
; /* region start (instruction number) */
29 long end
; /* region end */
30 long cnt
; /* number of accesses */
31 int reg
; /* register allocated to this region */
34 static struct rgn
*rgn
; /* live regions */
35 static int rgn_n
; /* number of entries in rgn[] */
36 static int rgn_sz
; /* size of rgn[] */
38 static int *loc_ptr
; /* if the address of locals is accessed */
39 static int loc_n
; /* number of locals */
41 static long *dst_head
; /* lists of jumps to each instruction */
42 static long *dst_next
; /* next entries in dst_head[] lists */
44 static void rgn_add(long loc
, long beg
, long end
, long cnt
)
47 for (i
= 0; i
< rgn_n
; i
++) {
48 if (rgn
[i
].loc
== loc
&& rgn
[i
].beg
< end
&& rgn
[i
].end
> beg
) {
57 for (i
= 0; i
< rgn_n
; i
++)
61 if (rgn_n
>= rgn_sz
) {
62 rgn_sz
= MAX(16, rgn_sz
* 2);
63 rgn
= mextend(rgn
, rgn_n
, rgn_sz
, sizeof(rgn
[0]));
74 /* return nonzero if register reg is free from beg till end */
75 static int rgn_available(long beg
, long end
, int reg
)
78 for (i
= 0; i
< rgn_n
; i
++)
79 if (rgn
[i
].reg
== reg
)
80 if (rgn
[i
].beg
< end
&& rgn
[i
].end
> beg
)
85 static long reg_region(struct ic
*ic
, long ic_n
, long loc
, long pos
,
86 long *beg
, long *end
, char *mark
)
90 for (; pos
>= 0; pos
--) {
98 if (IC_LST(ic
, pos
) == loc
)
100 if (IC_LLD(ic
, pos
) == loc
)
104 cnt
+= reg_region(ic
, ic_n
, loc
, dst
, beg
, end
, mark
);
107 if (pos
> 0 && ic
[pos
- 1].op
& O_JMP
)
113 /* compute local's live regions */
114 static void reg_regions(struct ic
*ic
, long ic_n
, long loc
)
120 mark
= calloc(ic_n
, sizeof(mark
[0]));
121 for (i
= 0; i
< ic_n
; i
++) {
122 if (IC_LLD(ic
, i
) == loc
&& !mark
[i
]) {
125 cnt
= reg_region(ic
, ic_n
, loc
, i
, &beg
, &end
, mark
);
126 rgn_add(loc
, beg
, end
, cnt
);
129 for (i
= 0; i
< ic_n
; i
++)
130 if (IC_LST(ic
, i
) == loc
&& !mark
[i
])
131 rgn_add(loc
, i
, i
+ 1, 1);
135 /* perform global register allocation */
136 static void reg_glob(int leaf
)
141 int regs_max
= MIN(N_TMPS
>> 1, 4);
142 long regs_mask
= leaf
? R_TMPS
: R_PERM
;
144 for (i
= leaf
? 1 : 3; i
< N_TMPS
&& regs_n
< regs_max
; i
++)
145 if ((1 << i
) & regs_mask
)
147 srt
= malloc(rgn_n
* sizeof(srt
[0]));
149 for (i
= 0; i
< rgn_n
; i
++) {
150 for (j
= i
- 1; j
>= 0 && rgn
[i
].cnt
> rgn
[srt
[j
]].cnt
; j
--)
154 /* allocating registers */
155 for (i
= 0; i
< rgn_n
; i
++) {
157 long loc
= rgn
[r
].loc
;
158 long beg
= rgn
[r
].beg
;
159 long end
= rgn
[r
].end
;
160 if (loc
< 0 || loc_ptr
[loc
])
162 if (leaf
&& loc
< N_ARGS
&& beg
== 0 &&
163 rgn_available(beg
, end
, argregs
[loc
])) {
164 rgn
[r
].reg
= argregs
[loc
];
167 for (j
= 0; j
< regs_n
; j
++)
168 if (rgn_available(beg
, end
, regs
[j
]))
171 rgn
[r
].reg
= regs
[j
];
176 void reg_init(struct ic
*ic
, long ic_n
)
182 for (i
= 0; i
< ic_n
; i
++)
183 if (ic
[i
].op
& O_LOC
&& !ic_loc(ic
, i
, &loc
, &off
))
184 if (loc
+ 1 >= loc_n
)
186 loc_ptr
= calloc(loc_n
, sizeof(loc_ptr
[0]));
187 loc_sz
= calloc(loc_n
, sizeof(loc_sz
[0]));
188 for (i
= 0; i
< ic_n
; i
++) {
189 long oc
= O_C(ic
[i
].op
);
190 if (ic_loc(ic
, i
, &loc
, &off
))
192 if (oc
== (O_LD
| O_LOC
) || oc
== (O_ST
| O_LOC
)) {
193 int sz
= T_SZ(O_T(ic
[i
].op
));
196 if (off
|| sz
< 2 || sz
!= loc_sz
[loc
])
199 if (oc
== (O_MOV
| O_LOC
))
203 for (i
= 0; i
< ic_n
; i
++)
204 if (ic
[i
].op
& O_CALL
)
206 dst_head
= malloc(ic_n
* sizeof(dst_head
[0]));
207 dst_next
= malloc(ic_n
* sizeof(dst_next
[0]));
208 for (i
= 0; i
< ic_n
; i
++)
210 for (i
= 0; i
< ic_n
; i
++)
212 for (i
= 0; i
< ic_n
; i
++) {
213 if (ic
[i
].op
& O_JXX
) {
214 dst_next
[i
] = dst_head
[ic
[i
].a3
];
215 dst_head
[ic
[i
].a3
] = i
;
218 for (i
= 0; i
< loc_n
; i
++)
220 reg_regions(ic
, ic_n
, i
);
228 for (i
= 0; i
< rgn_n
; i
++)
230 ret
|= 1 << rgn
[i
].reg
;
234 /* return the allocated register of local loc */
235 int reg_lmap(long c
, long loc
)
238 for (i
= 0; i
< rgn_n
; i
++)
239 if (rgn
[i
].loc
== loc
)
240 if (rgn
[i
].beg
<= c
&& rgn
[i
].end
> c
)
245 /* return the local to which register reg is allocated */
246 int reg_rmap(long c
, long reg
)
249 for (i
= 0; i
< rgn_n
; i
++)
250 if (rgn
[i
].reg
== reg
)
251 if (rgn
[i
].beg
<= c
&& rgn
[i
].end
> c
)
269 int reg_safe(long loc
)
271 return loc
< loc_n
&& !loc_ptr
[loc
];