66
66
struct hardware_register * HwTemporary;
67
67
unsigned int NumHwTemporaries;
69
* If an instruction is inside of a loop, end_loop will be the
70
* IP of the ENDLOOP instruction, otherwise end_loop will be 0
70
75
static void print_live_intervals(struct live_intervals * src)
161
166
static void scan_callback(void * data, struct rc_instruction * inst,
162
rc_register_file file, unsigned int index, unsigned int chan)
167
rc_register_file file, unsigned int index, unsigned int mask)
164
169
struct regalloc_state * s = data;
165
170
struct register_info * reg;
179
184
reg->Live.Start = inst->IP;
180
185
reg->Live.End = inst->IP;
182
if (inst->IP > reg->Live.End)
183
reg->Live.End = inst->IP;
186
} else if (s->end_loop)
187
reg->Live.End = s->end_loop;
188
else if (inst->IP > reg->Live.End)
189
reg->Live.End = inst->IP;
187
static void compute_live_intervals(struct regalloc_state * s)
192
static void compute_live_intervals(struct radeon_compiler *c,
193
struct regalloc_state *s)
195
memset(s, 0, sizeof(*s));
197
s->NumHwTemporaries = c->max_temp_regs;
199
memory_pool_malloc(&c->Pool,
200
s->NumHwTemporaries * sizeof(struct hardware_register));
201
memset(s->HwTemporary, 0, s->NumHwTemporaries * sizeof(struct hardware_register));
189
203
rc_recompute_ips(s->C);
191
205
for(struct rc_instruction * inst = s->C->Program.Instructions.Next;
192
206
inst != &s->C->Program.Instructions;
193
207
inst = inst->Next) {
194
rc_for_all_reads(inst, scan_callback, s);
195
rc_for_all_writes(inst, scan_callback, s);
209
/* For all instructions inside of a loop, the ENDLOOP
210
* instruction is used as the end of the live interval. */
211
if (inst->U.I.Opcode == RC_OPCODE_BGNLOOP && !s->end_loop) {
213
struct rc_instruction * tmp;
214
for(tmp = inst->Next;
215
tmp != &s->C->Program.Instructions;
217
if (tmp->U.I.Opcode == RC_OPCODE_BGNLOOP) {
219
} else if (tmp->U.I.Opcode
220
== RC_OPCODE_ENDLOOP) {
222
s->end_loop = tmp->IP;
229
if (inst->IP == s->end_loop)
232
rc_for_all_reads_mask(inst, scan_callback, s);
233
rc_for_all_writes_mask(inst, scan_callback, s);
199
static void rewrite_register(struct regalloc_state * s,
237
static void remap_register(void * data, struct rc_instruction * inst,
200
238
rc_register_file * file, unsigned int * index)
240
struct regalloc_state * s = data;
202
241
const struct register_info * reg;
204
243
if (*file == RC_FILE_TEMPORARY)
217
static void rewrite_normal_instruction(struct regalloc_state * s, struct rc_sub_instruction * inst)
219
const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
221
if (opcode->HasDstReg) {
222
rc_register_file file = inst->DstReg.File;
223
unsigned int index = inst->DstReg.Index;
225
rewrite_register(s, &file, &index);
227
inst->DstReg.File = file;
228
inst->DstReg.Index = index;
231
for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
232
rc_register_file file = inst->SrcReg[src].File;
233
unsigned int index = inst->SrcReg[src].Index;
235
rewrite_register(s, &file, &index);
237
inst->SrcReg[src].File = file;
238
inst->SrcReg[src].Index = index;
242
static void rewrite_pair_instruction(struct regalloc_state * s, struct rc_pair_instruction * inst)
244
if (inst->RGB.WriteMask) {
245
rc_register_file file = RC_FILE_TEMPORARY;
246
unsigned int index = inst->RGB.DestIndex;
248
rewrite_register(s, &file, &index);
250
inst->RGB.DestIndex = index;
253
if (inst->Alpha.WriteMask) {
254
rc_register_file file = RC_FILE_TEMPORARY;
255
unsigned int index = inst->Alpha.DestIndex;
257
rewrite_register(s, &file, &index);
259
inst->Alpha.DestIndex = index;
262
for(unsigned int src = 0; src < 3; ++src) {
263
if (inst->RGB.Src[src].Used) {
264
rc_register_file file = inst->RGB.Src[src].File;
265
unsigned int index = inst->RGB.Src[src].Index;
267
rewrite_register(s, &file, &index);
269
inst->RGB.Src[src].File = file;
270
inst->RGB.Src[src].Index = index;
273
if (inst->Alpha.Src[src].Used) {
274
rc_register_file file = inst->Alpha.Src[src].File;
275
unsigned int index = inst->Alpha.Src[src].Index;
277
rewrite_register(s, &file, &index);
279
inst->Alpha.Src[src].File = file;
280
inst->Alpha.Src[src].Index = index;
285
256
static void do_regalloc(struct regalloc_state * s)
287
258
/* Simple and stupid greedy register allocation */
310
281
for(struct rc_instruction * inst = s->C->Program.Instructions.Next;
311
282
inst != &s->C->Program.Instructions;
312
283
inst = inst->Next) {
313
if (inst->Type == RC_INSTRUCTION_NORMAL)
314
rewrite_normal_instruction(s, &inst->U.I);
316
rewrite_pair_instruction(s, &inst->U.P);
284
rc_remap_registers(inst, &remap_register, s);
335
void rc_pair_regalloc(struct r300_fragment_program_compiler *c, unsigned maxtemps)
303
void rc_pair_regalloc(struct radeon_compiler *cc, void *user)
305
struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)cc;
337
306
struct regalloc_state s;
339
memset(&s, 0, sizeof(s));
341
s.NumHwTemporaries = maxtemps;
342
s.HwTemporary = memory_pool_malloc(&s.C->Pool, maxtemps*sizeof(struct hardware_register));
343
memset(s.HwTemporary, 0, maxtemps*sizeof(struct hardware_register));
345
compute_live_intervals(&s);
308
compute_live_intervals(cc, &s);
347
310
c->AllocateHwInputs(c, &alloc_input, &s);
315
/* This functions offsets the temporary register indices by the number
316
* of input registers, because input registers are actually temporaries and
317
* should not occupy the same space.
319
* This pass is supposed to be used to maintain correct allocation of inputs
320
* if the standard register allocation is disabled. */
321
void rc_pair_regalloc_inputs_only(struct radeon_compiler *cc, void *user)
323
struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)cc;
324
struct regalloc_state s;
326
compute_live_intervals(cc, &s);
328
c->AllocateHwInputs(c, &alloc_input, &s);
330
int temp_reg_offset = 0;
331
for (unsigned i = 0; i < RC_REGISTER_MAX_INDEX; i++) {
332
if (s.Input[i].Allocated && temp_reg_offset <= s.Input[i].Index)
333
temp_reg_offset = s.Input[i].Index + 1;
336
if (temp_reg_offset) {
337
for (unsigned i = 0; i < RC_REGISTER_MAX_INDEX; i++) {
338
if (s.Temporary[i].Used) {
339
s.Temporary[i].Allocated = 1;
340
s.Temporary[i].File = RC_FILE_TEMPORARY;
341
s.Temporary[i].Index = i + temp_reg_offset;
345
/* Rewrite all registers. */
346
for (struct rc_instruction *inst = cc->Program.Instructions.Next;
347
inst != &cc->Program.Instructions;
349
rc_remap_registers(inst, &remap_register, &s);