summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-29 18:15:28 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-29 18:15:28 +0000
commit952f3892254990bdb086e3dc25e9f63ee28848a6 (patch)
tree34f87eb5fb8a95b70ad305222bd287b998c72b59 /gcc/expr.c
parent95091c079182f509ea1c63304032802ded32ea6b (diff)
downloadgcc-952f3892254990bdb086e3dc25e9f63ee28848a6.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140760 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c71
1 files changed, 36 insertions, 35 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index ae0daf0b251..32c8d01fe7f 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7744,13 +7744,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
case ARRAY_RANGE_REF:
normal_inner_ref:
{
- enum machine_mode mode1;
+ enum machine_mode mode1, mode2;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
- int volatilep = 0;
+ int volatilep = 0, must_force_mem;
tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode1, &unsignedp, &volatilep, true);
- rtx orig_op0;
+ rtx orig_op0, memloc;
/* If we got back the original object, something is wrong. Perhaps
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,
/* 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
to have to do. This occurs in unchecked conversion in Ada. */
-
orig_op0 = op0
= expand_expr (tem,
(TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
@@ -7774,45 +7773,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|| modifier == EXPAND_STACK_PARM)
? modifier : EXPAND_NORMAL);
- /* If this is a constant, put it into a register if it is a legitimate
- constant, OFFSET is 0, and we won't try to extract outside the
- register (in case we were passed a partially uninitialized object
- or a view_conversion to a larger size) or a BLKmode piece of it
- (e.g. if it is unchecked-converted to a record type in Ada). Force
- the constant to memory otherwise. */
- if (CONSTANT_P (op0))
- {
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
- if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
- && offset == 0
- && 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
- || (bitpos + bitsize
- > GET_MODE_BITSIZE (GET_MODE (op0)))))
+ mode2
+ = CONSTANT_P (op0) ? TYPE_MODE (TREE_TYPE (tem)) : GET_MODE (op0);
+
+ /* If we have either an offset, a BLKmode result, or a reference
+ outside the underlying object, we must force it to memory.
+ Such a case can occur in Ada if we have unchecked conversion
+ 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
+ passed a partially uninitialized object or a view-conversion
+ to a larger size. */
+ must_force_mem = (offset
+ || mode1 == BLKmode
+ || bitpos + bitsize > GET_MODE_BITSIZE (mode2));
+
+ /* 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),
(TYPE_QUALS (TREE_TYPE (tem))
| TYPE_QUAL_CONST));
- rtx memloc = assign_temp (nt, 1, 1, 1);
-
+ memloc = assign_temp (nt, 1, 1, 1);
emit_move_insn (memloc, op0);
op0 = memloc;
}
- if (offset != 0)
+ if (offset)
{
rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
EXPAND_SUM);