From: Jason Merrill Date: Sun, 13 Feb 2005 06:43:58 +0000 (-0500) Subject: re PR libmudflap/19319 (Mudflap produce many violations on simple, correct c++ program) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=38116e3d1dfad4dc10da5863e1676e69b4682c54;p=gcc.git re PR libmudflap/19319 (Mudflap produce many violations on simple, correct c++ program) PR mudflap/19319 * gimplify.c (gimplify_modify_expr_rhs) [CALL_EXPR]: Make return slot explicit. PR c++/16405 * fold-const.c (fold_indirect_ref_1): Split out from... (build_fold_indirect_ref): Here. (fold_indirect_ref): New fn. * tree.h: Declare it. * gimplify.c (gimplify_compound_lval): Call fold_indirect_ref. (gimplify_modify_expr_rhs): Likewise. (gimplify_expr): Likewise. From-SVN: r94979 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 35f46de3d7c..aa96a6ac7fe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2005-02-13 Jason Merrill + + PR mudflap/19319 + * gimplify.c (gimplify_modify_expr_rhs) [CALL_EXPR]: Make return + slot explicit. + + PR c++/16405 + * fold-const.c (fold_indirect_ref_1): Split out from... + (build_fold_indirect_ref): Here. + (fold_indirect_ref): New fn. + * tree.h: Declare it. + * gimplify.c (gimplify_compound_lval): Call fold_indirect_ref. + (gimplify_modify_expr_rhs): Likewise. + (gimplify_expr): Likewise. + 2005-02-13 James A. Morrison PR tree-optimization/14303 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 601f023ce9a..afe3afc4663 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11217,17 +11217,21 @@ build_fold_addr_expr (tree t) return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t))); } -/* Builds an expression for an indirection through T, simplifying some - cases. */ +/* Given a pointer value T, return a simplified version of an indirection + through T, or NULL_TREE if no simplification is possible. */ -tree -build_fold_indirect_ref (tree t) +static tree +fold_indirect_ref_1 (tree t) { tree type = TREE_TYPE (TREE_TYPE (t)); tree sub = t; tree subtype; STRIP_NOPS (sub); + subtype = TREE_TYPE (sub); + if (!POINTER_TYPE_P (subtype)) + return NULL_TREE; + if (TREE_CODE (sub) == ADDR_EXPR) { tree op = TREE_OPERAND (sub, 0); @@ -11242,7 +11246,6 @@ build_fold_indirect_ref (tree t) } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ - subtype = TREE_TYPE (sub); if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype)))) { @@ -11250,7 +11253,34 @@ build_fold_indirect_ref (tree t) return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE); } - return build1 (INDIRECT_REF, type, t); + return NULL_TREE; +} + +/* Builds an expression for an indirection through T, simplifying some + cases. */ + +tree +build_fold_indirect_ref (tree t) +{ + tree sub = fold_indirect_ref_1 (t); + + if (sub) + return sub; + else + return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); +} + +/* Given an INDIRECT_REF T, return either T or a simplified version. */ + +tree +fold_indirect_ref (tree t) +{ + tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0)); + + if (sub) + return sub; + else + return t; } /* Strip non-trapping, non-side-effecting tree nodes from an expression diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 0fd39436325..ddb72bc63be 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1433,8 +1433,15 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p, VARRAY_GENERIC_PTR_NOGC_INIT (stack, 10, "stack"); /* We can handle anything that get_inner_reference can deal with. */ - for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0)) - VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p); + for (p = expr_p; ; p = &TREE_OPERAND (*p, 0)) + { + /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */ + if (TREE_CODE (*p) == INDIRECT_REF) + *p = fold_indirect_ref (*p); + if (!handled_component_p (*p)) + break; + VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p); + } gcc_assert (VARRAY_ACTIVE_SIZE (stack)); @@ -2845,16 +2852,10 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, This kind of code arises in C++ when an object is bound to a const reference, and if "x" is a TARGET_EXPR we want to take advantage of the optimization below. */ - tree pointer; - - pointer = TREE_OPERAND (*from_p, 0); - STRIP_NOPS (pointer); - if (TREE_CODE (pointer) == ADDR_EXPR - && (lang_hooks.types_compatible_p - (TREE_TYPE (TREE_OPERAND (pointer, 0)), - TREE_TYPE (*from_p)))) + tree t = fold_indirect_ref (*from_p); + if (t != *from_p) { - *from_p = TREE_OPERAND (pointer, 0); + *from_p = t; ret = GS_OK; } else @@ -2912,6 +2913,55 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, ret = GS_UNHANDLED; break; + case CALL_EXPR: + /* For calls that return in memory, give *to_p as the CALL_EXPR's + return slot so that we don't generate a temporary. */ + if (aggregate_value_p (*from_p, *from_p)) + { + tree init = *from_p; + tree fn = TREE_OPERAND (init, 0); + tree args = TREE_OPERAND (init, 1); + tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))); + tree arg = *to_p; + tree type; + + /* Only use the original target if *to_p isn't already + addressable; if its address escapes, and the called function + uses the NRV optimization, a conforming program could see + *to_p change before the called function returns. */ + bool use_temp = !is_gimple_non_addressable (*to_p); + if (use_temp) + { + arg = create_tmp_var (rettype, "ret"); + *from_p = arg; + } + + type = TREE_TYPE (arg); + /* FIXME: Mark the address as not escaping. */ + lang_hooks.mark_addressable (arg); + arg = build1 (ADDR_EXPR, build_pointer_type (type), arg); + /* The return type might have different cv-quals from arg. */ + arg = convert (build_pointer_type (rettype), arg); + args = tree_cons (NULL_TREE, arg, args); + init = build3 (CALL_EXPR, rettype, fn, args, NULL_TREE); + CALL_EXPR_HAS_RETURN_SLOT_ADDR (init) = 1; + TREE_USED (init) = 1; + + if (use_temp) + gimplify_and_add (init, pre_p); + else if (want_value) + { + gimplify_and_add (init, pre_p); + *expr_p = *to_p; + } + else + *expr_p = init; + ret = GS_OK; + } + else + ret = GS_UNHANDLED; + break; + default: ret = GS_UNHANDLED; break; @@ -3544,7 +3594,7 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p) ret = GS_OK; if (TREE_CODE (init) == BIND_EXPR) gimplify_bind_expr (&init, temp, pre_p); - if (init != temp) + if (init != temp) { init = build (MODIFY_EXPR, void_type_node, temp, init); ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, @@ -3795,9 +3845,13 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, recalculate_side_effects (*expr_p); break; + case INDIRECT_REF: + *expr_p = fold_indirect_ref (*expr_p); + if (*expr_p != save_expr) + break; + /* else fall through. */ case ALIGN_INDIRECT_REF: case MISALIGNED_INDIRECT_REF: - case INDIRECT_REF: ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_reg, fb_rvalue); recalculate_side_effects (*expr_p); diff --git a/gcc/tree.h b/gcc/tree.h index dea3136e009..62e9bb332bb 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3546,6 +3546,7 @@ extern tree fold_build_cleanup_point_expr (tree type, tree expr); extern tree fold_strip_sign_ops (tree); extern tree build_fold_addr_expr_with_type (tree, tree); extern tree build_fold_indirect_ref (tree); +extern tree fold_indirect_ref (tree); extern tree constant_boolean_node (int, tree); extern tree build_low_bits_mask (tree, unsigned);