OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index 62a1080..aba4b7f 100644 (file)
@@ -1,6 +1,7 @@
 /* Emit RTL for the GCC expander.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -165,7 +166,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
 #define first_label_num (cfun->emit->x_first_label_num)
 
 static rtx make_call_insn_raw (rtx);
-static rtx find_line_note (rtx);
 static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
 static void unshare_all_decls (tree);
 static void reset_used_decls (tree);
@@ -444,64 +444,28 @@ immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode)
   rtx value;
   unsigned int i;
 
+  /* There are the following cases (note that there are no modes with
+     HOST_BITS_PER_WIDE_INT < GET_MODE_BITSIZE (mode) < 2 * HOST_BITS_PER_WIDE_INT):
+
+     1) If GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT, then we use
+       gen_int_mode.
+     2) GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT, but the value of
+       the integer fits into HOST_WIDE_INT anyway (i.e., i1 consists only
+       from copies of the sign bit, and sign of i0 and i1 are the same),  then 
+       we return a CONST_INT for i0.
+     3) Otherwise, we create a CONST_DOUBLE for i0 and i1.  */
   if (mode != VOIDmode)
     {
-      int width;
-      
       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
                  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
                  /* We can get a 0 for an error mark.  */
                  || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
                  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
 
-      /* We clear out all bits that don't belong in MODE, unless they and
-        our sign bit are all one.  So we get either a reasonable negative
-        value or a reasonable unsigned value for this mode.  */
-      width = GET_MODE_BITSIZE (mode);
-      if (width < HOST_BITS_PER_WIDE_INT
-         && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
-             != ((HOST_WIDE_INT) (-1) << (width - 1))))
-       i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;
-      else if (width == HOST_BITS_PER_WIDE_INT
-              && ! (i1 == ~0 && i0 < 0))
-       i1 = 0;
-      else
-       /* We should be able to represent this value as a constant.  */
-       gcc_assert (width <= 2 * HOST_BITS_PER_WIDE_INT);
-
-      /* If this would be an entire word for the target, but is not for
-        the host, then sign-extend on the host so that the number will
-        look the same way on the host that it would on the target.
-
-        For example, when building a 64 bit alpha hosted 32 bit sparc
-        targeted compiler, then we want the 32 bit unsigned value -1 to be
-        represented as a 64 bit value -1, and not as 0x00000000ffffffff.
-        The latter confuses the sparc backend.  */
-
-      if (width < HOST_BITS_PER_WIDE_INT
-         && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
-       i0 |= ((HOST_WIDE_INT) (-1) << width);
-
-      /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a
-        CONST_INT.
-
-        ??? Strictly speaking, this is wrong if we create a CONST_INT for
-        a large unsigned constant with the size of MODE being
-        HOST_BITS_PER_WIDE_INT and later try to interpret that constant
-        in a wider mode.  In that case we will mis-interpret it as a
-        negative number.
-
-        Unfortunately, the only alternative is to make a CONST_DOUBLE for
-        any constant in any mode if it is an unsigned constant larger
-        than the maximum signed integer in an int on the host.  However,
-        doing this will break everyone that always expects to see a
-        CONST_INT for SImode and smaller.
-
-        We have always been making CONST_INTs in this case, so nothing
-        new is being broken.  */
-
-      if (width <= HOST_BITS_PER_WIDE_INT)
-       i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0;
+      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+       return gen_int_mode (i0, mode);
+
+      gcc_assert (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT);
     }
 
   /* If this integer fits in one word, return a CONST_INT.  */
@@ -1632,8 +1596,9 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
                                     index, low_bound);
 
              off_tree = size_binop (PLUS_EXPR,
-                                    size_binop (MULT_EXPR, convert (sizetype,
-                                                                    index),
+                                    size_binop (MULT_EXPR,
+                                                fold_convert (sizetype,
+                                                              index),
                                                 unit_size),
                                     off_tree);
              t2 = TREE_OPERAND (t2, 0);
@@ -2178,10 +2143,11 @@ unshare_all_rtl_again (rtx insn)
   unshare_all_rtl_1 (cfun->decl, insn);
 }
 
-void
+unsigned int
 unshare_all_rtl (void)
 {
   unshare_all_rtl_1 (current_function_decl, get_insns ());
+  return 0;
 }
 
 struct tree_opt_pass pass_unshare_all_rtl =
@@ -2326,6 +2292,20 @@ verify_rtl_sharing (void)
        reset_used_flags (PATTERN (p));
        reset_used_flags (REG_NOTES (p));
        reset_used_flags (LOG_LINKS (p));
