aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/emit-rtl.c57
-rw-r--r--gcc/expr.c126
-rw-r--r--gcc/expr.h5
-rw-r--r--gcc/final.c88
-rw-r--r--gcc/function.c9
-rw-r--r--gcc/function.h13
-rw-r--r--gcc/integrate.c9
-rw-r--r--gcc/regclass.c18
-rw-r--r--gcc/stmt.c17
10 files changed, 282 insertions, 85 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a85d7dd..dd5331c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 50819c6..c7c6140 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -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;
}
@@ -1878,6 +1885,32 @@ adjust_address_1 (memref, mode, offset, validate)
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
+ by putting something into a register. */
+
+rtx
replace_equiv_address (memref, addr)
rtx memref;
rtx addr;
@@ -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);
diff --git a/gcc/expr.c b/gcc/expr.c
index e06d4b1..f486b32 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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
+/* 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
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. */
diff --git a/gcc/expr.h b/gcc/expr.h
index af79fd5..ad24cb7 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -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
diff --git a/gcc/final.c b/gcc/final.c
index 5d2d8d9..38ec173 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -3264,6 +3264,30 @@ output_operand_lossage (msgid)
/* 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);
}
diff --git a/gcc/function.c b/gcc/function.c
index 19b9f50..51beeef 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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)
diff --git a/gcc/function.h b/gcc/function.h
index e339911..cc01d16 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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
{
diff --git a/gcc/integrate.c b/gcc/integrate.c
index 1cbeca0..392ac59 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -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 ();
}
diff --git a/gcc/regclass.c b/gcc/regclass.c
index a514bd5..826da24 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -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:
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 6a8f235..1d84eea 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -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);