Various MEM (and REG!) tracking stuff

Richard Kenner kenner@vlsi1.ultra.nyu.edu
Thu Oct 18 14:39:00 GMT 2001


This contains a number of lightly-related things:

(1) It tracks the decl corresponding to a pseudo.  Since we have
ORIGINAL_REGNO, this means we retain that linkage after reload.

(2) Using that info and the recently-added MEM_DECL, if -fverbose-asm is
enabled, it writes out variable names corresponding to operands, in the
order of the operands, as assembler comments.

(3) Two new functions are added to enable proper adjustment of alignment
when a new MEM is made corresponding to addressing into an array.

(4) There are some minor fixes with ptr_mode vs. Pmode confusion in
code related to the above item and an error in init_emit is also fixed.

Tested on alphaev56.

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.
	
*** emit-rtl.c	2001/10/17 09:31:35	1.210
--- emit-rtl.c	2001/10/18 19:04:15
*************** gen_reg_rtx (mode)
*** 660,671 ****
      }
  
!   /* Make sure regno_pointer_align 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;
        new = xrealloc (f->emit->regno_pointer_align, old_size * 2);
        memset (new + old_size, 0, old_size);
--- 660,673 ----
      }
  
!   /* 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;
        char *new;
+       rtx *new1;
+       tree *new2;
+ 
        new = xrealloc (f->emit->regno_pointer_align, old_size * 2);
        memset (new + old_size, 0, old_size);
*************** gen_reg_rtx (mode)
*** 677,680 ****
--- 679,687 ----
        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;
      }
*************** adjust_address_1 (memref, mode, offset, 
*** 1879,1882 ****
--- 1886,1915 ----
  
  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
+    by putting something into a register.  */
+ 
+ rtx
  replace_equiv_address (memref, addr)
       rtx memref;
*************** free_emit_status (f)
*** 1979,1982 ****
--- 2012,2016 ----
    free (f->emit->x_regno_reg_rtx);
    free (f->emit->regno_pointer_align);
+   free (f->emit->regno_decl);
    free (f->emit);
    f->emit = NULL;
*************** init_emit ()
*** 4403,4408 ****
  
    regno_reg_rtx
!     = (rtx *) xcalloc (f->emit->regno_pointer_align_length * sizeof (rtx),
! 		       sizeof (rtx));
  
    /* Put copies of all the virtual register rtx into regno_reg_rtx.  */
--- 4437,4444 ----
  
    regno_reg_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.  */
*************** mark_emit_status (es)
*** 4461,4464 ****
--- 4497,4501 ----
  {
    rtx *r;
+   tree *t;
    int i;
  
*************** mark_emit_status (es)
*** 4466,4472 ****
      return;
  
!   for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx;
!        i > 0; --i, ++r)
!     ggc_mark_rtx (*r);
  
    mark_sequence_stack (es->sequence_stack);
--- 4503,4513 ----
      return;
  
!   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);
*** expr.c	2001/10/17 09:31:35	1.360
--- expr.c	2001/10/18 19:05:30
*************** static enum memory_use_mode
*** 165,168 ****
--- 165,169 ----
    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));
*************** expand_assignment (to, from, want_value,
*** 3761,3768 ****
  	    }
  
! 	  to_rtx = change_address (to_rtx, VOIDmode,
! 				   gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
! 						 force_reg (ptr_mode,
! 							    offset_rtx)));
  	}
  
--- 3762,3767 ----
  	    }
  
! 	  to_rtx = offset_address (to_rtx, offset_rtx,
! 				   highest_pow2_factor (offset));
  	}
  
