emit-rtl.c (gen_reg_rtx): Also reallocate reg_decl array.
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>
Thu, 18 Oct 2001 21:34:14 +0000 (21:34 +0000)
committerRichard Kenner <kenner@gcc.gnu.org>
Thu, 18 Oct 2001 21:34:14 +0000 (17:34 -0400)
* emit-rtl.c (gen_reg_rtx): Also reallocate reg_decl array.
(offset_address): New function.
(free_emit_status): Free regno_decl.
(init_emit): Pass proper number of elements to xcalloc.
Allocate regno_decl.
(mark_emit_status): Mark regno_decl values.
* expr.c (highest_pow2_factor): New function.
(expand_assigment): Use it and offset_address.
Properly handle ptr_mode vs. Pmode in offset calculation.
(store_constructor, expand_expr_unaligned): Likewise.
(expand_expr, case COMPONENT_EXPR): Likewise.
* expr.h (offset_address): New decl.
* function.h (struct emit_status): Add regno_decl.
(REGNO_DECL): New macro.
* final.c (output_asm_name): Move in file and don't conditionalize
on flag_print_asm_name.
(output_asm_insn): Only call output_asm_name if flag_print_asm_name.
Output names of operands, if known.
* function.c (assign_parms): Set REGNO_DECL.
* integrate.c (integrate_decl_tree): Likewise.
* stmt.c (expand_decl): Likewise.
* regclass.c (reg_scan_mark_refs): Propagate REGNO_DECL for copies.

From-SVN: r46337

gcc/ChangeLog
gcc/emit-rtl.c
gcc/expr.c
gcc/expr.h
gcc/final.c
gcc/function.c
gcc/function.h
gcc/integrate.c
gcc/regclass.c
gcc/stmt.c

index a85d7ddd449f310cededeb0d1542938515e8f007..dd5331c63c80d323f3272f4b8891ad4f921a54d6 100644 (file)
@@ -1,3 +1,28 @@
+Thu Oct 18 16:07:39 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * emit-rtl.c (gen_reg_rtx): Also reallocate reg_decl array.
+       (offset_address): New function.
+       (free_emit_status): Free regno_decl.
+       (init_emit): Pass proper number of elements to xcalloc.
+       Allocate regno_decl.
+       (mark_emit_status): Mark regno_decl values.
+       * expr.c (highest_pow2_factor): New function.
+       (expand_assigment): Use it and offset_address.
+       Properly handle ptr_mode vs. Pmode in offset calculation.
+       (store_constructor, expand_expr_unaligned): Likewise.
+       (expand_expr, case COMPONENT_EXPR): Likewise.
+       * expr.h (offset_address): New decl.
+       * function.h (struct emit_status): Add regno_decl.
+       (REGNO_DECL): New macro.
+       * final.c (output_asm_name): Move in file and don't conditionalize
+       on flag_print_asm_name.
+       (output_asm_insn): Only call output_asm_name if flag_print_asm_name.
+       Output names of operands, if known.
+       * function.c (assign_parms): Set REGNO_DECL.
+       * integrate.c (integrate_decl_tree): Likewise.
+       * stmt.c (expand_decl): Likewise.
+       * regclass.c (reg_scan_mark_refs): Propagate REGNO_DECL for copies.
+       
 2001-10-18  Alexandre Oliva  <aoliva@redhat.com>
 
        * attribs.c (handle_noinline_attribute): New function.
index 50819c6840ca79f82e72da0f0f228b23b5baaad1..c7c61401b5e2f620f6efe65c4a6c0faba54b0bf5 100644 (file)
@@ -659,14 +659,16 @@ gen_reg_rtx (mode)
       return gen_rtx_CONCAT (mode, realpart, imagpart);
     }
 
