aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-07-16 14:13:08 -0700
committerRichard Henderson <rth@gcc.gnu.org>2004-07-16 14:13:08 -0700
commitd25cee4d2b1a7c4f387a47c4163d8f7c241f2a1c (patch)
treea6887d7a4c296d5e39f29a2367845311f7100e89 /gcc
parent4c86f32571913801c3e876d2621ef74adce3fdbc (diff)
downloadgcc-d25cee4d2b1a7c4f387a47c4163d8f7c241f2a1c.zip
gcc-d25cee4d2b1a7c4f387a47c4163d8f7c241f2a1c.tar.gz
gcc-d25cee4d2b1a7c4f387a47c4163d8f7c241f2a1c.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/calls.c1
-rw-r--r--gcc/explow.c25
-rw-r--r--gcc/expr.c6
-rw-r--r--gcc/gimplify.c94
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20020210-1.c1
-rw-r--r--gcc/tree-alias-common.c3
-rw-r--r--gcc/tree-eh.c9
-rw-r--r--gcc/tree-gimple.c37
-rw-r--r--gcc/tree-inline.c6
-rw-r--r--gcc/tree-nested.c3
-rw-r--r--gcc/tree-pretty-print.c8
-rw-r--r--gcc/tree-sra.c5
-rw-r--r--gcc/tree-ssa-alias.c3
-rw-r--r--gcc/tree-ssa-ccp.c16
-rw-r--r--gcc/tree-ssa-operands.c37
-rw-r--r--gcc/tree-tailcall.c2
-rw-r--r--gcc/tree.def7
19 files changed, 226 insertions, 69 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 054c04a..2647e88 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,33 @@
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,
lhd_tree_inlining_copy_res_decl_for_inlining): Remove.
* langhooks.c (lhd_tree_inlining_copy_res_decl_for_inlining): Remove.
diff --git a/gcc/calls.c b/gcc/calls.c
index 231d69b..c48fd82 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3045,6 +3045,7 @@ expand_call (tree exp, rtx target, int ignore)
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
stack_pointer_delta = old_stack_pointer_delta;
pending_stack_adjust = old_pending_adj;
+ old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
stack_arg_under_construction = old_stack_arg_under_construction;
highest_outgoing_arg_in_use = initial_highest_arg_in_use;
stack_usage_map = initial_stack_usage_map;
diff --git a/gcc/explow.c b/gcc/explow.c
index 54a8635..3fb0f94 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -240,7 +240,12 @@ eliminate_constant_term (rtx x, rtx *constptr)
rtx
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);
}
@@ -251,17 +256,17 @@ expr_size (tree exp)
HOST_WIDE_INT
int_expr_size (tree exp)
{
- tree t = lang_hooks.expr_size (exp);
-
- if (t == 0
- || TREE_CODE (t) != INTEGER_CST
- || TREE_OVERFLOW (t)
- || TREE_INT_CST_HIGH (t) != 0
- /* If the result would appear negative, it's too big to represent. */
- || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
+ tree size;
+
+ if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+ size = TREE_OPERAND (exp, 1);
+ else
+ size = lang_hooks.expr_size (exp);
+
+ if (size == 0 || !host_integerp (size, 0))
return -1;
- return TREE_INT_CST_LOW (t);
+ return tree_low_cst (size, 0);
}
/* Return a copy of X in which all memory references
diff --git a/gcc/expr.c b/gcc/expr.c
index 302c4ee..dd1aad9 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8651,6 +8651,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
expand_asm_expr (exp);
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:
return lang_hooks.expand_expr (exp, original_target, tmode,
modifier, alt_rtl);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 642cff9..6cf5d48 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -72,8 +72,6 @@ typedef struct gimple_temp_hash_elt
} elt_t;
/* 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);
@@ -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. */
static enum gimplify_status
@@ -1806,6 +1825,9 @@ gimplify_arg (tree *expr_p, tree *pre_p)
else
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
the argument list must occur before the actual call. So, when
gimplifying arguments, force gimplify_expr to use an internal
@@ -2316,18 +2338,14 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
a call to __builtin_memcpy. */
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;
to = TREE_OPERAND (*expr_p, 0);
from = TREE_OPERAND (*expr_p, 1);
- t = TYPE_SIZE_UNIT (TREE_TYPE (from));
- t = unshare_expr (t);
- t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
- t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, from);
- args = tree_cons (NULL, t, NULL);
+ args = tree_cons (NULL, size, NULL);
t = build_fold_addr_expr (from);
args = tree_cons (NULL, t, args);
@@ -2352,16 +2370,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value)
a CONSTRUCTOR with an empty element list. */
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;
to = TREE_OPERAND (*expr_p, 0);
- t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (*expr_p, 1)));
- t = unshare_expr (t);
- t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
- args = tree_cons (NULL, t, NULL);
+ args = tree_cons (NULL, size, NULL);
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)
if (ret != GS_UNHANDLED)
return ret;
- /* If the value being copied is of variable width, expose the length
- if the copy by converting the whole thing to a memcpy/memset.
- Note that we need to do this before gimplifying any of the operands
- so that we can resolve any PLACEHOLDER_EXPRs in the size.
- Also note that the RTL expander uses the size of the expression to
- be copied, not of the destination, so that is what we must here.
- The types on both sides of the MODIFY_EXPR should be the same,
- 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);
- }
+ /* If the value being copied is of variable width, compute the length
+ of the copy into a WITH_SIZE_EXPR. Note that we need to do this
+ before gimplifying any of the operands so that we can resolve any
+ PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
+ the size of the expression to be copied, not of the destination, so
+ that is what we must here. */
+ maybe_with_size_expr (from_p);
ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
if (ret == GS_ERROR)
@@ -2805,6 +2809,23 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
if (ret != GS_UNHANDLED)
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 (is_gimple_tmp_var (*to_p) || !want_value)
ret = GS_ALL_DONE;
@@ -3784,6 +3805,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
ret = gimplify_statement_list (expr_p);
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:
/* ??? 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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 83f2839..bdf36ea 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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>
* lib/fortran-torture.exp (fortran-torture): Don't test compile
diff --git a/gcc/testsuite/gcc.c-torture/compile/20020210-1.c b/gcc/testsuite/gcc.c-torture/compile/20020210-1.c
index 960e3d5..5ca27f4 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20020210-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20020210-1.c
@@ -1,3 +1,2 @@
/* 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) {}
diff --git a/gcc/tree-alias-common.c b/gcc/tree-alias-common.c
index 790d70a..a7ce22d 100644
--- a/gcc/tree-alias-common.c
+++ b/gcc/tree-alias-common.c
@@ -448,7 +448,10 @@ find_func_aliases (tree stp)
{
op0 = TREE_OPERAND (stp, 0);
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 = get_alias_var (op0);
if (!lhsAV)
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index b0638c0..b7fe64d 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1723,14 +1723,17 @@ tree_could_trap_p (tree expr)
honor_trapv = true;
}
+ restart:
switch (code)
{
case COMPONENT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
case BIT_FIELD_REF:
- t = TREE_OPERAND (expr, 0);
- return tree_could_trap_p (t);
+ case WITH_SIZE_EXPR:
+ expr = TREE_OPERAND (expr, 0);
+ code = TREE_CODE (expr);
+ goto restart;
case ARRAY_RANGE_REF:
/* Let us be conservative here for now. We might be checking bounds of
@@ -1843,6 +1846,8 @@ tree_could_throw_p (tree t)
t = TREE_OPERAND (t, 1);
}
+ if (TREE_CODE (t) == WITH_SIZE_EXPR)
+ t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR)
return (call_expr_flags (t) & ECF_NOTHROW) == 0;
if (flag_non_call_exceptions)
diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c
index 193f093..c081b5a 100644
--- a/gcc/tree-gimple.c
+++ b/gcc/tree-gimple.c
@@ -118,12 +118,22 @@ Boston, MA 02111-1307, USA. */
addr-expr-arg: ID
| compref
+ with-size-arg: addr-expr-arg
+ | indirectref
+ | call-stmt
+
+ indirectref : INDIRECT_REF
+ op0 -> val
+
lhs : addr-expr-arg
- | '*' val
| bitfieldref
+ | indirectref
+ | WITH_SIZE_EXPR
+ op0 -> with-size-arg
+ op1 -> val
min-lval : ID
- | '*' val
+ | indirectref
bitfieldref : BIT_FIELD_REF
op0 -> inner-compref
@@ -155,18 +165,26 @@ Boston, MA 02111-1307, USA. */
op0 -> inner-compref
condition : val
- | val RELOP val
+ | RELOP
+ op0 -> val
+ op1 -> val
val : ID
| CONST
rhs : lhs
| CONST
- | '&' addr-expr-arg
- | call_expr
- | UNOP val
- | val BINOP val
- | val RELOP val
+ | call-stmt
+ | ADDR_EXPR
+ op0 -> addr-expr-arg
+ | UNOP
+ op0 -> val
+ | BINOP
+ op0 -> val
+ op1 -> val
+ | RELOP
+ op0 -> val
+ op1 -> val
*/
static inline bool is_gimple_id (tree);
@@ -286,6 +304,7 @@ is_gimple_lvalue (tree t)
{
return (is_gimple_addr_expr_arg (t)
|| TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == WITH_SIZE_EXPR
/* These are complex lvalues, but don't have addresses, so they
go here. */
|| TREE_CODE (t) == BIT_FIELD_REF);
@@ -506,6 +525,8 @@ get_call_expr_in (tree t)
{
if (TREE_CODE (t) == MODIFY_EXPR)
t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == WITH_SIZE_EXPR)
+ t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR)
return t;
return NULL_TREE;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 705216a..edd5fae 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1262,6 +1262,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
case EXIT_EXPR:
case LOOP_EXPR:
case PHI_NODE:
+ case WITH_SIZE_EXPR:
break;
/* 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)
case MODIFY_EXPR:
stmt_p = &TREE_OPERAND (stmt, 1);
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)
break;
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index fdcaaf8..16db5cf 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -1196,7 +1196,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
case RETURN_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;
break;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 65d362a..c187b1a 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1413,6 +1413,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_decimal_int (buffer, SSA_NAME_VERSION (node));
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:
pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
break;
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 423ee3c..73866b4 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -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. */
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:
expr_p = &TREE_OPERAND (inner, 0);
inner = expr = *expr_p;
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 0d96b16..ed4ffd9 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -1680,6 +1680,9 @@ add_pointed_to_expr (tree ptr, tree value)
{
struct ptr_info_def *pi;
+ if (TREE_CODE (value) == WITH_SIZE_EXPR)
+ value = TREE_OPERAND (value, 0);
+
#if defined ENABLE_CHECKING
/* Pointer variables should have been handled by merge_pointed_to_info. */
if (TREE_CODE (value) == SSA_NAME
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 7f28a9f..0c35717 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2085,13 +2085,16 @@ get_rhs (tree stmt)
{
case RETURN_EXPR:
stmt = TREE_OPERAND (stmt, 0);
- if (stmt)
- return get_rhs (stmt);
- else
- return NULL;
+ if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
+ return stmt;
+ /* FALLTHRU */
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:
return COND_EXPR_COND (stmt);
@@ -2143,6 +2146,9 @@ set_rhs (tree *stmt_p, tree expr)
/* FALLTHRU */
case MODIFY_EXPR:
+ op = TREE_OPERAND (stmt, 1);
+ if (TREE_CODE (op) == WITH_SIZE_EXPR)
+ stmt = op;
TREE_OPERAND (stmt, 1) = expr;
break;
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index af21f12..bb60bd8 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -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);
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:
get_call_expr_operands (stmt, expr, prev_vops);
return;
case MODIFY_EXPR:
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
+ {
+ int subflags;
+ tree op;
+
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
+
+ op = TREE_OPERAND (expr, 0);
+ if (TREE_CODE (op) == WITH_SIZE_EXPR)
+ op = TREE_OPERAND (expr, 0);
+ if (TREE_CODE (op) == ARRAY_REF
+ || TREE_CODE (op) == COMPONENT_REF
+ || TREE_CODE (op) == REALPART_EXPR
+ || TREE_CODE (op) == IMAGPART_EXPR)
+ subflags = opf_is_def;
+ else
+ subflags = opf_is_def | opf_kill_def;
- if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF
- || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF
- || TREE_CODE (TREE_OPERAND (expr, 0)) == REALPART_EXPR
- || TREE_CODE (TREE_OPERAND (expr, 0)) == IMAGPART_EXPR)
- get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def,
- prev_vops);
- else
- get_expr_operands (stmt, &TREE_OPERAND (expr, 0),
- opf_is_def | opf_kill_def, prev_vops);
- return;
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags, prev_vops);
+ return;
+ }
case VA_ARG_EXPR:
/* Mark VA_ARG_EXPR nodes as making volatile references. FIXME,
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index f69bf34..5a89868 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -384,6 +384,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
{
ass_var = TREE_OPERAND (stmt, 0);
call = TREE_OPERAND (stmt, 1);
+ if (TREE_CODE (call) == WITH_SIZE_EXPR)
+ call = TREE_OPERAND (call, 0);
}
else
{
diff --git a/gcc/tree.def b/gcc/tree.def
index 8068f26..65fd479 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -885,6 +885,13 @@ DEFTREECODE (VALUE_HANDLE, "value_handle", 'x', 0)
baseclass of itself or another class. */
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:
mode:c