+       if (GET_CODE (PATTERN (p)) == SEQUENCE)
+         {
+           int i;
+           rtx q, sequence = PATTERN (p);
+
+           for (i = 0; i < XVECLEN (sequence, 0); i++)
+             {
+               q = XVECEXP (sequence, 0, i);
+               gcc_assert (INSN_P (q));
+               reset_used_flags (PATTERN (q));
+               reset_used_flags (REG_NOTES (q));
+               reset_used_flags (LOG_LINKS (q));
+             }
+         }
       }
 
   for (p = get_insns (); p; p = NEXT_INSN (p))
@@ -2467,11 +2447,7 @@ repeat:
 
   if (RTX_FLAG (x, used))
     {
-      rtx copy;
-
-      copy = rtx_alloc (code);
-      memcpy (copy, x, RTX_SIZE (code));
-      x = copy;
+      x = shallow_copy_rtx (x);
       copied = 1;
     }
   RTX_FLAG (x, used) = 1;
@@ -3700,95 +3676,6 @@ reorder_insns (rtx from, rtx to, rtx after)
     }
 }
 
-/* Return the line note insn preceding INSN.  */
-
-static rtx
-find_line_note (rtx insn)
-{
-  if (no_line_numbers)
-    return 0;
-
-  for (; insn; insn = PREV_INSN (insn))
-    if (NOTE_P (insn)
-       && NOTE_LINE_NUMBER (insn) >= 0)
-      break;
-
-  return insn;
-}
-
-/* Remove unnecessary notes from the instruction stream.  */
-
-void
-remove_unnecessary_notes (void)
-{
-  rtx eh_stack = NULL_RTX;
-  rtx insn;
-  rtx next;
-  rtx tmp;
-
-  /* We must not remove the first instruction in the function because
-     the compiler depends on the first instruction being a note.  */
-  for (insn = NEXT_INSN (get_insns ()); insn; insn = next)
-    {
-      /* Remember what's next.  */
-      next = NEXT_INSN (insn);
-
-      /* We're only interested in notes.  */
-      if (!NOTE_P (insn))
-       continue;
-
-      switch (NOTE_LINE_NUMBER (insn))
-       {
-       case NOTE_INSN_DELETED:
-         remove_insn (insn);
-         break;
-
-       case NOTE_INSN_EH_REGION_BEG:
-         eh_stack = alloc_INSN_LIST (insn, eh_stack);
-         break;
-
-       case NOTE_INSN_EH_REGION_END:
-         /* Too many end notes.  */
-         gcc_assert (eh_stack);
-         /* Mismatched nesting.  */
-         gcc_assert (NOTE_EH_HANDLER (XEXP (eh_stack, 0))
-                     == NOTE_EH_HANDLER (insn));
-         tmp = eh_stack;
-         eh_stack = XEXP (eh_stack, 1);
-         free_INSN_LIST_node (tmp);
-         break;
-
-       case NOTE_INSN_BLOCK_BEG:
-       case NOTE_INSN_BLOCK_END:
-          /* BLOCK_END and BLOCK_BEG notes only exist in the `final' pass.  */
-          gcc_unreachable ();
-
-       default:
-         break;
-       }
-    }
-
-  /* Too many EH_REGION_BEG notes.  */
-  gcc_assert (!eh_stack);
-}
-
-struct tree_opt_pass pass_remove_unnecessary_notes =
-{
-  "eunotes",                            /* name */ 
-  NULL,                                        /* gate */
-  remove_unnecessary_notes,             /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  0,                                   /* tv_id */ 
-  0,                                   /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  0                                     /* letter */ 
-};
-
 \f
 /* Emit insn(s) of given code and pattern
    at a specified place within the doubly-linked list.
@@ -4073,22 +3960,6 @@ emit_insn_after_noloc (rtx x, rtx after)
   return last;
 }
 
-/* Similar to emit_insn_after, except that line notes are to be inserted so
-   as to act as if this insn were at FROM.  */
-
-void
-emit_insn_after_with_line_notes (rtx x, rtx after, rtx from)
-{
-  rtx from_line = find_line_note (from);
-  rtx after_line = find_line_note (after);
-  rtx insn = emit_insn_after (x, after);
-
-  if (from_line)
-    emit_note_copy_after (from_line, after);
-
-  if (after_line)
-    emit_note_copy_after (after_line, insn);
-}
 
 /* Make an insn of code JUMP_INSN with body X
    and output it after the insn AFTER.  */
@@ -4208,28 +4079,6 @@ emit_note_after (int subtype, rtx after)
   add_insn_after (note, after);
   return note;
 }
