]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
IRA: Check that reg classes contain a hard reg of given mode in reg move cost calculation
authorVladimir N. Makarov <vmakarov@redhat.com>
Thu, 15 Dec 2022 19:11:05 +0000 (14:11 -0500)
committerVladimir N. Makarov <vmakarov@redhat.com>
Thu, 15 Dec 2022 19:19:19 +0000 (14:19 -0500)
IRA calculates wrong AVR costs for moving general hard regs of SFmode.  To
calculate the costs we did not exclude sub-classes which do not contain
hard regs of given mode.  This was the reason for spilling a pseudo in the
PR. The patch fixes this.

        PR rtl-optimization/90706

gcc/ChangeLog:

* ira-costs.cc: Include print-rtl.h.
(record_reg_classes, scan_one_insn): Add code to print debug info.
* ira.cc (ira_init_register_move_cost): Check that at least one hard
reg of the mode are in the class contents to calculate the
register move costs.

gcc/testsuite/ChangeLog:

* gcc.target/avr/pr90706.c: New.

gcc/ira-costs.cc
gcc/ira.cc
gcc/testsuite/gcc.target/avr/pr90706.c [new file with mode: 0644]

index 964c94a06ef56e27d0134a66eee7f60700ecfbab..732a0edd4c1d26c517046fa17942964d1df42696 100644 (file)
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ira-int.h"
 #include "addresses.h"
 #include "reload.h"
+#include "print-rtl.h"
 
 /* The flags is set up every time when we calculate pseudo register
    classes through function ira_set_pseudo_classes.  */
@@ -503,6 +504,18 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
   int insn_allows_mem[MAX_RECOG_OPERANDS];
   move_table *move_in_cost, *move_out_cost;
   short (*mem_cost)[2];
+  const char *p;
+
+  if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
+    {
+      fprintf (ira_dump_file, "    Processing insn %u", INSN_UID (insn));
+      if (INSN_CODE (insn) >= 0
+         && (p = get_insn_name (INSN_CODE (insn))) != NULL)
+       fprintf (ira_dump_file, " {%s}", p);
+      fprintf (ira_dump_file, " (freq=%d)\n",
+              REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)));
+      dump_insn_slim (ira_dump_file, insn);
+  }
 
   for (i = 0; i < n_ops; i++)
     insn_allows_mem[i] = 0;
@@ -526,6 +539,21 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
          continue;
        }
 
+      if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
+       {
+         fprintf (ira_dump_file, "      Alt %d:", alt);
+         for (i = 0; i < n_ops; i++)
+           {
+             p = constraints[i];
+             if (*p == '\0')
+               continue;
+             fprintf (ira_dump_file, "  (%d) ", i);
+             for (; *p != '\0' && *p != ',' && *p != '#'; p++)
+               fputc (*p, ira_dump_file);
+           }
+         fprintf (ira_dump_file, "\n");
+       }
+      
       for (i = 0; i < n_ops; i++)
        {
          unsigned char c;
@@ -593,12 +621,16 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                     register, this alternative can't be used.  */
 
                  if (classes[j] == NO_REGS)
-                   alt_fail = 1;
-                 /* Otherwise, add to the cost of this alternative
-                    the cost to copy the other operand to the hard
-                    register used for this operand.  */
+                   {
+                     alt_fail = 1;
+                   }
                  else
-                   alt_cost += copy_cost (ops[j], mode, classes[j], 1, NULL);
+                   /* Otherwise, add to the cost of this alternative the cost
+                      to copy the other operand to the hard register used for
+                      this operand.  */
+                   {
+                     alt_cost += copy_cost (ops[j], mode, classes[j], 1, NULL);
+                   }
                }
              else
                {
@@ -1021,18 +1053,45 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
       for (i = 0; i < n_ops; i++)
        if (REG_P (ops[i]) && REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)
          {
+           int old_cost;
+           bool cost_change_p = false;
            struct costs *pp = op_costs[i], *qq = this_op_costs[i];
            int *pp_costs = pp->cost, *qq_costs = qq->cost;
            int scale = 1 + (recog_data.operand_type[i] == OP_INOUT);
            cost_classes_t cost_classes_ptr
              = regno_cost_classes[REGNO (ops[i])];
 
-           pp->mem_cost = MIN (pp->mem_cost,
+           old_cost = pp->mem_cost;
+           pp->mem_cost = MIN (old_cost,
                                (qq->mem_cost + op_cost_add) * scale);
 
+           if (ira_dump_file != NULL && internal_flag_ira_verbose > 5
+               && pp->mem_cost < old_cost)
+             {
+               cost_change_p = true;
+               fprintf (ira_dump_file, "        op %d(r=%u) new costs MEM:%d",
+                        i, REGNO(ops[i]), pp->mem_cost);
+             }
            for (k = cost_classes_ptr->num - 1; k >= 0; k--)
-             pp_costs[k]
-               = MIN (pp_costs[k], (qq_costs[k] + op_cost_add) * scale);
+             {
+               old_cost = pp_costs[k];
+               pp_costs[k]
+                 = MIN (old_cost, (qq_costs[k] + op_cost_add) * scale);
+               if (ira_dump_file != NULL && internal_flag_ira_verbose > 5
+                   && pp_costs[k] < old_cost)
+                 {
+                   if (!cost_change_p)
+                     fprintf (ira_dump_file, "        op %d(r=%u) new costs",
+                              i, REGNO(ops[i]));
+                   cost_change_p = true;
+                   fprintf (ira_dump_file, " %s:%d",
+                            reg_class_names[cost_classes_ptr->classes[k]],
+                            pp_costs[k]);
+                 }
+             }
+           if (ira_dump_file != NULL && internal_flag_ira_verbose > 5
+               && cost_change_p)
+             fprintf (ira_dump_file, "\n");
          }
     }
 
@@ -1506,6 +1565,18 @@ scan_one_insn (rtx_insn *insn)
 
   record_operand_costs (insn, pref);
 
+  if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
+    {
+      const char *p;
+      fprintf (ira_dump_file, "    Final costs after insn %u", INSN_UID (insn));
+      if (INSN_CODE (insn) >= 0
+         && (p = get_insn_name (INSN_CODE (insn))) != NULL)
+       fprintf (ira_dump_file, " {%s}", p);
+      fprintf (ira_dump_file, " (freq=%d)\n",
+              REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)));
+      dump_insn_slim (ira_dump_file, insn);
+    }
+
   /* Now add the cost for each operand to the total costs for its
      allocno.  */
   for (i = 0; i < recog_data.n_operands; i++)
