diff options
author | Rob Clark <[email protected]> | 2014-03-01 12:06:44 -0500 |
---|---|---|
committer | Rob Clark <[email protected]> | 2014-03-02 11:26:35 -0500 |
commit | e0007f733dfffff2b5c3729546d6c16ecba6faa9 (patch) | |
tree | 497b719fe899ba80c0a05b144b7284a424965c54 /src/gallium/drivers/freedreno | |
parent | 26530716ab9398703f91285381033073f47e8bd4 (diff) |
freedreno/a3xx/compiler: fix for resolving PHI's
A value may be assigned on only one side of an if/else. In this case we
can simply substitute a mov.f32f32.
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno')
-rw-r--r-- | src/gallium/drivers/freedreno/a3xx/ir3_flatten.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/src/gallium/drivers/freedreno/a3xx/ir3_flatten.c b/src/gallium/drivers/freedreno/a3xx/ir3_flatten.c index 3cf76db5005..00a2bf1dc47 100644 --- a/src/gallium/drivers/freedreno/a3xx/ir3_flatten.c +++ b/src/gallium/drivers/freedreno/a3xx/ir3_flatten.c @@ -51,7 +51,9 @@ static struct ir3_register *unwrap(struct ir3_register *reg) switch (instr->opc) { case OPC_META_OUTPUT: case OPC_META_FLOW: - return instr->regs[1]; + if (instr->regs_count > 1) + return instr->regs[1]; + return NULL; default: break; } @@ -78,25 +80,38 @@ static void ir3_instr_flatten(struct ir3_flatten_ctx *ctx, if (instr->opc == OPC_META_PHI) { struct ir3_register *cond, *t, *f; - /* convert the PHI instruction to sel.{f16,f32} */ - instr->category = 3; + cond = unwrap(instr->regs[1]); + t = unwrap(instr->regs[2]); /* true val */ + f = unwrap(instr->regs[3]); /* false val */ - /* instruction type based on dst size: */ - if (instr->regs[0]->flags & IR3_REG_HALF) - instr->opc = OPC_SEL_F16; - else - instr->opc = OPC_SEL_F32; - - /* swap around src register order, to match what - * hw expects: + /* must have cond, but t or f may be null if only written + * one one side of the if/else (in which case we can just + * convert the PHI to a simple move). */ - cond = instr->regs[1]; - t = instr->regs[2]; /* true val */ - f = instr->regs[3]; /* false val */ - - instr->regs[1] = unwrap(f); - instr->regs[2] = unwrap(cond); - instr->regs[3] = unwrap(t); + assert(cond); + assert(t || f); + + if (t && f) { + /* convert the PHI instruction to sel.{b16,b32} */ + instr->category = 3; + + /* instruction type based on dst size: */ + if (instr->regs[0]->flags & IR3_REG_HALF) + instr->opc = OPC_SEL_B16; + else + instr->opc = OPC_SEL_B32; + + instr->regs[1] = t; + instr->regs[2] = cond; + instr->regs[3] = f; + } else { + /* convert to simple mov: */ + instr->category = 1; + instr->cat1.dst_type = TYPE_F32; + instr->cat1.src_type = TYPE_F32; + instr->regs_count = 2; + instr->regs[1] = t ? t : f; + } ctx->cnt++; } else if ((instr->opc == OPC_META_INPUT) && |