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
This commit is contained in:
parent
eacecf9665
commit
0d4903b81e
@ -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.
|
||||
|
@ -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)
|
||||
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);
|
||||
|
124
gcc/expr.c
124
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
|
||||
}
|
||||
|
||||
to_rtx
|
||||
= change_address (to_rtx, VOIDmode,
|
||||
gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
|
||||
force_reg (ptr_mode,
|
||||
offset_rtx)));
|
||||
#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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
#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);
|
||||
#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. */
|
||||
|
@ -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
|
||||
|
72
gcc/final.c
72
gcc/final.c
@ -3264,29 +3264,12 @@ output_operand_lossage (msgid)
|
||||
|
||||
/* Output of assembler code from a template, and its subroutines. */
|
||||
|
||||
/* Output text from TEMPLATE to the assembler output file,
|
||||
obeying %-directions to substitute operands taken from
|
||||
the vector OPERANDS.
|
||||
|
||||
%N (for N a digit) means print operand N in usual manner.
|
||||
%lN means require operand N to be a CODE_LABEL or LABEL_REF
|
||||
and print the label name with no punctuation.
|
||||
%cN means require operand N to be a constant
|
||||
and print the constant expression with no punctuation.
|
||||
%aN means expect operand N to be a memory address
|
||||
(not a memory reference!) and print a reference
|
||||
to that address.
|
||||
%nN means expect operand N to be a constant
|
||||
and print a constant expression for minus the value
|
||||
of the operand, with no other punctuation. */
|
||||
/* Annotate the assembly with a comment describing the pattern and
|
||||
alternative used. */
|
||||
|
||||
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);
|
||||
@ -3303,9 +3286,24 @@ output_asm_name ()
|
||||
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.
|
||||
|
||||
%N (for N a digit) means print operand N in usual manner.
|
||||
%lN means require operand N to be a CODE_LABEL or LABEL_REF
|
||||
and print the label name with no punctuation.
|
||||
%cN means require operand N to be a constant
|
||||
and print the constant expression with no punctuation.
|
||||
%aN means expect operand N to be a memory address
|
||||
(not a memory reference!) and print a reference
|
||||
to that address.
|
||||
%nN means expect operand N to be a constant
|
||||
and print a constant expression for minus the value
|
||||
of the operand, with no other punctuation. */
|
||||
|
||||
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':
|
||||
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,6 +3489,29 @@ output_asm_insn (template, operands)
|
||||
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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
17
gcc/stmt.c
17
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);
|
||||
|
Loading…
Reference in New Issue
Block a user