diff options
author | Tom Stellard <[email protected]> | 2011-10-01 15:22:24 -0700 |
---|---|---|
committer | Tom Stellard <[email protected]> | 2011-10-02 15:21:15 -0700 |
commit | d64c6d2ffc086bde7a025269b80c0980f7d908f1 (patch) | |
tree | 1217548ef93e5e16d0562d6097ed8a331d0c0093 | |
parent | 13814b0103812adbb5aba0dba4664249e8566290 (diff) |
r300/compiler: Fix error in OMOD optimization
Classic compiler mistake. In the example below, the OMOD optimization
was combining instructions 4 and 10, but since there was an instruction
(#8) in between them that wrote to the same registers as instruction 10,
instruction 11 was reading the wrong value.
Example of the mistake:
Before OMOD:
4: MAD temp[0].y, temp[3]._y__, const[0]._x__, const[0]._y__;
...
8: ADD temp[2].x, temp[1].x___, -temp[4].x___;
...
10: MUL temp[2].x, const[1].y___, temp[0].y___;
11: FRC temp[5].x, temp[2].x___;
After OMOD:
4: MAD temp[2].x / 8, temp[3]._y__, const[0]._x__, const[0]._y__;
...
8: ADD temp[2].x, temp[1].x___, -temp[4].x___;
...
11: FRC temp[5].x, temp[2].x___;
https://bugs.freedesktop.org/show_bug.cgi?id=41367
-rw-r--r-- | src/gallium/drivers/r300/compiler/radeon_optimize.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/src/gallium/drivers/r300/compiler/radeon_optimize.c b/src/gallium/drivers/r300/compiler/radeon_optimize.c index b7a0e20797c..2d799a6547a 100644 --- a/src/gallium/drivers/r300/compiler/radeon_optimize.c +++ b/src/gallium/drivers/r300/compiler/radeon_optimize.c @@ -681,6 +681,20 @@ static void omod_filter_reader_cb( } } +static void omod_filter_writer_cb( + void * userdata, + struct rc_instruction * inst, + rc_register_file file, + unsigned int index, + unsigned int mask) +{ + struct peephole_mul_cb_data * d = userdata; + if (file == d->Writer->File && index == d->Writer->Index && + (mask & d->Writer->WriteMask)) { + d->Clobbered = 1; + } +} + static int peephole_mul_omod( struct radeon_compiler * c, struct rc_instruction * inst_mul, @@ -788,6 +802,8 @@ static int peephole_mul_omod( inst = inst->Prev) { rc_for_all_reads_mask(inst, omod_filter_reader_cb, &cb_data); + rc_for_all_writes_mask(inst, omod_filter_writer_cb, + &cb_data); if (cb_data.Clobbered) { break; } |