OSDN Git Service

* config/h8300/h8300.c (h8300_adjust_insn_length): Clean up.
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index 8faef45..e248af1 100644 (file)
@@ -1,6 +1,6 @@
 /* Emit RTL for the GNU C-Compiler expander.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -196,6 +196,7 @@ static mem_attrs *get_mem_attrs             PARAMS ((HOST_WIDE_INT, tree, rtx,
                                                 rtx, unsigned int,
                                                 enum machine_mode));
 static tree component_ref_for_mem_expr PARAMS ((tree));
+static rtx gen_const_vector_0          PARAMS ((enum machine_mode));
 
 /* Probability of the conditional branch currently proceeded by try_split.
    Set to -1 otherwise.  */
@@ -292,7 +293,8 @@ get_mem_attrs (alias, expr, offset, size, align, mode)
       && (size == 0
          || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
       && (align == BITS_PER_UNIT
-         || (mode != BLKmode && align == GET_MODE_ALIGNMENT (mode))))
+         || (STRICT_ALIGNMENT
+             && mode != BLKmode && align == GET_MODE_ALIGNMENT (mode))))
     return 0;
 
   attrs.alias = alias;
@@ -410,6 +412,9 @@ gen_rtx_REG (mode, regno)
       if (regno == RETURN_ADDRESS_POINTER_REGNUM)
        return return_address_pointer_rtx;
 #endif
+      if (regno == PIC_OFFSET_TABLE_REGNUM
+         && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
+        return pic_offset_table_rtx;
       if (regno == STACK_POINTER_REGNUM)
        return stack_pointer_rtx;
     }
@@ -919,13 +924,11 @@ gen_lowpart_common (mode, x)
        low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);
       else
        low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
-
 #ifdef HOST_WORDS_BIG_ENDIAN
       u.i[0] = high, u.i[1] = low;
 #else
       u.i[0] = low, u.i[1] = high;
 #endif
-
       return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
     }
 
@@ -1009,12 +1012,16 @@ gen_lowpart_common (mode, x)
          high = CONST_DOUBLE_HIGH (x);
        }
 
+#if HOST_BITS_PER_WIDE_INT == 32
       /* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
         target machine.  */
       if (WORDS_BIG_ENDIAN)
        i[0] = high, i[1] = low;
       else
        i[0] = low, i[1] = high;
+#else
+      i[0] = low;
+#endif
 
       r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
       return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
@@ -1200,7 +1207,7 @@ gen_highpart (mode, x)
   /* simplify_gen_subreg is not guaranteed to return a valid operand for
      the target if we have a MEM.  gen_highpart must return a valid operand,
      emitting code if necessary to do so.  */
-  if (GET_CODE (result) == MEM)
+  if (result != NULL_RTX && GET_CODE (result) == MEM)
     result = validize_mem (result);
 
   if (!result)
@@ -1996,7 +2003,8 @@ adjust_address_1 (memref, mode, offset, validate, adjust)
      lowest-order set bit in OFFSET, but don't change the alignment if OFFSET
      if zero.  */
   if (offset != 0)
-    memalign = MIN (memalign, (offset & -offset) * BITS_PER_UNIT);
+    memalign = MIN (memalign,
+                   (unsigned int) (offset & -offset) * BITS_PER_UNIT);
 
   /* We can compute the size in a number of ways.  */
   if (GET_MODE (new) != BLKmode)
@@ -2039,16 +2047,34 @@ offset_address (memref, offset, pow2)
      rtx offset;
      HOST_WIDE_INT pow2;
 {
-  rtx new = change_address_1 (memref, VOIDmode,
-                             gen_rtx_PLUS (Pmode, XEXP (memref, 0),
-                                           force_reg (Pmode, offset)), 1);
+  rtx new, addr = XEXP (memref, 0);
+
+  new = simplify_gen_binary (PLUS, Pmode, addr, offset);
+
+  /* At this point we don't know _why_ the address is invalid.  It 
+     could have secondary memory refereces, multiplies or anything.
+
+     However, if we did go and rearrange things, we can wind up not
+     being able to recognize the magic around pic_offset_table_rtx.
+     This stuff is fragile, and is yet another example of why it is
+     bad to expose PIC machinery too early.  */
+  if (! memory_address_p (GET_MODE (memref), new)
+      && GET_CODE (addr) == PLUS
+      && XEXP (addr, 0) == pic_offset_table_rtx)
+    {
+      addr = force_reg (GET_MODE (addr), addr);
+      new = simplify_gen_binary (PLUS, Pmode, addr, offset);
+    }
+
+  new = change_address_1 (memref, VOIDmode, new, 1);
 
   /* Update the alignment to reflect the offset.  Reset the offset, which
      we don't know.  */
-  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
-                                  0, 0, MIN (MEM_ALIGN (memref),
-                                             pow2 * BITS_PER_UNIT),
-                                  GET_MODE (new));
+  MEM_ATTRS (new)
+    = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
+                    MIN (MEM_ALIGN (memref),
+                         (unsigned int) pow2 * BITS_PER_UNIT),
+                    GET_MODE (new));
   return new;
 }
   
