diff options
Diffstat (limited to 'gcc/tree-ssa-operands.c')
-rw-r--r-- | gcc/tree-ssa-operands.c | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 5d5f6ba..62bb8c9 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1452,6 +1452,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags) case TRUTH_XOR_EXPR: case COMPOUND_EXPR: case OBJ_TYPE_REF: + case ASSERT_EXPR: do_binary: { tree op0 = TREE_OPERAND (expr, 0); @@ -1735,7 +1736,7 @@ get_call_expr_operands (tree stmt, tree expr) && !bitmap_empty_p (call_clobbered_vars) && !(call_flags & ECF_NOVOPS)) { - /* A 'pure' or a 'const' functions never call clobber anything. + /* A 'pure' or a 'const' function never call-clobbers anything. A 'noreturn' function might, but since we don't return anyway there is no point in recording that. */ if (TREE_SIDE_EFFECTS (expr) @@ -1798,6 +1799,24 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags) if (TREE_THIS_VOLATILE (sym) && s_ann) s_ann->has_volatile_ops = true; + /* If the variable cannot be modified and this is a V_MAY_DEF change + it into a VUSE. This happens when read-only variables are marked + call-clobbered and/or aliased to writeable variables. So we only + check that this only happens on stores, and not writes to GIMPLE + registers. + + FIXME: The C++ FE is emitting assignments in the IL stream for + read-only globals. This is wrong, but for the time being disable + this transformation on V_MUST_DEF operands (otherwise, we + mis-optimize SPEC2000's eon). */ + if ((flags & opf_is_def) + && !(flags & opf_kill_def) + && unmodifiable_var_p (var)) + { + gcc_assert (!is_real_op); + flags &= ~opf_is_def; + } + if (is_real_op) { /* The variable is a GIMPLE register. Add it to real operands. */ @@ -1858,17 +1877,35 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags) if (flags & opf_is_def) { + bool added_may_defs_p = false; + /* If the variable is also an alias tag, add a virtual operand for it, otherwise we will miss representing references to the members of the variable's alias set. This fixes the bug in gcc.c-torture/execute/20020503-1.c. */ if (v_ann->is_alias_tag) - append_v_may_def (var); + { + added_may_defs_p = true; + append_v_may_def (var); + } for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++) - append_v_may_def (VARRAY_TREE (aliases, i)); + { + /* While VAR may be modifiable, some of its aliases + may not be. If that's the case, we don't really + need to add them a V_MAY_DEF for them. */ + tree alias = VARRAY_TREE (aliases, i); + + if (unmodifiable_var_p (alias)) + append_vuse (alias); + else + { + append_v_may_def (alias); + added_may_defs_p = true; + } + } - if (s_ann) + if (s_ann && added_may_defs_p) s_ann->makes_aliased_stores = 1; } else @@ -2000,8 +2037,7 @@ add_call_clobber_ops (tree stmt) EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi) { tree var = referenced_var (i); - if (TREE_READONLY (var) - && (TREE_STATIC (var) || DECL_EXTERNAL (var))) + if (unmodifiable_var_p (var)) add_stmt_operand (&var, &empty_ann, opf_none); else add_stmt_operand (&var, &empty_ann, opf_is_def); |