Commit e675826d by Eric Botcazou Committed by Eric Botcazou

expr.c (expand_expr_real_1): When converting to BLKmode, try to fetch an inner memory reference.

	* expr.c (expand_expr_real_1) <VIEW_CONVERT_EXPR>: When converting
	to BLKmode, try to fetch an inner memory reference.  Use 'mode' in
	lieu of TYPE_MODE (type) throughout.

From-SVN: r139139
parent 853ff9e2
2008-08-15 Eric Botcazou <ebotcazou@adacore.com>
* expr.c (expand_expr_real_1) <VIEW_CONVERT_EXPR>: When converting
to BLKmode, try to fetch an inner memory reference. Use 'mode' in
lieu of TYPE_MODE (type) throughout.
2008-08-15 Joseph Myers <joseph@codesourcery.com> 2008-08-15 Joseph Myers <joseph@codesourcery.com>
* config/arm/arm.c (add_minipool_backward_ref): Check for * config/arm/arm.c (add_minipool_backward_ref): Check for
......
...@@ -8157,26 +8157,89 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -8157,26 +8157,89 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return REDUCE_BIT_FIELD (op0); return REDUCE_BIT_FIELD (op0);
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier); 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, mode, modifier);
/* If the input and output modes are both the same, we are done. */ /* If the input and output modes are both the same, we are done. */
if (TYPE_MODE (type) == GET_MODE (op0)) if (mode == GET_MODE (op0))
; ;
/* If neither mode is BLKmode, and both modes are the same size /* If neither mode is BLKmode, and both modes are the same size
then we can use gen_lowpart. */ then we can use gen_lowpart. */
else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode else if (mode != BLKmode && GET_MODE (op0) != BLKmode
&& GET_MODE_SIZE (TYPE_MODE (type)) && GET_MODE_SIZE (mode) == GET_MODE_SIZE (GET_MODE (op0)))
== GET_MODE_SIZE (GET_MODE (op0)))
{ {
if (GET_CODE (op0) == SUBREG) if (GET_CODE (op0) == SUBREG)
op0 = force_reg (GET_MODE (op0), op0); op0 = force_reg (GET_MODE (op0), op0);
op0 = gen_lowpart (TYPE_MODE (type), op0); op0 = gen_lowpart (mode, op0);
} }
/* If both modes are integral, then we can convert from one to the /* If both modes are integral, then we can convert from one to the
other. */ other. */
else if (SCALAR_INT_MODE_P (GET_MODE (op0)) else if (SCALAR_INT_MODE_P (GET_MODE (op0)) && SCALAR_INT_MODE_P (mode))
&& SCALAR_INT_MODE_P (TYPE_MODE (type))) op0 = convert_modes (mode, GET_MODE (op0), op0,
op0 = convert_modes (TYPE_MODE (type), GET_MODE (op0), op0,
TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
/* As a last resort, spill op0 to memory, and reload it in a /* As a last resort, spill op0 to memory, and reload it in a
different mode. */ different mode. */
...@@ -8200,8 +8263,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -8200,8 +8263,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op0 = target; op0 = target;
} }
/* At this point, OP0 is in the correct mode. If the output type is such /* At this point, OP0 is in the correct mode. If the output type is
that the operand is known to be aligned, indicate that it is. such that the operand is known to be aligned, indicate that it is.
Otherwise, we need only be concerned about alignment for non-BLKmode Otherwise, we need only be concerned about alignment for non-BLKmode
results. */ results. */
if (MEM_P (op0)) if (MEM_P (op0))
...@@ -8210,22 +8273,24 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -8210,22 +8273,24 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (TYPE_ALIGN_OK (type)) if (TYPE_ALIGN_OK (type))
set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT else if (STRICT_ALIGNMENT
&& MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type))) && mode != BLKmode
&& MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
{ {
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
HOST_WIDE_INT temp_size HOST_WIDE_INT temp_size
= MAX (int_size_in_bytes (inner_type), = MAX (int_size_in_bytes (inner_type),
(HOST_WIDE_INT) GET_MODE_SIZE (TYPE_MODE (type))); (HOST_WIDE_INT) GET_MODE_SIZE (mode));
rtx new_rtx = assign_stack_temp_for_type (TYPE_MODE (type), rtx new_rtx
temp_size, 0, type); = assign_stack_temp_for_type (mode, temp_size, 0, type);
rtx new_with_op0_mode = adjust_address (new_rtx, GET_MODE (op0), 0); rtx new_with_op0_mode
= adjust_address (new_rtx, GET_MODE (op0), 0);
gcc_assert (!TREE_ADDRESSABLE (exp)); gcc_assert (!TREE_ADDRESSABLE (exp));
if (GET_MODE (op0) == BLKmode) if (GET_MODE (op0) == BLKmode)
emit_block_move (new_with_op0_mode, op0, emit_block_move (new_with_op0_mode, op0,
GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))), GEN_INT (GET_MODE_SIZE (mode)),
(modifier == EXPAND_STACK_PARM (modifier == EXPAND_STACK_PARM
? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
else else
...@@ -8234,7 +8299,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -8234,7 +8299,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op0 = new_rtx; op0 = new_rtx;
} }
op0 = adjust_address (op0, TYPE_MODE (type), 0); op0 = adjust_address (op0, mode, 0);
} }
return op0; return op0;
......
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