@@ -2382,6 +2408,7 @@ copy_rtx_if_shared (orig)
     case QUEUED:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case CODE_LABEL:
     case PC:
@@ -2498,6 +2525,7 @@ reset_used_flags (x)
     case QUEUED:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case CODE_LABEL:
     case PC:
@@ -3248,6 +3276,8 @@ add_insn_after (insn, after)
       && (bb = BLOCK_FOR_INSN (after)))
     {
       set_block_for_insn (insn, bb);
+      if (INSN_P (insn))
+        bb->flags |= BB_DIRTY;
       /* Should not happen as first in the BB is always
         either NOTE or LABEL.  */
       if (bb->end == after
@@ -3315,6 +3345,8 @@ add_insn_before (insn, before)
       && (bb = BLOCK_FOR_INSN (before)))
     {
       set_block_for_insn (insn, bb);
+      if (INSN_P (insn))
+        bb->flags |= BB_DIRTY;
       /* Should not happen as first in the BB is always
         either NOTE or LABEl.  */
       if (bb->head == insn
@@ -3392,6 +3424,8 @@ remove_insn (insn)
       && (unsigned int)INSN_UID (insn) < basic_block_for_insn->num_elements
       && (bb = BLOCK_FOR_INSN (insn)))
     {
+      if (INSN_P (insn))
+        bb->flags |= BB_DIRTY;
       if (bb->head == insn)
        {
          /* Never ever delete the basic block note without deleting whole basic
@@ -3469,6 +3503,7 @@ reorder_insns (from, to, after)
       && (bb = BLOCK_FOR_INSN (after)))
     {
       rtx x;
+      bb->flags |= BB_DIRTY;
  
       if (basic_block_for_insn
          && (unsigned int)INSN_UID (from) < basic_block_for_insn->num_elements
@@ -3476,6 +3511,7 @@ reorder_insns (from, to, after)
        {
          if (bb2->end == to)
            bb2->end = prev;
+         bb2->flags |= BB_DIRTY;
        }
 
       if (bb->end == after)
@@ -3554,6 +3590,7 @@ remove_unnecessary_notes ()
       switch (NOTE_LINE_NUMBER (insn))
        {
        case NOTE_INSN_DELETED:
+       case NOTE_INSN_LOOP_END_TOP_COND:
          remove_insn (insn);
          break;
 
@@ -3999,6 +4036,7 @@ emit_insns_after (first, after)
       && (unsigned int)INSN_UID (after) < basic_block_for_insn->num_elements
       && (bb = BLOCK_FOR_INSN (after)))
     {
+      bb->flags |= BB_DIRTY;
       for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
        set_block_for_insn (last, bb);
       set_block_for_insn (last, bb);
@@ -4532,6 +4570,7 @@ copy_insn_1 (orig)
     case QUEUED:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case CODE_LABEL:
     case PC:
@@ -4770,6 +4809,33 @@ mark_emit_status (es)
   ggc_mark_rtx (es->x_first_insn);
 }
 
+/* Generate the constant 0.  */
+
+static rtx
+gen_const_vector_0 (mode)
+     enum machine_mode mode;
+{
+  rtx tem;
+  rtvec v;
+  int units, i;
+  enum machine_mode inner;
+
+  units = GET_MODE_NUNITS (mode);
+  inner = GET_MODE_INNER (mode);
+
+  v = rtvec_alloc (units);
+
+  /* We need to call this function after we to set CONST0_RTX first.  */
+  if (!CONST0_RTX (inner))
+    abort ();
+
+  for (i = 0; i < units; ++i)
+    RTVEC_ELT (v, i) = CONST0_RTX (inner);
+
+  tem = gen_rtx_CONST_VECTOR (mode, v);
+  return tem;
+}
+
 /* Create some permanent unique rtl objects shared between all functions.
    LINE_NUMBERS is nonzero if line numbers are to be generated.  */
 
@@ -4911,6 +4977,16 @@ init_emit_once (line_numbers)
        const_tiny_rtx[i][(int) mode] = GEN_INT (i);
     }
 
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    const_tiny_rtx[0][(int) mode] = gen_const_vector_0 (mode);
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    const_tiny_rtx[0][(int) mode] = gen_const_vector_0 (mode);
+
   for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i)
     if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC)
       const_tiny_rtx[0][i] = const0_rtx;
@@ -4970,7 +5046,7 @@ init_emit_once (line_numbers)
 #endif
 
   if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
-    pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+    pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
 
   ggc_add_rtx_root (&pic_offset_table_rtx, 1);
   ggc_add_rtx_root (&struct_value_rtx, 1);