+ op0 = NULL_RTX;
+
+ /* If we are converting to BLKmode, try to avoid an intermediate
+ temporary by fetching an inner memory reference. */
+ if (mode == BLKmode
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
+ && TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != BLKmode
+ && handled_component_p (TREE_OPERAND (exp, 0)))
+ {
+ enum machine_mode mode1;
+ HOST_WIDE_INT bitsize, bitpos;
+ tree offset;
+ int unsignedp;
+ int volatilep = 0;
+ tree tem
+ = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, &bitpos,
+ &offset, &mode1, &unsignedp, &volatilep,
+ true);
+ rtx orig_op0;
+
+ /* ??? We should work harder and deal with non-zero offsets. */
+ if (!offset
+ && (bitpos % BITS_PER_UNIT) == 0
+ && bitsize >= 0
+ && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) == 0)
+ {
+ /* See the normal_inner_ref case for the rationale. */
+ orig_op0
+ = expand_expr (tem,
+ (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+ && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+ != INTEGER_CST)
+ && modifier != EXPAND_STACK_PARM
+ ? target : NULL_RTX),
+ VOIDmode,
+ (modifier == EXPAND_INITIALIZER
+ || modifier == EXPAND_CONST_ADDRESS
+ || modifier == EXPAND_STACK_PARM)
+ ? modifier : EXPAND_NORMAL);
+
+ if (MEM_P (orig_op0))
+ {
+ op0 = orig_op0;
+
+ /* Get a reference to just this component. */
+ if (modifier == EXPAND_CONST_ADDRESS
+ || modifier == EXPAND_SUM
+ || modifier == EXPAND_INITIALIZER)
+ op0 = adjust_address_nv (op0, mode, bitpos / BITS_PER_UNIT);
+ else
+ op0 = adjust_address (op0, mode, bitpos / BITS_PER_UNIT);
+
+ if (op0 == orig_op0)
+ op0 = copy_rtx (op0);
+
+ set_mem_attributes (op0, TREE_OPERAND (exp, 0), 0);
+ if (REG_P (XEXP (op0, 0)))
+ mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
+
+ MEM_VOLATILE_P (op0) |= volatilep;
+ }
+ }
+ }
+
+ if (!op0)
+ op0 = expand_expr (TREE_OPERAND (exp, 0),
+ NULL_RTX, VOIDmode, modifier);