-
-/* Emit a copy of note ORIG after the insn AFTER.  */
-
-rtx
-emit_note_copy_after (rtx orig, rtx after)
-{
-  rtx note;
-
-  if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers)
-    {
-      cur_insn_uid++;
-      return 0;
-    }
-
-  note = rtx_alloc (NOTE);
-  INSN_UID (note) = cur_insn_uid++;
-  NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig);
-  NOTE_DATA (note) = NOTE_DATA (orig);
-  BLOCK_FOR_INSN (note) = NULL;
-  add_insn_after (note, after);
-  return note;
-}
 \f
 /* Like emit_insn_after_noloc, but set INSN_LOCATOR according to SCOPE.  */
 rtx
@@ -4614,12 +4463,6 @@ emit_note_copy (rtx orig)
 {
   rtx note;
   
-  if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers)
-    {
-      cur_insn_uid++;
-      return NULL_RTX;
-    }
-  
   note = rtx_alloc (NOTE);
   
   INSN_UID (note) = cur_insn_uid++;
@@ -4978,13 +4821,11 @@ copy_insn_1 (rtx orig)
       break;
     }
 
-  copy = rtx_alloc (code);
-
-  /* Copy the various flags, and other information.  We assume that
-     all fields need copying, and then clear the fields that should
+  /* Copy the various flags, fields, and other information.  We assume
+     that all fields need copying, and then clear the fields that should
      not be copied.  That is the sensible default behavior, and forces
      us to explicitly document why we are *not* copying a flag.  */
-  memcpy (copy, orig, RTX_HDR_SIZE);
+  copy = shallow_copy_rtx (orig);
 
   /* We do not copy the USED flag, which is used as a mark bit during
      walks over the RTL.  */
@@ -5001,43 +4842,40 @@ copy_insn_1 (rtx orig)
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
 
   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
-    {
-      copy->u.fld[i] = orig->u.fld[i];
-      switch (*format_ptr++)
-       {
-       case 'e':
-         if (XEXP (orig, i) != NULL)
-           XEXP (copy, i) = copy_insn_1 (XEXP (orig, i));
-         break;
+    switch (*format_ptr++)
+      {
+      case 'e':
+       if (XEXP (orig, i) != NULL)
+         XEXP (copy, i) = copy_insn_1 (XEXP (orig, i));
+       break;
 
-       case 'E':
-       case 'V':
-         if (XVEC (orig, i) == orig_asm_constraints_vector)
-           XVEC (copy, i) = copy_asm_constraints_vector;
-         else if (XVEC (orig, i) == orig_asm_operands_vector)
-           XVEC (copy, i) = copy_asm_operands_vector;
-         else if (XVEC (orig, i) != NULL)
-           {
-             XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
-             for (j = 0; j < XVECLEN (copy, i); j++)
-               XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j));
-           }
-         break;
+      case 'E':
+      case 'V':
+       if (XVEC (orig, i) == orig_asm_constraints_vector)
+         XVEC (copy, i) = copy_asm_constraints_vector;
+       else if (XVEC (orig, i) == orig_asm_operands_vector)
+         XVEC (copy, i) = copy_asm_operands_vector;
+       else if (XVEC (orig, i) != NULL)
+         {
+           XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
+           for (j = 0; j < XVECLEN (copy, i); j++)
+             XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j));
+         }
+       break;
 
-       case 't':
-       case 'w':
-       case 'i':
-       case 's':
-       case 'S':
-       case 'u':
-       case '0':
-         /* These are left unchanged.  */
-         break;
+      case 't':
+      case 'w':
+      case 'i':
+      case 's':
+      case 'S':
+      case 'u':
+      case '0':
+       /* These are left unchanged.  */
+       break;
 
-       default:
-         gcc_unreachable ();
-       }
-    }
+      default:
+       gcc_unreachable ();
+      }
 
   if (code == SCRATCH)
     {
@@ -5459,14 +5297,12 @@ emit_copy_of_insn_after (rtx insn, rtx after)
       {
        if (GET_CODE (link) == EXPR_LIST)
          REG_NOTES (new)
-           = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
-                                             XEXP (link, 0),
-                                             REG_NOTES (new)));
+               = gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
+                 copy_insn_1 (XEXP (link, 0)),  REG_NOTES (new));
        else
          REG_NOTES (new)
-           = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
-                                             XEXP (link, 0),
-                                             REG_NOTES (new)));
+              = gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
+                XEXP (link, 0),  REG_NOTES (new));
       }
 
   /* Fix the libcall sequences.  */