out: exit if there is no room for more relocations or symbols
[neatcc.git] / reg.c
blob33137d5d6c5293c10af59709b18e132d44f4538a
1 /* neatcc register allocation */
2 #include <stdio.h>
3 #include <string.h>
4 #include "gen.h"
5 #include "ncc.h"
6 #include "reg.h"
8 static int l_sz[NLOCALS]; /* size of locals */
9 static int l_nr[NLOCALS]; /* # of reads */
10 static int l_nw[NLOCALS]; /* # of writes */
11 static int l_na[NLOCALS]; /* # of address accesses */
12 static int l_reg[NLOCALS]; /* register mapped to locals */
13 static int l_n; /* # of locals */
15 static int f_argc; /* number of arguments */
16 static int f_varg; /* function has variable argument list */
17 static int f_lregs; /* mask of R_TMPS allocated to locals */
18 static int f_sargs; /* mask of R_ARGS to be saved */
20 void r_func(int nargs, int varg)
22 int i;
23 f_varg = varg;
24 f_argc = nargs;
25 f_lregs = 0;
26 l_n = 0;
27 for (i = 0; i < f_argc; i++)
28 r_mk(LONGSZ);
29 f_sargs = f_varg ? R_ARGS : 0;
30 for (i = 0; i < f_argc && i < N_ARGS; i++)
31 f_sargs |= 1 << argregs[i];
34 void r_mk(int sz)
36 if (!f_lregs) {
37 l_sz[l_n] = sz;
38 l_nr[l_n] = 0;
39 l_nw[l_n] = 0;
40 l_na[l_n] = 0;
41 l_reg[l_n] = -1;
42 l_n++;
46 void r_rm(int id)
50 void r_read(int id)
52 l_nr[id]++;
55 void r_write(int id)
57 l_nw[id]++;
60 void r_addr(int id)
62 l_na[id]++;
65 void r_label(int l)
69 void r_jmp(int l)
73 int r_regmap(int id)
75 return l_reg[id];
78 int r_lregs(void)
80 return f_lregs;
83 int r_sargs(void)
85 return f_sargs;
88 /* sort locals for register allocation based on the number of accesses */
89 static int *sortedlocals(void)
91 static int ord[NLOCALS];
92 int i, j;
93 for (i = 0; i < l_n; i++) {
94 for (j = i - 1; j >= 0; j--) {
95 if (l_nr[i] + l_nw[i] <= l_nw[ord[j]] + l_nr[ord[j]])
96 break;
97 ord[j + 1] = ord[j];
99 ord[j + 1] = i;
101 return ord;
104 int r_alloc(int leaf, int used)
106 int nlocregs = 0;
107 int *ord = sortedlocals();
108 int idx = 0;
109 int i;
110 f_lregs = 0;
111 f_sargs = f_varg ? R_ARGS : 0;
112 /* except unused arguments, save all arguments on the stack */
113 for (i = 0; i < f_argc && i < N_ARGS; i++)
114 if (f_varg || l_nr[i] + l_nw[i] + l_na[i])
115 f_sargs |= 1 << argregs[i];
116 /* letting arguments stay in their registers for leaf functions */
117 if (!f_varg && leaf) {
118 for (i = 0; i < f_argc && i < N_ARGS; i++) {
119 if (l_sz[i] > LONGSZ || (1 << argregs[i]) & used)
120 continue;
121 if (l_nr[i] + l_nw[i] && !l_na[i]) {
122 l_reg[i] = argregs[i];
123 f_sargs &= ~(1 << argregs[i]);
124 f_lregs |= (1 << argregs[i]);
125 nlocregs++;
129 /* try finding a register for each local */
130 for (i = 0; i < l_n; i++) {
131 int l = ord[i];
132 int nmask = (leaf ? 0 : ~R_SAVED) | used | f_lregs;
133 if (l_reg[l] >= 0 || (f_varg && l < f_argc))
134 continue;
135 /* find a free register */
136 while (idx < N_TMPS && ((1 << tmpregs[idx]) & nmask))
137 idx++;
138 if (idx >= N_TMPS)
139 break;
140 if (l_sz[l] > LONGSZ || l_na[l])
141 continue;
142 if (l_nr[l] + l_nw[l] > (leaf ? 0 : 1)) {
143 l_reg[l] = tmpregs[idx];
144 f_lregs |= 1 << tmpregs[idx];
145 if (l < N_ARGS && l < f_argc)
146 f_sargs &= ~(1 << argregs[l]);
147 nlocregs++;
148 idx++;
151 return nlocregs;