diff options
author | Tom Stellard <tstellar@gmail.com> | 2011-01-28 22:10:57 -0800 |
---|---|---|
committer | Tom Stellard <tstellar@gmail.com> | 2011-01-29 21:38:24 -0800 |
commit | 908f61447f9ba593805b2b608f178e8b69e995d3 (patch) | |
tree | a3632bc9ba514e9b518de7b9c69a3b76faed18cc | |
parent | 158b9aeb384e2151b10a2b0ee0d779f4b4c8c5d0 (diff) |
Temp
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c | 103 |
1 files changed, 99 insertions, 4 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c index 5756055f9d5..c1cd2af094c 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_regalloc.c @@ -144,6 +144,8 @@ static void add_live_intervals_array(struct regalloc_state * s, static int overlap_live_intervals(struct live_intervals * dst, struct live_intervals * src) { + unsigned int space_before; + unsigned int space_after; if (VERBOSE) { DBG("overlap_live_intervals: "); print_live_intervals(dst); @@ -154,21 +156,26 @@ static int overlap_live_intervals(struct live_intervals * dst, struct live_inter while(src && dst) { if (dst->End <= src->Start) { + space_before = src->Start - dst->End - 1; dst = dst->Next; } else if (dst->End <= src->End) { DBG(" overlap\n"); - return 1; + return -1; } else if (dst->Start < src->End) { DBG(" overlap\n"); - return 1; + return -1; } else { + /* This value is only valid if the original src passed to + * the function had src->Next == NULL. */ + space_after = dst->Begin - src->End - 1; src = src->Next; } } DBG(" no overlap\n"); - return 0; + /* XXX: We could possibly use a better heuristic here. */ + return space_before + space_after; } static void scan_read_callback(void * data, struct rc_instruction * inst, @@ -332,7 +339,7 @@ static void do_regalloc(struct regalloc_state * s) for (chan = 0; chan < 4; chan++) { if (overlap_live_intervals( s->HwTemporary[hwreg].UsedChan[chan], - reg->LiveChan[chan])) { + reg->LiveChan[chan]) < 0) { break; } @@ -413,6 +420,93 @@ static void do_regalloc_inputs_only(struct regalloc_state * s) } } +static struct live_interval * remove_live_interval( + struct regalloc_state * s, + unsigned int ip, + unsigned int index, + unsigned int chan) +{ + struct live_interval * li = s->Temporary[index]->LiveChan[chan]; + while (li->Start < ip) { + li = li->Next; + } + return li; +} + +static void pack_registers_callback( + void * userdata, + struct rc_instruction * inst, + rc_register_file file, + unsigned int index, + unsigned int chan) + +{ + struct regalloc_state * s = userdata; + struct live_interval * live_interval; + unsigned int i, chan_index; + unsigned int best_index = index; + unsigned int best_chan = chan; + unsigned int best_score = -1; + struct rc_reader_data reader_data; + /* We only want to rewrite instructions that write to a single channel. + * We can't rewrite instructions that write to the alpha channel, + * then we would have to convert them to vector instructions. */ + if ((chan != RC_SWIZZLE_X && chan != RC_SWIZZLE_Y && chan != RC_SWIZZLE_Z) + || file != RC_FILE_TEMPORARY) { + return; + } + + live_interval = remove_live_interval(s, inst->IP, index, chan); + for (i = 0; i < s->NumTemporaries; i++) { + for (chan_index = 0; chan_index < 4; chan++) { + int score; + if (chan_index == chan) { + continue; + } + score = overlap_live_intervals( + s->Temporary[i]->LiveChan[chan_index], + live_interval); + + if(score != -1 && + (best_score == -1 || score < best_score)) { + + best_score = score; + best_index = i; + best_chan = chan_index; + } + } + } + + rc_get_readers(s->C, inst, &reader_data, NULL, NULL, NULL); + /* Don't rewrite in this scenario. */ + if (reader_data->Abort || (best_index == index && best_chan == chan)){ + best_index = index; + best_chan = chan; + } else { + unsigned int rindex; + for (rindex = 0; rindex < reader_data; rindex++) { + struct rc_reader reader = reader_data.Readers[rindex]; + if (reader.Inst->Type == RC_INSTRUCTION_NORMAL) { + reader.U.Src->Index = best_index; + reader.U.Src->Swizzle = chan; + } else { + + } + } + } +} + +static void pack_registers(struct regalloc_state * s) +{ + struct rc_instruction * inst; + for (inst = s->C->Program.Instructions.Next; + inst != c->C->Program.Instructions; + inst = inst->Next) { + + rc_for_all_writes_mask(inst, pack_registers_callback, s); + } +} + /** * @param user This parameter should be a pointer to an integer value. If this * integer value is zero, then a simple register allocator will be used that @@ -432,6 +526,7 @@ void rc_pair_regalloc(struct radeon_compiler *cc, void *user) c->AllocateHwInputs(c, &alloc_input_simple, &s); do_regalloc_inputs_only(&s); } else { + pack_registers(&s); c->AllocateHwInputs(c, &alloc_input, &s); do_regalloc(&s); } |