-  /* Make sure regno_pointer_align and regno_reg_rtx are large enough
-     to have an element for this pseudo reg number.  */
+  /* Make sure regno_pointer_align, regno_decl, and regno_reg_rtx are large
+     enough to have an element for this pseudo reg number.  */
 
   if (reg_rtx_no == f->emit->regno_pointer_align_length)
     {
       int old_size = f->emit->regno_pointer_align_length;
-      rtx *new1;
       char *new;
+      rtx *new1;
+      tree *new2;
+
       new = xrealloc (f->emit->regno_pointer_align, old_size * 2);
       memset (new + old_size, 0, old_size);
       f->emit->regno_pointer_align = (unsigned char *) new;
@@ -676,6 +678,11 @@ gen_reg_rtx (mode)
       memset (new1 + old_size, 0, old_size * sizeof (rtx));
       regno_reg_rtx = new1;
 
+      new2 = (tree *) xrealloc (f->emit->regno_decl,
+                               old_size * 2 * sizeof (tree));
+      memset (new2 + old_size, 0, old_size * sizeof (tree));
+      f->emit->regno_decl = new2;
+
       f->emit->regno_pointer_align_length = old_size * 2;
     }
 
@@ -1872,6 +1879,32 @@ adjust_address_1 (memref, mode, offset, validate)
   return new;
 }
 
+/* Return a memory reference like MEMREF, but with its address changed to
+   ADDR.  The caller is asserting that the actual piece of memory pointed
+   to is the same, just the form of the address is being changed, such as
+   by putting something into a register.  */
+
+rtx
+offset_address (memref, offset, pow2)
+     rtx memref;
+     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);
+  unsigned int memalign = MEM_ALIGN (memref);
+
+  /* Update the alignment to reflect the offset.  Reset the offset, which
+     we don't know.  */
+  while (pow2 % memalign != 0)
+    memalign >>= 1;
+
+  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
+                                  0, 0, memalign);
+  return new;
+}
+  
 /* Return a memory reference like MEMREF, but with its address changed to
    ADDR.  The caller is asserting that the actual piece of memory pointed
    to is the same, just the form of the address is being changed, such as
@@ -1978,6 +2011,7 @@ free_emit_status (f)
 {
   free (f->emit->x_regno_reg_rtx);
   free (f->emit->regno_pointer_align);
+  free (f->emit->regno_decl);
   free (f->emit);
   f->emit = NULL;
 }
@@ -4402,8 +4436,10 @@ init_emit ()
                                 sizeof (unsigned char));
 
   regno_reg_rtx
-    = (rtx *) xcalloc (f->emit->regno_pointer_align_length * sizeof (rtx),
-                      sizeof (rtx));
+    = (rtx *) xcalloc (f->emit->regno_pointer_align_length, sizeof (rtx));
+
+  f->emit->regno_decl
+    = (tree *) xcalloc (f->emit->regno_pointer_align_length, sizeof (tree));
 
   /* Put copies of all the virtual register rtx into regno_reg_rtx.  */
   init_virtual_regs (f->emit);
@@ -4460,14 +4496,19 @@ mark_emit_status (es)
      struct emit_status *es;
 {
   rtx *r;
+  tree *t;
   int i;
 
   if (es == 0)
     return;
 
-  for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx;
-       i > 0; --i, ++r)
-    ggc_mark_rtx (*r);
+  for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx,
+       t = es->regno_decl;
+       i > 0; --i, ++r, ++t)
+    {
+      ggc_mark_rtx (*r);
+      ggc_mark_tree (*t);
+    }
 
   mark_sequence_stack (es->sequence_stack);
   ggc_mark_tree (es->sequence_rtl_expr);
index e06d4b10974659f9060703608d6f912c9d1408b7..f486b32e4fdc4b86b2aaa299b7b3add0ed7ad610 100644 (file)
@@ -164,6 +164,7 @@ static rtx store_field              PARAMS ((rtx, HOST_WIDE_INT,
 static enum memory_use_mode
   get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
 static rtx var_rtx             PARAMS ((tree));
+static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
 static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
 static rtx expand_increment    PARAMS ((tree, int, int));
 static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
@@ -3760,10 +3761,8 @@ expand_assignment (to, from, want_value, suggest_reg)
              bitpos = 0;
            }
 
-         to_rtx = change_address (to_rtx, VOIDmode,
-                                  gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
-                                                force_reg (ptr_mode,
-                                                           offset_rtx)));
+         to_rtx = offset_address (to_rtx, offset_rtx,
+                                  highest_pow2_factor (offset));
        }
 
       if (volatilep)
