[Mesa-dev] [PATCH 6/6] glsl: Generate IR for switch statements
Ian Romanick
idr at freedesktop.org
Mon Jun 27 14:37:53 PDT 2011
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 06/24/2011 05:11 PM, Dan McCabe wrote:
> On 06/24/2011 01:17 PM, Dan McCabe wrote:
>> On 06/20/2011 03:50 PM, Ian Romanick wrote:
>>> -----BEGIN PGP SIGNED MESSAGE-----
>>> Hash: SHA1
>>>
>>> On 06/17/2011 05:43 PM, Dan McCabe wrote:
>>>> Beware! Here be dragons!
>>>>
>>>>
>>> I think this will generate the wrong code for:
>>>
>>> for (i = 0; i< 10; i++) {
>>> switch (i) {
>>> default: continue;
>>> }
>>> }
>>>
>>> It seems like that will generate some approximation of:
>>>
>>> for (i = 0; i< 10; i++) {
>>> do {
>>> continue;
>>> break;
>>> } while (true);
>>> }
>>>
>>> Right? This is why I had originally tracked loops and switch-statements
>>> in a single stack. In this situation, you'd want to set a "do a
>>> continue" flag in the switch-statement and emit a break (from the
>>> switch). Something like:
>>>
>>>
>>> for (i = 0; i< 10; i++) {
>>> bool do_cont = false;
>>>
>>> do {
>>> do_cont = true;
>>> break;
>>> break;
>>> } while (true);
>>>
>>> if (do_cont)
>>> continue;
>>> }
>>>
>>>
>> Yikes! Looks like you tripped over one of those dragons :(.
>>
>> Using a do_cont variable (or similar device) feels kludgey to me. I've
>> been mulling this over for the last couple of days while I did other
>> things and I think the right way to do this might be to get rid of the
>> use of "loop" altogether.
>>
>> But the devil is in the details, which I haven't worked out yet. Going
>> back to the unified loop/switch stack might be needed, though.
>>
>> cheers, danm
>>
>
> All is not lost! (But you already knew that :)
>
> One of the motivations of using the loop device is that it enabled the
> relatively unmodified infrastructure for break statements. But let's get
> rid of the break device and see where we go.
>
> Without xlating switch stmts into loops, we can still retain the
> test_val_tmp and is_fallthru_tmp temporaries (in fact, we need to;
> nothing changes there since that is how case labels are managed).
>
> However, the standard break processing no longer applies, since we are
> not in a loop (for the switch stmt in any event). If we introduce a bool
> temporary called is_break_tmp and initialize it to false, then when we
> encounter a break stmt, we set is_break_tmp to true. Now we must guard
> the case statement with both fallthru_var and is_break_var. If
> is_break_tmp was set, we simply clear is_fallthru_tmp right after all
> case tests to false.
>
> Note that this approach does require maintaining a loop/switch stack as
> the code originally did so that we can tell if a break statement is
> associate with a loop or with a switch stmt. Only if the top of the
> stack indicates that switch is being processed will the above break
> processing be invoked.
>
> Looking at a translation of my canonical example:
>
> switch (expr) {
> case c0:
> case c1:
> stmt0;
> case c2:
> case c3:
> stmt1;
> break;
> case c4:
> default:
> stmt2;
> }
>
> We can translated this into:
>
> int test_val_tmp = expr;
> bool is_fallthru_tmp = false;
> bool is_break_tmp = false;
>
> if (test_val_tmp == c0) {
> is_fallthru_tmp = true;
> }
> if (test_val_tmp == c1) {
> is_fallthru_tmp = true;
> }
> if (is_break_tmp) {
> is_fallthru_tmp = false;
> }
> if (is_fallthru_tmp) {
> stmt0;
> }
>
> if (test_val_tmp == c2) {
> is_fallthru_tmp = true;
> }
> if (test_val_tmp == c3) {
> is_fallthru_tmp = true;
> }
> if (is_break_tmp) {
> is_fallthru_tmp = false;
> }
> if (is_fallthru_tmp) {
> stmt1;
> is_break_tmp = true; // break stmt
> }
>
> if (test_val_tmp == c4) {
> is_fallthru_tmp = true;
> }
> is_fallthru_tmp = true; // default
> if (is_break_tmp) {
> is_fallthru_tmp = false;
> }
> if (is_fallthru_tmp) {
> stmt2;
> }
>
> Comparing this to what we did previously, the things that change in this
> code are:
> 1) no enclosing loop
> 2) create a bool is_break_tmp initialized to false
> 3) after all case labels and before each case statement list, clear
> is_fallthru_tmp when is_break_tmp
> 4) set is_break_tmp for each break statement
That sounds very reasonable.
> And maintain the loop/switch stack again as in the original code.
>
> I'll get this cranked out on Monday and resubmit for review. If anyone
> has concerns or questions about what I'm doing here, please let me know.
>
> cheers, danm
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAk4I+DEACgkQX1gOwKyEAw9bugCgiAH72AG2WnDQ0pvQAxMHTShd
NSgAn13bahn00ZW5vTxmnic2tWWG2+DS
=93jZ
-----END PGP SIGNATURE-----
More information about the mesa-dev
mailing list