aco: coalesce copies more aggressively when lowering to hw
authorDaniel Schürmann <daniel@schuermann.dev>
Thu, 7 May 2020 17:15:59 +0000 (18:15 +0100)
committerMarge Bot <eric+marge@anholt.net>
Tue, 9 Jun 2020 21:25:38 +0000 (21:25 +0000)
Helps some Detroit : Become Human shaders.

Totals from affected shaders: (VEGA)
Code Size: 9880420 -> 9879088 (-0.01 %) bytes
Instructions: 1918553 -> 1918220 (-0.02 %)
Copies: 177783 -> 177450 (-0.19 %)

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

src/amd/compiler/aco_lower_to_hw_instr.cpp

index b0b8701720b94ccb9606517695fb1e0cbc2b5418..323dfdadf9854cbda9a46fc9cb8e36ee4964f802 100644 (file)
@@ -1223,6 +1223,26 @@ void handle_operands(std::map<PhysReg, copy_operation>& copy_map, lower_context*
          it->second.bytes = 8;
       }
 
+      /* try to coalesce copies */
+      if (it->second.bytes < 8 && !it->second.op.isConstant() &&
+          it->first.reg_b % util_next_power_of_two(it->second.bytes + 1) == 0 &&
+          it->second.op.physReg().reg_b % util_next_power_of_two(it->second.bytes + 1) == 0) {
+         // TODO try more relaxed alignment for subdword copies
+         PhysReg other_def_reg = it->first;
+         other_def_reg.reg_b += it->second.bytes;
+         PhysReg other_op_reg = it->second.op.physReg();
+         other_op_reg.reg_b += it->second.bytes;
+         std::map<PhysReg, copy_operation>::iterator other = copy_map.find(other_def_reg);
+         if (other != copy_map.end() &&
+             other->second.op.physReg() == other_op_reg &&
+             it->second.bytes + other->second.bytes <= 8) {
+            it->second.bytes += other->second.bytes;
+            it->second.def = Definition(it->first, RegClass::get(it->second.def.regClass().type(), it->second.bytes));
+            it->second.op = Operand(it->second.op.physReg(), RegClass::get(it->second.op.regClass().type(), it->second.bytes));
+            copy_map.erase(other);
+         }
+      }
+
       /* check if the definition reg is used by another copy operation */
       for (std::pair<const PhysReg, copy_operation>& copy : copy_map) {
          if (copy.second.op.isConstant())