diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-29 18:15:28 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-29 18:15:28 +0000 |
commit | 952f3892254990bdb086e3dc25e9f63ee28848a6 (patch) | |
tree | 34f87eb5fb8a95b70ad305222bd287b998c72b59 /gcc/expr.c | |
parent | 95091c079182f509ea1c63304032802ded32ea6b (diff) | |
download | gcc-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.c | 71 |
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); |