summaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c79
1 files changed, 44 insertions, 35 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f6a35bdff00..20196fecfed 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -509,20 +509,17 @@ declare_tmp_vars (tree vars, tree scope)
temps = nreverse (last);
TREE_CHAIN (last) = BIND_EXPR_VARS (scope);
BIND_EXPR_VARS (scope) = temps;
-
- /* We don't add the temps to the block for this BIND_EXPR, as we're
- not interested in debugging info for them. */
}
}
void
gimple_add_tmp_var (tree tmp)
{
- if (TREE_CHAIN (tmp) || tmp->decl.seen_in_bind_expr)
+ if (TREE_CHAIN (tmp) || DECL_SEEN_IN_BIND_EXPR_P (tmp))
abort ();
DECL_CONTEXT (tmp) = current_function_decl;
- tmp->decl.seen_in_bind_expr = 1;
+ DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
if (gimplify_ctxp)
{
@@ -657,19 +654,6 @@ copy_if_shared_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
TREE_VISITED (t) = 1;
}
- /* Special-case BIND_EXPR. We should never be copying these, therefore
- we can omit examining BIND_EXPR_VARS. Which also avoids problems with
- double processing of the DECL_INITIAL, which could be seen via both
- the BIND_EXPR_VARS and a DECL_EXPR. */
- else if (code == BIND_EXPR)
- {
- if (TREE_VISITED (t))
- abort ();
- TREE_VISITED (t) = 1;
- *walk_subtrees = 0;
- walk_tree (&BIND_EXPR_BODY (t), copy_if_shared_r, NULL, NULL);
- }
-
/* If this node has been visited already, unshare it and don't look
any deeper. */
else if (TREE_VISITED (t))
@@ -713,8 +697,9 @@ unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
return NULL_TREE;
}
-/* Unshare all the trees in BODY_P, a pointer to the body of FNDECL, and the
- bodies of any nested functions. */
+/* Unshare all the trees in BODY_P, a pointer into the body of FNDECL, and the
+ bodies of any nested functions if we are unsharing the entire body of
+ FNDECL. */
static void
unshare_body (tree *body_p, tree fndecl)
@@ -722,8 +707,9 @@ unshare_body (tree *body_p, tree fndecl)
struct cgraph_node *cgn = cgraph_node (fndecl);
walk_tree (body_p, copy_if_shared_r, NULL, NULL);
- for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
- unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+ if (body_p == &DECL_SAVED_TREE (fndecl))
+ for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
+ unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
}
/* Likewise, but mark all trees as not visited. */
@@ -734,8 +720,9 @@ unvisit_body (tree *body_p, tree fndecl)
struct cgraph_node *cgn = cgraph_node (fndecl);
walk_tree (body_p, unmark_visited_r, NULL, NULL);
- for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
- unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+ if (body_p == &DECL_SAVED_TREE (fndecl))
+ for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
+ unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
}
/* Unshare T and all the trees reached from T via TREE_CHAIN. */
@@ -890,7 +877,7 @@ gimplify_bind_expr (tree *expr_p, tree temp, tree *pre_p)
/* Mark variables seen in this bind expr. */
for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t))
- t->decl.seen_in_bind_expr = 1;
+ DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
gimple_push_bind_expr (bind_expr);
gimplify_ctxp->save_stack = false;
@@ -1668,7 +1655,8 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval, fallback);
ret = MIN (ret, tret);
- /* And finally, the indices and operands to BIT_FIELD_REF. */
+ /* And finally, the indices and operands to BIT_FIELD_REF. During this
+ loop we also remove any useless conversions. */
for (; VARRAY_ACTIVE_SIZE (stack) > 0; )
{
tree t = VARRAY_TOP_TREE (stack);
@@ -1700,7 +1688,9 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
is_gimple_val, fb_rvalue);
ret = MIN (ret, tret);
}
-
+
+ STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
+
/* The innermost expression P may have originally had TREE_SIDE_EFFECTS
set which would have caused all the outer expressions in EXPR_P
leading to P to also have had TREE_SIDE_EFFECTS set. */
@@ -2321,7 +2311,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value)
to = TREE_OPERAND (*expr_p, 0);
from = TREE_OPERAND (*expr_p, 1);
- t = TYPE_SIZE_UNIT (TREE_TYPE (to));
+ 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);
@@ -2356,7 +2346,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, bool want_value)
to = TREE_OPERAND (*expr_p, 0);
- t = TYPE_SIZE_UNIT (TREE_TYPE (to));
+ 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);
@@ -2772,8 +2762,15 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
/* 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. */
- if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) != INTEGER_CST)
+ 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);
@@ -3361,7 +3358,7 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p)
TREE_OPERAND (targ, 3) = init;
TARGET_EXPR_INITIAL (targ) = NULL_TREE;
}
- else if (!temp->decl.seen_in_bind_expr)
+ else if (!DECL_SEEN_IN_BIND_EXPR_P (temp))
/* We should have expanded this before. */
abort ();
@@ -3699,8 +3696,20 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
break;
case CONSTRUCTOR:
- /* Don't reduce this in place; let gimplify_init_constructor work
- its magic. */
+ /* Don't reduce this in place; let gimplify_init_constructor work its
+ magic. Buf if we're just elaborating this for side effects, just
+ gimplify any element that has side-effects. */
+ if (fallback == fb_none)
+ {
+ for (tmp = CONSTRUCTOR_ELTS (*expr_p); tmp;
+ tmp = TREE_CHAIN (tmp))
+ if (TREE_SIDE_EFFECTS (TREE_VALUE (tmp)))
+ gimplify_expr (&TREE_VALUE (tmp), pre_p, post_p,
+ gimple_test_f, fallback);
+
+ *expr_p = NULL_TREE;
+ }
+
ret = GS_ALL_DONE;
break;
@@ -3801,7 +3810,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
tmp = *expr_p;
if (!TREE_STATIC (tmp) && !DECL_EXTERNAL (tmp)
&& decl_function_context (tmp) == current_function_decl
- && !tmp->decl.seen_in_bind_expr)
+ && !DECL_SEEN_IN_BIND_EXPR_P (tmp))
{
#ifdef ENABLE_CHECKING
if (!errorcount && !sorrycount)