r300/compiler: Fix error in OMOD optimization
authorTom Stellard <tstellar@gmail.com>
Sat, 1 Oct 2011 22:22:24 +0000 (15:22 -0700)
committerTom Stellard <tstellar@gmail.com>
Sun, 2 Oct 2011 22:21:15 +0000 (15:21 -0700)
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

src/gallium/drivers/r300/compiler/radeon_optimize.c

index b7a0e20797c03ddb63fe98ac6282ca9690c2609e..2d799a6547a564be2125d24655417d9339842cd8 100644 (file)
@@ -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;
                        }