aco: replace extract_vector with copies
authorRhys Perry <pendingchaos02@gmail.com>
Mon, 9 Dec 2019 21:20:10 +0000 (21:20 +0000)
committerMarge Bot <eric+marge@anholt.net>
Tue, 14 Jan 2020 12:56:28 +0000 (12:56 +0000)
Helps a small number of small shaders with situations like this:
a = p_create_vector ...
b = p_extract_vector a, 3
and copy propagation can't be done

Totals from affected shaders:
SGPRS: 14304 -> 14416 (0.78 %)
VGPRS: 8716 -> 6592 (-24.37 %)
Spilled SGPRs: 0 -> 0 (0.00 %)
Spilled VGPRs: 0 -> 0 (0.00 %)
Code Size: 184664 -> 176888 (-4.21 %) bytes
Max Waves: 6260 -> 6260 (0.00 %)
Instructions: 35561 -> 33617 (-5.47 %)

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2883>

src/amd/compiler/aco_optimizer.cpp

index 605b06c5b1ab4858af17b18fca7457ff0eba0c59..19e78f9e656962fffcc608b1018a61e73038b080 100644 (file)
@@ -2353,7 +2353,7 @@ void select_instruction(opt_ctx &ctx, aco_ptr<Instruction>& instr)
       return;
    }
 
-   /* convert split_vector into extract_vector if only one definition is ever used */
+   /* convert split_vector into a copy or extract_vector if only one definition is ever used */
    if (instr->opcode == aco_opcode::p_split_vector) {
       unsigned num_used = 0;
       unsigned idx = 0;
@@ -2363,7 +2363,39 @@ void select_instruction(opt_ctx &ctx, aco_ptr<Instruction>& instr)
             idx = i;
          }
       }
-      if (num_used == 1) {
+      bool done = false;
+      if (num_used == 1 && ctx.info[instr->operands[0].tempId()].is_vec() &&
+          ctx.uses[instr->operands[0].tempId()] == 1) {
+         Instruction *vec = ctx.info[instr->operands[0].tempId()].instr;
+
+         unsigned off = 0;
+         Operand op;
+         for (Operand& vec_op : vec->operands) {
+            if (off == idx * instr->definitions[0].size()) {
+               op = vec_op;
+               break;
+            }
+            off += vec_op.size();
+         }
+         if (off != instr->operands[0].size()) {
+            ctx.uses[instr->operands[0].tempId()]--;
+            for (Operand& vec_op : vec->operands) {
+               if (vec_op.isTemp())
+                  ctx.uses[vec_op.tempId()]--;
+            }
+            if (op.isTemp())
+               ctx.uses[op.tempId()]++;
+
+            aco_ptr<Pseudo_instruction> extract{create_instruction<Pseudo_instruction>(aco_opcode::p_create_vector, Format::PSEUDO, 1, 1)};
+            extract->operands[0] = op;
+            extract->definitions[0] = instr->definitions[idx];
+            instr.reset(extract.release());
+
+            done = true;
+         }
+      }
+
+      if (!done && num_used == 1) {
          aco_ptr<Pseudo_instruction> extract{create_instruction<Pseudo_instruction>(aco_opcode::p_extract_vector, Format::PSEUDO, 2, 1)};
          extract->operands[0] = instr->operands[0];
          extract->operands[1] = Operand((uint32_t) idx);