2015-07-16 Vladimir Makarov <vmakarov@redhat.com>
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Jul 2015 15:26:35 +0000 (15:26 +0000)
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Jul 2015 15:26:35 +0000 (15:26 +0000)
PR rtl-optimization/66626
* ira.h (emit-rtl.h): Include.
(non_spilled_static_chain_regno_p): New.
* ira-color.c (setup_profitable_hard_regs): Clear profitable regs
unless it is non spilled static chain pseudo.
(assign_hard_rego): Spill memory profitable allocno unless it is
non spilled static chain pseudo.
(allocno_spill_priority_compare): Put non spilled static chain
pseudo at the end of sorted array.
(improve_allocation): Do nothing if we have static chain and
non-local goto.
(allocno__priority_compare_func): Put non spilled static chain
pseudo at the beginning of sorted array.
(move_spill_restore): Ignore non spilled static chain pseudo.
* ira-costs.c (find_costs_and_classes): Don't assign class NO_REGS
to non spilled static chain pseudo.
* lra-assigns.c (pseudo_compare_func): Put non spilled static chain
pseudo at the beginning of sorted array.
(spill_for): Spill non spilled static chain pseudo last.
* lra-constraints.c (lra_constraints): Remove static chain pseudo
check for equivalence.

2015-07-16  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/66626
* gcc.target/i386/pr66626-2.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@225891 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ira-color.c
gcc/ira-costs.c
gcc/ira.h
gcc/lra-assigns.c
gcc/lra-constraints.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr66626-2.c [new file with mode: 0644]

index fa938d8..a7949ec 100644 (file)
@@ -1,3 +1,27 @@
+2015-07-16  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/66626
+       * ira.h (emit-rtl.h): Include.
+       (non_spilled_static_chain_regno_p): New.
+       * ira-color.c (setup_profitable_hard_regs): Clear profitable regs
+       unless it is non spilled static chain pseudo.
+       (assign_hard_rego): Spill memory profitable allocno unless it is
+       non spilled static chain pseudo.
+       (allocno_spill_priority_compare): Put non spilled static chain
+       pseudo at the end of sorted array.
+       (improve_allocation): Do nothing if we have static chain and
+       non-local goto.
+       (allocno__priority_compare_func): Put non spilled static chain
+       pseudo at the beginning of sorted array.
+       (move_spill_restore): Ignore non spilled static chain pseudo.
+       * ira-costs.c (find_costs_and_classes): Don't assign class NO_REGS
+       to non spilled static chain pseudo.
+       * lra-assigns.c (pseudo_compare_func): Put non spilled static chain
+       pseudo at the beginning of sorted array.
+       (spill_for): Spill non spilled static chain pseudo last.
+       * lra-constraints.c (lra_constraints): Remove static chain pseudo
+       check for equivalence.
+
 2015-07-16  Martin Liska  <mliska@suse.cz>
 
        PR ipa/66896.
index b2b1b7e..74d2c2e 100644 (file)
@@ -1044,7 +1044,10 @@ setup_profitable_hard_regs (void)
        continue;
       data = ALLOCNO_COLOR_DATA (a);
       if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
-         && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a))
+         && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a)
+         /* Do not empty profitable regs for static chain pointer
+            pseudo when non-local goto is used.  */
+         && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
        CLEAR_HARD_REG_SET (data->profitable_hard_regs);
       else
        {
@@ -1126,7 +1129,10 @@ setup_profitable_hard_regs (void)
              if (! TEST_HARD_REG_BIT (data->profitable_hard_regs,
                                       hard_regno))
                continue;
-             if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j])
+             if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j]
+                 /* Do not remove HARD_REGNO for static chain pointer
+                    pseudo when non-local goto is used.  */
+                 && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
                CLEAR_HARD_REG_BIT (data->profitable_hard_regs,
                                    hard_regno);
              else if (min_cost > costs[j])
@@ -1134,7 +1140,10 @@ setup_profitable_hard_regs (void)
            }
        }
       else if (ALLOCNO_UPDATED_MEMORY_COST (a)
-              < ALLOCNO_UPDATED_CLASS_COST (a))
+              < ALLOCNO_UPDATED_CLASS_COST (a)
+              /* Do not empty profitable regs for static chain
+                 pointer pseudo when non-local goto is used.  */
+              && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
        CLEAR_HARD_REG_SET (data->profitable_hard_regs);
       if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
        ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
@@ -1854,7 +1863,10 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
          ira_assert (hard_regno >= 0);
        }
     }
