pan/bi: Pack BI_BITWISE
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tue, 28 Apr 2020 18:19:34 +0000 (14:19 -0400)
committerMarge Bot <eric+marge@anholt.net>
Wed, 29 Apr 2020 00:30:05 +0000 (00:30 +0000)
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4790>

src/panfrost/bifrost/bi_pack.c
src/panfrost/bifrost/bifrost.h

index aa8d590c733f070c39f071f6915ad88a64cea936..e884417476f555bdc0b974a075237da029961b08 100644 (file)
@@ -1063,8 +1063,71 @@ bi_pack_fma_cmp(bi_instruction *ins, struct bi_registers *regs)
                 unreachable("Unknown cmp type");
         }
 }
+
+static unsigned
+bi_fma_bitwise_op(enum bi_bitwise_op op, bool rshift)
+{
+        switch (op) {
+        case BI_BITWISE_OR:
+                /* Via De Morgan's */
+                return rshift ?
+                        BIFROST_FMA_OP_RSHIFT_NAND :
+                        BIFROST_FMA_OP_LSHIFT_NAND;
+        case BI_BITWISE_AND:
+                return rshift ?
+                        BIFROST_FMA_OP_RSHIFT_AND :
+                        BIFROST_FMA_OP_LSHIFT_AND;
+        case BI_BITWISE_XOR:
+                /* Shift direction handled out of band */
+                return BIFROST_FMA_OP_RSHIFT_XOR;
+        default:
+                unreachable("Unknown op");
+        }
+}
  
+static unsigned
+bi_pack_fma_bitwise(bi_instruction *ins, struct bi_registers *regs)
+{
+        unsigned size = nir_alu_type_get_type_size(ins->dest_type);
+        assert(size <= 32);
+
+        bool invert_0 = ins->bitwise.src_invert[0];
+        bool invert_1 = ins->bitwise.src_invert[1];
 
+        if (ins->op.bitwise == BI_BITWISE_OR) {
+                /* Becomes NAND, so via De Morgan's:
+                 *      f(A) | f(B) = ~(~f(A) & ~f(B))
+                 *                  = NAND(~f(A), ~f(B))
+                 */
+
+                invert_0 = !invert_0;
+                invert_1 = !invert_1;
+        } else if (ins->op.bitwise == BI_BITWISE_XOR) {
+                /* ~A ^ ~B = ~(A ^ ~B) = ~(~(A ^ B)) = A ^ B
+                 * ~A ^  B = ~(A ^ B) = A ^ ~B
+                 */
+
+                invert_0 ^= invert_1;
+                invert_1 = false;
+
+                /* invert_1 ends up specifying shift direction */
+                invert_1 = !ins->bitwise.rshift;
+        }
+
+        struct bifrost_shift_fma pack = {
+                .src0 = bi_get_src(ins, regs, 0, true),
+                .src1 = bi_get_src(ins, regs, 1, true),
+                .src2 = bi_get_src(ins, regs, 2, true),
+                .half = (size == 32) ? 0 : (size == 16) ? 0x7 : (size == 8) ? 0x4 : 0,
+                .unk = 1, /* XXX */
+                .invert_1 = invert_0,
+                .invert_2 = invert_1,
+                .op = bi_fma_bitwise_op(ins->op.bitwise, ins->bitwise.rshift)
+        };
+
+        RETURN_PACKED(pack);
+}
 static unsigned
 bi_pack_fma(bi_clause *clause, bi_bundle bundle, struct bi_registers *regs)
 {
@@ -1077,7 +1140,7 @@ bi_pack_fma(bi_clause *clause, bi_bundle bundle, struct bi_registers *regs)
         case BI_CMP:
                 return bi_pack_fma_cmp(bundle.fma, regs);
         case BI_BITWISE:
-               return BIFROST_FMA_NOP;
+                return bi_pack_fma_bitwise(bundle.fma, regs);
         case BI_CONVERT:
                return bi_pack_convert(bundle.fma, regs, true);
         case BI_CSEL:
index bef8cd84f0023c44f7c560067efba289a46b335a..bfbaa2c2e564e3fd8345cf638b8d22c2fad55ad0 100644 (file)
@@ -363,11 +363,23 @@ struct bifrost_csel4 {
         unsigned op   : 8;
 } __attribute__((packed));
 
+#define BIFROST_FMA_OP_RSHIFT_NAND     (0x60000 >> 12)
+#define BIFROST_FMA_OP_RSHIFT_AND      (0x61000 >> 12)
+#define BIFROST_FMA_OP_LSHIFT_NAND     (0x62000 >> 12)
+#define BIFROST_FMA_OP_LSHIFT_AND      (0x63000 >> 12)
+#define BIFROST_FMA_OP_RSHIFT_XOR      (0x64000 >> 12)
+#define BIFROST_FMA_OP_LSHIFT_ADD_32   (0x65200 >> 6)
+#define BIFROST_FMA_OP_LSHIFT_SUB_32   (0x65600 >> 6)
+#define BIFROST_FMA_OP_LSHIFT_RSUB_32  (0x65a00 >> 6)
+#define BIFROST_FMA_OP_RSHIFT_ADD_32   (0x65e00 >> 6)
+#define BIFROST_FMA_OP_RSHIFT_SUB_32   (0x66200 >> 6)
+#define BIFROST_FMA_OP_RSHIFT_RSUB_32  (0x66600 >> 6)
+
 struct bifrost_shift_fma {
         unsigned src0 : 3;
         unsigned src1 : 3;
         unsigned src2 : 3;
-        unsigned half : 3; /* 000 for i32, 100 for i8, 111 for v2i16 */
+        unsigned half : 3;
         unsigned unk  : 1; /* always set? */
         unsigned invert_1 : 1; /* Inverts sources to combining op */
         /* For XOR, switches RSHIFT to LSHIFT since only one invert needed */