freedreno/ir3: eliminate unnecessary absneg's
authorRob Clark <robclark@freedesktop.org>
Tue, 5 Apr 2016 16:39:47 +0000 (12:39 -0400)
committerRob Clark <robclark@freedesktop.org>
Tue, 5 Apr 2016 19:04:25 +0000 (15:04 -0400)
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 <robclark@freedesktop.org>
src/gallium/drivers/freedreno/ir3/ir3.h
src/gallium/drivers/freedreno/ir3/ir3_cp.c

index 23e43b1e13dc5b98074817e0d33c8ad3c90be09b..3859f6a39f319ad834a82276742f1441b3978141 100644 (file)
@@ -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
index f032f0bd53f8f7b3af6da95fbd348dc1b4103d6b..6037becf22f9a6ea302a9b91c14ffc49c3f57e21 100644 (file)
@@ -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