aco: handle phi affinities transitively through parallelcopies
authorDaniel Schürmann <daniel@schuermann.dev>
Mon, 13 Jan 2020 14:13:19 +0000 (15:13 +0100)
committerDaniel Schürmann <daniel@schuermann.dev>
Thu, 16 Jan 2020 15:01:59 +0000 (16:01 +0100)
This can coalesce most unnecessarily inserted parallelcopies
from lowering to CSSA.

v2: refactor loop a bit to make it more efficient and readable.

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

src/amd/compiler/aco_register_allocation.cpp

index a137a952d4325d62d30f73831fe12972b674564e..ec8838d97edd8d0b28e3591a94f7919cce92d6f2 100644 (file)
@@ -1112,18 +1112,10 @@ void register_allocation(Program *program, std::vector<std::set<Temp>> live_out_
       std::vector<aco_ptr<Instruction>>::reverse_iterator rit;
       for (rit = block.instructions.rbegin(); rit != block.instructions.rend(); ++rit) {
          aco_ptr<Instruction>& instr = *rit;
-         if (!is_phi(instr)) {
-            for (const Operand& op : instr->operands) {
-               if (op.isTemp())
-                  live.emplace(op.getTemp());
-            }
-            if (instr->opcode == aco_opcode::p_create_vector) {
-               for (const Operand& op : instr->operands) {
-                  if (op.isTemp() && op.getTemp().type() == instr->definitions[0].getTemp().type())
-                     vectors[op.tempId()] = instr.get();
-               }
-            }
-         } else if (!instr->definitions[0].isKill() && !instr->definitions[0].isFixed()) {
+         if (is_phi(instr)) {
+            live.erase(instr->definitions[0].getTemp());
+            if (instr->definitions[0].isKill() || instr->definitions[0].isFixed())
+               continue;
             /* collect information about affinity-related temporaries */
             std::vector<Temp> affinity_related;
             /* affinity_related[0] is the last seen affinity-related temp */
@@ -1136,15 +1128,41 @@ void register_allocation(Program *program, std::vector<std::set<Temp>> live_out_
                }
             }
             phi_ressources.emplace_back(std::move(affinity_related));
+            continue;
          }
 
-         /* erase from live */
-         for (const Definition& def : instr->definitions) {
-            if (def.isTemp()) {
-               live.erase(def.getTemp());
-               std::map<unsigned, unsigned>::iterator it = temp_to_phi_ressources.find(def.tempId());
-               if (it != temp_to_phi_ressources.end() && def.regClass() == phi_ressources[it->second][0].regClass())
-                  phi_ressources[it->second][0] = def.getTemp();
+         /* add vector affinities */
+         if (instr->opcode == aco_opcode::p_create_vector) {
+            for (const Operand& op : instr->operands) {
+               if (op.isTemp() && op.getTemp().type() == instr->definitions[0].getTemp().type())
+                  vectors[op.tempId()] = instr.get();
+            }
+         }
+
+         /* add operands to live variables */
+         for (const Operand& op : instr->operands) {
+            if (op.isTemp())
+               live.emplace(op.getTemp());
+         }
+
+         /* erase definitions from live */
+         for (unsigned i = 0; i < instr->definitions.size(); i++) {
+            const Definition& def = instr->definitions[i];
+            if (!def.isTemp())
+               continue;
+            live.erase(def.getTemp());
+            /* mark last-seen phi operand */
+            std::map<unsigned, unsigned>::iterator it = temp_to_phi_ressources.find(def.tempId());
+            if (it != temp_to_phi_ressources.end() && def.regClass() == phi_ressources[it->second][0].regClass()) {
+               phi_ressources[it->second][0] = def.getTemp();
+               /* try to coalesce phi affinities with parallelcopies */
+               if (!def.isFixed() && instr->opcode == aco_opcode::p_parallelcopy) {
+                  Operand op = instr->operands[i];
+                  if (op.isTemp() && op.isFirstKill() && def.regClass() == op.regClass()) {
+                     phi_ressources[it->second].emplace_back(op.getTemp());
+                     temp_to_phi_ressources[op.tempId()] = it->second;
+                  }
+               }
             }
          }
       }