Commit d25cee4d by Richard Henderson Committed by Richard Henderson

tree-def (WITH_SIZE_EXPR): New.

        * tree-def (WITH_SIZE_EXPR): New.
        * explow.c (expr_size, int_expr_size): Handle WITH_SIZE_EXPR.
        * expr.c (expand_expr_real_1): Likewise.
        * gimplify.c (maybe_with_size_expr): New.
        (gimplify_arg, gimplify_modify_expr): Use it.
        (gimplify_modify_expr_to_memcpy): Take size parameter.
        (gimplify_modify_expr_to_memset): Likewise.
        (gimplify_expr): Handle WITH_SIZE_EXPR.
        * tree-alias-common.c (find_func_aliases): Likewise.
        * tree-eh.c (tree_could_trap_p): Likewise.
        (tree_could_throw_p): Likewise.
        * tree-gimple.c (is_gimple_lvalue): Likewise.
        (get_call_expr_in): Likewise.
        * tree-inline.c (estimate_num_insns_1): Likewise.
        (expand_calls_inline): Likewise.
        * tree-nested.c (convert_call_expr): Likewise.
        * tree-pretty-print.c (dump_generic_node): Likewise.
        * tree-sra.c (sra_walk_expr): Likewise.
        * tree-ssa-alias.c (add_pointed_to_expr): Likewise.
        * tree-ssa-ccp.c (get_rhs, set_rhs): Likewise.
        * tree-ssa-operands.c (get_expr_operands): Likewise.
        * tree-tailcall.c (find_tail_calls): Likewise.

        * calls.c (expand_call): Reset old_stack_allocated after
        calling emit_stack_restore.

        * gcc.c-torture/compile/20020210-1.c: Remove XFAIL.

