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

Kenneth Graunke kenneth at whitecape.org
Mon Jun 27 17:15:04 PDT 2011


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


More information about the mesa-dev mailing list