aco: update IR validator
authorRhys Perry <pendingchaos02@gmail.com>
Mon, 25 Nov 2019 16:12:44 +0000 (16:12 +0000)
committerMarge Bot <eric+marge@anholt.net>
Tue, 14 Jan 2020 12:56:27 +0000 (12:56 +0000)
GFX10 increased the constant bus limit and allowed literals on VOP3

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2883>

src/amd/compiler/aco_validate.cpp

index 655fb0c3bceb2d9c8ed61e03490fc3da05245388..8d69952c811d303b3cbab238d825145876681160 100644 (file)
@@ -105,60 +105,71 @@ void validate(Program* program, FILE * output)
             }
          }
 
-         /* check num literals */
          if (instr->isSALU() || instr->isVALU()) {
-            unsigned num_literals = 0;
+            /* check literals */
+            Operand literal(s1);
             for (unsigned i = 0; i < instr->operands.size(); i++)
             {
-               if (instr->operands[i].isLiteral() && instr->isVOP3() && program->chip_class >= GFX10) {
-                  num_literals++;
-               } else if (instr->operands[i].isLiteral()) {
-                  check(instr->format == Format::SOP1 ||
-                        instr->format == Format::SOP2 ||
-                        instr->format == Format::SOPC ||
-                        instr->format == Format::VOP1 ||
-                        instr->format == Format::VOP2 ||
-                        instr->format == Format::VOPC,
-                        "Literal applied on wrong instruction format", instr.get());
-
-                  num_literals++;
-                  check(!instr->isVALU() || i == 0 || i == 2, "Wrong source position for Literal argument", instr.get());
-               }
+               Operand op = instr->operands[i];
+               if (!op.isLiteral())
+                  continue;
+
+               check(instr->format == Format::SOP1 ||
+                     instr->format == Format::SOP2 ||
+                     instr->format == Format::SOPC ||
+                     instr->format == Format::VOP1 ||
+                     instr->format == Format::VOP2 ||
+                     instr->format == Format::VOPC ||
+                     (instr->isVOP3() && program->chip_class >= GFX10),
+                     "Literal applied on wrong instruction format", instr.get());
+
+               check(literal.isUndefined() || (literal.size() == op.size() && literal.constantValue() == op.constantValue()), "Only 1 Literal allowed", instr.get());
+               literal = op;
+               check(!instr->isVALU() || instr->isVOP3() || i == 0 || i == 2, "Wrong source position for Literal argument", instr.get());
             }
-            check(num_literals <= 1, "Only 1 Literal allowed", instr.get());
 
             /* check num sgprs for VALU */
             if (instr->isVALU()) {
+               bool is_shift64 = instr->opcode == aco_opcode::v_lshlrev_b64 ||
+                                 instr->opcode == aco_opcode::v_lshrrev_b64 ||
+                                 instr->opcode == aco_opcode::v_ashrrev_i64;
+               unsigned const_bus_limit = 1;
+               if (program->chip_class >= GFX10 && !is_shift64)
+                  const_bus_limit = 2;
+
                check(instr->definitions[0].getTemp().type() == RegType::vgpr ||
                      (int) instr->format & (int) Format::VOPC ||
                      instr->opcode == aco_opcode::v_readfirstlane_b32 ||
                      instr->opcode == aco_opcode::v_readlane_b32 ||
                      instr->opcode == aco_opcode::v_readlane_b32_e64,
                      "Wrong Definition type for VALU instruction", instr.get());
-               unsigned num_sgpr = 0;
-               unsigned sgpr_idx = instr->operands.size();
-               for (unsigned i = 0; i < instr->operands.size(); i++) {
+               unsigned num_sgprs = 0;
+               unsigned sgpr[] = {0, 0};
+               for (unsigned i = 0; i < instr->operands.size(); i++)
+               {
+                  Operand op = instr->operands[i];
                   if (instr->opcode == aco_opcode::v_readfirstlane_b32 ||
                       instr->opcode == aco_opcode::v_readlane_b32 ||
                       instr->opcode == aco_opcode::v_readlane_b32_e64 ||
                       instr->opcode == aco_opcode::v_writelane_b32 ||
                       instr->opcode == aco_opcode::v_writelane_b32_e64) {
-                     check(!instr->operands[i].isLiteral(), "No literal allowed on VALU instruction", instr.get());
-                     check(i == 1 || (instr->operands[i].isTemp() && instr->operands[i].regClass() == v1), "Wrong Operand type for VALU instruction", instr.get());
+                     check(!op.isLiteral(), "No literal allowed on VALU instruction", instr.get());
+                     check(i == 1 || (op.isTemp() && op.regClass() == v1), "Wrong Operand type for VALU instruction", instr.get());
                      continue;
                   }
-                  if (instr->operands[i].isTemp() && instr->operands[i].regClass().type() == RegType::sgpr) {
-                     check(i != 1 || (int) instr->format & (int) Format::VOP3A, "Wrong source position for SGPR argument", instr.get());
+                  if (op.isTemp() && instr->operands[i].regClass().type() == RegType::sgpr) {
+                     check(i != 1 || instr->isVOP3(), "Wrong source position for SGPR argument", instr.get());
 
-                     if (sgpr_idx == instr->operands.size() || instr->operands[sgpr_idx].tempId() != instr->operands[i].tempId())
-                        num_sgpr++;
-                     sgpr_idx = i;
+                     if (op.tempId() != sgpr[0] && op.tempId() != sgpr[1]) {
+                        if (num_sgprs < 2)
+                           sgpr[num_sgprs++] = op.tempId();
+                     }
                   }
 
-                  if (instr->operands[i].isConstant() && !instr->operands[i].isLiteral())
-                     check(i == 0 || (int) instr->format & (int) Format::VOP3A, "Wrong source position for constant argument", instr.get());
+                  if (op.isConstant() && !op.isLiteral())
+                     check(i == 0 || instr->isVOP3(), "Wrong source position for constant argument", instr.get());
                }
-               check(num_sgpr + num_literals <= 1, "Only 1 Literal OR 1 SGPR allowed", instr.get());
+               check(num_sgprs + (literal.isUndefined() ? 0 : 1) <= const_bus_limit, "Too many SGPRs/literals", instr.get());
             }
 
             if (instr->format == Format::SOP1 || instr->format == Format::SOP2) {