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:
Richard Kenner 2001-10-18 21:34:14 +00:00 committed by Richard Kenner
parent eacecf9665
commit 0d4903b81e
10 changed files with 286 additions and 89 deletions

View File

@ -1,3 +1,28 @@
Thu Oct 18 16:07:39 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* emit-rtl.c (gen_reg_rtx): Also reallocate reg_decl array.
(offset_address): New function.
(free_emit_status): Free regno_decl.
(init_emit): Pass proper number of elements to xcalloc.
Allocate regno_decl.
(mark_emit_status): Mark regno_decl values.
* expr.c (highest_pow2_factor): New function.
(expand_assigment): Use it and offset_address.
Properly handle ptr_mode vs. Pmode in offset calculation.
(store_constructor, expand_expr_unaligned): Likewise.
(expand_expr, case COMPONENT_EXPR): Likewise.
* expr.h (offset_address): New decl.
* function.h (struct emit_status): Add regno_decl.
(REGNO_DECL): New macro.
* final.c (output_asm_name): Move in file and don't conditionalize
on flag_print_asm_name.
(output_asm_insn): Only call output_asm_name if flag_print_asm_name.
Output names of operands, if known.
* function.c (assign_parms): Set REGNO_DECL.
* integrate.c (integrate_decl_tree): Likewise.
* stmt.c (expand_decl): Likewise.
* regclass.c (reg_scan_mark_refs): Propagate REGNO_DECL for copies.
2001-10-18 Alexandre Oliva <aoliva@redhat.com>
* attribs.c (handle_noinline_attribute): New function.

View File

@ -659,14 +659,16 @@ gen_reg_rtx (mode)
return gen_rtx_CONCAT (mode, realpart, imagpart);
}
/* Make sure regno_pointer_align and regno_reg_rtx are large enough
to have an element for this pseudo reg number. */
/* Make sure regno_pointer_align, regno_decl, and regno_reg_rtx are large
enough to have an element for this pseudo reg number. */
if (reg_rtx_no == f->emit->regno_pointer_align_length)
{
int old_size = f->emit->regno_pointer_align_length;
rtx *new1;
char *new;
rtx *new1;
tree *new2;
new = xrealloc (f->emit->regno_pointer_align, old_size * 2);
memset (new + old_size, 0, old_size);
f->emit->regno_pointer_align = (unsigned char *) new;
@ -676,6 +678,11 @@ gen_reg_rtx (mode)
memset (new1 + old_size, 0, old_size * sizeof (rtx));
regno_reg_rtx = new1;
new2 = (tree *) xrealloc (f->emit->regno_decl,
old_size * 2 * sizeof (tree));
memset (new2 + old_size, 0, old_size * sizeof (tree));
f->emit->regno_decl = new2;
f->emit->regno_pointer_align_length = old_size * 2;
}
@ -1872,6 +1879,32 @@ adjust_address_1 (memref, mode, offset, validate)
return new;
}
/* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as
by putting something into a register. */
rtx
offset_address (memref, offset, pow2)
rtx memref;
rtx offset;
HOST_WIDE_INT pow2;
{
rtx new = change_address_1 (memref, VOIDmode,
gen_rtx_PLUS (Pmode, XEXP (memref, 0),
force_reg (Pmode, offset)), 1);
unsigned int memalign = MEM_ALIGN (memref);
/* Update the alignment to reflect the offset. Reset the offset, which
we don't know. */
while (pow2 % memalign != 0)
memalign >>= 1;
MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
0, 0, memalign);
return new;
}
/* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as
@ -1978,6 +2011,7 @@ free_emit_status (f)
{
free (f->emit->x_regno_reg_rtx);
free (f->emit->regno_pointer_align);
free (f->emit->regno_decl);
free (f->emit);
f->emit = NULL;
}
@ -4402,8 +4436,10 @@ init_emit ()
sizeof (unsigned char));
regno_reg_rtx
= (rtx *) xcalloc (f->emit->regno_pointer_align_length * sizeof (rtx),
sizeof (rtx));
= (rtx *) xcalloc (f->emit->regno_pointer_align_length, sizeof (rtx));
f->emit->regno_decl
= (tree *) xcalloc (f->emit->regno_pointer_align_length, sizeof (tree));
/* Put copies of all the virtual register rtx into regno_reg_rtx. */
init_virtual_regs (f->emit);
@ -4460,14 +4496,19 @@ mark_emit_status (es)
struct emit_status *es;
{
rtx *r;
tree *t;
int i;
if (es == 0)
return;
for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx;
i > 0; --i, ++r)
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);

View File

