void rc_get_stats(struct radeon_compiler *c, struct rc_program_stats *s) { int max_reg = -1; struct rc_instruction * tmp; memset(s, 0, sizeof(*s)); for(tmp = c->Program.Instructions.Next; tmp != &c->Program.Instructions; tmp = tmp->Next){ const struct rc_opcode_info * info; rc_for_all_reads_mask(tmp, reg_count_callback, &max_reg); if (tmp->Type == RC_INSTRUCTION_NORMAL) { if (tmp->U.I.PreSub.Opcode != RC_PRESUB_NONE) s->num_presub_ops++; info = rc_get_opcode_info(tmp->U.I.Opcode); } else { if (tmp->U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Used) s->num_presub_ops++; if (tmp->U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Used) s->num_presub_ops++; /* Assuming alpha will never be a flow control or * a tex instruction. */ if (tmp->U.P.Alpha.Opcode != RC_OPCODE_NOP) s->num_alpha_insts++; if (tmp->U.P.RGB.Opcode != RC_OPCODE_NOP) s->num_rgb_insts++; info = rc_get_opcode_info(tmp->U.P.RGB.Opcode); } if (info->IsFlowControl) s->num_fc_insts++; if (info->HasTexture) s->num_tex_insts++; s->num_insts++; } s->num_temp_regs = max_reg + 1; }
/** * Calls a callback function for all sourced register channels. * * This is conservative, i.e. channels may be called multiple times, * and the writemask of the instruction is not taken into account. */ void rc_for_all_reads_chan(struct rc_instruction * inst, rc_read_write_chan_fn cb, void * userdata) { struct mask_to_chan_data d; d.UserData = userdata; d.Fn = cb; rc_for_all_reads_mask(inst, &mask_to_chan_cb, &d); }
/** * This function fills in the parameter 'used' with a writemask that * represent which components of each temporary register are used by the * program. This is meant to be combined with rc_find_free_temporary_list as a * more efficient version of rc_find_free_temporary. * @param used The function does not initialize this parameter. */ void rc_get_used_temporaries( struct radeon_compiler * c, unsigned char * used, unsigned int used_length) { struct rc_instruction * inst; struct get_used_temporaries_data d; d.Used = used; d.UsedLength = used_length; for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { rc_for_all_reads_mask(inst, get_used_temporaries_cb, &d); rc_for_all_writes_mask(inst, get_used_temporaries_cb, &d); } }
void rc_get_stats(struct radeon_compiler *c, struct rc_program_stats *s) { struct rc_instruction * tmp; memset(s, 0, sizeof(*s)); for(tmp = c->Program.Instructions.Next; tmp != &c->Program.Instructions; tmp = tmp->Next){ const struct rc_opcode_info * info; rc_for_all_reads_mask(tmp, reg_count_callback, s); if (tmp->Type == RC_INSTRUCTION_NORMAL) { info = rc_get_opcode_info(tmp->U.I.Opcode); if (info->Opcode == RC_OPCODE_BEGIN_TEX) continue; if (tmp->U.I.PreSub.Opcode != RC_PRESUB_NONE) s->num_presub_ops++; } else { if (tmp->U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Used) s->num_presub_ops++; if (tmp->U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Used) s->num_presub_ops++; /* Assuming alpha will never be a flow control or * a tex instruction. */ if (tmp->U.P.Alpha.Opcode != RC_OPCODE_NOP) s->num_alpha_insts++; if (tmp->U.P.RGB.Opcode != RC_OPCODE_NOP) s->num_rgb_insts++; if (tmp->U.P.RGB.Omod != RC_OMOD_MUL_1 && tmp->U.P.RGB.Omod != RC_OMOD_DISABLE) { s->num_omod_ops++; } if (tmp->U.P.Alpha.Omod != RC_OMOD_MUL_1 && tmp->U.P.Alpha.Omod != RC_OMOD_DISABLE) { s->num_omod_ops++; } info = rc_get_opcode_info(tmp->U.P.RGB.Opcode); } if (info->IsFlowControl) s->num_fc_insts++; if (info->HasTexture) s->num_tex_insts++; s->num_insts++; } /* Increment here because the reg_count_callback store the max * temporary reg index in s->nun_temp_regs. */ s->num_temp_regs++; }
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); } }