nvir: introduce OP_BREV with lowering to EXTBF_REV for current GPUs
authorBen Skeggs <bskeggs@redhat.com>
Sat, 6 Jun 2020 23:51:51 +0000 (09:51 +1000)
committerMarge Bot <eric+marge@anholt.net>
Wed, 10 Jun 2020 22:52:41 +0000 (22:52 +0000)
SM70 has this instruction, but no BFE.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5377>

src/gallium/drivers/nouveau/codegen/nv50_ir.h
src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h
src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_print.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp

index 5b8595c961e90fa945ae6ef9b8511ef49ac52b82..e4bbc8edafb5e86e47e5cd87a38c2c1732e1390a 100644 (file)
@@ -152,6 +152,7 @@ enum operation
    OP_INSBF,  // insert first src1[8:15] bits of src0 into src2 at src1[0:7]
    OP_EXTBF,  // place bits [K,K+N) of src0 into dst, src1 = 0xNNKK
    OP_BFIND,  // find highest/lowest set bit
+   OP_BREV,   // bitfield reverse
    OP_PERMT,  // dst = bytes from src2,src0 selected by src1 (nvc0's src order)
    OP_ATOM,
    OP_BAR,    // execution barrier, sources = { id, thread count, predicate }
index 50c8345e4b662dbe1e0606f02bafb016090294e3..42731f32f92b6a6ff7eb949797b1d78c101e5da3 100644 (file)
@@ -1910,7 +1910,7 @@ Converter::visit(nir_intrinsic_instr *insn)
 
       if (op == nir_intrinsic_read_first_invocation) {
          mkOp1(OP_VOTE, TYPE_U32, tmp, mkImm(1))->subOp = NV50_IR_SUBOP_VOTE_ANY;
-         mkOp2(OP_EXTBF, TYPE_U32, tmp, tmp, mkImm(0x2000))->subOp = NV50_IR_SUBOP_EXTBF_REV;
+         mkOp1(OP_BREV, TYPE_U32, tmp, tmp);
          mkOp1(OP_BFIND, TYPE_U32, tmp, tmp)->subOp = NV50_IR_SUBOP_BFIND_SAMT;
       } else
          tmp = getSrc(&insn->src[1], 0);
@@ -2794,14 +2794,14 @@ Converter::visit(nir_alu_instr *insn)
    case nir_op_bitfield_reverse: {
       DEFAULT_CHECKS;
       LValues &newDefs = convert(&insn->dest);
-      mkOp2(OP_EXTBF, TYPE_U32, newDefs[0], getSrc(&insn->src[0]), mkImm(0x2000))->subOp = NV50_IR_SUBOP_EXTBF_REV;
+      mkOp1(OP_BREV, TYPE_U32, newDefs[0], getSrc(&insn->src[0]));
       break;
    }
    case nir_op_find_lsb: {
       DEFAULT_CHECKS;
       LValues &newDefs = convert(&insn->dest);
       Value *tmp = getSSA();
-      mkOp2(OP_EXTBF, TYPE_U32, tmp, getSrc(&insn->src[0]), mkImm(0x2000))->subOp = NV50_IR_SUBOP_EXTBF_REV;
+      mkOp1(OP_BREV, TYPE_U32, tmp, getSrc(&insn->src[0]));
       mkOp1(OP_BFIND, TYPE_U32, newDefs[0], tmp)->subOp = NV50_IR_SUBOP_BFIND_SAMT;
       break;
    }
index 60f3d582a0bb7668f2d022a089848da3413a065e..3fd76f64de05e272e23efe315dfe122c9c5b004d 100644 (file)
@@ -3401,8 +3401,7 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
       // ReadInvocationARB(src, findLSB(ballot(true)))
       val0 = getScratch();
       mkOp1(OP_VOTE, TYPE_U32, val0, mkImm(1))->subOp = NV50_IR_SUBOP_VOTE_ANY;
-      mkOp2(OP_EXTBF, TYPE_U32, val0, val0, mkImm(0x2000))
-         ->subOp = NV50_IR_SUBOP_EXTBF_REV;
+      mkOp1(OP_BREV, TYPE_U32, val0, val0);
       mkOp1(OP_BFIND, TYPE_U32, val0, val0)->subOp = NV50_IR_SUBOP_BFIND_SAMT;
       src1 = val0;
       /* fallthrough */
@@ -3820,8 +3819,7 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
       FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
          src0 = fetchSrc(0, c);
          val0 = getScratch();
-         geni = mkOp2(OP_EXTBF, TYPE_U32, val0, src0, mkImm(0x2000));
-         geni->subOp = NV50_IR_SUBOP_EXTBF_REV;
+         mkOp1(OP_BREV, TYPE_U32, val0, src0);
          geni = mkOp1(OP_BFIND, TYPE_U32, dst0[c], val0);
          geni->subOp = NV50_IR_SUBOP_BFIND_SAMT;
       }
