static unsigned int loop_max_possible_iterations(struct radeon_compiler *c, struct loop_info * loop) { unsigned int total_i = rc_recompute_ips(c); unsigned int loop_i = (loop->EndLoop->IP - loop->BeginLoop->IP) - 1; /* +1 because the program already has one iteration of the loop. */ return 1 + ((c->max_alu_insts - total_i) / loop_i); }
static void compute_live_intervals(struct regalloc_state * s) { rc_recompute_ips(s->C); for(struct rc_instruction * inst = s->C->Program.Instructions.Next; inst != &s->C->Program.Instructions; inst = inst->Next) { rc_for_all_reads(inst, scan_callback, s); rc_for_all_writes(inst, scan_callback, s); } }
/** * This function renames registers in an attempt to get the code close to * SSA form. After this function has completed, most of the register are only * written to one time, with a few exceptions. * * This function assumes all the instructions are still of type * RC_INSTRUCTION_NORMAL. */ void rc_rename_regs(struct radeon_compiler *c, void *user) { unsigned int i, used_length; int new_index; struct rc_instruction * inst; struct rc_reader_data reader_data; unsigned char * used; /* XXX Remove this once the register allocation works with flow control. */ for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { if (inst->U.I.Opcode == RC_OPCODE_BGNLOOP) return; } used_length = 2 * rc_recompute_ips(c); used = memory_pool_malloc(&c->Pool, sizeof(unsigned char) * used_length); memset(used, 0, sizeof(unsigned char) * used_length); rc_get_used_temporaries(c, used, used_length); for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { if (inst->U.I.DstReg.File != RC_FILE_TEMPORARY) continue; reader_data.ExitOnAbort = 1; rc_get_readers(c, inst, &reader_data, NULL, NULL, NULL); if (reader_data.Abort || reader_data.ReaderCount == 0) continue; new_index = rc_find_free_temporary_list(c, used, used_length, RC_MASK_XYZW); if (new_index < 0) { rc_error(c, "Ran out of temporary registers\n"); return; } reader_data.Writer->U.I.DstReg.Index = new_index; for(i = 0; i < reader_data.ReaderCount; i++) { reader_data.Readers[i].U.I.Src->Index = new_index; } } }
static void compute_live_intervals(struct radeon_compiler *c, struct regalloc_state *s) { memset(s, 0, sizeof(*s)); s->C = c; s->NumHwTemporaries = c->max_temp_regs; s->HwTemporary = memory_pool_malloc(&c->Pool, s->NumHwTemporaries * sizeof(struct hardware_register)); memset(s->HwTemporary, 0, s->NumHwTemporaries * sizeof(struct hardware_register)); rc_recompute_ips(s->C); for(struct rc_instruction * inst = s->C->Program.Instructions.Next; inst != &s->C->Program.Instructions; inst = inst->Next) { /* For all instructions inside of a loop, the ENDLOOP * instruction is used as the end of the live interval. */ if (inst->U.I.Opcode == RC_OPCODE_BGNLOOP && !s->end_loop) { int loops = 1; struct rc_instruction * tmp; for(tmp = inst->Next; tmp != &s->C->Program.Instructions; tmp = tmp->Next) { if (tmp->U.I.Opcode == RC_OPCODE_BGNLOOP) { loops++; } else if (tmp->U.I.Opcode == RC_OPCODE_ENDLOOP) { if(!--loops) { s->end_loop = tmp->IP; break; } } } } if (inst->IP == s->end_loop) s->end_loop = 0; rc_for_all_reads_mask(inst, scan_callback, s); rc_for_all_writes_mask(inst, scan_callback, s); } }
static void allocate_temporary_registers(struct radeon_compiler *c, void *user) { struct r300_vertex_program_compiler *compiler = (struct r300_vertex_program_compiler*)c; struct rc_instruction *inst; struct rc_instruction *end_loop = NULL; unsigned int num_orig_temps = 0; char hwtemps[RC_REGISTER_MAX_INDEX]; struct temporary_allocation * ta; unsigned int i, j; memset(hwtemps, 0, sizeof(hwtemps)); rc_recompute_ips(c); /* Pass 1: Count original temporaries. */ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); for (i = 0; i < opcode->NumSrcRegs; ++i) { if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { if (inst->U.I.SrcReg[i].Index >= num_orig_temps) num_orig_temps = inst->U.I.SrcReg[i].Index + 1; } } if (opcode->HasDstReg) { if (inst->U.I.DstReg.File == RC_FILE_TEMPORARY) { if (inst->U.I.DstReg.Index >= num_orig_temps) num_orig_temps = inst->U.I.DstReg.Index + 1; } } } ta = (struct temporary_allocation*)memory_pool_malloc(&compiler->Base.Pool, sizeof(struct temporary_allocation) * num_orig_temps); memset(ta, 0, sizeof(struct temporary_allocation) * num_orig_temps); /* Pass 2: Determine original temporary lifetimes */ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); /* Instructions inside of loops need to use the ENDLOOP * instruction as their LastRead. */ if (!end_loop && inst->U.I.Opcode == RC_OPCODE_BGNLOOP) { int endloops = 1; struct rc_instruction * ptr; for(ptr = inst->Next; ptr != &compiler->Base.Program.Instructions; ptr = ptr->Next){ if (ptr->U.I.Opcode == RC_OPCODE_BGNLOOP) { endloops++; } else if (ptr->U.I.Opcode == RC_OPCODE_ENDLOOP) { endloops--; if (endloops <= 0) { end_loop = ptr; break; } } } } if (inst == end_loop) { end_loop = NULL; continue; } for (i = 0; i < opcode->NumSrcRegs; ++i) { if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { ta[inst->U.I.SrcReg[i].Index].LastRead = end_loop ? end_loop : inst; } } } /* Pass 3: Register allocation */ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); for (i = 0; i < opcode->NumSrcRegs; ++i) { if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { unsigned int orig = inst->U.I.SrcReg[i].Index; inst->U.I.SrcReg[i].Index = ta[orig].HwTemp; if (ta[orig].Allocated && inst == ta[orig].LastRead) hwtemps[ta[orig].HwTemp] = 0; } } if (opcode->HasDstReg) { if (inst->U.I.DstReg.File == RC_FILE_TEMPORARY) { unsigned int orig = inst->U.I.DstReg.Index; if (!ta[orig].Allocated) { for(j = 0; j < c->max_temp_regs; ++j) { if (!hwtemps[j]) break; } ta[orig].Allocated = 1; ta[orig].HwTemp = j; hwtemps[ta[orig].HwTemp] = 1; } inst->U.I.DstReg.Index = ta[orig].HwTemp; } } } }