Mesa (main): aco: support DPP8

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Dec 31 21:15:17 UTC 2021


Module: Mesa
Branch: main
Commit: da0412e55b1cd49f083abd1cb3d349c02e1c85e1
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=da0412e55b1cd49f083abd1cb3d349c02e1c85e1

Author: Tatsuyuki Ishi <ishitatsuyuki at gmail.com>
Date:   Mon Nov 29 00:12:04 2021 +0900

aco: support DPP8

Reviewed-by: Rhys Perry <pendingchaos02 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13971>

---

 src/amd/compiler/aco_assembler.cpp               | 20 +++++-
 src/amd/compiler/aco_builder_h.py                |  9 ++-
 src/amd/compiler/aco_ir.cpp                      | 44 +++++++-----
 src/amd/compiler/aco_ir.h                        | 47 +++++++++----
 src/amd/compiler/aco_opcodes.py                  |  5 +-
 src/amd/compiler/aco_opt_value_numbering.cpp     | 19 +++--
 src/amd/compiler/aco_optimizer.cpp               | 89 ++++++++++++++++--------
 src/amd/compiler/aco_optimizer_postRA.cpp        | 42 +++++++----
 src/amd/compiler/aco_print_ir.cpp                | 13 ++--
 src/amd/compiler/aco_validate.cpp                |  3 +-
 src/amd/compiler/tests/test_optimizer.cpp        |  4 +-
 src/amd/compiler/tests/test_optimizer_postRA.cpp |  4 +-
 12 files changed, 202 insertions(+), 97 deletions(-)

diff --git a/src/amd/compiler/aco_assembler.cpp b/src/amd/compiler/aco_assembler.cpp
index e520da50fec..4c404bab7e8 100644
--- a/src/amd/compiler/aco_assembler.cpp
+++ b/src/amd/compiler/aco_assembler.cpp
@@ -662,14 +662,14 @@ emit_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction* inst
             encoding |= vop3.neg_lo[i] << (29 + i);
          out.push_back(encoding);
 