-  if (min_full_cost > mem_cost)
+  if (min_full_cost > mem_cost
+      /* Do not spill static chain pointer pseudo when non-local goto
+        is used.  */
+      && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
     {
       if (! retry_p && internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
        fprintf (ira_dump_file, "(memory is more profitable %d vs %d) ",
@@ -2480,6 +2492,12 @@ allocno_spill_priority_compare (ira_allocno_t a1, ira_allocno_t a2)
 {
   int pri1, pri2, diff;
 
+  /* Avoid spilling static chain pointer pseudo when non-local goto is
+     used.  */
+  if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))
+    return 1;
+  else if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2)))
+    return -1;
   if (ALLOCNO_BAD_SPILL_P (a1) && ! ALLOCNO_BAD_SPILL_P (a2))
     return 1;
   if (ALLOCNO_BAD_SPILL_P (a2) && ! ALLOCNO_BAD_SPILL_P (a1))
@@ -2732,6 +2750,11 @@ improve_allocation (void)
   ira_allocno_t a;
   bitmap_iterator bi;
 
+  /* Don't bother to optimize the code with static chain pointer and
+     non-local goto in order not to spill the chain pointer
+     pseudo.  */
+  if (cfun->static_chain_decl && crtl->has_nonlocal_goto)
+    return;
   /* Clear counts used to process conflicting allocnos only once for
      each allocno.  */
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
@@ -2938,6 +2961,12 @@ allocno_priority_compare_func (const void *v1p, const void *v2p)
   ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
   int pri1, pri2;
 
+  /* Assign hard reg to static chain pointer pseudo first when
+     non-local goto is used.  */
+  if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))
+    return 1;
+  else if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2)))
+    return -1;
   pri1 = allocno_priorities[ALLOCNO_NUM (a1)];
   pri2 = allocno_priorities[ALLOCNO_NUM (a2)];
   if (pri2 != pri1)
@@ -3379,7 +3408,10 @@ move_spill_restore (void)
                 by copy although the allocno will not get memory
                 slot.  */
              || ira_equiv_no_lvalue_p (regno)
-             || !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a)))
+             || !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a))
+             /* Do not spill static chain pointer pseudo when
+                non-local goto is used.  */
+             || non_spilled_static_chain_regno_p (regno))
            continue;
          mode = ALLOCNO_MODE (a);
          rclass = ALLOCNO_CLASS (a);
index 0a5b1e1..eded4d9 100644 (file)
@@ -1836,7 +1836,8 @@ find_costs_and_classes (FILE *dump_file)
                alt_class = reg_class_subunion[alt_class][rclass];
            }
          alt_class = ira_allocno_class_translate[alt_class];
-         if (best_cost > i_mem_cost)
+         if (best_cost > i_mem_cost
+             && ! non_spilled_static_chain_regno_p (i))
            regno_aclass[i] = NO_REGS;
          else if (!optimize && !targetm.class_likely_spilled_p (best))
            /* Registers in the alternative class are likely to need
@@ -1875,7 +1876,10 @@ find_costs_and_classes (FILE *dump_file)
            }
          if (pass == flag_expensive_optimizations)
            {
-             if (best_cost > i_mem_cost)
+             if (best_cost > i_mem_cost
+                 /* Do not assign NO_REGS to static chain pointer
+                    pseudo when non-local goto is used.  */
+                 && ! non_spilled_static_chain_regno_p (i))
                best = alt_class = NO_REGS;
              else if (best == alt_class)
                alt_class = NO_REGS;
@@ -1890,7 +1894,9 @@ find_costs_and_classes (FILE *dump_file)
          regno_best_class[i] = best;
          if (! allocno_p)
            {
-             pref[i] = best_cost > i_mem_cost ? NO_REGS : best;
+             pref[i] = (best_cost > i_mem_cost
+                        && ! non_spilled_static_chain_regno_p (i)
+                        ? NO_REGS : best);
              continue;
            }
          for (a = ira_regno_allocno_map[i];
index 5b52cb1..504b5e6 100644 (file)
--- a/gcc/ira.h
+++ b/gcc/ira.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_IRA_H
 #define GCC_IRA_H
 
+#include "emit-rtl.h"
+
 /* True when we use LRA instead of reload pass for the current
    function.  */
 extern bool ira_use_lra_p;
@@ -209,4 +211,15 @@ extern void ira_adjust_equiv_reg_cost (unsigned, int);
 /* ira-costs.c */
 extern void ira_costs_c_finalize (void);
 
+/* Spilling static chain pseudo may result in generation of wrong
+   non-local goto code using frame-pointer to address saved stack
+   pointer value after restoring old frame pointer value.  The
+   function returns TRUE if REGNO is such a static chain pseudo.  */
+static inline bool
+non_spilled_static_chain_regno_p (int regno)
+{
+  return (cfun->static_chain_decl && crtl->has_nonlocal_goto
+         && REG_EXPR (regno_reg_rtx[regno]) == cfun->static_chain_decl);
+}
+
 #endif /* GCC_IRA_H */
index 839036c..2986f57 100644 (file)
@@ -255,6 +255,13 @@ pseudo_compare_func (const void *v1p, const void *v2p)
   int r1 = *(const int *) v1p, r2 = *(const int *) v2p;
   int diff;
 
+  /* Assign hard reg to static chain pointer first pseudo when
+     non-local goto is used.  */
+  if (non_spilled_static_chain_regno_p (r1))
+    return -1;
+  else if (non_spilled_static_chain_regno_p (r2))
+    return 1;
+
   /* Prefer to assign more frequently used registers first.  */
   if ((diff = lra_reg_info[r2].freq - lra_reg_info[r1].freq) != 0)
     return diff;
@@ -892,6 +899,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
 {
   int i, j, n, p, hard_regno, best_hard_regno, cost, best_cost, rclass_size;
   int reload_hard_regno, reload_cost;
+  bool static_p, best_static_p;
   machine_mode mode;
   enum reg_class rclass;
   unsigned int spill_regno, reload_regno, uid;
@@ -914,6 +922,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
     }
   best_hard_regno = -1;
   best_cost = INT_MAX;
+  best_static_p = TRUE;
   best_insn_pseudos_num = INT_MAX;
   smallest_bad_spills_num = INT_MAX;
   rclass_size = ira_class_hard_regs_num[rclass];
@@ -936,6 +945,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
                           &try_hard_reg_pseudos[hard_regno + j]);
        }
       /* Spill pseudos.         */
