summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2001-11-19 20:38:07 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2001-11-19 15:38:07 -0500
commited239f5a439be5360c431fea7ff3063c6d844692 (patch)
tree2542ba620d211064d29aeacfe75ac81b9312fd17 /gcc/expr.c
parenta5a9cb26e59353c633db9c6eb2eac959d1b3e697 (diff)
downloadgcc-ed239f5a439be5360c431fea7ff3063c6d844692.tar.gz
tree.def (VIEW_CONVERT_EXPR): New tree code.
* tree.def (VIEW_CONVERT_EXPR): New tree code. * tree.h (handled_component_p): New declaration. * alias.c (handled_component_p): Move function from here ... * expr.c (handled_component_p): ... to here and non longer static. (is_zeros_p, case VIEW_CONVERT_EXPR): New case. (store_field): Remove unneeded MEM_COPY_ATTRIBUTES call. (get_inner_reference): Handle VIEW_CONVERT_EXPR. (expand_expr, case VAR_DECL): Clean up handling of re-layout case. (expand_expr, case VIEW_CONVERT_EXPR): New case. (expand_expr, cse ADDR_EXPR): No need to copy if already BIGGEST_ALIGNMENT. * fold-const.c (fold, case VIEW_CONVERT_EXPR): New case. * varasm.c (initializer_constant_value_p, case VIEW_CONVERT_EXPR): New. (output_constant): Handle VIEW_CONVERT_EXPR. * dwarf2out.c (loc-descriptor_from_tree, add_bound_info): Add new case for VIEW_CONVERT_EXPR. From-SVN: r47179
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c119
1 files changed, 115 insertions, 4 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 324f5cd106c..0c5429ec187 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4360,6 +4360,7 @@ is_zeros_p (exp)
case CONVERT_EXPR:
case NOP_EXPR:
case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
return is_zeros_p (TREE_OPERAND (exp, 0));
case INTEGER_CST:
@@ -5151,7 +5152,6 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
rtx blk_object = copy_rtx (object);
PUT_MODE (blk_object, BLKmode);
- MEM_COPY_ATTRIBUTES (blk_object, object);
if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
emit_move_insn (object, target);
@@ -5451,6 +5451,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
continue;
}
else if (TREE_CODE (exp) != NON_LVALUE_EXPR
+ && TREE_CODE (exp) != VIEW_CONVERT_EXPR
&& ! ((TREE_CODE (exp) == NOP_EXPR
|| TREE_CODE (exp) == CONVERT_EXPR)
&& (TYPE_MODE (TREE_TYPE (exp))
@@ -5479,6 +5480,32 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
return exp;
}
+/* Return 1 if T is an expression that get_inner_reference handles. */
+
+int
+handled_component_p (t)
+ tree t;
+{
+ switch (TREE_CODE (t))
+ {
+ case BIT_FIELD_REF:
+ case COMPONENT_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
+ return 1;
+
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ return (TYPE_MODE (TREE_TYPE (t))
+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
+
+ default:
+ return 0;
+ }
+}
+
/* Subroutine of expand_exp: compute memory_usage from modifier. */
static enum memory_use_mode
@@ -6287,9 +6314,19 @@ expand_expr (exp, target, tmode, modifier)
if (DECL_SIZE (exp) == 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
{
+ rtx value = DECL_RTL_IF_SET (exp);
+
layout_decl (exp, 0);
- PUT_MODE (DECL_RTL (exp), DECL_MODE (exp));
- set_mem_align (DECL_RTL (exp), DECL_ALIGN (exp));
+
+ /* If the RTL was already set, update its mode and memory
+ attributes. */
+ if (value != 0)
+ {
+ PUT_MODE (value, DECL_MODE (exp));
+ SET_DECL_RTL (exp, 0);
+ set_mem_attributes (value, exp, 1);
+ SET_DECL_RTL (exp, value);
+ }
}
/* Although static-storage variables start off initialized, according to
@@ -7500,6 +7537,79 @@ expand_expr (exp, target, tmode, modifier)
TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
return target;
+ case VIEW_CONVERT_EXPR:
+ op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0);
+
+ /* If the input and output modes are both the same, we are done.
+ Otherwise, if neither mode is BLKmode and both are within a word, we
+ can use gen_lowpart. If neither is true, store the operand into
+ memory and convert the MEM to the new mode. */
+ if (TYPE_MODE (type) == GET_MODE (op0))
+ ;
+ else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode
+ && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD
+ && GET_MODE_SIZE (GET_MODE (op0)) <= UNITS_PER_WORD)
+ op0 = gen_lowpart (TYPE_MODE (type), op0);
+ else
+ {
+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ enum machine_mode non_blkmode
+ = GET_MODE (op0) == BLKmode ? TYPE_MODE (type) : GET_MODE (op0);
+
+ if (CONSTANT_P (op0))
+ op0 = validize_mem (force_const_mem (TYPE_MODE (inner_type), op0));
+ else
+ {
+ if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type))
+ target
+ = assign_stack_temp_for_type (TYPE_MODE (inner_type),
+ GET_MODE_SIZE (non_blkmode),
+ 0, inner_type);
+
+ if (GET_MODE (target) == BLKmode)
+ emit_block_move (target, op0,
+ expr_size (TREE_OPERAND (exp, 0)));
+ else
+ emit_move_insn (target, op0);
+
+ op0 = target;
+ }
+ }
+
+ if (GET_CODE (op0) == MEM)
+ {
+ op0 = copy_rtx (op0);
+
+ /* If the output type 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 results. */
+ if (TYPE_ALIGN_OK (type))
+ set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
+ else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT
+ && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+ {
+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ HOST_WIDE_INT temp_size = MAX (int_size_in_bytes (inner_type),
+ GET_MODE_SIZE (TYPE_MODE (type)));
+ rtx new = assign_stack_temp_for_type (TYPE_MODE (type),
+ temp_size, 0, type);
+ rtx new_with_op0_mode = copy_rtx (new);
+
+ PUT_MODE (new_with_op0_mode, GET_MODE (op0));
+ if (GET_MODE (op0) == BLKmode)
+ emit_block_move (new_with_op0_mode, op0,
+ GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
+ else
+ emit_move_insn (new_with_op0_mode, op0);
+
+ op0 = new;
+ }
+
+ PUT_MODE (op0, TYPE_MODE (type));
+ }
+
+ return op0;
+
case PLUS_EXPR:
/* We come here from MINUS_EXPR when the second operand is a
constant. */
@@ -8668,7 +8778,8 @@ expand_expr (exp, target, tmode, modifier)
strict alignment. */
if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
&& (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
- > MEM_ALIGN (op0)))
+ > MEM_ALIGN (op0))
+ && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
{
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
rtx new