-      } else if (instr->isDPP()) {
+      } else if (instr->isDPP16()) {
          assert(ctx.chip_class >= GFX8);
-         DPP_instruction& dpp = instr->dpp();
+         DPP16_instruction& dpp = instr->dpp16();
 
          /* first emit the instruction without the DPP operand */
          Operand dpp_op = instr->operands[0];
          instr->operands[0] = Operand(PhysReg{250}, v1);
-         instr->format = (Format)((uint16_t)instr->format & ~(uint16_t)Format::DPP);
+         instr->format = (Format)((uint16_t)instr->format & ~(uint16_t)Format::DPP16);
          emit_instruction(ctx, out, instr);
          uint32_t encoding = (0xF & dpp.row_mask) << 28;
          encoding |= (0xF & dpp.bank_mask) << 24;
@@ -684,6 +684,20 @@ emit_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction* inst
          encoding |= (0xFF) & dpp_op.physReg();
          out.push_back(encoding);
          return;
+      } else if (instr->isDPP8()) {
+         assert(ctx.chip_class >= GFX10);
+         DPP8_instruction& dpp = instr->dpp8();
+
+         /* first emit the instruction without the DPP operand */
+         Operand dpp_op = instr->operands[0];
+         instr->operands[0] = Operand(PhysReg{234}, v1);
+         instr->format = (Format)((uint16_t)instr->format & ~(uint16_t)Format::DPP8);
+         emit_instruction(ctx, out, instr);
+         uint32_t encoding = (0xFF) & dpp_op.physReg();
+         for (unsigned i = 0; i < 8; ++i)
+            encoding |= dpp.lane_sel[i] << (8 + i * 3);
+         out.push_back(encoding);
+         return;
       } else if (instr->isSDWA()) {
          SDWA_instruction& sdwa = instr->sdwa();
 
diff --git a/src/amd/compiler/aco_builder_h.py b/src/amd/compiler/aco_builder_h.py
index 9ebf633eef0..a5a9eee22f2 100644
--- a/src/amd/compiler/aco_builder_h.py
+++ b/src/amd/compiler/aco_builder_h.py
@@ -536,9 +536,12 @@ formats = [("pseudo", [Format.PSEUDO], 'Pseudo_instruction', list(itertools.prod
            ("vop3", [Format.VOP3], 'VOP3_instruction', [(1, 3), (1, 2), (1, 1), (2, 2)]),
            ("vop3p", [Format.VOP3P], 'VOP3P_instruction', [(1, 2), (1, 3)]),
            ("vintrp", [Format.VINTRP], 'Interp_instruction', [(1, 2), (1, 3)]),
-           ("vop1_dpp", [Format.VOP1, Format.DPP], 'DPP_instruction', [(1, 1)]),
-           ("vop2_dpp", [Format.VOP2, Format.DPP], 'DPP_instruction', itertools.product([1, 2], [2, 3])),
-           ("vopc_dpp", [Format.VOPC, Format.DPP], 'DPP_instruction', itertools.product([1, 2], [2])),
+           ("vop1_dpp", [Format.VOP1, Format.DPP16], 'DPP16_instruction', [(1, 1)]),
+           ("vop2_dpp", [Format.VOP2, Format.DPP16], 'DPP16_instruction', itertools.product([1, 2], [2, 3])),
+           ("vopc_dpp", [Format.VOPC, Format.DPP16], 'DPP16_instruction', itertools.product([1, 2], [2])),
+           ("vop1_dpp8", [Format.VOP1, Format.DPP8], 'DPP8_instruction', [(1, 1)]),
+           ("vop2_dpp8", [Format.VOP2, Format.DPP8], 'DPP8_instruction', itertools.product([1, 2], [2, 3])),
+           ("vopc_dpp8", [Format.VOPC, Format.DPP8], 'DPP8_instruction', itertools.product([1, 2], [2])),
            ("vop1_e64", [Format.VOP1, Format.VOP3], 'VOP3_instruction', itertools.product([1], [1])),
            ("vop2_e64", [Format.VOP2, Format.VOP3], 'VOP3_instruction', itertools.product([1, 2], [2, 3])),
            ("vopc_e64", [Format.VOPC, Format.VOP3], 'VOP3_instruction', itertools.product([1, 2], [2])),
diff --git a/src/amd/compiler/aco_ir.cpp b/src/amd/compiler/aco_ir.cpp
index eee2eb2e882..523b25e619e 100644
--- a/src/amd/compiler/aco_ir.cpp
+++ b/src/amd/compiler/aco_ir.cpp
@@ -292,12 +292,12 @@ convert_to_SDWA(chip_class chip, aco_ptr<Instruction>& instr)
 }
 
 bool
-can_use_DPP(const aco_ptr<Instruction>& instr, bool pre_ra)
+can_use_DPP(const aco_ptr<Instruction>& instr, bool pre_ra, bool dpp8)
 {
    assert(instr->isVALU() && !instr->operands.empty());
 
    if (instr->isDPP())
-      return true;
+      return instr->isDPP8() == dpp8;
 
    if (instr->operands.size() && instr->operands[0].isLiteral())
       return false;
@@ -316,6 +316,8 @@ can_use_DPP(const aco_ptr<Instruction>& instr, bool pre_ra)
       const VOP3_instruction* vop3 = &instr->vop3();
       if (vop3->clamp || vop3->omod || vop3->opsel)
          return false;
+      if (dpp8)
+         return false;
       if (instr->format == Format::VOP3)
          return false;
       if (instr->operands.size() > 1 && !instr->operands[1].isOfType(RegType::vgpr))
@@ -331,29 +333,39 @@ can_use_DPP(const aco_ptr<Instruction>& instr, bool pre_ra)
 }
 
 aco_ptr<Instruction>
-convert_to_DPP(aco_ptr<Instruction>& instr)
+convert_to_DPP(aco_ptr<Instruction>& instr, bool dpp8)
 {
    if (instr->isDPP())
       return NULL;
 
    aco_ptr<Instruction> tmp = std::move(instr);
-   Format format =
-      (Format)(((uint32_t)tmp->format & ~(uint32_t)Format::VOP3) | (uint32_t)Format::DPP);
-   instr.reset(create_instruction<DPP_instruction>(tmp->opcode, format, tmp->operands.size(),
-                                                   tmp->definitions.size()));
+   Format format = (Format)(((uint32_t)tmp->format & ~(uint32_t)Format::VOP3) |
+                            (dpp8 ? (uint32_t)Format::DPP8 : (uint32_t)Format::DPP16));
+   if (dpp8)
+      instr.reset(create_instruction<DPP8_instruction>(tmp->opcode, format, tmp->operands.size(),
+                                                       tmp->definitions.size()));
+   else
+      instr.reset(create_instruction<DPP16_instruction>(tmp->opcode, format, tmp->operands.size(),
+                                                        tmp->definitions.size()));
    std::copy(tmp->operands.cbegin(), tmp->operands.cend(), instr->operands.begin());
    for (unsigned i = 0; i < instr->definitions.size(); i++)
       instr->definitions[i] = tmp->definitions[i];
 
-   DPP_instruction* dpp = &instr->dpp();
-   dpp->dpp_ctrl = dpp_quad_perm(0, 1, 2, 3);
-   dpp->row_mask = 0xf;
-   dpp->bank_mask = 0xf;
-
-   if (tmp->isVOP3()) {
-      const VOP3_instruction* vop3 = &tmp->vop3();
-      memcpy(dpp->neg, vop3->neg, sizeof(dpp->neg));
-      memcpy(dpp->abs, vop3->abs, sizeof(dpp->abs));
+   if (dpp8) {
+      DPP8_instruction* dpp = &instr->dpp8();
+      for (unsigned i = 0; i < 8; i++)
+         dpp->lane_sel[i] = i;
+   } else {
+      DPP16_instruction* dpp = &instr->dpp16();
+      dpp->dpp_ctrl = dpp_quad_perm(0, 1, 2, 3);
+      dpp->row_mask = 0xf;
+      dpp->bank_mask = 0xf;
+
+      if (tmp->isVOP3()) {
+         const VOP3_instruction* vop3 = &tmp->vop3();
+         memcpy(dpp->neg, vop3->neg, sizeof(dpp->neg));
+         memcpy(dpp->abs, vop3->abs, sizeof(dpp->abs));
+      }
    }
 
    if (instr->isVOPC() || instr->definitions.size() > 1)
diff --git a/src/amd/compiler/aco_ir.h b/src/amd/compiler/aco_ir.h
index e8c3e56c2dd..39b2e3aa70f 100644
--- a/src/amd/compiler/aco_ir.h
+++ b/src/amd/compiler/aco_ir.h
@@ -102,8 +102,9 @@ enum class Format : std::uint16_t {
    VOP3 = 1 << 11,
    /* Vector Parameter Interpolation Format */
    VINTRP = 1 << 12,
-   DPP = 1 << 13,
+   DPP16 = 1 << 13,
    SDWA = 1 << 14,
+   DPP8 = 1 << 15,
 };
 
 enum class instr_class : uint8_t {
@@ -294,7 +295,7 @@ asSDWA(Format format)
 constexpr Format
 withoutDPP(Format format)
 {
-   return (Format)((uint32_t)format & ~(uint32_t)Format::DPP);
+   return (Format)((uint32_t)format & ~((uint32_t)Format::DPP16 | (uint32_t)Format::DPP8));
 }
 
 enum class RegType {
@@ -996,7 +997,8 @@ struct VOP2_instruction;
 struct VOPC_instruction;
 struct VOP3_instruction;
 struct Interp_instruction;
-struct DPP_instruction;
+struct DPP16_instruction;
+struct DPP8_instruction;
 struct SDWA_instruction;
 
 struct Instruction {
@@ -1282,17 +1284,29 @@ struct Instruction {
       return *(Interp_instruction*)this;
    }
    constexpr bool isVINTRP() const noexcept { return (uint16_t)format & (uint16_t)Format::VINTRP; }
-   DPP_instruction& dpp() noexcept
+   DPP16_instruction& dpp16() noexcept
    {
-      assert(isDPP());
-      return *(DPP_instruction*)this;
+      assert(isDPP16());
+      return *(DPP16_instruction*)this;
    }
-   const DPP_instruction& dpp() const noexcept
+   const DPP16_instruction& dpp16() const noexcept
    {
-      assert(isDPP());
-      return *(DPP_instruction*)this;
+      assert(isDPP16());
+      return *(DPP16_instruction*)this;
    }
-   constexpr bool isDPP() const noexcept { return (uint16_t)format & (uint16_t)Format::DPP; }
+   constexpr bool isDPP16() const noexcept { return (uint16_t)format & (uint16_t)Format::DPP16; }
+   DPP8_instruction& dpp8() noexcept
+   {
+      assert(isDPP8());
+      return *(DPP8_instruction*)this;
+   }
+   const DPP8_instruction& dpp8() const noexcept
+   {
+      assert(isDPP8());
+      return *(DPP8_instruction*)this;
+   }
+   constexpr bool isDPP8() const noexcept { return (uint16_t)format & (uint16_t)Format::DPP8; }
+   constexpr bool isDPP() const noexcept { return isDPP16() || isDPP8(); }
    SDWA_instruction& sdwa() noexcept
    {
       assert(isSDWA());
@@ -1405,7 +1419,7 @@ static_assert(sizeof(VOP3P_instruction) == sizeof(Instruction) + 8, "Unexpected
  * The swizzle applies to the src0 operand.
  *
  */
-struct DPP_instruction : public Instruction {
+struct DPP16_instruction : public Instruction {
    bool abs[2];
    bool neg[2];
    uint16_t dpp_ctrl;
@@ -1414,7 +1428,12 @@ struct DPP_instruction : public Instruction {
    bool bound_ctrl : 1;
    uint8_t padding : 7;
 };
-static_assert(sizeof(DPP_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
+static_assert(sizeof(DPP16_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
+
+struct DPP8_instruction : public Instruction {
+   uint8_t lane_sel[8];
+};
+static_assert(sizeof(DPP8_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
 
 struct SubdwordSel {
    enum sdwa_sel : uint8_t {
@@ -1760,10 +1779,10 @@ bool is_dead(const std::vector<uint16_t>& uses, Instruction* instr);
 bool can_use_opsel(chip_class chip, aco_opcode op, int idx, bool high);
 bool instr_is_16bit(chip_class chip, aco_opcode op);
 bool can_use_SDWA(chip_class chip, const aco_ptr<Instruction>& instr, bool pre_ra);
-bool can_use_DPP(const aco_ptr<Instruction>& instr, bool pre_ra);
+bool can_use_DPP(const aco_ptr<Instruction>& instr, bool pre_ra, bool dpp8);
 /* updates "instr" and returns the old instruction (or NULL if no update was needed) */
 aco_ptr<Instruction> convert_to_SDWA(chip_class chip, aco_ptr<Instruction>& instr);
-aco_ptr<Instruction> convert_to_DPP(aco_ptr<Instruction>& instr);
+aco_ptr<Instruction> convert_to_DPP(aco_ptr<Instruction>& instr, bool dpp8);
 bool needs_exec_mask(const Instruction* instr);
 
 aco_opcode get_ordered(aco_opcode op);
diff --git a/src/amd/compiler/aco_opcodes.py b/src/amd/compiler/aco_opcodes.py
index bb027180456..16494a701c4 100644
--- a/src/amd/compiler/aco_opcodes.py
+++ b/src/amd/compiler/aco_opcodes.py
@@ -74,8 +74,9 @@ class Format(Enum):
    VOPC = 1 << 10
    VOP3 = 1 << 11
    VINTRP = 1 << 12
-   DPP = 1 << 13
+   DPP16 = 1 << 13
    SDWA = 1 << 14
+   DPP8 = 1 << 15
 
    def get_builder_fields(self):
       if self == Format.SOPK:
@@ -147,7 +148,7 @@ class Format(Enum):
       elif self == Format.VINTRP:
          return [('unsigned', 'attribute', None),
                  ('unsigned', 'component', None)]
-      elif self == Format.DPP:
+      elif self == Format.DPP16:
          return [('uint16_t', 'dpp_ctrl', None),
                  ('uint8_t', 'row_mask', '0xF'),
                  ('uint8_t', 'bank_mask', '0xF'),
diff --git a/src/amd/compiler/aco_opt_value_numbering.cpp b/src/amd/compiler/aco_opt_value_numbering.cpp
index d650665e0d0..dba86b87538 100644
--- a/src/amd/compiler/aco_opt_value_numbering.cpp
+++ b/src/amd/compiler/aco_opt_value_numbering.cpp
@@ -87,8 +87,11 @@ struct InstrHash {
       if (instr->isVOP3())
          return hash_murmur_32<VOP3_instruction>(instr);
 
-      if (instr->isDPP())
-         return hash_murmur_32<DPP_instruction>(instr);
+      if (instr->isDPP16())
+         return hash_murmur_32<DPP16_instruction>(instr);
+
+      if (instr->isDPP8())
+         return hash_murmur_32<DPP8_instruction>(instr);
 
       if (instr->isSDWA())
          return hash_murmur_32<SDWA_instruction>(instr);
@@ -172,15 +175,21 @@ struct InstrPred {
          }
          return a3.clamp == b3.clamp && a3.omod == b3.omod && a3.opsel == b3.opsel;
       }
-      if (a->isDPP()) {
-         DPP_instruction& aDPP = a->dpp();
-         DPP_instruction& bDPP = b->dpp();
+      if (a->isDPP16()) {
+         DPP16_instruction& aDPP = a->dpp16();
+         DPP16_instruction& bDPP = b->dpp16();
          return aDPP.pass_flags == bDPP.pass_flags && aDPP.dpp_ctrl == bDPP.dpp_ctrl &&
                 aDPP.bank_mask == bDPP.bank_mask && aDPP.row_mask == bDPP.row_mask &&
                 aDPP.bound_ctrl == bDPP.bound_ctrl && aDPP.abs[0] == bDPP.abs[0] &&
                 aDPP.abs[1] == bDPP.abs[1] && aDPP.neg[0] == bDPP.neg[0] &&
                 aDPP.neg[1] == bDPP.neg[1];
       }
+      if (a->isDPP8()) {
+         DPP8_instruction& aDPP = a->dpp8();
+         DPP8_instruction& bDPP = b->dpp8();
+         return aDPP.pass_flags == bDPP.pass_flags &&
+                !memcmp(aDPP.lane_sel, bDPP.lane_sel, sizeof(aDPP.lane_sel));
+      }
       if (a->isSDWA()) {
          SDWA_instruction& aSDWA = a->sdwa();
          SDWA_instruction& bSDWA = b->sdwa();
diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp
index 2c346b976ba..031b88745ae 100644
--- a/src/amd/compiler/aco_optimizer.cpp
+++ b/src/amd/compiler/aco_optimizer.cpp
@@ -120,12 +120,14 @@ enum Label {
    label_canonicalized = 1ull << 32,
    label_extract = 1ull << 33,
    label_insert = 1ull << 34,
-   label_dpp = 1ull << 35,
+   label_dpp16 = 1ull << 35,
+   label_dpp8 = 1ull << 36,
 };
 
 static constexpr uint64_t instr_usedef_labels =
    label_vec | label_mul | label_mad | label_add_sub | label_vop3p | label_bitwise |
-   label_uniform_bitwise | label_minmax | label_vopc | label_usedef | label_extract | label_dpp;
+   label_uniform_bitwise | label_minmax | label_vopc | label_usedef | label_extract | label_dpp16 |
+   label_dpp8;
 static constexpr uint64_t instr_mod_labels =
    label_omod2 | label_omod4 | label_omod5 | label_clamp | label_insert;
 
@@ -455,13 +457,21 @@ struct ssa_info {
 
    bool is_insert() { return label & label_insert; }
 
-   void set_dpp(Instruction* mov)
+   void set_dpp16(Instruction* mov)
    {
-      add_label(label_dpp);
+      add_label(label_dpp16);
       instr = mov;
    }
 
-   bool is_dpp() { return label & label_dpp; }
+   void set_dpp8(Instruction* mov)
+   {
+      add_label(label_dpp8);
+      instr = mov;
+   }
+
+   bool is_dpp() { return label & (label_dpp16 | label_dpp8); }
+   bool is_dpp16() { return label & label_dpp16; }
+   bool is_dpp8() { return label & label_dpp8; }
 };
 
 struct opt_ctx {
@@ -1215,7 +1225,7 @@ label_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
          if (instr->isSDWA())
             can_use_mod = can_use_mod && instr->sdwa().sel[i].size() == 4;
          else
-            can_use_mod = can_use_mod && (instr->isDPP() || can_use_VOP3(ctx, instr));
+            can_use_mod = can_use_mod && (instr->isDPP16() || can_use_VOP3(ctx, instr));
 
          if (info.is_neg() && instr->opcode == aco_opcode::v_add_f32) {
             instr->opcode = i ? aco_opcode::v_sub_f32 : aco_opcode::v_subrev_f32;
@@ -1228,8 +1238,8 @@ label_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
             if (!instr->isDPP() && !instr->isSDWA())
                to_VOP3(ctx, instr);
             instr->operands[i].setTemp(info.temp);
-            if (instr->isDPP() && !instr->dpp().abs[i])
-               instr->dpp().neg[i] = true;
+            if (instr->isDPP16() && !instr->dpp16().abs[i])
+               instr->dpp16().neg[i] = true;
             else if (instr->isSDWA() && !instr->sdwa().abs[i])
                instr->sdwa().neg[i] = true;
             else if (instr->isVOP3() && !instr->vop3().abs[i])
@@ -1239,8 +1249,8 @@ label_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
             if (!instr->isDPP() && !instr->isSDWA())
                to_VOP3(ctx, instr);
             instr->operands[i] = Operand(info.temp);
-            if (instr->isDPP())
-               instr->dpp().abs[i] = true;
+            if (instr->isDPP16())
+               instr->dpp16().abs[i] = true;
             else if (instr->isSDWA())
                instr->sdwa().abs[i] = true;
             else
@@ -1579,10 +1589,12 @@ label_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
       }
       break;
    case aco_opcode::v_mov_b32:
-      if (instr->isDPP()) {
+      if (instr->isDPP16()) {
          /* anything else doesn't make sense in SSA */
-         assert(instr->dpp().row_mask == 0xf && instr->dpp().bank_mask == 0xf);
-         ctx.info[instr->definitions[0].tempId()].set_dpp(instr.get());
+         assert(instr->dpp16().row_mask == 0xf && instr->dpp16().bank_mask == 0xf);
+         ctx.info[instr->definitions[0].tempId()].set_dpp16(instr.get());
+      } else if (instr->isDPP8()) {
+         ctx.info[instr->definitions[0].tempId()].set_dpp8(instr.get());
       }
       break;
    case aco_opcode::p_is_helper:
@@ -2250,10 +2262,10 @@ combine_inverse_comparison(opt_ctx& ctx, aco_ptr<Instruction>& instr)
       new_sdwa->clamp = cmp_sdwa.clamp;
       new_sdwa->omod = cmp_sdwa.omod;
       new_instr = new_sdwa;
-   } else if (cmp->isDPP()) {
-      DPP_instruction* new_dpp = create_instruction<DPP_instruction>(
-         new_opcode, (Format)((uint16_t)Format::DPP | (uint16_t)Format::VOPC), 2, 1);
-      DPP_instruction& cmp_dpp = cmp->dpp();
+   } else if (cmp->isDPP16()) {
+      DPP16_instruction* new_dpp = create_instruction<DPP16_instruction>(
+         new_opcode, (Format)((uint16_t)Format::DPP16 | (uint16_t)Format::VOPC), 2, 1);
+      DPP16_instruction& cmp_dpp = cmp->dpp16();
       memcpy(new_dpp->abs, cmp_dpp.abs, sizeof(new_dpp->abs));
       memcpy(new_dpp->neg, cmp_dpp.neg, sizeof(new_dpp->neg));
       new_dpp->dpp_ctrl = cmp_dpp.dpp_ctrl;
@@ -2261,6 +2273,12 @@ combine_inverse_comparison(opt_ctx& ctx, aco_ptr<Instruction>& instr)
       new_dpp->bank_mask = cmp_dpp.bank_mask;
       new_dpp->bound_ctrl = cmp_dpp.bound_ctrl;
       new_instr = new_dpp;
+   } else if (cmp->isDPP8()) {
+      DPP8_instruction* new_dpp = create_instruction<DPP8_instruction>(
+         new_opcode, (Format)((uint16_t)Format::DPP8 | (uint16_t)Format::VOPC), 2, 1);
+      DPP8_instruction& cmp_dpp = cmp->dpp8();
+      memcpy(new_dpp->lane_sel, cmp_dpp.lane_sel, sizeof(new_dpp->lane_sel));
+      new_instr = new_dpp;
    } else {
       new_instr = create_instruction<VOPC_instruction>(new_opcode, Format::VOPC, 2, 1);
       instr->definitions[0].setHint(vcc);
@@ -4005,23 +4023,34 @@ select_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
 
          aco_opcode swapped_op;
          if (info.is_dpp() && info.instr->pass_flags == instr->pass_flags &&
-             (i == 0 || can_swap_operands(instr, &swapped_op)) && can_use_DPP(instr, true) &&
-             !instr->isDPP()) {
-            convert_to_DPP(instr);
-            DPP_instruction* dpp = static_cast<DPP_instruction*>(instr.get());
-            if (i) {
-               instr->opcode = swapped_op;
-               std::swap(instr->operands[0], instr->operands[1]);
-               std::swap(dpp->neg[0], dpp->neg[1]);
-               std::swap(dpp->abs[0], dpp->abs[1]);
+             (i == 0 || can_swap_operands(instr, &swapped_op)) &&
+             can_use_DPP(instr, true, info.is_dpp8()) && !instr->isDPP()) {
+            bool dpp8 = info.is_dpp8();
+            convert_to_DPP(instr, dpp8);
+            if (dpp8) {
+               DPP8_instruction* dpp = &instr->dpp8();
+               for (unsigned j = 0; j < 8; ++j)
+                  dpp->lane_sel[j] = info.instr->dpp8().lane_sel[j];
+               if (i) {
+                  instr->opcode = swapped_op;
+                  std::swap(instr->operands[0], instr->operands[1]);
+               }
+            } else {
+               DPP16_instruction* dpp = &instr->dpp16();
+               if (i) {
+                  instr->opcode = swapped_op;
+                  std::swap(instr->operands[0], instr->operands[1]);
+                  std::swap(dpp->neg[0], dpp->neg[1]);
+                  std::swap(dpp->abs[0], dpp->abs[1]);
+               }
+               dpp->dpp_ctrl = info.instr->dpp16().dpp_ctrl;
+               dpp->bound_ctrl = info.instr->dpp16().bound_ctrl;
+               dpp->neg[0] ^= info.instr->dpp16().neg[0] && !dpp->abs[0];
+               dpp->abs[0] |= info.instr->dpp16().abs[0];
             }
             if (--ctx.uses[info.instr->definitions[0].tempId()])
                ctx.uses[info.instr->operands[0].tempId()]++;
             instr->operands[0].setTemp(info.instr->operands[0].getTemp());
-            dpp->dpp_ctrl = info.instr->dpp().dpp_ctrl;
-            dpp->bound_ctrl = info.instr->dpp().bound_ctrl;
-            dpp->neg[0] ^= info.instr->dpp().neg[0] && !dpp->abs[0];
-            dpp->abs[0] |= info.instr->dpp().abs[0];
             break;
          }
       }
diff --git a/src/amd/compiler/aco_optimizer_postRA.cpp b/src/amd/compiler/aco_optimizer_postRA.cpp
index 5019eb619f0..1953c00d4a6 100644
--- a/src/amd/compiler/aco_optimizer_postRA.cpp
+++ b/src/amd/compiler/aco_optimizer_postRA.cpp
@@ -386,7 +386,7 @@ try_combine_dpp(pr_opt_ctx& ctx, aco_ptr<Instruction>& instr)
     *
     */
 
-   if (!instr->isVALU() || instr->isDPP() || !can_use_DPP(instr, false))
+   if (!instr->isVALU() || instr->isDPP())
       return;
 
    for (unsigned i = 0; i < MIN2(2, instr->operands.size()); i++) {
@@ -394,9 +394,12 @@ try_combine_dpp(pr_opt_ctx& ctx, aco_ptr<Instruction>& instr)
       if (!op_instr_idx.found())
          continue;
 
-      Instruction* mov = ctx.get(op_instr_idx);
+      const Instruction* mov = ctx.get(op_instr_idx);
       if (mov->opcode != aco_opcode::v_mov_b32 || !mov->isDPP())
          continue;
+      bool dpp8 = mov->isDPP8();
+      if (!can_use_DPP(instr, false, dpp8))
+         return;
 
       /* If we aren't going to remove the v_mov_b32, we have to ensure that it doesn't overwrite
        * it's own operand before we use it.
@@ -412,25 +415,34 @@ try_combine_dpp(pr_opt_ctx& ctx, aco_ptr<Instruction>& instr)
       if (i && !can_swap_operands(instr, &instr->opcode))
          continue;
 
-      /* anything else doesn't make sense in SSA */
-      assert(mov->dpp().row_mask == 0xf && mov->dpp().bank_mask == 0xf);
+      if (!dpp8) /* anything else doesn't make sense in SSA */
+         assert(mov->dpp16().row_mask == 0xf && mov->dpp16().bank_mask == 0xf);
 
       if (--ctx.uses[mov->definitions[0].tempId()])
          ctx.uses[mov->operands[0].tempId()]++;
 
-      convert_to_DPP(instr);
+      convert_to_DPP(instr, dpp8);
 
-      DPP_instruction* dpp = &instr->dpp();
-      if (i) {
-         std::swap(dpp->operands[0], dpp->operands[1]);
-         std::swap(dpp->neg[0], dpp->neg[1]);
-         std::swap(dpp->abs[0], dpp->abs[1]);
+      if (dpp8) {
+         DPP8_instruction* dpp = &instr->dpp8();
+         if (i) {
+            std::swap(dpp->operands[0], dpp->operands[1]);
+         }
+         dpp->operands[0] = mov->operands[0];
+         memcpy(dpp->lane_sel, mov->dpp8().lane_sel, sizeof(dpp->lane_sel));
+      } else {
+         DPP16_instruction* dpp = &instr->dpp16();
+         if (i) {
+            std::swap(dpp->operands[0], dpp->operands[1]);
+            std::swap(dpp->neg[0], dpp->neg[1]);
+            std::swap(dpp->abs[0], dpp->abs[1]);
+         }
+         dpp->operands[0] = mov->operands[0];
+         dpp->dpp_ctrl = mov->dpp16().dpp_ctrl;
+         dpp->bound_ctrl = true;
+         dpp->neg[0] ^= mov->dpp16().neg[0] && !dpp->abs[0];
+         dpp->abs[0] |= mov->dpp16().abs[0];
       }
-      dpp->operands[0] = mov->operands[0];
-      dpp->dpp_ctrl = mov->dpp().dpp_ctrl;
-      dpp->bound_ctrl = true;
-      dpp->neg[0] ^= mov->dpp().neg[0] && !dpp->abs[0];
-      dpp->abs[0] |= mov->dpp().abs[0];
       return;
    }
 }
diff --git a/src/amd/compiler/aco_print_ir.cpp b/src/amd/compiler/aco_print_ir.cpp
index 750f54a4c22..d3b24dc0a57 100644
--- a/src/amd/compiler/aco_print_ir.cpp
+++ b/src/amd/compiler/aco_print_ir.cpp
@@ -566,8 +566,8 @@ print_instr_format_specific(const Instruction* instr, FILE* output)
          fprintf(output, " clamp");
       if (vop3.opsel & (1 << 3))
          fprintf(output, " opsel_hi");
-   } else if (instr->isDPP()) {
-      const DPP_instruction& dpp = instr->dpp();
+   } else if (instr->isDPP16()) {
+      const DPP16_instruction& dpp = instr->dpp16();
       if (dpp.dpp_ctrl <= 0xff) {
          fprintf(output, " quad_perm:[%d,%d,%d,%d]", dpp.dpp_ctrl & 0x3, (dpp.dpp_ctrl >> 2) & 0x3,
                  (dpp.dpp_ctrl >> 4) & 0x3, (dpp.dpp_ctrl >> 6) & 0x3);
@@ -602,6 +602,11 @@ print_instr_format_specific(const Instruction* instr, FILE* output)
          fprintf(output, " bank_mask:0x%.1x", dpp.bank_mask);
       if (dpp.bound_ctrl)
          fprintf(output, " bound_ctrl:1");
+   } else if (instr->isDPP8()) {
+      const DPP8_instruction& dpp = instr->dpp8();
+      fprintf(output, " dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]", dpp.lane_sel[0], dpp.lane_sel[1],
+              dpp.lane_sel[2], dpp.lane_sel[3], dpp.lane_sel[4], dpp.lane_sel[5], dpp.lane_sel[6],
+              dpp.lane_sel[7]);
    } else if (instr->isSDWA()) {
       const SDWA_instruction& sdwa = instr->sdwa();
       switch (sdwa.omod) {
@@ -668,8 +673,8 @@ aco_print_instr(const Instruction* instr, FILE* output, unsigned flags)
             neg[i] = vop3.neg[i];
             opsel[i] = vop3.opsel & (1 << i);
          }
-      } else if (instr->isDPP()) {
-         const DPP_instruction& dpp = instr->dpp();
+      } else if (instr->isDPP16()) {
+         const DPP16_instruction& dpp = instr->dpp16();
          for (unsigned i = 0; i < 2; ++i) {
             abs[i] = dpp.abs[i];
             neg[i] = dpp.neg[i];
diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp
index 445b4cd4918..7469fd8a964 100644
--- a/src/amd/compiler/aco_validate.cpp
+++ b/src/amd/compiler/aco_validate.cpp
@@ -116,7 +116,8 @@ validate_ir(Program* program)
          /* check base format */
          Format base_format = instr->format;
          base_format = (Format)((uint32_t)base_format & ~(uint32_t)Format::SDWA);
-         base_format = (Format)((uint32_t)base_format & ~(uint32_t)Format::DPP);
+         base_format = (Format)((uint32_t)base_format & ~(uint32_t)Format::DPP16);
+         base_format = (Format)((uint32_t)base_format & ~(uint32_t)Format::DPP8);
          if ((uint32_t)base_format & (uint32_t)Format::VOP1)
             base_format = Format::VOP1;
          else if ((uint32_t)base_format & (uint32_t)Format::VOP2)
diff --git a/src/amd/compiler/tests/test_optimizer.cpp b/src/amd/compiler/tests/test_optimizer.cpp
index f33de4caf76..50fa46b1fb1 100644
--- a/src/amd/compiler/tests/test_optimizer.cpp
+++ b/src/amd/compiler/tests/test_optimizer.cpp
@@ -988,7 +988,7 @@ BEGIN_TEST(optimizer.dpp)
    //! v1: %res3 = v_add_f32 -%a, %b row_mirror bound_ctrl:1
    //! p_unit_test 3, %res3
    auto tmp3 = bld.vop1_dpp(aco_opcode::v_mov_b32, bld.def(v1), a, dpp_row_mirror);
-   tmp3.instr->dpp().neg[0] = true;
+   tmp3.instr->dpp16().neg[0] = true;
    Temp res3 = bld.vop2(aco_opcode::v_add_f32, bld.def(v1), tmp3, b);
    writeout(3, res3);
 
@@ -1010,7 +1010,7 @@ BEGIN_TEST(optimizer.dpp)
    //! v1: %res6 = v_add_f32 |%a|, %b row_mirror bound_ctrl:1
    //! p_unit_test 6, %res6
    auto tmp6 = bld.vop1_dpp(aco_opcode::v_mov_b32, bld.def(v1), a, dpp_row_mirror);
-   tmp6.instr->dpp().neg[0] = true;
+   tmp6.instr->dpp16().neg[0] = true;
    auto res6 = bld.vop2_e64(aco_opcode::v_add_f32, bld.def(v1), tmp6, b);
    res6.instr->vop3().abs[0] = true;
    writeout(6, res6);
diff --git a/src/amd/compiler/tests/test_optimizer_postRA.cpp b/src/amd/compiler/tests/test_optimizer_postRA.cpp
index f0345296fc4..468a24cdb51 100644
--- a/src/amd/compiler/tests/test_optimizer_postRA.cpp
+++ b/src/amd/compiler/tests/test_optimizer_postRA.cpp
@@ -319,7 +319,7 @@ BEGIN_TEST(optimizer_postRA.dpp)
    //! v1: %res3:v[2] = v_add_f32 -%a:v[0], %b:v[1] row_mirror bound_ctrl:1
    //! p_unit_test 3, %res3:v[2]
    auto tmp3 = bld.vop1_dpp(aco_opcode::v_mov_b32, bld.def(v1, reg_v2), a, dpp_row_mirror);
-   tmp3.instr->dpp().neg[0] = true;
+   tmp3.instr->dpp16().neg[0] = true;
    Temp res3 = bld.vop2(aco_opcode::v_add_f32, bld.def(v1, reg_v2), Operand(tmp3, reg_v2), b);
    writeout(3, Operand(res3, reg_v2));
 
@@ -341,7 +341,7 @@ BEGIN_TEST(optimizer_postRA.dpp)
    //! v1: %res6:v[2] = v_add_f32 |%a:v[0]|, %b:v[1] row_mirror bound_ctrl:1
    //! p_unit_test 6, %res6:v[2]
    auto tmp6 = bld.vop1_dpp(aco_opcode::v_mov_b32, bld.def(v1, reg_v2), a, dpp_row_mirror);
-   tmp6.instr->dpp().neg[0] = true;
+   tmp6.instr->dpp16().neg[0] = true;
    auto res6 = bld.vop2_e64(aco_opcode::v_add_f32, bld.def(v1, reg_v2), Operand(tmp6, reg_v2), b);
    res6.instr->vop3().abs[0] = true;
    writeout(6, Operand(res6, reg_v2));



More information about the mesa-commit mailing list