diff options
author | Rob Clark <[email protected]> | 2016-04-05 12:39:47 -0400 |
---|---|---|
committer | Rob Clark <[email protected]> | 2016-04-05 15:04:25 -0400 |
commit | f9cdbf44054009122fcc16c887fb90ccc33b52c9 (patch) | |
tree | 592fcae6b07a4a68f22ef6ddee239f0d9c2aceec | |
parent | 0daab9878d2b96356cf667591a2c877d912be52d (diff) |
freedreno/ir3: eliminate unnecessary absneg's
The frontend inserts (abs) and (neg)'s to convert between NIR boolean
(~0/0) and native boolean (1/0). So we'd end up with things like:
cmps.s.ge r1.x, ...
absneg.s r1.x, (neg)r1.x
absneg.s r1.x, (abs)r1.x
sel.b32 r2.x, r0.x, r1.x, r0.y
The (neg) already gets collapsed due to the following (abs). Now by
realizing that r1.x comes from a cmps.s instruction, we can drop the
(abs) as well.
Signed-off-by: Rob Clark <[email protected]>
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3.h | 12 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_cp.c | 17 |
2 files changed, 26 insertions, 3 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h index 23e43b1e13d..3859f6a39f3 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.h +++ b/src/gallium/drivers/freedreno/ir3/ir3.h @@ -628,6 +628,18 @@ static inline bool is_input(struct ir3_instruction *instr) } } +static inline bool is_bool(struct ir3_instruction *instr) +{ + switch (instr->opc) { + case OPC_CMPS_F: + case OPC_CMPS_S: + case OPC_CMPS_U: + return true; + default: + return false; + } +} + static inline bool is_meta(struct ir3_instruction *instr) { /* TODO how should we count PHI (and maybe fan-in/out) which diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cp.c b/src/gallium/drivers/freedreno/ir3/ir3_cp.c index f032f0bd53f..6037becf22f 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_cp.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_cp.c @@ -189,8 +189,10 @@ static bool valid_flags(struct ir3_instruction *instr, unsigned n, /* propagate register flags from src to dst.. negates need special * handling to cancel each other out. */ -static void combine_flags(unsigned *dstflags, unsigned srcflags) +static void combine_flags(unsigned *dstflags, struct ir3_instruction *src) { + unsigned srcflags = src->regs[1]->flags; + /* if what we are combining into already has (abs) flags, * we can drop (neg) from src: */ @@ -216,6 +218,15 @@ static void combine_flags(unsigned *dstflags, unsigned srcflags) *dstflags |= srcflags & IR3_REG_IMMED; *dstflags |= srcflags & IR3_REG_RELATIV; *dstflags |= srcflags & IR3_REG_ARRAY; + + /* if src of the src is boolean we can drop the (abs) since we know + * the source value is already a postitive integer. This cleans + * up the absnegs that get inserted when converting between nir and + * native boolean (see ir3_b2n/n2b) + */ + struct ir3_instruction *srcsrc = ssa(src->regs[1]); + if (srcsrc && is_bool(srcsrc)) + *dstflags &= ~IR3_REG_SABS; } /** @@ -241,7 +252,7 @@ reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n) struct ir3_register *src_reg = src->regs[1]; unsigned new_flags = reg->flags; - combine_flags(&new_flags, src_reg->flags); + combine_flags(&new_flags, src); if (valid_flags(instr, n, new_flags)) { if (new_flags & IR3_REG_ARRAY) { @@ -262,7 +273,7 @@ reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n) struct ir3_register *src_reg = src->regs[1]; unsigned new_flags = reg->flags; - combine_flags(&new_flags, src_reg->flags); + combine_flags(&new_flags, src); if (!valid_flags(instr, n, new_flags)) { /* special case for "normal" mad instructions, we can |