[Mesa-dev] [PATCH 6/6] glsl: Generate IR for switch statements

Dan McCabe zen3d.linux at gmail.com
Mon Jun 27 17:23:30 PDT 2011


On 06/27/2011 05:15 PM, Kenneth Graunke wrote:
> On 06/24/2011 05:11 PM, Dan McCabe wrote:
>> 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;
>>     }
>
> I must admit, I'm not particularly crazy about the amount of 
> if-statements being generated here.  A couple of ideas...
>
> 1. Use conditional moves:
>
> (assign (ir_expression all_equal (var_ref test_val_tmp) c0) ; condition
>         (var_ref is_fallthru_tmp) ; assignee
>         (constant bool (1))) ; true
>
> Then again Ian's new optimization pass should do this for us, so maybe 
> leaving it as if-statements is fine.
>
> Since we'd have two conditional moves (for c0 and c1) with the same 
> target and value, it'd be nice to combine them...but that sounds like 
> a pretty obscure optimization pass.
>
> 2. Use ORs:
>
> is_fallthru_tmp = false;
> is_fallthru_tmp = is_fallthru_tmp || test_val_tmp == c0;
> is_fallthru_tmp = is_fallthru_tmp || test_val_tmp == c1;
>
> This seems somewhat easier to optimize...I imagine tree-grafting, 
> constant/copy propagation, etc. might be able to reduce this to:
>
> is_fallthru_tmp = test_val_tmp == c0 || test_val_tmp == c1;
>
> Again, I'm not sure.  Ian, do you have an opinion?
>
> In the end, this may be a moot point---we eventually want to take 
> advantage of hardware jump instructions.  When switching on a uniform 
> (I'm guessing this is common), all the channels would take the same 
> path, so a simple ADD to the IP would work.  Even for non-uniform 
> control flow, I suspect we could use the Gen "break" instruction, 
> which will jump if all channels take the path.  But that's for later.
>
> --Kenneth
Since I am just about to start modifying the IR generation, I'm open to 
suggestion.

#1 looks like a better choice. But I might change my mind when I 
actually get to modifying the code.

I originally considered #2, but the IR that was generated by such code 
didn't look any better (i.e., you would up with a bunch of IF code 
anyway). That is why I went the route I did.




More information about the mesa-dev mailing list