From-SVN: r84833
parent 4c86f325
2004-07-16 Richard Henderson <rth@redhat.com> 2004-07-16 Richard Henderson <rth@redhat.com>
* tree-def (WITH_SIZE_EXPR): New.
* explow.c (expr_size, int_expr_size): Handle WITH_SIZE_EXPR.
* expr.c (expand_expr_real_1): Likewise.
* gimplify.c (maybe_with_size_expr): New.
(gimplify_arg, gimplify_modify_expr): Use it.
(gimplify_modify_expr_to_memcpy): Take size parameter.
(gimplify_modify_expr_to_memset): Likewise.
(gimplify_expr): Handle WITH_SIZE_EXPR.
* tree-alias-common.c (find_func_aliases): Likewise.
* tree-eh.c (tree_could_trap_p): Likewise.
(tree_could_throw_p): Likewise.
* tree-gimple.c (is_gimple_lvalue): Likewise.
(get_call_expr_in): Likewise.
* tree-inline.c (estimate_num_insns_1): Likewise.
(expand_calls_inline): Likewise.
* tree-nested.c (convert_call_expr): Likewise.
* tree-pretty-print.c (dump_generic_node): Likewise.
* tree-sra.c (sra_walk_expr): Likewise.
* tree-ssa-alias.c (add_pointed_to_expr): Likewise.
* tree-ssa-ccp.c (get_rhs, set_rhs): Likewise.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-tailcall.c (find_tail_calls): Likewise.
* calls.c (expand_call): Reset old_stack_allocated after
calling emit_stack_restore.
2004-07-16 Richard Henderson <rth@redhat.com>
* langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, * langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING,
lhd_tree_inlining_copy_res_decl_for_inlining): Remove. lhd_tree_inlining_copy_res_decl_for_inlining): Remove.
* langhooks.c (lhd_tree_inlining_copy_res_decl_for_inlining): Remove. * langhooks.c (lhd_tree_inlining_copy_res_decl_for_inlining): Remove.
......
...@@ -3045,6 +3045,7 @@ expand_call (tree exp, rtx target, int ignore) ...@@ -3045,6 +3045,7 @@ expand_call (tree exp, rtx target, int ignore)
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
stack_pointer_delta = old_stack_pointer_delta; stack_pointer_delta = old_stack_pointer_delta;
pending_stack_adjust = old_pending_adj; pending_stack_adjust = old_pending_adj;
old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
stack_arg_under_construction = old_stack_arg_under_construction; stack_arg_under_construction = old_stack_arg_under_construction;
highest_outgoing_arg_in_use = initial_highest_arg_in_use; highest_outgoing_arg_in_use = initial_highest_arg_in_use;
stack_usage_map = initial_stack_usage_map; stack_usage_map = initial_stack_usage_map;
......
...@@ -240,7 +240,12 @@ eliminate_constant_term (rtx x, rtx *constptr) ...@@ -240,7 +240,12 @@ eliminate_constant_term (rtx x, rtx *constptr)
rtx rtx
expr_size (tree exp) expr_size (tree exp)
{ {
tree size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp); tree size;
if (TREE_CODE (exp) == WITH_SIZE_EXPR)
size = TREE_OPERAND (exp, 1);
else
size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0); return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
} }
...@@ -251,17 +256,17 @@ expr_size (tree exp) ...@@ -251,17 +256,17 @@ expr_size (tree exp)
HOST_WIDE_INT HOST_WIDE_INT
int_expr_size (tree exp) int_expr_size (tree exp)
{ {
tree t = lang_hooks.expr_size (exp); tree size;
if (t == 0 if (TREE_CODE (exp) == WITH_SIZE_EXPR)
|| TREE_CODE (t) != INTEGER_CST size = TREE_OPERAND (exp, 1);
|| TREE_OVERFLOW (t) else
|| TREE_INT_CST_HIGH (t) != 0 size = lang_hooks.expr_size (exp);
/* If the result would appear negative, it's too big to represent. */
|| (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0) if (size == 0 || !host_integerp (size, 0))
return -1; return -1;
return TREE_INT_CST_LOW (t); return tree_low_cst (size, 0);
} }
/* Return a copy of X in which all memory references /* Return a copy of X in which all memory references
......
...@@ -8651,6 +8651,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -8651,6 +8651,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
expand_asm_expr (exp); expand_asm_expr (exp);
return const0_rtx; return const0_rtx;
case WITH_SIZE_EXPR:
/* WITH_SIZE_EXPR expands to its first argument. The caller should
have pulled out the size to use in whatever context it needed. */
return expand_expr_real (TREE_OPERAND (exp, 0), original_target, tmode,
modifier, alt_rtl);
default: default:
return lang_hooks.expand_expr (exp, original_target, tmode, return lang_hooks.expand_expr (exp, original_target, tmode,
modifier, alt_rtl); modifier, alt_rtl);
......
...@@ -72,8 +72,6 @@ typedef struct gimple_temp_hash_elt ...@@ -72,8 +72,6 @@ typedef struct gimple_temp_hash_elt
} elt_t; } elt_t;
/* Forward declarations. */ /* Forward declarations. */
static enum gimplify_status gimplify_modify_expr_rhs (tree *, tree *, tree *,
tree *, tree *, bool);
static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool); static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
...@@ -1788,6 +1786,27 @@ gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p, ...@@ -1788,6 +1786,27 @@ gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p,
} }
} }
/* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
static void
maybe_with_size_expr (tree *expr_p)
{
tree expr, type, size;
expr = *expr_p;
type = TREE_TYPE (expr);
if (type == error_mark_node)
return;
size = TYPE_SIZE_UNIT (type);
if (size && TREE_CODE (size) != INTEGER_CST)
{
size = unshare_expr (size);
size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
*expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
}
}
/* Subroutine of gimplify_call_expr: Gimplify a single argument. */ /* Subroutine of gimplify_call_expr: Gimplify a single argument. */
static enum gimplify_status static enum gimplify_status
...@@ -1806,6 +1825,9 @@ gimplify_arg (tree *expr_p, tree *pre_p) ...@@ -1806,6 +1825,9 @@ gimplify_arg (tree *expr_p, tree *pre_p)
else else
test = is_gimple_lvalue, fb = fb_either; test = is_gimple_lvalue, fb = fb_either;
/* If this is a variable sized type, we must remember the size. */
maybe_with_size_expr (expr_p);
/* There is a sequence point before a function call. Side effects in /* There is a sequence point before a function call. Side effects in
the argument list must occur before the actual call. So, when the argument list must occur before the actual call. So, when
gimplifying arguments, force gimplify_expr to use an internal gimplifying arguments, force gimplify_expr to use an internal
...@@ -2316,18 +2338,14 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target) ...@@ -2316,18 +2338,14 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
a call to __builtin_memcpy. */ a call to __builtin_memcpy. */
static enum gimplify_status static enum gimplify_status
gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value) gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value)
{ {
tree args, t, to, to_ptr, from; tree args, t, to, to_ptr, from;
to = TREE_OPERAND (*expr_p, 0); to = TREE_OPERAND (*expr_p, 0);
from = TREE_OPERAND (*expr_p, 1); from = TREE_OPERAND (*expr_p, 1);
t = TYPE_SIZE_UNIT (TREE_TYPE (from)); args = tree_cons (NULL, size, NULL);
t = unshare_expr (t);
t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, from);
args = tree_cons (NULL, t, NULL);
t = build_fold_addr_expr (from); t = build_fold_addr_expr (from);
args = tree_cons (NULL, t, args); args = tree_cons (NULL, t, args);
...@@ -2352,16 +2370,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value) ...@@ -2352,16 +2370,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value)
a CONSTRUCTOR with an empty element list. */ a CONSTRUCTOR with an empty element list. */
static enum gimplify_status static enum gimplify_status
gimplify_modify_expr_to_memset (tree *expr_p, bool want_value) gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value)
{ {
tree args, t, to, to_ptr; tree args, t, to, to_ptr;
to = TREE_OPERAND (*expr_p, 0); to = TREE_OPERAND (*expr_p, 0);
t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (*expr_p, 1))); args = tree_cons (NULL, size, NULL);
t = unshare_expr (t);
t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
args = tree_cons (NULL, t, NULL);
args = tree_cons (NULL, integer_zero_node, args); args = tree_cons (NULL, integer_zero_node, args);
...@@ -2771,24 +2786,13 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) ...@@ -2771,24 +2786,13 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
if (ret != GS_UNHANDLED) if (ret != GS_UNHANDLED)
return ret; return ret;
/* If the value being copied is of variable width, expose the length /* If the value being copied is of variable width, compute the length
if the copy by converting the whole thing to a memcpy/memset. of the copy into a WITH_SIZE_EXPR. Note that we need to do this
Note that we need to do this before gimplifying any of the operands before gimplifying any of the operands so that we can resolve any
so that we can resolve any PLACEHOLDER_EXPRs in the size. PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
Also note that the RTL expander uses the size of the expression to the size of the expression to be copied, not of the destination, so
be copied, not of the destination, so that is what we must here. that is what we must here. */
The types on both sides of the MODIFY_EXPR should be the same, maybe_with_size_expr (from_p);
but they aren't always and there are problems with class-wide types
in Ada where it's hard to make it "correct". */
if (TREE_CODE (TREE_TYPE (*from_p)) != ERROR_MARK
&& TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
&& TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*from_p))) != INTEGER_CST)
{
if (TREE_CODE (*from_p) == CONSTRUCTOR)
return gimplify_modify_expr_to_memset (expr_p, want_value);
else
return gimplify_modify_expr_to_memcpy (expr_p, want_value);
}
ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue); ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
if (ret == GS_ERROR) if (ret == GS_ERROR)
...@@ -2805,6 +2809,23 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) ...@@ -2805,6 +2809,23 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
if (ret != GS_UNHANDLED) if (ret != GS_UNHANDLED)
return ret; return ret;
/* If we've got a variable sized assignment between two lvalues (i.e. does
not involve a call), then we can make things a bit more straightforward
by converting the assignment to memcpy or memset. */
if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
{
tree from = TREE_OPERAND (*from_p, 0);
tree size = TREE_OPERAND (*from_p, 1);
if (TREE_CODE (from) == CONSTRUCTOR)
return gimplify_modify_expr_to_memset (expr_p, size, want_value);
if (is_gimple_addr_expr_arg (from))
{
*from_p = from;
return gimplify_modify_expr_to_memcpy (expr_p, size, want_value);
}
}
/* If the destination is already simple, nothing else needed. */ /* If the destination is already simple, nothing else needed. */
if (is_gimple_tmp_var (*to_p) || !want_value) if (is_gimple_tmp_var (*to_p) || !want_value)
ret = GS_ALL_DONE; ret = GS_ALL_DONE;
...@@ -3784,6 +3805,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, ...@@ -3784,6 +3805,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
ret = gimplify_statement_list (expr_p); ret = gimplify_statement_list (expr_p);
break; break;
case WITH_SIZE_EXPR:
{
enum gimplify_status r0, r1;
r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
post_p == &internal_post ? NULL : post_p,
gimple_test_f, fallback);
r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
is_gimple_val, fb_rvalue);
}
break;
case VAR_DECL: case VAR_DECL:
/* ??? If this is a local variable, and it has not been seen in any /* ??? If this is a local variable, and it has not been seen in any
outer BIND_EXPR, then it's probably the result of a duplicate outer BIND_EXPR, then it's probably the result of a duplicate
......
2004-07-16 Richard Henderson <rth@redhat.com>
* gcc.c-torture/compile/20020210-1.c: Remove XFAIL.
2004-07-16 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de> 2004-07-16 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
* lib/fortran-torture.exp (fortran-torture): Don't test compile * lib/fortran-torture.exp (fortran-torture): Don't test compile
......
/* PR c/5615 */ /* PR c/5615 */
/* { dg-xfail-if "regression/16417" { "*-*-*" } { "-O1" "-O2" "-O3 -fomit-frame-pointer" "-O3 -g" "-Os" } { "" } } */
void f(int a, struct {int b[a];} c) {} void f(int a, struct {int b[a];} c) {}
...@@ -448,7 +448,10 @@ find_func_aliases (tree stp) ...@@ -448,7 +448,10 @@ find_func_aliases (tree stp)
{ {
op0 = TREE_OPERAND (stp, 0); op0 = TREE_OPERAND (stp, 0);
op1 = TREE_OPERAND (stp, 1); op1 = TREE_OPERAND (stp, 1);
if (TREE_CODE (op1) == WITH_SIZE_EXPR)
op1 = TREE_OPERAND (op1, 0);
} }
/* lhsAV should always have an alias variable */ /* lhsAV should always have an alias variable */
lhsAV = get_alias_var (op0); lhsAV = get_alias_var (op0);
if (!lhsAV) if (!lhsAV)
......
...@@ -1723,14 +1723,17 @@ tree_could_trap_p (tree expr) ...@@ -1723,14 +1723,17 @@ tree_could_trap_p (tree expr)
honor_trapv = true; honor_trapv = true;
} }
restart:
switch (code) switch (code)
{ {
case COMPONENT_REF: case COMPONENT_REF:
case REALPART_EXPR: case REALPART_EXPR:
case IMAGPART_EXPR: case IMAGPART_EXPR:
case BIT_FIELD_REF: case BIT_FIELD_REF:
t = TREE_OPERAND (expr, 0); case WITH_SIZE_EXPR:
return tree_could_trap_p (t); expr = TREE_OPERAND (expr, 0);
code = TREE_CODE (expr);
goto restart;
case ARRAY_RANGE_REF: case ARRAY_RANGE_REF:
/* Let us be conservative here for now. We might be checking bounds of /* Let us be conservative here for now. We might be checking bounds of
...@@ -1843,6 +1846,8 @@ tree_could_throw_p (tree t) ...@@ -1843,6 +1846,8 @@ tree_could_throw_p (tree t)
t = TREE_OPERAND (t, 1); t = TREE_OPERAND (t, 1);
} }
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR) if (TREE_CODE (t) == CALL_EXPR)
return (call_expr_flags (t) & ECF_NOTHROW) == 0; return (call_expr_flags (t) & ECF_NOTHROW) == 0;
if (flag_non_call_exceptions) if (flag_non_call_exceptions)
......
...@@ -118,12 +118,22 @@ Boston, MA 02111-1307, USA. */ ...@@ -118,12 +118,22 @@ Boston, MA 02111-1307, USA. */
addr-expr-arg: ID addr-expr-arg: ID
| compref | compref
with-size-arg: addr-expr-arg
| indirectref
| call-stmt
indirectref : INDIRECT_REF
op0 -> val
lhs : addr-expr-arg lhs : addr-expr-arg
| '*' val
| bitfieldref | bitfieldref
| indirectref
| WITH_SIZE_EXPR
op0 -> with-size-arg
op1 -> val
min-lval : ID min-lval : ID
| '*' val | indirectref
bitfieldref : BIT_FIELD_REF bitfieldref : BIT_FIELD_REF
op0 -> inner-compref op0 -> inner-compref
...@@ -155,18 +165,26 @@ Boston, MA 02111-1307, USA. */ ...@@ -155,18 +165,26 @@ Boston, MA 02111-1307, USA. */
op0 -> inner-compref op0 -> inner-compref
condition : val condition : val
| val RELOP val | RELOP
op0 -> val
op1 -> val
val : ID val : ID
| CONST | CONST
rhs : lhs rhs : lhs
| CONST | CONST
| '&' addr-expr-arg | call-stmt
| call_expr | ADDR_EXPR
| UNOP val op0 -> addr-expr-arg
| val BINOP val | UNOP
| val RELOP val op0 -> val
| BINOP
op0 -> val
op1 -> val
| RELOP
op0 -> val
op1 -> val
*/ */
static inline bool is_gimple_id (tree); static inline bool is_gimple_id (tree);
...@@ -286,6 +304,7 @@ is_gimple_lvalue (tree t) ...@@ -286,6 +304,7 @@ is_gimple_lvalue (tree t)
{ {
return (is_gimple_addr_expr_arg (t) return (is_gimple_addr_expr_arg (t)
|| TREE_CODE (t) == INDIRECT_REF || TREE_CODE (t) == INDIRECT_REF
|| TREE_CODE (t) == WITH_SIZE_EXPR
/* These are complex lvalues, but don't have addresses, so they /* These are complex lvalues, but don't have addresses, so they
go here. */ go here. */
|| TREE_CODE (t) == BIT_FIELD_REF); || TREE_CODE (t) == BIT_FIELD_REF);
...@@ -506,6 +525,8 @@ get_call_expr_in (tree t) ...@@ -506,6 +525,8 @@ get_call_expr_in (tree t)
{ {
if (TREE_CODE (t) == MODIFY_EXPR) if (TREE_CODE (t) == MODIFY_EXPR)
t = TREE_OPERAND (t, 1); t = TREE_OPERAND (t, 1);
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR) if (TREE_CODE (t) == CALL_EXPR)
return t; return t;
return NULL_TREE; return NULL_TREE;
......
...@@ -1262,6 +1262,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) ...@@ -1262,6 +1262,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
case EXIT_EXPR: case EXIT_EXPR:
case LOOP_EXPR: case LOOP_EXPR:
case PHI_NODE: case PHI_NODE:
case WITH_SIZE_EXPR:
break; break;
/* We don't account constants for now. Assume that the cost is amortized /* We don't account constants for now. Assume that the cost is amortized
...@@ -1779,6 +1780,11 @@ expand_calls_inline (tree *stmt_p, inline_data *id) ...@@ -1779,6 +1780,11 @@ expand_calls_inline (tree *stmt_p, inline_data *id)
case MODIFY_EXPR: case MODIFY_EXPR:
stmt_p = &TREE_OPERAND (stmt, 1); stmt_p = &TREE_OPERAND (stmt, 1);
stmt = *stmt_p; stmt = *stmt_p;
if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
{
stmt_p = &TREE_OPERAND (stmt, 0);
stmt = *stmt_p;
}
if (TREE_CODE (stmt) != CALL_EXPR) if (TREE_CODE (stmt) != CALL_EXPR)
break; break;
......
...@@ -1196,7 +1196,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data) ...@@ -1196,7 +1196,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
case RETURN_EXPR: case RETURN_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
/* Only return and modify may contain calls. */ case WITH_SIZE_EXPR:
/* Only return modify and with_size_expr may contain calls. */
*walk_subtrees = 1; *walk_subtrees = 1;
break; break;
......
...@@ -1413,6 +1413,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, ...@@ -1413,6 +1413,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_decimal_int (buffer, SSA_NAME_VERSION (node)); pp_decimal_int (buffer, SSA_NAME_VERSION (node));
break; break;
case WITH_SIZE_EXPR:
pp_string (buffer, "WITH_SIZE_EXPR <");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
pp_string (buffer, ">");
break;
case VALUE_HANDLE: case VALUE_HANDLE:
pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node)); pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
break; break;
......
...@@ -731,6 +731,11 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output, ...@@ -731,6 +731,11 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output,
type other than the one we've scalarized. */ type other than the one we've scalarized. */
goto use_all; goto use_all;
case WITH_SIZE_EXPR:
/* This is a transparent wrapper. The entire inner expression really
is being used. */
goto use_all;
use_all: use_all:
expr_p = &TREE_OPERAND (inner, 0); expr_p = &TREE_OPERAND (inner, 0);
inner = expr = *expr_p; inner = expr = *expr_p;
......
...@@ -1680,6 +1680,9 @@ add_pointed_to_expr (tree ptr, tree value) ...@@ -1680,6 +1680,9 @@ add_pointed_to_expr (tree ptr, tree value)
{ {
struct ptr_info_def *pi; struct ptr_info_def *pi;
if (TREE_CODE (value) == WITH_SIZE_EXPR)
value = TREE_OPERAND (value, 0);
#if defined ENABLE_CHECKING #if defined ENABLE_CHECKING
/* Pointer variables should have been handled by merge_pointed_to_info. */ /* Pointer variables should have been handled by merge_pointed_to_info. */
if (TREE_CODE (value) == SSA_NAME if (TREE_CODE (value) == SSA_NAME
......
...@@ -2085,13 +2085,16 @@ get_rhs (tree stmt) ...@@ -2085,13 +2085,16 @@ get_rhs (tree stmt)
{ {
case RETURN_EXPR: case RETURN_EXPR:
stmt = TREE_OPERAND (stmt, 0); stmt = TREE_OPERAND (stmt, 0);
if (stmt) if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
return get_rhs (stmt); return stmt;
else /* FALLTHRU */
return NULL;
case MODIFY_EXPR: case MODIFY_EXPR:
return TREE_OPERAND (stmt, 1); stmt = TREE_OPERAND (stmt, 1);
if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
return TREE_OPERAND (stmt, 0);
else
return stmt;
case COND_EXPR: case COND_EXPR:
return COND_EXPR_COND (stmt); return COND_EXPR_COND (stmt);
...@@ -2143,6 +2146,9 @@ set_rhs (tree *stmt_p, tree expr) ...@@ -2143,6 +2146,9 @@ set_rhs (tree *stmt_p, tree expr)
/* FALLTHRU */ /* FALLTHRU */
case MODIFY_EXPR: case MODIFY_EXPR:
op = TREE_OPERAND (stmt, 1);
if (TREE_CODE (op) == WITH_SIZE_EXPR)
stmt = op;
TREE_OPERAND (stmt, 1) = expr; TREE_OPERAND (stmt, 1) = expr;
break; break;
......
...@@ -931,23 +931,38 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops) ...@@ -931,23 +931,38 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops); get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops);
return; return;
case WITH_SIZE_EXPR:
/* WITH_SIZE_EXPR is a pass-through reference to it's first argument,
and an rvalue reference to its second argument. */
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops);
return;
case CALL_EXPR: case CALL_EXPR:
get_call_expr_operands (stmt, expr, prev_vops); get_call_expr_operands (stmt, expr, prev_vops);
return; return;
case MODIFY_EXPR: case MODIFY_EXPR:
{
int subflags;
tree op;
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops); get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF op = TREE_OPERAND (expr, 0);
|| TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF if (TREE_CODE (op) == WITH_SIZE_EXPR)
|| TREE_CODE (TREE_OPERAND (expr, 0)) == REALPART_EXPR op = TREE_OPERAND (expr, 0);
|| TREE_CODE (TREE_OPERAND (expr, 0)) == IMAGPART_EXPR) if (TREE_CODE (op) == ARRAY_REF
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def, || TREE_CODE (op) == COMPONENT_REF
prev_vops); || TREE_CODE (op) == REALPART_EXPR
|| TREE_CODE (op) == IMAGPART_EXPR)
subflags = opf_is_def;
else else
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags = opf_is_def | opf_kill_def;
opf_is_def | opf_kill_def, prev_vops);
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags, prev_vops);
return; return;
}
case VA_ARG_EXPR: case VA_ARG_EXPR:
/* Mark VA_ARG_EXPR nodes as making volatile references. FIXME, /* Mark VA_ARG_EXPR nodes as making volatile references. FIXME,
......
...@@ -384,6 +384,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret) ...@@ -384,6 +384,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
{ {
ass_var = TREE_OPERAND (stmt, 0); ass_var = TREE_OPERAND (stmt, 0);
call = TREE_OPERAND (stmt, 1); call = TREE_OPERAND (stmt, 1);
if (TREE_CODE (call) == WITH_SIZE_EXPR)
call = TREE_OPERAND (call, 0);
} }
else else
{ {
......
...@@ -885,6 +885,13 @@ DEFTREECODE (VALUE_HANDLE, "value_handle", 'x', 0) ...@@ -885,6 +885,13 @@ DEFTREECODE (VALUE_HANDLE, "value_handle", 'x', 0)
baseclass of itself or another class. */ baseclass of itself or another class. */
DEFTREECODE (TREE_BINFO, "tree_binfo", 'x', 0) DEFTREECODE (TREE_BINFO, "tree_binfo", 'x', 0)
/* Records the size for an expression of variable size type. This is
for use in contexts in which we are accessing the entire object,
such as for a function call, or block copy.
Operand 0 is the real expression.
Operand 1 is the size of the type in the expression. */
DEFTREECODE (WITH_SIZE_EXPR, "with_size_expr", 'e', 2)
/* /*
Local variables: Local variables:
mode:c mode:c
......
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