OSDN Git Service

* config/i386/i386.c (override_options): Define c3-2 as a 686 with SSE.
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index a9f94a6..24f8691 100644 (file)
@@ -120,6 +120,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 \f
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "tm_p.h"
@@ -140,9 +142,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "obstack.h"
 #include "splay-tree.h"
 
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
    the stack pointer does not matter.  The value is tested only in
    functions that have frame pointers.
@@ -272,10 +271,10 @@ struct propagate_block_info
   /* The length of mem_set_list.  */
   int mem_set_list_len;
 
-  /* Non-zero if the value of CC0 is live.  */
+  /* Nonzero if the value of CC0 is live.  */
   int cc0_live;
 
-  /* Flags controling the set of information propagate_block collects.  */
+  /* Flags controlling the set of information propagate_block collects.  */
   int flags;
 };
 
@@ -373,10 +372,14 @@ check_function_return_warnings ()
         is no longer in the chain.  */
       if (INSN_UID (cfun->x_clobber_return_insn) < max_uid)
        {
-         /* Recompute insn->block mapping, since the initial mapping is
-            set before we delete unreachable blocks.  */
-         if (BLOCK_FOR_INSN (cfun->x_clobber_return_insn) != NULL)
-           warning ("control reaches end of non-void function");
+         rtx insn;
+
+         for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+           if (insn == cfun->x_clobber_return_insn)
+             {
+               warning ("control reaches end of non-void function");
+               break;
+             }
        }
     }
 }
@@ -430,6 +433,16 @@ life_analysis (f, file, flags)
   SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
 #endif
 
+
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  if (flags & PROP_REG_INFO)
+    {
+      int j;
+      for (j=0; j < NUM_MACHINE_MODES; ++j)
+       INIT_REG_SET (&subregs_of_mode[j]);
+    }
+#endif
+
   if (! optimize)
     flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
 
@@ -680,6 +693,16 @@ update_life_info (blocks, extent, prop_flags)
             partial improvement (see MAX_MEM_SET_LIST_LEN usage).
             Further improvement may be possible.  */
          cleanup_cfg (CLEANUP_EXPENSIVE);
+
+         /* Zap the life information from the last round.  If we don't 
+            do this, we can wind up with registers that no longer appear
+            in the code being marked live at entry, which twiggs bogus
+            warnings from regno_uninitialized.  */
+         FOR_EACH_BB (bb)
+           {
+             CLEAR_REG_SET (bb->global_live_at_start);
+             CLEAR_REG_SET (bb->global_live_at_end);
+           }
        }
 
       /* If asked, remove notes from the blocks we'll update.  */
@@ -796,7 +819,7 @@ update_life_info_in_dirty_blocks (extent, prop_flags)
 
 /* Free the variables allocated by find_basic_blocks.
 
-   KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed.  */
+   KEEP_HEAD_END_P is nonzero if basic_block_info is not to be freed.  */
 
 void
 free_basic_block_vars (keep_head_end_p)
@@ -995,7 +1018,7 @@ mark_regs_live_at_end (set)
   /* Many architectures have a GP register even without flag_pic.
      Assume the pic register is not in use, or will be handled by
      other means, if it is not fixed.  */
-  if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+  if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
       && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
     SET_REGNO_REG_SET (set, PIC_OFFSET_TABLE_REGNUM);
 #endif
@@ -1084,7 +1107,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
   int i;
 
   /* Some passes used to forget clear aux field of basic block causing
-     sick behaviour here.  */
+     sick behavior here.  */
 #ifdef ENABLE_CHECKING
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     if (bb->aux)
@@ -1224,7 +1247,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
          /* Any constant, or pseudo with constant equivalences, may
             require reloading from memory using the pic register.  */
-         if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+         if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
              && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
            SET_REGNO_REG_SET (new_live_at_end, PIC_OFFSET_TABLE_REGNUM);
        }
@@ -1372,7 +1395,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 }
 
 \f
-/* This structure is used to pass parameters to an from the
+/* This structure is used to pass parameters to and from the
    the function find_regno_partial(). It is used to pass in the
    register number we are looking, as well as to return any rtx
    we find.  */
@@ -1519,6 +1542,7 @@ allocate_reg_life_data ()
       REG_N_DEATHS (i) = 0;
       REG_N_CALLS_CROSSED (i) = 0;
       REG_LIVE_LENGTH (i) = 0;
+      REG_FREQ (i) = 0;
       REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
     }
 }
@@ -1644,7 +1668,42 @@ propagate_one_insn (pbi, insn)
       if (libcall_is_dead)
        prev = propagate_block_delete_libcall ( insn, note);
       else
-       propagate_block_delete_insn (insn);
+       {
+
+       /* If INSN contains a RETVAL note and is dead, but the libcall
+          as a whole is not dead, then we want to remove INSN, but
+          not the whole libcall sequence.
+
+          However, we need to also remove the dangling REG_LIBCALL     
+          note so that we do not have mis-matched LIBCALL/RETVAL
+          notes.  In theory we could find a new location for the
+          REG_RETVAL note, but it hardly seems worth the effort. 
+
+          NOTE at this point will be the RETVAL note if it exists.  */
+         if (note)
+           {
+             rtx libcall_note;
+        
+             libcall_note
+               = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
+             remove_note (XEXP (note, 0), libcall_note);
+           }
+
+         /* Similarly if INSN contains a LIBCALL note, remove the
+            dangling REG_RETVAL note.  */
+         note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
+         if (note)
+           {
+             rtx retval_note;
+
+             retval_note
+               = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL_RTX);
+             remove_note (XEXP (note, 0), retval_note);
+           }
+
+         /* Now delete INSN.  */
+         propagate_block_delete_insn (insn);
+       }
 
       return prev;
     }
