aco: fix live-range splits of phis
authorDaniel Schürmann <daniel@schuermann.dev>
Tue, 29 Oct 2019 10:58:21 +0000 (11:58 +0100)
committerDaniel Schürmann <daniel@schuermann.dev>
Wed, 30 Oct 2019 19:48:33 +0000 (19:48 +0000)
Reviewed-by: Rhys Perry <pendingchaos02@gmail.com>
src/amd/compiler/aco_register_allocation.cpp

index 621bc1f7636cb972d9045b68f4b45a23a345e7a5..9e3d796dc2f55cccd67f40e4cce9408aee8465c3 100644 (file)
@@ -1272,6 +1272,29 @@ void register_allocation(Program *program, std::vector<std::set<Temp>> live_out_
 
             /* process parallelcopy */
             for (std::pair<Operand, Definition> pc : parallelcopy) {
+               /* see if it's a copy from a different phi */
+               //TODO: prefer moving some previous phis over live-ins
+               //TODO: somehow prevent phis fixed before the RA from being updated (shouldn't be a problem in practice since they can only be fixed to exec)
+               Instruction *prev_phi = NULL;
+               std::vector<aco_ptr<Instruction>>::iterator phi_it;
+               for (phi_it = instructions.begin(); phi_it != instructions.end(); ++phi_it) {
+                  if ((*phi_it)->definitions[0].tempId() == pc.first.tempId())
+                     prev_phi = phi_it->get();
+               }
+               phi_it = it;
+               while (!prev_phi && is_phi(*++phi_it)) {
+                  if ((*phi_it)->definitions[0].tempId() == pc.first.tempId())
+                     prev_phi = phi_it->get();
+               }
+               if (prev_phi) {
+                  /* if so, just update that phi's register */
+                  prev_phi->definitions[0].setFixed(pc.second.physReg());
+                  ctx.assignments[prev_phi->definitions[0].tempId()] = {pc.second.physReg(), pc.second.regClass()};
+                  for (unsigned reg = pc.second.physReg(); reg < pc.second.physReg() + pc.second.size(); reg++)
+                     register_file[reg] = prev_phi->definitions[0].tempId();
+                  continue;
+               }
+
                /* rename */
                std::map<unsigned, Temp>::iterator orig_it = ctx.orig_names.find(pc.first.tempId());
                Temp orig = pc.first.getTemp();
@@ -1282,20 +1305,6 @@ void register_allocation(Program *program, std::vector<std::set<Temp>> live_out_
                renames[block.index][orig.id()] = pc.second.getTemp();
                renames[block.index][pc.second.tempId()] = pc.second.getTemp();
 
-               /* see if it's a copy from a previous phi */
-               //TODO: prefer moving some previous phis over live-ins
-               //TODO: somehow prevent phis fixed before the RA from being updated (shouldn't be a problem in practice since they can only be fixed to exec)
-               Instruction *prev_phi = NULL;
-               for (auto it2 = instructions.begin(); it2 != instructions.end(); ++it2) {
-                  if ((*it2)->definitions[0].tempId() == pc.first.tempId())
-                     prev_phi = it2->get();
-               }
-               if (prev_phi) {
-                  /* if so, just update that phi */
-                  prev_phi->definitions[0] = pc.second;
-                  continue;
-               }
-
                /* otherwise, this is a live-in and we need to create a new phi
                 * to move it in this block's predecessors */
                aco_opcode opcode = pc.first.getTemp().is_linear() ? aco_opcode::p_linear_phi : aco_opcode::p_phi;