@@ -3900,8 +3899,8 @@ expand_assignment (to, from, want_value, suggest_reg)
       else
        {
 #ifdef POINTERS_EXTEND_UNSIGNED
-         if (TREE_CODE (TREE_TYPE (to)) == REFERENCE_TYPE
-            || TREE_CODE (TREE_TYPE (to)) == POINTER_TYPE)
+         if (POINTER_TYPE_P (TREE_TYPE (to))
+             && GET_MODE (to_rtx) != GET_MODE (value))
            value = convert_memory_address (GET_MODE (to_rtx), value);
 #endif
          emit_move_insn (to_rtx, value);
@@ -4648,19 +4647,15 @@ store_constructor (exp, target, align, cleared, size)
                abort ();
 
              if (GET_MODE (offset_rtx) != ptr_mode)
-               {
+               offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+
 #ifdef POINTERS_EXTEND_UNSIGNED
-                  offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
-#else
-                  offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+             offset_rtx = convert_memory_address (Pmode, offset_rtx);
 #endif
-                }
 
-             to_rtx
-               = change_address (to_rtx, VOIDmode,
-                                 gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
-                                               force_reg (ptr_mode,
-                                                          offset_rtx)));
+             to_rtx = offset_address (to_rtx, offset_rtx,
+                                      highest_pow2_factor (offset));
+
              align = DECL_OFFSET_ALIGN (field);
            }
 
@@ -4820,7 +4815,7 @@ store_constructor (exp, target, align, cleared, size)
            {
              tree lo_index = TREE_OPERAND (index, 0);
              tree hi_index = TREE_OPERAND (index, 1);
-             rtx index_r, pos_rtx, addr, hi_r, loop_top, loop_end;
+             rtx index_r, pos_rtx, hi_r, loop_top, loop_end;
              struct nesting *loop;
              HOST_WIDE_INT lo, hi, count;
              tree position;
@@ -4884,8 +4879,9 @@ store_constructor (exp, target, align, cleared, size)
                                                  TYPE_SIZE_UNIT (elttype)));
 
                  pos_rtx = expand_expr (position, 0, VOIDmode, 0);
-                 addr = gen_rtx_PLUS (Pmode, XEXP (target, 0), pos_rtx);
-                 xtarget = change_address (target, mode, addr);
+                 xtarget = offset_address (target, pos_rtx,
+                                           highest_pow2_factor (position));
+                 xtarget = adjust_address (xtarget, mode, 0);
                  if (TREE_CODE (value) == CONSTRUCTOR)
                    store_constructor (value, xtarget, align, cleared,
                                       bitsize / BITS_PER_UNIT);
@@ -4906,7 +4902,6 @@ store_constructor (exp, target, align, cleared, size)
          else if ((index != 0 && ! host_integerp (index, 0))
                   || ! host_integerp (TYPE_SIZE (elttype), 1))
            {
-             rtx pos_rtx, addr;
              tree position;
 
              if (index == 0)
@@ -4920,9 +4915,10 @@ store_constructor (exp, target, align, cleared, size)
              position = size_binop (MULT_EXPR, index,
                                     convert (ssizetype,
                                              TYPE_SIZE_UNIT (elttype)));
-             pos_rtx = expand_expr (position, 0, VOIDmode, 0);
-             addr = gen_rtx_PLUS (Pmode, XEXP (target, 0), pos_rtx);
-             xtarget = change_address (target, mode, addr);
+             xtarget = offset_address (target,
+                                       expand_expr (position, 0, VOIDmode, 0),
+                                       highest_pow2_factor (position));
+             xtarget = adjust_address (xtarget, mode, 0);
              store_expr (value, xtarget, 0);
            }
          else
