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.


_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to