From 0d4903b81e2e5f9371c330a82ddad63af0bb272a Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Thu, 18 Oct 2001 21:34:14 +0000 Subject: [PATCH] emit-rtl.c (gen_reg_rtx): Also reallocate reg_decl array. * 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 | 25 +++++++++ gcc/emit-rtl.c | 57 +++++++++++++++++--- gcc/expr.c | 134 ++++++++++++++++++++++++++++++++---------------- gcc/expr.h | 5 ++ gcc/final.c | 88 ++++++++++++++++++++----------- gcc/function.c | 9 ++++ gcc/function.h | 13 +++-- gcc/integrate.c | 9 ++++ gcc/regclass.c | 18 +++++++ gcc/stmt.c | 17 ++++-- 10 files changed, 286 insertions(+), 89 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a85d7ddd449..dd5331c63c8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +Thu Oct 18 16:07:39 2001 Richard Kenner + + * 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 * attribs.c (handle_noinline_attribute): New function. diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 50819c6840c..c7c61401b5e 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; } @@ -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); diff --git a/gcc/expr.c b/gcc/expr.c index e06d4b10974..f486b32e4fd 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) - { -#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 - } + 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)); - 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); } @@ -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) - { -#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 - } + offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0); - op0 = change_address (op0, VOIDmode, - gen_rtx_PLUS (ptr_mode, XEXP (op0, 0), - force_reg (ptr_mode, - offset_rtx))); +#ifdef POINTERS_EXTEND_UNSIGNED + offset_rtx = convert_memory_address (ptr_mode, offset_rtx); +#endif + + 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 af79fd581be..ad24cb7ae74 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 5d2d8d9ae69..38ec17302f5 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 19b9f505798..51beeef08cb 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 e339911062b..cc01d164975 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 1cbeca06081..392ac5923e9 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 a514bd5a4a6..826da242dc1 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 6a8f235ee54..1d84eea4637 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);