@@ -5965,6 +5961,62 @@ check_max_integer_computation_mode (exp)
 }
 #endif
 \f
+/* Return the highest power of two that EXP is known to be a multiple of.
+   This is used in updating alignment of MEMs in array references.  */
+
+static HOST_WIDE_INT
+highest_pow2_factor (exp)
+     tree exp;
+{
+  HOST_WIDE_INT c0, c1;
+
+  switch (TREE_CODE (exp))
+    {
+    case INTEGER_CST:
+      /* If the integer is expressable in a HOST_WIDE_INT, we can find
+        the lowest bit that's a one.  If the result is zero or negative,
+        pessimize by returning 1.  This is overly-conservative, but such
+        things should not happen in the offset expressions that we are
+        called with.  */
+      if (host_integerp (exp, 0))
+       {
+         c0 = tree_low_cst (exp, 0);
+         return c0 >= 0 ? c0 & -c0 : 1;
+       }
+      break;
+
+    case PLUS_EXPR:  case MINUS_EXPR:
+      c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
+      c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+      return MIN (c0, c1);
+
+    case MULT_EXPR:
+      c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
+      c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+      return c0 * c1;
+
+    case ROUND_DIV_EXPR:  case TRUNC_DIV_EXPR:  case FLOOR_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+      c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
+      c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+      return c0 / c1;
+
+    case NON_LVALUE_EXPR:  case NOP_EXPR:  case CONVERT_EXPR:
+    case COMPOUND_EXPR:  case SAVE_EXPR:
+      return highest_pow2_factor (TREE_OPERAND (exp, 0));
+
+    case COND_EXPR:
+      c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+      c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
+      return MIN (c0, c1);
+
+    default:
+      break;
+    }
+
+  return 1;
+}
+\f
 /* Return an object on the placeholder list that matches EXP, a
    PLACEHOLDER_EXPR.  An object "matches" if it is of the type of the
    PLACEHOLDER_EXPR or a pointer type to it.  For further information, see
@@ -7018,13 +7070,11 @@ expand_expr (exp, target, tmode, modifier)
              abort ();
 
            if (GET_MODE (offset_rtx) != ptr_mode)
-             {
+             offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+
 #ifdef POINTERS_EXTEND_UNSIGNED
-               offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
-#else
-               offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+           offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
 #endif
-             }
 
            /* A constant address in OP0 can have VOIDmode, we must not try
               to call force_reg for that case.  Avoid that case.  */
@@ -7048,10 +7098,8 @@ expand_expr (exp, target, tmode, modifier)
                bitpos = 0;
              }
 
-           op0 = change_address (op0, VOIDmode,
-                                 gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
-                                               force_reg (ptr_mode,
-                                                          offset_rtx)));
+           op0 = offset_address (op0, offset_rtx,
+                                 highest_pow2_factor (offset));
          }
 
        /* Don't forget about volatility even if this is a bitfield.  */
@@ -9036,18 +9084,14 @@ expand_expr_unaligned (exp, palign)
              abort ();
 
            if (GET_MODE (offset_rtx) != ptr_mode)
-             {
+             offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+
 #ifdef POINTERS_EXTEND_UNSIGNED
-               offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
-#else
-               offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+           offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
 #endif
-             }
 
-           op0 = change_address (op0, VOIDmode,
-                                 gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
-                                               force_reg (ptr_mode,
-                                                          offset_rtx)));
+           op0 = offset_address (op0, offset_rtx,
+                                 highest_pow2_factor (offset));
          }
 
        /* Don't forget about volatility even if this is a bitfield.  */
index af79fd581bee1cbc4d676a1afe2e9c88fdea572a..ad24cb7ae7469796bcad605169b258f365a6a898 100644 (file)
@@ -633,6 +633,11 @@ extern rtx change_address PARAMS ((rtx, enum machine_mode, rtx));
 extern rtx adjust_address_1 PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT,
                                     int));
 