@@ -1521,7 +1592,7 @@ scan_one_insn (rtx_insn *insn)
          struct costs *q = op_costs[i];
          int *p_costs = p->cost, *q_costs = q->cost;
          cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
-         int add_cost;
+         int add_cost = 0;
          
          /* If the already accounted for the memory "cost" above, don't
             do so again.  */
@@ -1533,6 +1604,11 @@ scan_one_insn (rtx_insn *insn)
              else
                p->mem_cost += add_cost;
            }
+         if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
+           {
+             fprintf (ira_dump_file, "        op %d(r=%u) MEM:%d(+%d)",
+                      i, REGNO(op), p->mem_cost, add_cost);
+           }
          for (k = cost_classes_ptr->num - 1; k >= 0; k--)
            {
              add_cost = q_costs[k];
@@ -1540,7 +1616,15 @@ scan_one_insn (rtx_insn *insn)
                p_costs[k] = INT_MAX;
              else
                p_costs[k] += add_cost;
+             if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
+               {
+                 fprintf (ira_dump_file, " %s:%d(+%d)",
+                          reg_class_names[cost_classes_ptr->classes[k]],
+                          p_costs[k], add_cost);
+               }
            }
+         if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
+           fprintf (ira_dump_file, "\n");
        }
     }
   return insn;
index d28a67b2546f1a160761ba342e4e98151af43e84..cb4bfca739d42c979022fbc65df6a4c42c4fed1b 100644 (file)
@@ -1627,14 +1627,22 @@ ira_init_register_move_cost (machine_mode mode)
                 *p2 != LIM_REG_CLASSES; p2++)
              if (ira_class_hard_regs_num[*p2] > 0
                  && (ira_reg_class_max_nregs[*p2][mode]
-                     <= ira_class_hard_regs_num[*p2]))
+                     <= ira_class_hard_regs_num[*p2])
+                 && hard_reg_set_intersect_p (ok_regs,
+                                              reg_class_contents[cl1])
+                 && hard_reg_set_intersect_p (ok_regs,
+                                              reg_class_contents[*p2]))
                cost = MAX (cost, ira_register_move_cost[mode][cl1][*p2]);
            
            for (p1 = &reg_class_subclasses[cl1][0];
                 *p1 != LIM_REG_CLASSES; p1++)
              if (ira_class_hard_regs_num[*p1] > 0
                  && (ira_reg_class_max_nregs[*p1][mode]
-                     <= ira_class_hard_regs_num[*p1]))
+                     <= ira_class_hard_regs_num[*p1])
+                 && hard_reg_set_intersect_p (ok_regs,
+                                              reg_class_contents[cl2])
+                 && hard_reg_set_intersect_p (ok_regs,
+                                              reg_class_contents[*p1]))
                cost = MAX (cost, ira_register_move_cost[mode][*p1][cl2]);
            
            ira_assert (cost <= 65535);
diff --git a/gcc/testsuite/gcc.target/avr/pr90706.c b/gcc/testsuite/gcc.target/avr/pr90706.c
new file mode 100644 (file)
index 0000000..4b9bcbe
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+unsigned char check(float x)
+{
+   return (0.0 < x);
+}
+ /* { dg-final { scan-assembler-not "ldd" } } */
+ /* { dg-final { scan-assembler-not "std" } } */