expr.c (expand_expr_real_1): Force op0 to non-constant memory if it cannot be forced...
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 29 Sep 2008 18:15:28 +0000 (18:15 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 29 Sep 2008 18:15:28 +0000 (18:15 +0000)
* 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

gcc/ChangeLog
gcc/expr.c

index 7eff8160678c1e204eb6c44608b34c53551b6a90..a8d787bd86b2076a28367ac903cc3e383cf6bf2b 100644 (file)
@@ -1,4 +1,10 @@
-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.
 
index ae0daf0b251fd89a02fa1562af1b4882374dc924..32c8d01fe7f40d5bf82179a1f66d29964e03c017 100644 (file)
@@ -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);