@@ -1744,8 +1803,7 @@ propagate_one_insn (pbi, insn)
            if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
              {
                /* We do not want REG_UNUSED notes for these registers.  */
-               mark_set_1 (pbi, CLOBBER, gen_rtx_REG (reg_raw_mode[i], i),
-                           cond, insn,
+               mark_set_1 (pbi, CLOBBER, regno_reg_rtx[i], cond, insn,
                            pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO));
              }
        }
@@ -1793,8 +1851,7 @@ propagate_one_insn (pbi, insn)
             so they are made live.  */
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
            if (global_regs[i])
-             mark_used_reg (pbi, gen_rtx_REG (reg_raw_mode[i], i),
-                            cond, insn);
+             mark_used_reg (pbi, regno_reg_rtx[i], cond, insn);
        }
     }
 
@@ -2008,7 +2065,7 @@ free_propagate_block_info (pbi)
    case, the resulting set will be equal to the union of the two sets that
    would otherwise be computed.
 
-   Return non-zero if an INSN is deleted (i.e. by dead code removal).  */
+   Return nonzero if an INSN is deleted (i.e. by dead code removal).  */
 
 int
 propagate_block (bb, live, local_set, cond_local_set, flags)
@@ -2062,7 +2119,7 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
    (SET expressions whose destinations are registers dead after the insn).
    NEEDED is the regset that says which regs are alive after the insn.
 
-   Unless CALL_OK is non-zero, an insn is needed if it contains a CALL.
+   Unless CALL_OK is nonzero, an insn is needed if it contains a CALL.
 
    If X is the entire body of an insn, NOTES contains the reg notes
    pertaining to the insn.  */
@@ -2076,6 +2133,10 @@ insn_dead_p (pbi, x, call_ok, notes)
 {
   enum rtx_code code = GET_CODE (x);
 
+  /* Don't eliminate insns that may trap.  */
+  if (flag_non_call_exceptions && may_trap_p (x))
+    return 0;
+
 #ifdef AUTO_INC_DEC
   /* As flow is invoked after combine, we must take existing AUTO_INC
      expressions into account.  */
@@ -2328,7 +2389,7 @@ regno_uninitialized (regno)
              || FUNCTION_ARG_REGNO_P (regno))))
     return 0;
 
-  return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno);
+  return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->global_live_at_end, regno);
 }
 
 /* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -2343,7 +2404,7 @@ regno_clobbered_at_setjmp (regno)
     return 0;
 
   return ((REG_N_SETS (regno) > 1
-          || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno))
+          || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->global_live_at_end, regno))
          && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
 }
 \f
@@ -2794,7 +2855,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
                    if (! REGNO_REG_SET_P (pbi->reg_live, i))
                      REG_NOTES (insn)
                        = alloc_EXPR_LIST (REG_UNUSED,
-                                          gen_rtx_REG (reg_raw_mode[i], i),
+                                          regno_reg_rtx[i],
                                           REG_NOTES (insn));
                }
            }
@@ -3324,7 +3385,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
 
       /* We now know we'll be doing this change, so emit the
         new insn(s) and do the updates.  */
-      emit_insns_before (insns, insn);
+      emit_insn_before (insns, insn);
 
       if (pbi->bb->head == insn)
        pbi->bb->head = insns;
@@ -3477,6 +3538,12 @@ find_auto_inc (pbi, x, insn)
                                                                  addr,
                                                                  inc_val)),
                          insn, x, incr, addr);
+      else if (HAVE_PRE_MODIFY_DISP && offset == INTVAL (inc_val))
+       attempt_auto_inc (pbi, gen_rtx_PRE_MODIFY (Pmode, addr,
+                                                   gen_rtx_PLUS (Pmode,
+                                                                 addr,
+                                                                 inc_val)),
+                         insn, x, incr, addr);
     }
   else if (GET_CODE (inc_val) == REG
           && ! reg_set_between_p (inc_val, PREV_INSN (insn),
@@ -3602,7 +3669,7 @@ mark_used_reg (pbi, reg, cond, insn)
                && ! dead_or_set_regno_p (insn, i))
              REG_NOTES (insn)
                = alloc_EXPR_LIST (REG_DEAD,
-                                  gen_rtx_REG (reg_raw_mode[i], i),
+                                  regno_reg_rtx[i],
                                   REG_NOTES (insn));
        }
     }
@@ -3775,12 +3842,11 @@ mark_used_regs (pbi, x, cond, insn)
       break;
 
     case SUBREG:
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
       if (GET_CODE (SUBREG_REG (x)) == REG
-         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
-         && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
-                                        GET_MODE (SUBREG_REG (x))))
-       REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1;
+         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
+       SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (x)],
+                          REGNO (SUBREG_REG (x)));
 #endif
 
       /* While we're here, optimize this case.  */
@@ -3824,13 +3890,12 @@ mark_used_regs (pbi, x, cond, insn)
               || GET_CODE (testreg) == SIGN_EXTRACT
               || GET_CODE (testreg) == SUBREG)
          {
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
            if (GET_CODE (testreg) == SUBREG
                && GET_CODE (SUBREG_REG (testreg)) == REG
-               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
-               && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)),
-                                              GET_MODE (testreg)))
-             REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1;
+               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
+             SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (testreg)],
+                                REGNO (SUBREG_REG (testreg)));
 #endif
 
            /* Modifying a single register in an alternate mode
@@ -4176,7 +4241,7 @@ dump_regset (r, outf)
     });
 }
 
-/* Print a human-reaable representation of R on the standard error
+/* Print a human-readable representation of R on the standard error
    stream.  This function is designed to be used from within the
    debugger.  */