@@ -3836,8 +3834,7 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
    case TGSI_OPCODE_BREV:
       FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
          src0 = fetchSrc(0, c);
-         geni = mkOp2(OP_EXTBF, TYPE_U32, dst0[c], src0, mkImm(0x2000));
-         geni->subOp = NV50_IR_SUBOP_EXTBF_REV;
+         mkOp1(OP_BREV, TYPE_U32, dst0[c], src0);
       }
       break;
    case TGSI_OPCODE_POPC:
index a60881000fe29453585b2b6253f626a4f9b74ea3..ccdc2f98ef6fa42f5ee3828afb1e8d1b06a49869 100644 (file)
@@ -310,6 +310,14 @@ NVC0LegalizeSSA::handleSET(CmpInstruction *cmp)
    cmp->sType = hTy;
 }
 
+void
+NVC0LegalizeSSA::handleBREV(Instruction *i)
+{
+   i->op = OP_EXTBF;
+   i->subOp = NV50_IR_SUBOP_EXTBF_REV;
+   i->setSrc(1, bld.mkImm(0x2000));
+}
+
 bool
 NVC0LegalizeSSA::visit(Function *fn)
 {
@@ -354,6 +362,9 @@ NVC0LegalizeSSA::visit(BasicBlock *bb)
          if (typeSizeof(i->sType) == 8 && i->sType != TYPE_F64)
             handleSET(i->asCmp());
          break;
+      case OP_BREV:
+         handleBREV(i);
+         break;
       default:
          break;
       }
index b4c405a9ea5611f72378983204a1cc1fd79e250e..a4925013ee447975c2b68bc37a3dd7f932700e05 100644 (file)
@@ -68,6 +68,7 @@ private:
    void handleSET(CmpInstruction *);
    void handleTEXLOD(TexInstruction *);
    void handleShift(Instruction *);
+   void handleBREV(Instruction *);
 
 protected:
    BuildUtil bld;
index 5c3d15968cf4891b54ada546b75582ee58d64a1c..d17e605a51e05402fe016ee7550589cf39bbfc08 100644 (file)
@@ -1534,6 +1534,12 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue &imm0, int s)
       i->subOp = 0;
       break;
    }
+   case OP_BREV: {
+      uint32_t res = util_bitreverse(imm0.reg.data.u32);
+      i->setSrc(0, new_ImmediateValue(i->bb->getProgram(), res));
+      i->op = OP_MOV;
+      break;
+   }
    case OP_POPCNT: {
       // Only deal with 1-arg POPCNT here
       if (i->srcExists(1))
index b85ace15b87eba65c83deffbf7ee92c928303db4..e3bac648761e3504759ab73e91611909bf8e1f86 100644 (file)
@@ -178,6 +178,7 @@ const char *operationStr[OP_LAST + 1] =
    "insbf",
    "extbf",
    "bfind",
+   "brev",
    "permt",
    "atom",
    "bar",
index e801722ec09640071a7f21f0f6570bb31c7de507..77edf41e1243add125a4a54732167652f4ae4acd 100644 (file)
@@ -51,7 +51,7 @@ const uint8_t Target::operationSrcNr[] =
    0,                      // TEXBAR
    1, 1,                   // DFDX, DFDY
    1, 2, 1, 2, 0, 0,       // RDSV, WRSV, PIXLD, QUADOP, QUADON, QUADPOP
-   2, 3, 2, 1, 3,          // POPCNT, INSBF, EXTBF, BFIND, PERMT
+   2, 3, 2, 1, 1, 3,       // POPCNT, INSBF, EXTBF, BFIND, BREV, PERMT
    2, 2,                   // ATOM, BAR
    2, 2, 2, 2, 3, 2,       // VADD, VAVG, VMIN, VMAX, VSAD, VSET,
    2, 2, 2, 1,             // VSHR, VSHL, VSEL, CCTL
@@ -120,9 +120,9 @@ const OpClass Target::operationClass[] =
    // DFDX, DFDY, RDSV, WRSV; PIXLD, QUADOP, QUADON, QUADPOP
    OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_OTHER,
    OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_CONTROL, OPCLASS_CONTROL,
-   // POPCNT, INSBF, EXTBF, BFIND; PERMT
+   // POPCNT, INSBF, EXTBF, BFIND, BREV; PERMT
    OPCLASS_BITFIELD, OPCLASS_BITFIELD, OPCLASS_BITFIELD, OPCLASS_BITFIELD,
-   OPCLASS_BITFIELD,
+   OPCLASS_BITFIELD, OPCLASS_BITFIELD,
    // ATOM, BAR
    OPCLASS_ATOMIC, OPCLASS_CONTROL,
    // VADD, VAVG, VMIN, VMAX