+/* Return a memory reference like MEMREF, but whose address is changed by
+   adding OFFSET, an RTX, to it.  POW2 is the highest power of two factor
+   known to be in OFFSET (possibly 1).  */
+extern rtx offset_address PARAMS ((rtx, rtx, HOST_WIDE_INT));
+
 /* Return a memory reference like MEMREF, but with its address changed to
    ADDR.  The caller is asserting that the actual piece of memory pointed
    to is the same, just the form of the address is being changed, such as
index 5d2d8d9ae69efa434c886ff2356f6299dc7c528b..38ec17302f57b2a8395a0e463e0d36f8fb24e01a 100644 (file)
@@ -3264,6 +3264,30 @@ output_operand_lossage (msgid)
 \f
 /* Output of assembler code from a template, and its subroutines.  */
 
+/* Annotate the assembly with a comment describing the pattern and
+   alternative used.  */
+
+static void
+output_asm_name ()
+{
+  if (debug_insn)
+    {
+      int num = INSN_CODE (debug_insn);
+      fprintf (asm_out_file, "\t%s %d\t%s",
+              ASM_COMMENT_START, INSN_UID (debug_insn),
+              insn_data[num].name);
+      if (insn_data[num].n_alternatives > 1)
+       fprintf (asm_out_file, "/%d", which_alternative + 1);
+#ifdef HAVE_ATTR_length
+      fprintf (asm_out_file, "\t[length = %d]",
+              get_attr_length (debug_insn));
+#endif
+      /* Clear this so only the first assembler insn
+        of any rtl insn will get the special comment for -dp.  */
+      debug_insn = 0;
+    }
+}
+
 /* Output text from TEMPLATE to the assembler output file,
    obeying %-directions to substitute operands taken from
    the vector OPERANDS.
@@ -3280,32 +3304,6 @@ output_operand_lossage (msgid)
       and print a constant expression for minus the value
       of the operand, with no other punctuation.  */
 
-static void
-output_asm_name ()
-{
-  if (flag_print_asm_name)
-    {
-      /* Annotate the assembly with a comment describing the pattern and
-        alternative used.  */
-      if (debug_insn)
-       {
-         int num = INSN_CODE (debug_insn);
-         fprintf (asm_out_file, "\t%s %d\t%s",
-                  ASM_COMMENT_START, INSN_UID (debug_insn),
-                  insn_data[num].name);
-         if (insn_data[num].n_alternatives > 1)
-           fprintf (asm_out_file, "/%d", which_alternative + 1);
-#ifdef HAVE_ATTR_length
-         fprintf (asm_out_file, "\t[length = %d]",
-                  get_attr_length (debug_insn));
-#endif
-         /* Clear this so only the first assembler insn
-            of any rtl insn will get the special comment for -dp.  */
-         debug_insn = 0;
-       }
-    }
-}
-
 void
 output_asm_insn (template, operands)
      const char *template;
@@ -3316,6 +3314,8 @@ output_asm_insn (template, operands)
 #ifdef ASSEMBLER_DIALECT
   int dialect = 0;
 #endif
+  int oporder[MAX_RECOG_OPERANDS];
+  int ops = 0;
 
   /* An insn may return a null string template
      in a case where no assembler code is needed.  */
@@ -3333,7 +3333,9 @@ output_asm_insn (template, operands)
     switch (c)
       {
       case '\n':
-       output_asm_name ();
+       if (flag_print_asm_name)
+         output_asm_name ();
+
        putc (c, asm_out_file);
 #ifdef ASM_OUTPUT_OPCODE
        while ((c = *p) == '\t')
@@ -3425,7 +3427,8 @@ output_asm_insn (template, operands)
 
            if (! (*p >= '0' && *p <= '9'))
              output_operand_lossage ("operand number missing after %-letter");
-           else if (this_is_asm_operands && (c < 0 || (unsigned int) c >= insn_noperands))
+           else if (this_is_asm_operands
+                    && (c < 0 || (unsigned int) c >= insn_noperands))
              output_operand_lossage ("operand number out of range");
            else if (letter == 'l')
              output_asm_label (operands[c]);
@@ -3452,6 +3455,8 @@ output_asm_insn (template, operands)
            else
              output_operand (operands[c], letter);
 
+           oporder[ops++] = c;
+
            while ((c = *p) >= '0' && c <= '9')
              p++;
          }