*************** expand_assignment (to, from, want_value,
*** 3901,3906 ****
  	{
  #ifdef POINTERS_EXTEND_UNSIGNED
! 	  if (TREE_CODE (TREE_TYPE (to)) == REFERENCE_TYPE
! 	     || TREE_CODE (TREE_TYPE (to)) == POINTER_TYPE)
  	    value = convert_memory_address (GET_MODE (to_rtx), value);
  #endif
--- 3900,3905 ----
  	{
  #ifdef POINTERS_EXTEND_UNSIGNED
! 	  if (POINTER_TYPE_P (TREE_TYPE (to))
! 	      && GET_MODE (to_rtx) != GET_MODE (value))
  	    value = convert_memory_address (GET_MODE (to_rtx), value);
  #endif
*************** store_constructor (exp, target, align, c
*** 4649,4665 ****
  
  	      if (GET_MODE (offset_rtx) != ptr_mode)
! 		{
  #ifdef POINTERS_EXTEND_UNSIGNED
!                   offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
! #else
!                   offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
  #endif
!                 }
  
- 	      to_rtx
- 		= change_address (to_rtx, VOIDmode,
- 				  gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
- 						force_reg (ptr_mode,
- 							   offset_rtx)));
  	      align = DECL_OFFSET_ALIGN (field);
  	    }
--- 4648,4660 ----
  
  	      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 (Pmode, offset_rtx);
  #endif
! 
! 	      to_rtx = offset_address (to_rtx, offset_rtx,
! 				       highest_pow2_factor (offset));
  
  	      align = DECL_OFFSET_ALIGN (field);
  	    }
*************** store_constructor (exp, target, align, c
*** 4821,4825 ****
  	      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;
  	      struct nesting *loop;
  	      HOST_WIDE_INT lo, hi, count;
--- 4816,4820 ----
  	      tree lo_index = TREE_OPERAND (index, 0);
  	      tree hi_index = TREE_OPERAND (index, 1);
! 	      rtx index_r, pos_rtx, hi_r, loop_top, loop_end;
  	      struct nesting *loop;
  	      HOST_WIDE_INT lo, hi, count;
*************** store_constructor (exp, target, align, c
*** 4885,4890 ****
  
  		  pos_rtx = expand_expr (position, 0, VOIDmode, 0);
! 		  addr = gen_rtx_PLUS (Pmode, XEXP (target, 0), pos_rtx);
! 		  xtarget = change_address (target, mode, addr);
  		  if (TREE_CODE (value) == CONSTRUCTOR)
  		    store_constructor (value, xtarget, align, cleared,
--- 4880,4886 ----
  
  		  pos_rtx = expand_expr (position, 0, VOIDmode, 0);
! 		  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,
*************** store_constructor (exp, target, align, c
*** 4907,4911 ****
  		   || ! host_integerp (TYPE_SIZE (elttype), 1))
  	    {
- 	      rtx pos_rtx, addr;
  	      tree position;
  
--- 4903,4906 ----
*************** store_constructor (exp, target, align, c
*** 4921,4927 ****
  				     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);
  	      store_expr (value, xtarget, 0);
  	    }
--- 4916,4923 ----
  				     convert (ssizetype,
  					      TYPE_SIZE_UNIT (elttype)));
! 	      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);
  	    }
*************** check_max_integer_computation_mode (exp)
*** 5966,5969 ****
--- 5962,6021 ----
  #endif
  
+ /* 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;
+ }
+ 
  /* Return an object on the placeholder list that matches EXP, a
     PLACEHOLDER_EXPR.  An object "matches" if it is of the type of the
*************** expand_expr (exp, target, tmode, modifie
*** 7019,7029 ****
  
  	    if (GET_MODE (offset_rtx) != ptr_mode)
! 	      {
  #ifdef POINTERS_EXTEND_UNSIGNED
! 		offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
! #else
! 		offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
  #endif
- 	      }
  
  	    /* A constant address in OP0 can have VOIDmode, we must not try
--- 7071,7079 ----
  
  	    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);
  #endif
  
  	    /* A constant address in OP0 can have VOIDmode, we must not try
*************** expand_expr (exp, target, tmode, modifie
*** 7049,7056 ****
  	      }
  
! 	    op0 = change_address (op0, VOIDmode,
! 				  gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
! 						force_reg (ptr_mode,
! 							   offset_rtx)));
  	  }
  
--- 7099,7104 ----
  	      }
  
! 	    op0 = offset_address (op0, offset_rtx,
! 				  highest_pow2_factor (offset));
  	  }
  
*************** expand_expr_unaligned (exp, palign)
*** 9037,9052 ****
  
  	    if (GET_MODE (offset_rtx) != ptr_mode)
! 	      {
  #ifdef POINTERS_EXTEND_UNSIGNED
! 		offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
! #else
! 		offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
  #endif
- 	      }
  
! 	    op0 = change_address (op0, VOIDmode,
! 				  gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
! 						force_reg (ptr_mode,
! 							   offset_rtx)));
  	  }
  
--- 9085,9096 ----
  
  	    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);
  #endif
  
! 	    op0 = offset_address (op0, offset_rtx,
! 				  highest_pow2_factor (offset));
  	  }
  
*** expr.h	2001/10/17 09:31:36	1.96
--- expr.h	2001/10/18 19:05:44
*************** extern rtx adjust_address_1 PARAMS ((rtx
*** 634,637 ****
--- 634,642 ----
  				     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
*** final.c	2001/10/12 10:51:12	1.209
--- final.c	2001/10/18 19:06:15
*************** output_operand_lossage (msgid)
*** 3265,3268 ****
--- 3265,3292 ----
  /* 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
*************** output_operand_lossage (msgid)
*** 3281,3310 ****
        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)
--- 3305,3308 ----
*************** output_asm_insn (template, operands)
*** 3317,3320 ****
--- 3315,3320 ----
    int dialect = 0;
  #endif
+   int oporder[MAX_RECOG_OPERANDS];
+   int ops = 0;
  
    /* An insn may return a null string template
*************** output_asm_insn (template, operands)
*** 3334,3338 ****
        {
        case '\n':
! 	output_asm_name ();
  	putc (c, asm_out_file);
  #ifdef ASM_OUTPUT_OPCODE
--- 3334,3340 ----
        {
        case '\n':
! 	if (flag_print_asm_name)
! 	  output_asm_name ();
! 
  	putc (c, asm_out_file);
  #ifdef ASM_OUTPUT_OPCODE
*************** output_asm_insn (template, operands)
*** 3426,3430 ****
  	    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))
  	      output_operand_lossage ("operand number out of range");
  	    else if (letter == 'l')
--- 3428,3433 ----
  	    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))
  	      output_operand_lossage ("operand number out of range");
  	    else if (letter == 'l')
*************** output_asm_insn (template, operands)
*** 3453,3456 ****
--- 3456,3461 ----
  	      output_operand (operands[c], letter);
  
+ 	    oporder[ops++] = c;
+ 
  	    while ((c = *p) >= '0' && c <= '9')
  	      p++;
*************** output_asm_insn (template, operands)
*** 3465,3468 ****
--- 3470,3475 ----
  	    else
  	      output_operand (operands[c], 0);
+ 
+ 	    oporder[ops++] = c;
  	    while ((c = *p) >= '0' && c <= '9')
  	      p++;
*************** output_asm_insn (template, operands)
*** 3482,3487 ****
  	putc (c, asm_out_file);
        }
  
!   output_asm_name ();
  
    putc ('\n', asm_out_file);
--- 3489,3517 ----
  	putc (c, asm_out_file);
        }
+ 
+   /* 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);
*** function.c	2001/10/11 03:15:40	1.314
--- function.c	2001/10/18 19:07:08
*************** assign_parms (fndecl)
*** 5023,5026 ****
--- 5023,5035 ----
  	  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;
+ 	}
+ 
      }
  
*** function.h	2001/10/09 22:40:11	1.69
--- function.h	2001/10/18 19:07:12
*************** struct emit_status
*** 98,105 ****
    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.  */
    int regno_pointer_align_length;
  
--- 98,105 ----
    const char *x_last_filename;
  
!   /* 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;
  
*************** struct emit_status
*** 109,112 ****
--- 109,116 ----
    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.  */
*************** struct emit_status
*** 121,124 ****
--- 125,129 ----
  
  #define REGNO_POINTER_ALIGN(REGNO) (cfun->emit->regno_pointer_align[REGNO])
+ #define REGNO_DECL(REGNO) (cfun->emit->regno_decl[REGNO])
  
  struct expr_status
*** integrate.c	2001/10/11 03:15:48	1.169
--- integrate.c	2001/10/18 19:19:02
*************** integrate_decl_tree (let, map)
*** 1780,1783 ****
--- 1780,1792 ----
  	  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 ();
  	}
*** regclass.c	2001/10/11 03:15:57	1.136
--- regclass.c	2001/10/18 19:08:05
*************** reg_scan_mark_refs (x, insn, note_flag, 
*** 2497,2500 ****
--- 2497,2518 ----
  	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 ...  */
  
*** stmt.c	2001/10/17 00:32:56	1.220
--- stmt.c	2001/10/18 19:08:59
*************** expand_decl (decl)
*** 4000,4003 ****
--- 4000,4012 ----
  
        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));
  
*************** expand_decl (decl)
*** 4021,4024 ****
--- 4030,4034 ----
        rtx oldaddr = 0;
        rtx addr;
+       rtx x;
  
        /* If we previously made RTL for this decl, it must be an array
*************** expand_decl (decl)
*** 4034,4044 ****
  	}
  
-       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;
  
        if (oldaddr)
--- 4044,4055 ----
  	}
  
        /* 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)



More information about the Gcc-patches mailing list