@ -164,6 +164,7 @@ static rtx store_field PARAMS ((rtx, HOST_WIDE_INT,
static enum memory_use_mode
get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
static rtx var_rtx PARAMS ((tree));
static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
static rtx expand_increment PARAMS ((tree, int, int));
static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
@ -3760,10 +3761,8 @@ expand_assignment (to, from, want_value, suggest_reg)
bitpos = 0;
}
to_rtx = change_address (to_rtx, VOIDmode,
gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
force_reg (ptr_mode,
offset_rtx)));
to_rtx = offset_address (to_rtx, offset_rtx,
highest_pow2_factor (offset));
}
if (volatilep)
@ -3900,8 +3899,8 @@ expand_assignment (to, from, want_value, suggest_reg)
else
{
#ifdef POINTERS_EXTEND_UNSIGNED
if (TREE_CODE (TREE_TYPE (to)) == REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (to)) == POINTER_TYPE)
if (POINTER_TYPE_P (TREE_TYPE (to))
&& GET_MODE (to_rtx) != GET_MODE (value))
value = convert_memory_address (GET_MODE (to_rtx), value);
#endif
emit_move_insn (to_rtx, value);
@ -4648,19 +4647,15 @@ store_constructor (exp, target, align, cleared, size)
abort ();
if (GET_MODE (offset_rtx) != ptr_mode)
{
#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. */

View File

@ -633,6 +633,11 @@ extern rtx change_address PARAMS ((rtx, enum machine_mode, rtx));
extern rtx adjust_address_1 PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT,
int));
/* Return a memory reference like MEMREF, but whose address is changed by
adding OFFSET, an RTX, to it. POW2 is the highest power of two factor
known to be in OFFSET (possibly 1). */
extern rtx offset_address PARAMS ((rtx, rtx, HOST_WIDE_INT));
/* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as

View File

@ -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);

View 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)

View File

@ -97,10 +97,10 @@ struct emit_status
int x_last_linenum;
const char *x_last_filename;
/* The length of the regno_pointer_align and x_regno_reg_rtx vectors.
Since these vectors are needed during the expansion phase when
the total number of registers in the function is not yet known,
the vectors are copied and made bigger when necessary. */
/* The length of the regno_pointer_align, regno_decl, and x_regno_reg_rtx
vectors. Since these vectors are needed during the expansion phase when
the total number of registers in the function is not yet known, the
vectors are copied and made bigger when necessary. */
int regno_pointer_align_length;
/* Indexed by pseudo register number, if nonzero gives the known alignment
@ -108,6 +108,10 @@ struct emit_status
Allocated in parallel with x_regno_reg_rtx. */
unsigned char *regno_pointer_align;
/* Indexed by pseudo register number, if nonzero gives the decl
corresponding to that register. */
tree *regno_decl;
/* Indexed by pseudo register number, gives the rtx for that pseudo.
Allocated in parallel with regno_pointer_align. */
rtx *x_regno_reg_rtx;
@ -120,6 +124,7 @@ struct emit_status
#define seq_stack (cfun->emit->sequence_stack)
#define REGNO_POINTER_ALIGN(REGNO) (cfun->emit->regno_pointer_align[REGNO])
#define REGNO_DECL(REGNO) (cfun->emit->regno_decl[REGNO])
struct expr_status
{

View File

@ -1779,6 +1779,15 @@ integrate_decl_tree (let, map)
r = DECL_RTL (d);
subst_constants (&r, NULL_RTX, map, 1);
SET_DECL_RTL (d, r);
if (GET_CODE (r) == REG)
REGNO_DECL (REGNO (r)) = d;
else if (GET_CODE (r) == CONCAT)
{
REGNO_DECL (REGNO (XEXP (r, 0))) = d;
REGNO_DECL (REGNO (XEPX (r, 1))) = d;
}
apply_change_group ();
}

View File

@ -2496,6 +2496,24 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
|| GET_CODE (XEXP (note, 0)) == LABEL_REF))))
REG_POINTER (SET_DEST (x)) = 1;
/* If this is setting a register from a register or from a simple
conversion of a register, propagate REG_DECL. */
if (GET_CODE (dest) == REG)
{
rtx src = SET_SRC (x);
while (GET_CODE (src) == SIGN_EXTEND
|| GET_CODE (src) == ZERO_EXTEND
|| GET_CODE (src) == TRUNCATE
|| (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
src = XEXP (src, 0);
if (GET_CODE (src) == REG && REGNO_DECL (REGNO (src)) == 0)
REGNO_DECL (REGNO (src)) = REGNO_DECL (REGNO (dest));
else if (GET_CODE (src) == REG && REGNO_DECL (REGNO (dest)) == 0)
REGNO_DECL (REGNO (dest)) = REGNO_DECL (REGNO (src));
}
/* ... fall through ... */
default:

View File

@ -3999,6 +3999,15 @@ expand_decl (decl)
= promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
SET_DECL_RTL (decl, gen_reg_rtx (reg_mode));
if (GET_CODE (DECL_RTL (decl)) == REG)
REGNO_DECL (REGNO (DECL_RTL (decl))) = decl;
else if (GET_CODE (DECL_RTL (decl)) == CONCAT)
{
REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 0))) = decl;
REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 1))) = decl;
}
mark_user_reg (DECL_RTL (decl));
if (POINTER_TYPE_P (type))
@ -4020,6 +4029,7 @@ expand_decl (decl)
/* Variable of fixed size that goes on the stack. */
rtx oldaddr = 0;
rtx addr;
rtx x;
/* If we previously made RTL for this decl, it must be an array
whose size was determined by the initializer.
@ -4033,14 +4043,15 @@ expand_decl (decl)
oldaddr = XEXP (DECL_RTL (decl), 0);
}
SET_DECL_RTL (decl,
assign_temp (TREE_TYPE (decl), 1, 1, 1));
/* Set alignment we actually gave this decl. */
DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
: GET_MODE_BITSIZE (DECL_MODE (decl)));
DECL_USER_ALIGN (decl) = 0;
x = assign_temp (TREE_TYPE (decl), 1, 1, 1);
set_mem_attributes (x, decl, 1);
SET_DECL_RTL (decl, x);
if (oldaddr)
{
addr = force_operand (XEXP (DECL_RTL (decl), 0), oldaddr);