r300/compiler: Handle loops in the register allocator
This commit is contained in:
@@ -583,3 +583,25 @@ struct rc_instruction * rc_match_endloop(struct rc_instruction * endloop)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The ENDLOOP instruction that ends the loop started by bgnloop.
|
||||
*/
|
||||
struct rc_instruction * rc_match_bgnloop(struct rc_instruction * bgnloop)
|
||||
{
|
||||
unsigned int bgnloop_count = 0;
|
||||
struct rc_instruction * inst;
|
||||
for (inst = bgnloop->Next; inst!=bgnloop; inst = inst->Next) {
|
||||
rc_opcode op = rc_get_flow_control_inst(inst);
|
||||
if (op == RC_OPCODE_BGNLOOP) {
|
||||
bgnloop_count++;
|
||||
} else if (op == RC_OPCODE_ENDLOOP) {
|
||||
if (bgnloop_count == 0) {
|
||||
return inst;
|
||||
} else {
|
||||
bgnloop_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -76,5 +76,6 @@ unsigned int rc_pair_remove_src(
|
||||
rc_opcode rc_get_flow_control_inst(struct rc_instruction * inst);
|
||||
|
||||
struct rc_instruction * rc_match_endloop(struct rc_instruction * endloop);
|
||||
struct rc_instruction * rc_match_bgnloop(struct rc_instruction * bgnloop);
|
||||
|
||||
#endif /* RADEON_PROGRAM_UTIL_H */
|
||||
|
||||
@@ -66,7 +66,7 @@ struct regalloc_state {
|
||||
unsigned int NumTemporaries;
|
||||
|
||||
unsigned int Simple;
|
||||
unsigned int HasLoop;
|
||||
int LoopEnd;
|
||||
};
|
||||
|
||||
enum rc_reg_class {
|
||||
@@ -176,7 +176,8 @@ static void scan_read_callback(void * data, struct rc_instruction * inst,
|
||||
}
|
||||
reg->Live[i].Used = 1;
|
||||
reg->Live[i].Start = 0;
|
||||
reg->Live[i].End = inst->IP;
|
||||
reg->Live[i].End =
|
||||
s->LoopEnd > inst->IP ? s->LoopEnd : inst->IP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,6 +510,14 @@ static void do_advanced_regalloc(struct regalloc_state * s)
|
||||
for (inst = s->C->Program.Instructions.Next;
|
||||
inst != &s->C->Program.Instructions;
|
||||
inst = inst->Next) {
|
||||
rc_opcode op = rc_get_flow_control_inst(inst);
|
||||
if (op == RC_OPCODE_BGNLOOP) {
|
||||
struct rc_instruction * endloop =
|
||||
rc_match_bgnloop(inst);
|
||||
if (endloop->IP > s->LoopEnd) {
|
||||
s->LoopEnd = endloop->IP;
|
||||
}
|
||||
}
|
||||
rc_for_all_reads_mask(inst, scan_read_callback, s);
|
||||
}
|
||||
|
||||
@@ -622,7 +631,6 @@ void rc_pair_regalloc(struct radeon_compiler *cc, void *user)
|
||||
(struct r300_fragment_program_compiler*)cc;
|
||||
struct regalloc_state s;
|
||||
int do_full_regalloc = (int)user;
|
||||
struct rc_instruction * inst;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.C = cc;
|
||||
@@ -636,20 +644,10 @@ void rc_pair_regalloc(struct radeon_compiler *cc, void *user)
|
||||
s.NumTemporaries * sizeof(struct register_info));
|
||||
memset(s.Temporary, 0, s.NumTemporaries * sizeof(struct register_info));
|
||||
|
||||
for(inst = cc->Program.Instructions.Next;
|
||||
inst != &cc->Program.Instructions;
|
||||
inst = inst->Next) {
|
||||
|
||||
if (inst->U.I.Opcode == RC_OPCODE_BGNLOOP) {
|
||||
s.HasLoop = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rc_recompute_ips(s.C);
|
||||
|
||||
c->AllocateHwInputs(c, &alloc_input_simple, &s);
|
||||
if (!s.HasLoop && do_full_regalloc) {
|
||||
if (do_full_regalloc) {
|
||||
do_advanced_regalloc(&s);
|
||||
} else {
|
||||
s.Simple = 1;
|
||||
|
||||
@@ -164,12 +164,75 @@ void rc_variable_compute_live_intervals(struct rc_variable * var)
|
||||
|
||||
for (i = 0; i < var->ReaderCount; i++) {
|
||||
unsigned int chan;
|
||||
unsigned int chan_start = start;
|
||||
unsigned int chan_end = var->Readers[i].Inst->IP;
|
||||
unsigned int mask = var->Readers[i].WriteMask;
|
||||
struct rc_instruction * inst;
|
||||
|
||||
/* Extend the live interval of T0 to the start of the
|
||||
* loop for sequences like:
|
||||
* BGNLOOP
|
||||
* read T0
|
||||
* ...
|
||||
* write T0
|
||||
* ENDLOOP
|
||||
*/
|
||||
if (var->Readers[i].Inst->IP < start) {
|
||||
struct rc_instruction * bgnloop =
|
||||
rc_match_endloop(var->Readers[i].Inst);
|
||||
chan_start = bgnloop->IP;
|
||||
}
|
||||
|
||||
/* Extend the live interval of T0 to the start of the
|
||||
* loop in case there is a BRK instruction in the loop
|
||||
* (we don't actually check for a BRK instruction we
|
||||
* assume there is one somewhere in the loop, which
|
||||
* there usually is) for sequences like:
|
||||
* BGNLOOP
|
||||
* ...
|
||||
* conditional BRK
|
||||
* ...
|
||||
* write T0
|
||||
* ENDLOOP
|
||||
* read T0
|
||||
***************************************************
|
||||
* Extend the live interval of T0 to the end of the
|
||||
* loop for sequences like:
|
||||
* write T0
|
||||
* BGNLOOP
|
||||
* ...
|
||||
* read T0
|
||||
* ENDLOOP
|
||||
*/
|
||||
for (inst = var->Inst; inst != var->Readers[i].Inst;
|
||||
inst = inst->Next) {
|
||||
rc_opcode op = rc_get_flow_control_inst(inst);
|
||||
if (op == RC_OPCODE_ENDLOOP) {
|
||||
struct rc_instruction * bgnloop =
|
||||
rc_match_endloop(inst);
|
||||
if (bgnloop->IP < chan_start) {
|
||||
chan_start = bgnloop->IP;
|
||||
}
|
||||
} else if (op == RC_OPCODE_BGNLOOP) {
|
||||
struct rc_instruction * endloop =
|
||||
rc_match_bgnloop(inst);
|
||||
if (endloop->IP > chan_end) {
|
||||
chan_end = endloop->IP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (chan = 0; chan < 4; chan++) {
|
||||
if ((mask >> chan) & 0x1) {
|
||||
var->Live[chan].Start = start;
|
||||
var->Live[chan].End =
|
||||
var->Readers[i].Inst->IP;
|
||||
if (!var->Live[chan].Used
|
||||
|| chan_start < var->Live[chan].Start) {
|
||||
var->Live[chan].Start =
|
||||
chan_start;
|
||||
}
|
||||
if (!var->Live[chan].Used
|
||||
|| chan_end > var->Live[chan].End) {
|
||||
var->Live[chan].End = chan_end;
|
||||
}
|
||||
var->Live[chan].Used = 1;
|
||||
}
|
||||
}
|
||||
@@ -197,10 +260,9 @@ static unsigned int readers_intersect(
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (reader_a.Inst->Type == RC_INSTRUCTION_PAIR
|
||||
&& reader_b.Inst->Type == RC_INSTRUCTION_PAIR
|
||||
&& reader_a.U.P.Arg == reader_b.U.P.Arg) {
|
||||
&& reader_a.U.P.Src == reader_b.U.P.Src) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -213,6 +275,7 @@ void rc_variable_add_friend(
|
||||
struct rc_variable * var,
|
||||
struct rc_variable * friend)
|
||||
{
|
||||
assert(var->Dst.Index == friend->Dst.Index);
|
||||
while(var->Friend) {
|
||||
var = var->Friend;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user