re PR rtl-optimization/23478 (Miscompilation due to reloading of a var that is also...
authorJakub Jelinek <jakub@redhat.com>
Thu, 1 Sep 2005 05:29:03 +0000 (07:29 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 1 Sep 2005 05:29:03 +0000 (07:29 +0200)
PR rtl-optimization/23478
* local-alloc.c (struct qty): Add n_throwing_calls_crossed field.
(alloc_qty): Initialize it.
(update_equiv_regs): Clear REG_N_THROWING_CALLS_CROSSED.
(combine_regs): Combine also n_throwing_calls_crossed fields.
(find_free_reg): Don't attempt to caller-save pseudos crossing
calls that might throw.
* global.c (struct allocno): Add throwing_calls_crossed field.
(global_alloc): Revert 2005-08-22 change.  Initialize
throwing_calls_crossed.
(find_reg): Don't attempt to caller-save pseudos crossing calls that
might throw.

From-SVN: r103718

gcc/ChangeLog
gcc/global.c
gcc/local-alloc.c

index 0d1946573d4c18bc60df350f466f1b97b7d9216d..b30b116d4f104c8b212049c2e3c9493b8cce9e93 100644 (file)
@@ -1,3 +1,18 @@
+2005-09-01  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/23478
+       * local-alloc.c (struct qty): Add n_throwing_calls_crossed field.
+       (alloc_qty): Initialize it.
+       (update_equiv_regs): Clear REG_N_THROWING_CALLS_CROSSED.
+       (combine_regs): Combine also n_throwing_calls_crossed fields.
+       (find_free_reg): Don't attempt to caller-save pseudos crossing
+       calls that might throw.
+       * global.c (struct allocno): Add throwing_calls_crossed field.
+       (global_alloc): Revert 2005-08-22 change.  Initialize
+       throwing_calls_crossed.
+       (find_reg): Don't attempt to caller-save pseudos crossing calls that
+       might throw.
+
 2005-09-01  Alan Modra  <amodra@bigpond.net.au>
 
        PR target/23649
index f82cd08017a15b8465778ef34133a5f75318400b..d4e2b773559d592ec957ac16f18ae3f928f10d0c 100644 (file)
@@ -97,6 +97,9 @@ struct allocno
   /* Number of calls crossed by each allocno.  */
   int calls_crossed;
 
+  /* Number of calls that might throw crossed by each allocno.  */
+  int throwing_calls_crossed;
+
   /* Number of refs to each allocno.  */
   int n_refs;
 
@@ -465,9 +468,7 @@ global_alloc (FILE *file)
        /* Don't allocate pseudos that cross calls,
           if this function receives a nonlocal goto.  */
        && (! current_function_has_nonlocal_label
-           || REG_N_CALLS_CROSSED (i) == 0)
-       /* Don't allocate pseudos that cross calls that may throw.  */
-       && REG_N_THROWING_CALLS_CROSSED (i) == 0)
+           || REG_N_CALLS_CROSSED (i) == 0))
       {
        if (reg_renumber[i] < 0
            && reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
@@ -488,6 +489,8 @@ global_alloc (FILE *file)
        allocno[num].reg = i;
        allocno[num].size = PSEUDO_REGNO_SIZE (i);
        allocno[num].calls_crossed += REG_N_CALLS_CROSSED (i);
+       allocno[num].throwing_calls_crossed
+         += REG_N_THROWING_CALLS_CROSSED (i);
        allocno[num].n_refs += REG_N_REFS (i);
        allocno[num].freq += REG_FREQ (i);
        if (allocno[num].live_length < REG_LIVE_LENGTH (i))
@@ -1207,9 +1210,11 @@ find_reg (int num, HARD_REG_SET losers, int alt_regs_p, int accept_call_clobbere
     {
       /* Did not find a register.  If it would be profitable to
         allocate a call-clobbered register and save and restore it
-        around calls, do that.  */
+        around calls, do that.  Don't do this if it crosses any calls
+        that might throw.  */
       if (! accept_call_clobbered
          && allocno[num].calls_crossed != 0
+         && allocno[num].throwing_calls_crossed == 0
          && CALLER_SAVE_PROFITABLE (allocno[num].n_refs,
                                     allocno[num].calls_crossed))
        {
index cd26174fa6a7a4ca77ee9d4492a785adaa381a87..4ee4991d0cd5b8a6007ca6113c7beee91571466f 100644 (file)
@@ -123,6 +123,11 @@ struct qty
 
   int n_calls_crossed;
 
+  /* Number of times a reg tied to given qty lives across a CALL_INSN
+     that might throw.  */
+
+  int n_throwing_calls_crossed;
+
   /* The register number of one pseudo register whose reg_qty value is Q.
      This register should be the head of the chain
      maintained in reg_next_in_qty.  */
@@ -324,6 +329,7 @@ alloc_qty (int regno, enum machine_mode mode, int size, int birth)
   qty[qtyno].mode = mode;
   qty[qtyno].birth = birth;
   qty[qtyno].n_calls_crossed = REG_N_CALLS_CROSSED (regno);
+  qty[qtyno].n_throwing_calls_crossed = REG_N_THROWING_CALLS_CROSSED (regno);
   qty[qtyno].min_class = reg_preferred_class (regno);
   qty[qtyno].alternate_class = reg_alternate_class (regno);
   qty[qtyno].n_refs = REG_N_REFS (regno);
@@ -1170,6 +1176,7 @@ update_equiv_regs (void)
 
                      REG_BASIC_BLOCK (regno) = bb->index;
                      REG_N_CALLS_CROSSED (regno) = 0;
+                     REG_N_THROWING_CALLS_CROSSED (regno) = 0;
                      REG_LIVE_LENGTH (regno) = 2;
 
                      if (insn == BB_HEAD (bb))
@@ -2011,6 +2018,8 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
 
       /* Update info about quantity SQTY.  */
       qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg);
+      qty[sqty].n_throwing_calls_crossed
+       += REG_N_THROWING_CALLS_CROSSED (sreg);
       qty[sqty].n_refs += REG_N_REFS (sreg);
       qty[sqty].freq += REG_FREQ (sreg);
       if (usize < ssize)
@@ -2315,12 +2324,14 @@ find_free_reg (enum reg_class class, enum machine_mode mode, int qtyno,
 
   /* We need not check to see if the current function has nonlocal
      labels because we don't put any pseudos that are live over calls in
-     registers in that case.  */
+     registers in that case.  Avoid putting pseudos crossing calls that
+     might throw into call used registers.  */
 
   if (! accept_call_clobbered
       && flag_caller_saves
       && ! just_try_suggested
       && qty[qtyno].n_calls_crossed != 0
+      && qty[qtyno].n_throwing_calls_crossed == 0
       && CALLER_SAVE_PROFITABLE (qty[qtyno].n_refs,
                                 qty[qtyno].n_calls_crossed))
     {