[Mesa-dev] [PATCH 2/2] prog_optimize: Add reads without writes optimization pass

Ian Romanick idr at freedesktop.org
Wed Mar 30 10:09:58 PDT 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/29/2011 08:27 PM, Tom Stellard wrote:
> On Tue, Mar 29, 2011 at 02:16:39PM -0700, Eric Anholt wrote:
> 
>> On Tue, 29 Mar 2011 11:35:33 -0700, Tom Stellard <tstellar at gmail.com> wrote:
>>> On Tue, Mar 29, 2011 at 10:19:13AM -0700, Eric Anholt wrote:
>>>> On Mon, 28 Mar 2011 22:59:31 -0700, Tom Stellard <tstellar at gmail.com> wrote:
>>>>> This pass scans programs for instructions that read registers that have
>>>>> not been written and replaces these reads with a read from a constant
>>>>> register with the value of zero.  This pass prevents phantom
>>>>> dependencies from being introduced by the register allocator and
>>>>> improves the efficiency of subsequent optimization passes.
>>>>
>>>> I'm not sure why optimizing a program with undefined behavior (using
>>>> undefined register values) is interesting.  It just seems like an
>>>> opportunity to make a mistake and break programs that should have
>>>> defined behavior.
>>>
>>> The main problem I am trying to fix with this is that these reads
>>> from undefined register values are causing the Mesa IR register allocator
>>> to alter the structure of the program by adding dependencies between
>>> instructions that should not be there.  This is limiting the number of
>>> optimization opportunities that are available to drivers, especially
>>> on architectures like r300 that need IFs lowered and thus use a lot of
>>> CMP instructions.
>>
>> Why do you have programs reading undefined values?  Why are these
>> programs interesting?
> 
> The reason there are reads of undefined values is because of all the
> conditional assignments generated by the IF to conditional assignment
> lowering pass.  ir_to_mesa transforms conditional assignments to
> CMP DST, COND SRC0 DST, with the assumption that if the condition fails
> assigning DST to itself will be a noop.  This is normally a safe assumption
> to make since all bug-free programs should initialize a value before using
> it in a conditional assignment, if the value is going to be used later
> in the program.
> 
> However, the conditional assignments that are generated by the IF
> lowering pass don't follow this pattern and the DST register is usually
> uninitialized when the instruction is executed, leading to a read from
> an undefined value.

Ah, that makes sense.  It would probably be good to replace the examples
in the current header comment with one of these cases.

> It seems like the real problem is that there is no good way to translate
> a GLSL IR conditional assignment to a MESA IR instruction.  From what
> I can tell, the semantics of conditional assignment are:
> if (cond)
> 	assign value
> else
> 	do nothing;

Correct.

> and the closest equivalent Mesa IR instruction (CMP) is:
> if (cond)
> 	assign value0
> else
> 	assign value1
> 
> Since this is only an issue on architectures that don't support flow
> control, I should modify my patch so the 'reads without writes' pass
> only runs on architectures that don't support flow control.  I'm also
> interested in hearing alternate solutions if anyone has other ideas,
> because I would really like to get this fixed.

It seems like there are two possible cases, and this doesn't really fix
either of them.

Case 1:

    if (cond)
        x = y;

This gets lowered to a conditional move to x.  If there is no 'else',
why do a conditional move at all?  In this case, replace the CMP (which
may be lowered to as many as 3 instructions in some vertex shaders) with
a MOV.

If x is used when cond is false before another assignment to x, the
result is undefined.  Reading y qualifies as much as reading 0s.  Right? :)

Case 2:

    if (cond)
        x = y;
    else
        x = z;

In this case we end up with two CMP instructions.  The first of the CMP
instructions will be potentially read from an uninitialized source.

    CMP x, cond, y, x;
    CMP x, cond, x, z;

In this case, the two CMP instructions should be fused into a single CMP.

    CMP x, cond, y, z;

Now that I think about it, the way the copy propagation works,
converting the first CMP to a MOV will make this happen automatically.

    CMP x, cond, y, x;
    CMP x, cond, x, z;

becomes

    MOV x, y;
    CMP x, cond, x, z;

becomes

    MOV x, y;
    CMP x, cond, y, z;

becomes

    CMP x, cond, y, z;
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk2TY+YACgkQX1gOwKyEAw8wAgCeM+GU/Ums9WeTTzvaGpimGasK
WKEAnjhmoWClU4Gg6rzopczOf1v82gAS
=yBOF
-----END PGP SIGNATURE-----


More information about the mesa-dev mailing list