diff options
author | Eric Anholt <[email protected]> | 2011-03-28 16:54:39 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2011-04-26 12:20:22 -0700 |
commit | 37642518b8864ce751754957b08cdb437998f4e7 (patch) | |
tree | 015040a68177e2533b0b1c26575e368a1eb66020 /src/mesa/drivers | |
parent | 445289b5093acb9abaf7e0a89bfa319fcb4a1c31 (diff) |
i965/fs: Add support for compute-to-mrf in 16-wide mode.
This is more painful than instruction scheduling, as we have to
compare two MRF writes to see if they coincide, and have to handle
partial GRF writes before that (for example, the result of a math
instruction written to color).
Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.cpp | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index ba5bf9e4405..21eb9e4e5e1 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -3370,10 +3370,6 @@ fs_visitor::compute_to_mrf() bool progress = false; int next_ip = 0; - /* Need to update the MRF tracking for compressed instructions. */ - if (c->dispatch_width == 16) - return false; - calculate_live_intervals(); foreach_iter(exec_list_iterator, iter, this->instructions) { @@ -3389,6 +3385,20 @@ fs_visitor::compute_to_mrf() inst->src[0].abs || inst->src[0].negate || inst->src[0].smear != -1) continue; + /* Work out which hardware MRF registers are written by this + * instruction. + */ + int mrf_low = inst->dst.hw_reg & ~BRW_MRF_COMPR4; + int mrf_high; + if (inst->dst.hw_reg & BRW_MRF_COMPR4) { + mrf_high = mrf_low + 4; + } else if (c->dispatch_width == 16 && + (!inst->force_uncompressed && !inst->force_sechalf)) { + mrf_high = mrf_low + 1; + } else { + mrf_high = mrf_low; + } + /* Can't compute-to-MRF this GRF if someone else was going to * read it later. */ @@ -3416,11 +3426,21 @@ fs_visitor::compute_to_mrf() } /* If it's predicated, it (probably) didn't populate all - * the channels. + * the channels. We might be able to rewrite everything + * that writes that reg, but it would require smarter + * tracking to delay the rewriting until complete success. */ if (scan_inst->predicated) break; + /* If it's half of register setup and not the same half as + * our MOV we're trying to remove, bail for now. + */ + if (scan_inst->force_uncompressed != inst->force_uncompressed || + scan_inst->force_sechalf != inst->force_sechalf) { + break; + } + /* SEND instructions can't have MRF as a destination. */ if (scan_inst->mlen) break; @@ -3470,12 +3490,29 @@ fs_visitor::compute_to_mrf() if (interfered) break; - if (scan_inst->dst.file == MRF && - scan_inst->dst.hw_reg == inst->dst.hw_reg) { - /* Somebody else wrote our MRF here, so we can't + if (scan_inst->dst.file == MRF) { + /* If somebody else writes our MRF here, we can't * compute-to-MRF before that. */ - break; + int scan_mrf_low = scan_inst->dst.hw_reg & ~BRW_MRF_COMPR4; + int scan_mrf_high; + + if (scan_inst->dst.hw_reg & BRW_MRF_COMPR4) { + scan_mrf_high = scan_mrf_low + 4; + } else if (c->dispatch_width == 16 && + (!scan_inst->force_uncompressed && + !scan_inst->force_sechalf)) { + scan_mrf_high = scan_mrf_low + 1; + } else { + scan_mrf_high = scan_mrf_low; + } + + if (mrf_low == scan_mrf_low || + mrf_low == scan_mrf_high || + mrf_high == scan_mrf_low || + mrf_high == scan_mrf_high) { + break; + } } if (scan_inst->mlen > 0) { @@ -3484,8 +3521,12 @@ fs_visitor::compute_to_mrf() * scan_inst->mlen - 1. Don't go pushing our MRF write up * above it. */ - if (inst->dst.hw_reg >= scan_inst->base_mrf && - inst->dst.hw_reg < scan_inst->base_mrf + scan_inst->mlen) { + if (mrf_low >= scan_inst->base_mrf && + mrf_low < scan_inst->base_mrf + scan_inst->mlen) { + break; + } + if (mrf_high >= scan_inst->base_mrf && + mrf_high < scan_inst->base_mrf + scan_inst->mlen) { break; } } |