@@ -3464,6 +3469,8 @@ output_asm_insn (template, operands)
              output_operand_lossage ("operand number out of range");
            else
              output_operand (operands[c], 0);
+
+           oporder[ops++] = c;
            while ((c = *p) >= '0' && c <= '9')
              p++;
          }
@@ -3482,7 +3489,30 @@ output_asm_insn (template, operands)
        putc (c, asm_out_file);
       }
 
-  output_asm_name ();
+  /* Write out the variable names for operands, if we know them.  */
+  if (flag_verbose_asm)
+    {
+      int wrote = 0;
+      int i;
+
+      for (i = 0; i < ops; i++)
+       {
+         rtx op = operands[oporder[i]];
+         tree decl = (GET_CODE (op) == REG ? REGNO_DECL (ORIGINAL_REGNO (op))
+                      : GET_CODE (op) == MEM ? MEM_DECL (op)
+                      : 0);
+
+         if (decl && DECL_NAME (decl))
+           {
+             fprintf (asm_out_file, "%s %s", wrote ? "," : ASM_COMMENT_START,
+                      IDENTIFIER_POINTER (DECL_NAME (decl)));
+             wrote = 1;
+           }
+       }
+    }
+
+  if (flag_print_asm_name)
+    output_asm_name ();
 
   putc ('\n', asm_out_file);
 }
index 19b9f5057984006ed9248f878494b3e05c441053..51beeef08cb9b5381caaf0ee2820887e6d777a2d 100644 (file)
@@ -5022,6 +5022,15 @@ assign_parms (fndecl)
          set_mem_attributes (x, result, 1);
          SET_DECL_RTL (result, x);
        }
+
+      if (GET_CODE (DECL_RTL (parm)) == REG)
+       REGNO_DECL (REGNO (DECL_RTL (parm))) = parm;
+      else if (GET_CODE (DECL_RTL (parm)) == CONCAT)
+       {
+         REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 0))) = parm;
+         REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 1))) = parm;
+       }
+
     }
 
   /* Output all parameter conversion instructions (possibly including calls)
index e339911062b92fc8b2727acd78016d6a622790e0..cc01d164975ccd425bb7ba3ef133417c704bf183 100644 (file)
@@ -97,10 +97,10 @@ struct emit_status
   int x_last_linenum;
   const char *x_last_filename;
 
-  /* The length of the regno_pointer_align and x_regno_reg_rtx vectors.
-     Since these vectors are needed during the expansion phase when
-     the total number of registers in the function is not yet known,
-     the vectors are copied and made bigger when necessary.  */
+  /* The length of the regno_pointer_align, regno_decl, and x_regno_reg_rtx
+     vectors.  Since these vectors are needed during the expansion phase when
+     the total number of registers in the function is not yet known, the
+     vectors are copied and made bigger when necessary.  */
   int regno_pointer_align_length;
 
   /* Indexed by pseudo register number, if nonzero gives the known alignment
@@ -108,6 +108,10 @@ struct emit_status
      Allocated in parallel with x_regno_reg_rtx.  */
   unsigned char *regno_pointer_align;
 
+  /* Indexed by pseudo register number, if nonzero gives the decl
+     corresponding to that register.  */
+  tree *regno_decl;
+
   /* Indexed by pseudo register number, gives the rtx for that pseudo.
      Allocated in parallel with regno_pointer_align.  */
   rtx *x_regno_reg_rtx;
@@ -120,6 +124,7 @@ struct emit_status
 #define seq_stack (cfun->emit->sequence_stack)
 
 #define REGNO_POINTER_ALIGN(REGNO) (cfun->emit->regno_pointer_align[REGNO])
