aco: fix when sub-dword create_vector operand cannot be placed perfectly
authorRhys Perry <pendingchaos02@gmail.com>
Tue, 23 Jun 2020 18:19:00 +0000 (19:19 +0100)
committerMarge Bot <eric+marge@anholt.net>
Wed, 24 Jun 2020 10:52:28 +0000 (10:52 +0000)
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/5207>

src/amd/compiler/aco_register_allocation.cpp

index 096fe80f6ea87977e319dc697f0e822efbf18600..9af9bdfe235f0cb09432f06a2b4aba93b00b10fd 100644 (file)
@@ -770,12 +770,13 @@ bool get_regs_for_copies(ra_ctx& ctx,
             PhysReg reg(def_reg_lo);
             for (unsigned i = 0; i < instr->operands.size(); i++) {
                if (instr->operands[i].isTemp() && instr->operands[i].tempId() == id) {
-                  assert(!reg_file.test(reg, var.rc.bytes()));
-                  res = {reg, !var.rc.is_subdword() || (reg.byte() % info.stride == 0)};
+                  res = {reg, (!var.rc.is_subdword() || (reg.byte() % info.stride == 0)) && !reg_file.test(reg, var.rc.bytes())};
                   break;
                }
                reg.reg_b += instr->operands[i].bytes();
             }
+            if (!res.second)
+               res = {var.reg, !reg_file.test(var.reg, var.rc.bytes())};
          } else {
             info.lb = def_reg_lo;
             info.ub = def_reg_hi + 1;
@@ -1364,19 +1365,21 @@ PhysReg get_reg_create_vector(ra_ctx& ctx,
    /* collect variables to be moved */
    std::set<std::pair<unsigned, unsigned>> vars = collect_vars(ctx, reg_file, PhysReg{best_pos}, size);
 
-   /* GFX9+: move killed operands which aren't yet at the correct position
-    * Moving all killed operands generally leads to more register swaps.
-    * This is only done on GFX9+ because of the cheap v_swap instruction.
-    */
-   if (ctx.program->chip_class >= GFX9) {
-      for (unsigned i = 0, offset = 0; i < instr->operands.size(); offset += instr->operands[i].bytes(), i++) {
-         if (instr->operands[i].isTemp() &&
-             instr->operands[i].isFirstKillBeforeDef() &&
-             instr->operands[i].getTemp().type() == rc.type() &&
-             instr->operands[i].physReg().reg_b != best_pos * 4 + offset) {
-            vars.emplace(instr->operands[i].bytes(), instr->operands[i].tempId());
-            reg_file.clear(instr->operands[i]);
-         }
+   for (unsigned i = 0, offset = 0; i < instr->operands.size(); offset += instr->operands[i].bytes(), i++) {
+      if (!instr->operands[i].isTemp() || !instr->operands[i].isFirstKillBeforeDef() ||
+          instr->operands[i].getTemp().type() != rc.type())
+         continue;
+      bool correct_pos = instr->operands[i].physReg().reg_b == best_pos * 4 + offset;
+      /* GFX9+: move killed operands which aren't yet at the correct position
+       * Moving all killed operands generally leads to more register swaps.
+       * This is only done on GFX9+ because of the cheap v_swap instruction.
+       */
+      if (ctx.program->chip_class >= GFX9 && !correct_pos) {
+         vars.emplace(instr->operands[i].bytes(), instr->operands[i].tempId());
+         reg_file.clear(instr->operands[i]);
+      /* fill operands which are in the correct position to avoid overwriting */
+      } else if (correct_pos) {
+         reg_file.fill(instr->operands[i]);
       }
    }
    ASSERTED bool success = false;