+      static_p = false;
       EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
        if ((pic_offset_table_rtx != NULL
             && spill_regno == REGNO (pic_offset_table_rtx))
@@ -945,6 +955,8 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
                && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno)
                && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno)))
          goto fail;
+       else if (non_spilled_static_chain_regno_p (spill_regno))
+         static_p = true;
       insn_pseudos_num = 0;
       bad_spills_num = 0;
       if (lra_dump_file != NULL)
@@ -1024,14 +1036,19 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
                     x = x->next ())
                  cost -= REG_FREQ_FROM_BB (BLOCK_FOR_INSN (x->insn ()));
            }
-         if (best_insn_pseudos_num > insn_pseudos_num
-             || (best_insn_pseudos_num == insn_pseudos_num
-                 && (bad_spills_num < smallest_bad_spills_num
-                     || (bad_spills_num == smallest_bad_spills_num
-                         && best_cost > cost))))
+         /* Avoid spilling static chain pointer pseudo when non-local
+            goto is used.  */
+         if ((! static_p && best_static_p)
+             || (static_p == best_static_p
+                 && (best_insn_pseudos_num > insn_pseudos_num
+                     || (best_insn_pseudos_num == insn_pseudos_num
+                         && (bad_spills_num < smallest_bad_spills_num
+                             || (bad_spills_num == smallest_bad_spills_num
+                                 && best_cost > cost))))))
            {
              best_insn_pseudos_num = insn_pseudos_num;
              smallest_bad_spills_num = bad_spills_num;
+             best_static_p = static_p;
              best_cost = cost;
              best_hard_regno = hard_regno;
              bitmap_copy (&best_spill_pseudos_bitmap, &spill_pseudos_bitmap);
index 58a388f..ddb91dd 100644 (file)
@@ -4306,13 +4306,7 @@ lra_constraints (bool first_p)
                    && ((CONST_POOL_OK_P (PSEUDO_REGNO_MODE (i), x)
                         && (targetm.preferred_reload_class
                             (x, lra_get_allocno_class (i)) == NO_REGS))
-                       || contains_symbol_ref_p (x)))
-               /* Static chain equivalence may contain eliminable
-                  regs and the result of elimination might be wrong
-                  after restoring frame pointer for a nonlocal
-                  goto.  */
-               || (cfun->static_chain_decl && crtl->has_nonlocal_goto
-                   && REG_EXPR (reg) == cfun->static_chain_decl))
+                       || contains_symbol_ref_p (x))))
              ira_reg_equiv[i].defined_p = false;
            if (contains_reg_p (x, false, true))
              ira_reg_equiv[i].profitable_p = false;
index aa807cc..527fe0f 100644 (file)
@@ -1,3 +1,8 @@
+2015-07-16  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/66626
+       * gcc.target/i386/pr66626-2.c: New.
+
 2015-07-16  Martin Liska  <mliska@suse.cz>
 
        * g++.dg/ipa/pr66896.c: New test.
diff --git a/gcc/testsuite/gcc.target/i386/pr66626-2.c b/gcc/testsuite/gcc.target/i386/pr66626-2.c
new file mode 100644 (file)
index 0000000..feba6a6
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mregparm=3" } */
+/* { dg-require-effective-target ia32 } */
+extern void abort (void);
+
+int s (int i)
+{
+  __label__ l1;
+  int f (int i)
+  {
+    if (i == 2)
+      goto l1;
+    return 0;
+  }
+  return f (i);
+ l1:;
+  return 1;
+}
+
+int main ()
+{
+  if (s (2) != 1)
+    abort ();
+
+  return 0;
+}