+#define REGNO_DECL(REGNO) (cfun->emit->regno_decl[REGNO])
 
 struct expr_status
 {
index 1cbeca0608173f901503f1b4519d1c5912bae7c9..392ac5923e9c9e5e4b7cf71734797bd498efbd72 100644 (file)
@@ -1779,6 +1779,15 @@ integrate_decl_tree (let, map)
          r = DECL_RTL (d);
          subst_constants (&r, NULL_RTX, map, 1);
          SET_DECL_RTL (d, r);
+
+         if (GET_CODE (r) == REG)
+           REGNO_DECL (REGNO (r)) = d;
+         else if (GET_CODE (r) == CONCAT)
+           {
+             REGNO_DECL (REGNO (XEXP (r, 0))) = d;
+             REGNO_DECL (REGNO (XEPX (r, 1))) = d;
+           }
+
          apply_change_group ();
        }
 
index a514bd5a4a6b2c14391f1c366a6042d8b9cc65c1..826da242dc188c3672d1ebdde74c08a5216d308f 100644 (file)
@@ -2496,6 +2496,24 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
                      || GET_CODE (XEXP (note, 0)) == LABEL_REF))))
        REG_POINTER (SET_DEST (x)) = 1;
 
+      /* If this is setting a register from a register or from a simple
+        conversion of a register, propagate REG_DECL.  */
+      if (GET_CODE (dest) == REG)
+       {
+         rtx src = SET_SRC (x);
+
+         while (GET_CODE (src) == SIGN_EXTEND
+                || GET_CODE (src) == ZERO_EXTEND
+                || GET_CODE (src) == TRUNCATE
+                || (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
+           src = XEXP (src, 0);
+
+         if (GET_CODE (src) == REG && REGNO_DECL (REGNO (src)) == 0)
+           REGNO_DECL (REGNO (src)) = REGNO_DECL (REGNO (dest));
+         else if (GET_CODE (src) == REG && REGNO_DECL (REGNO (dest)) == 0)
+           REGNO_DECL (REGNO (dest)) = REGNO_DECL (REGNO (src));
+       }
+
       /* ... fall through ...  */
 
     default:
index 6a8f235ee5491b8e02f0a20fb7b7d5ba39a31081..1d84eea4637c8d4d5138b95e65a6a422011ffc10 100644 (file)
@@ -3999,6 +3999,15 @@ expand_decl (decl)
        = promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
 
       SET_DECL_RTL (decl, gen_reg_rtx (reg_mode));
+
+      if (GET_CODE (DECL_RTL (decl)) == REG)
+       REGNO_DECL (REGNO (DECL_RTL (decl))) = decl;
+      else if (GET_CODE (DECL_RTL (decl)) == CONCAT)
+       {
+         REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 0))) = decl;
+         REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 1))) = decl;
+       }
+
       mark_user_reg (DECL_RTL (decl));
 
       if (POINTER_TYPE_P (type))
@@ -4020,6 +4029,7 @@ expand_decl (decl)
       /* Variable of fixed size that goes on the stack.  */
       rtx oldaddr = 0;
       rtx addr;
+      rtx x;
 
       /* If we previously made RTL for this decl, it must be an array
         whose size was determined by the initializer.
@@ -4033,14 +4043,15 @@ expand_decl (decl)
          oldaddr = XEXP (DECL_RTL (decl), 0);
        }
 
-      SET_DECL_RTL (decl,
-                   assign_temp (TREE_TYPE (decl), 1, 1, 1));
-
       /* Set alignment we actually gave this decl.  */
       DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
                           : GET_MODE_BITSIZE (DECL_MODE (decl)));
       DECL_USER_ALIGN (decl) = 0;
 
+      x = assign_temp (TREE_TYPE (decl), 1, 1, 1);
+      set_mem_attributes (x, decl, 1);
+      SET_DECL_RTL (decl, x);
+
       if (oldaddr)
        {
          addr = force_operand (XEXP (DECL_RTL (decl), 0), oldaddr);