diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2001-11-19 20:38:07 +0000 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 2001-11-19 15:38:07 -0500 |
commit | ed239f5a439be5360c431fea7ff3063c6d844692 (patch) | |
tree | 2542ba620d211064d29aeacfe75ac81b9312fd17 /gcc/expr.c | |
parent | a5a9cb26e59353c633db9c6eb2eac959d1b3e697 (diff) | |
download | gcc-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.c | 119 |
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 |