1 /* neatcc global register allocation */
6 #define IC_LOC(ic, i) ((ic)[i].arg1)
7 #define IC_LLD(ic, i) (O_C((ic)[i].op) == (O_LD | O_LOC))
8 #define IC_LST(ic, i) (O_C((ic)[i].op) == (O_ST | O_LOC))
10 /* local live region */
12 long loc
; /* local number */
13 long beg
; /* region start (instruction number) */
14 long end
; /* region end */
15 long cnt
; /* number of accesses */
16 int reg
; /* register allocated to this region */
19 static struct rgn
*rgn
; /* live regions */
20 static int rgn_n
; /* number of entries in rgn[] */
21 static int rgn_sz
; /* size of rgn[] */
23 static int *loc_ptr
; /* if the address of locals is accessed */
24 static int loc_n
; /* number of locals */
26 static long *dst_head
; /* lists of jumps to each instruction */
27 static long *dst_next
; /* next entries in dst_head[] lists */
29 static void rgn_add(long loc
, long beg
, long end
, long cnt
)
32 for (i
= 0; i
< rgn_n
; i
++) {
33 if (rgn
[i
].loc
== loc
&& rgn
[i
].beg
< end
&& rgn
[i
].end
> beg
) {
42 for (i
= 0; i
< rgn_n
; i
++)
46 if (rgn_n
>= rgn_sz
) {
47 rgn_sz
= MAX(16, rgn_sz
* 2);
48 rgn
= mextend(rgn
, rgn_n
, rgn_sz
, sizeof(rgn
[0]));
59 /* return nonzero if register reg is free from beg till end */
60 static int rgn_available(long beg
, long end
, int reg
)
63 for (i
= 0; i
< rgn_n
; i
++)
64 if (rgn
[i
].reg
== reg
)
65 if (rgn
[i
].beg
< end
&& rgn
[i
].end
> beg
)
70 static long reg_region(struct ic
*ic
, long ic_n
, long loc
, long pos
,
71 long *beg
, long *end
, char *mark
)
75 for (; pos
>= 0; pos
--) {
83 if (IC_LST(ic
, pos
) && IC_LOC(ic
, pos
) == loc
)
85 if (IC_LLD(ic
, pos
) && IC_LOC(ic
, pos
) == loc
)
89 cnt
+= reg_region(ic
, ic_n
, loc
, dst
, beg
, end
, mark
);
92 if (pos
> 0 && ic
[pos
- 1].op
& O_JMP
)
98 /* compute local's live regions */
99 static void reg_regions(struct ic
*ic
, long ic_n
, long loc
)
105 mark
= calloc(ic_n
, sizeof(mark
[0]));
106 for (i
= 0; i
< ic_n
; i
++) {
107 if (IC_LLD(ic
, i
) && IC_LOC(ic
, i
) == loc
&& !mark
[i
]) {
110 cnt
= reg_region(ic
, ic_n
, loc
, i
, &beg
, &end
, mark
);
111 rgn_add(loc
, beg
, end
, cnt
);
114 for (i
= 0; i
< ic_n
; i
++)
115 if (IC_LST(ic
, i
) && IC_LOC(ic
, i
) == loc
&& !mark
[i
])
116 rgn_add(loc
, i
, i
+ 1, 1);
120 /* perform global register allocation */
121 static void reg_glob(int leaf
)
126 int regs_max
= MIN(N_TMPS
>> 1, 4);
127 long regs_mask
= leaf
? R_TMPS
: R_PERM
;
129 for (i
= leaf
? 1 : 3; i
< N_TMPS
&& regs_n
< regs_max
; i
++)
130 if ((1 << i
) & regs_mask
)
132 srt
= malloc(rgn_n
* sizeof(srt
[0]));
134 for (i
= 0; i
< rgn_n
; i
++) {
135 for (j
= i
- 1; j
>= 0 && rgn
[i
].cnt
> rgn
[srt
[j
]].cnt
; j
--)
139 /* allocating registers */
140 for (i
= 0; i
< rgn_n
; i
++) {
142 long loc
= rgn
[r
].loc
;
143 long beg
= rgn
[r
].beg
;
144 long end
= rgn
[r
].end
;
145 if (loc
< 0 || loc_ptr
[loc
])
147 if (leaf
&& loc
< N_ARGS
&& beg
== 0 &&
148 rgn_available(beg
, end
, argregs
[loc
])) {
149 rgn
[r
].reg
= argregs
[loc
];
152 for (j
= 0; j
< regs_n
; j
++)
153 if (rgn_available(beg
, end
, regs
[j
]))
156 rgn
[r
].reg
= regs
[j
];
161 void reg_init(struct ic
*ic
, long ic_n
)
166 for (i
= 0; i
< ic_n
; i
++)
167 if (ic
[i
].op
& O_LOC
&& loc_n
< IC_LOC(ic
, i
) + 1)
168 loc_n
= IC_LOC(ic
, i
) + 1;
169 loc_ptr
= calloc(loc_n
, sizeof(loc_ptr
[0]));
170 loc_sz
= calloc(loc_n
, sizeof(loc_sz
[0]));
171 for (i
= 0; i
< ic_n
; i
++) {
172 long oc
= O_C(ic
[i
].op
);
173 if (oc
== (O_LD
| O_LOC
) || oc
== (O_ST
| O_LOC
)) {
174 int loc
= IC_LOC(ic
, i
);
175 int sz
= T_SZ(O_T(ic
[i
].op
));
178 if (ic
[i
].arg2
|| sz
< 2 || sz
!= loc_sz
[loc
])
181 if (oc
== (O_MOV
| O_LOC
))
182 loc_ptr
[IC_LOC(ic
, i
)]++;
185 for (i
= 0; i
< ic_n
; i
++)
186 if (ic
[i
].op
& O_CALL
)
188 dst_head
= malloc(ic_n
* sizeof(dst_head
[0]));
189 dst_next
= malloc(ic_n
* sizeof(dst_next
[0]));
190 for (i
= 0; i
< ic_n
; i
++)
192 for (i
= 0; i
< ic_n
; i
++)
194 for (i
= 0; i
< ic_n
; i
++) {
195 if (ic
[i
].op
& O_JXX
) {
196 dst_next
[i
] = dst_head
[ic
[i
].arg2
];
197 dst_head
[ic
[i
].arg2
] = i
;
200 for (i
= 0; i
< loc_n
; i
++)
202 reg_regions(ic
, ic_n
, i
);
210 for (i
= 0; i
< rgn_n
; i
++)
212 ret
|= 1 << rgn
[i
].reg
;
216 /* return the allocated register of local loc */
217 int reg_lmap(long c
, long loc
)
220 for (i
= 0; i
< rgn_n
; i
++)
221 if (rgn
[i
].loc
== loc
)
222 if (rgn
[i
].beg
<= c
&& rgn
[i
].end
> c
)
227 /* return the local to which register reg is allocated */
228 int reg_rmap(long c
, long reg
)
231 for (i
= 0; i
< rgn_n
; i
++)
232 if (rgn
[i
].reg
== reg
)
233 if (rgn
[i
].beg
<= c
&& rgn
[i
].end
> c
)
251 int reg_safe(long loc
)
253 return loc
< loc_n
&& !loc_ptr
[loc
];