Don't propagate for a more expensive reg-reg move.
authorliuhongt <hongtao.liu@intel.com>
Mon, 24 Jan 2022 10:17:47 +0000 (18:17 +0800)
committerliuhongt <hongtao.liu@intel.com>
Tue, 8 Feb 2022 04:39:31 +0000 (12:39 +0800)
For i386, it enables optimization like:

        vmovd   %xmm0, %edx
-       vmovd   %xmm0, %eax
+       movl    %edx, %eax

gcc/ChangeLog:

PR rtl-optimization/104059
* regcprop.cc (copyprop_hardreg_forward_1): Don't propagate
for a more expensive reg-reg move.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr104059.c: New test.

gcc/regcprop.cc
gcc/testsuite/gcc.target/i386/pr104059.c [new file with mode: 0644]

index 8e966f2..1fdc367 100644 (file)
@@ -892,6 +892,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
       if (set && REG_P (SET_SRC (set)))
        {
          rtx src = SET_SRC (set);
+         rtx dest = SET_DEST (set);
          unsigned int regno = REGNO (src);
          machine_mode mode = GET_MODE (src);
          unsigned int i;
@@ -915,7 +916,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
 
          /* If the destination is also a register, try to find a source
             register in the same class.  */
-         if (REG_P (SET_DEST (set)))
+         if (REG_P (dest))
            {
              new_rtx = find_oldest_value_reg (REGNO_REG_CLASS (regno),
                                               src, vd);
@@ -943,6 +944,20 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
                                       mode, i, regno);
              if (new_rtx != NULL_RTX)
                {
+                 /* Don't propagate for a more expensive reg-reg move.  */
+                 if (REG_P (dest))
+                   {
+                     enum reg_class from = REGNO_REG_CLASS (regno);
+                     enum reg_class to = REGNO_REG_CLASS (REGNO (dest));
+                     enum reg_class new_from = REGNO_REG_CLASS (i);
+                     unsigned int original_cost
+                       = targetm.register_move_cost (mode, from, to);
+                     unsigned int after_cost
+                       = targetm.register_move_cost (mode, new_from, to);
+                     if (after_cost > original_cost)
+                       continue;
+                   }
+
                  if (validate_change (insn, &SET_SRC (set), new_rtx, 0))
                    {
                      ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (src);
diff --git a/gcc/testsuite/gcc.target/i386/pr104059.c b/gcc/testsuite/gcc.target/i386/pr104059.c
new file mode 100644 (file)
index 0000000..4815fa3
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx2 -O2 -fdump-rtl-cprop_hardreg-details" } */
+/* { dg-final { scan-rtl-dump-not {replaced reg [0-9]* with [0-9]*} "cprop_hardreg" } } */
+
+#include<stdint.h>
+int test (uint8_t *p, uint32_t t[1][1], int n) {
+
+  int sum = 0;
+  uint32_t a0;
+  for (int i = 0; i < 4; i++, p++)
+    t[i][0] = p[0];
+
+  for (int i = 0; i < 4; i++) {
+    {
+      int t0 = t[0][i] + t[0][i];
+      a0 = t0;
+    };
+    sum += a0;
+  }
+  return (((uint16_t)sum) + ((uint32_t)sum >> 16)) >> 1;
+}
+