Commit ae00112b by Eric Botcazou

expr.c (expand_expr_real_1): Force op0 to non-constant memory if it cannot be…

expr.c (expand_expr_real_1): Force op0 to non-constant memory if it cannot be forced to constant memory.

	* expr.c (expand_expr_real_1) <normal_inner_ref>: Force op0 to
	non-constant memory if it cannot be forced to constant memory.
	Overhaul surrounding code and factor out common condition.

From-SVN: r140760
parent 6b5676ce
2008-09-11 Jeff Law <law@redhat.com> 2008-09-29 Eric Botcazou <ebotcazou@adacore.com>
* expr.c (expand_expr_real_1) <normal_inner_ref>: Force op0 to
non-constant memory if it cannot be forced to constant memory.
Overhaul surrounding code and factor out common condition.
2008-09-29 Jeff Law <law@redhat.com>
* reload1.c (alter_reg): Add missing curly braces. * reload1.c (alter_reg): Add missing curly braces.
......
...@@ -7744,13 +7744,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -7744,13 +7744,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
case ARRAY_RANGE_REF: case ARRAY_RANGE_REF:
normal_inner_ref: normal_inner_ref:
{ {
enum machine_mode mode1; enum machine_mode mode1, mode2;
HOST_WIDE_INT bitsize, bitpos; HOST_WIDE_INT bitsize, bitpos;
tree offset; tree offset;
int volatilep = 0; int volatilep = 0, must_force_mem;
tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode1, &unsignedp, &volatilep, true); &mode1, &unsignedp, &volatilep, true);
rtx orig_op0; rtx orig_op0, memloc;
/* If we got back the original object, something is wrong. Perhaps /* If we got back the original object, something is wrong. Perhaps
we are evaluating an expression too early. In any event, don't we are evaluating an expression too early. In any event, don't
...@@ -7760,7 +7760,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -7760,7 +7760,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
/* If TEM's type is a union of variable size, pass TARGET to the inner /* If TEM's type is a union of variable size, pass TARGET to the inner
computation, since it will need a temporary and TARGET is known computation, since it will need a temporary and TARGET is known
to have to do. This occurs in unchecked conversion in Ada. */ to have to do. This occurs in unchecked conversion in Ada. */
orig_op0 = op0 orig_op0 = op0
= expand_expr (tem, = expand_expr (tem,
(TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
...@@ -7774,45 +7773,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -7774,45 +7773,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|| modifier == EXPAND_STACK_PARM) || modifier == EXPAND_STACK_PARM)
? modifier : EXPAND_NORMAL); ? modifier : EXPAND_NORMAL);
/* If this is a constant, put it into a register if it is a legitimate mode2
constant, OFFSET is 0, and we won't try to extract outside the = CONSTANT_P (op0) ? TYPE_MODE (TREE_TYPE (tem)) : GET_MODE (op0);
register (in case we were passed a partially uninitialized object
or a view_conversion to a larger size) or a BLKmode piece of it /* If we have either an offset, a BLKmode result, or a reference
(e.g. if it is unchecked-converted to a record type in Ada). Force outside the underlying object, we must force it to memory.
the constant to memory otherwise. */ Such a case can occur in Ada if we have unchecked conversion
if (CONSTANT_P (op0)) of an expression from a scalar type to an aggregate type or
{ for an ARRAY_RANGE_REF whose type is BLKmode, or if we were
enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem)); passed a partially uninitialized object or a view-conversion
if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0) to a larger size. */
&& offset == 0 must_force_mem = (offset
&& mode1 != BLKmode
&& bitpos + bitsize <= GET_MODE_BITSIZE (mode))
op0 = force_reg (mode, op0);
else
op0 = validize_mem (force_const_mem (mode, op0));
}
/* Otherwise, if this object not in memory and we either have an
offset, a BLKmode result, or a reference outside the object, put it
there. Such cases can occur in Ada if we have unchecked conversion
of an expression from a scalar type to an array or record type or
for an ARRAY_RANGE_REF whose type is BLKmode. */
else if (!MEM_P (op0)
&& (offset != 0
|| mode1 == BLKmode || mode1 == BLKmode
|| (bitpos + bitsize || bitpos + bitsize > GET_MODE_BITSIZE (mode2));
> GET_MODE_BITSIZE (GET_MODE (op0)))))
/* If this is a constant, put it in a register if it is a legitimate
constant and we don't need a memory reference. */
if (CONSTANT_P (op0)
&& mode2 != BLKmode
&& LEGITIMATE_CONSTANT_P (op0)
&& !must_force_mem)
op0 = force_reg (mode2, op0);
/* Otherwise, if this is a constant, try to force it to the constant
pool. Note that back-ends, e.g. MIPS, may refuse to do so if it
is a legitimate constant. */
else if (CONSTANT_P (op0) && (memloc = force_const_mem (mode2, op0)))
op0 = validize_mem (memloc);
/* Otherwise, if this is a constant or the object is not in memory
and need be, put it there. */
else if (CONSTANT_P (op0) || (!MEM_P (op0) && must_force_mem))
{ {
tree nt = build_qualified_type (TREE_TYPE (tem), tree nt = build_qualified_type (TREE_TYPE (tem),
(TYPE_QUALS (TREE_TYPE (tem)) (TYPE_QUALS (TREE_TYPE (tem))
| TYPE_QUAL_CONST)); | TYPE_QUAL_CONST));
rtx memloc = assign_temp (nt, 1, 1, 1); memloc = assign_temp (nt, 1, 1, 1);
emit_move_insn (memloc, op0); emit_move_insn (memloc, op0);
op0 = memloc; op0 = memloc;
} }
if (offset != 0) if (offset)
{ {
rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
EXPAND_SUM); EXPAND_SUM);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment