aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r--gcc/tree-ssa.c82
1 files changed, 61 insertions, 21 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 175ce48..7d9e64d 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -705,6 +705,52 @@ walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data)
}
}
+/* Replaces VAR with REPL in memory reference expression *X in
+ statement STMT. */
+
+static void
+propagate_into_addr (tree stmt, tree var, tree *x, tree repl)
+{
+ tree new_var, ass_stmt, addr_var;
+ basic_block bb;
+ block_stmt_iterator bsi;
+
+ /* There is nothing special to handle in the other cases. */
+ if (TREE_CODE (repl) != ADDR_EXPR)
+ return;
+ addr_var = TREE_OPERAND (repl, 0);
+
+ while (TREE_CODE (*x) == ARRAY_REF
+ || TREE_CODE (*x) == COMPONENT_REF
+ || TREE_CODE (*x) == BIT_FIELD_REF)
+ x = &TREE_OPERAND (*x, 0);
+
+ if (TREE_CODE (*x) != INDIRECT_REF
+ || TREE_OPERAND (*x, 0) != var)
+ return;
+
+ modify_stmt (stmt);
+ if (TREE_TYPE (*x) == TREE_TYPE (addr_var))
+ {
+ *x = addr_var;
+ mark_new_vars_to_rename (stmt, vars_to_rename);
+ return;
+ }
+
+ /* Frontends sometimes produce expressions like *&a instead of a[0].
+ Create a temporary variable to handle this case. */
+ ass_stmt = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, repl);
+ new_var = duplicate_ssa_name (var, ass_stmt);
+ TREE_OPERAND (*x, 0) = new_var;
+ TREE_OPERAND (ass_stmt, 0) = new_var;
+
+ bb = bb_for_stmt (stmt);
+ tree_block_label (bb);
+ bsi = bsi_after_labels (bb);
+ bsi_insert_after (&bsi, ass_stmt, BSI_NEW_STMT);
+
+ mark_new_vars_to_rename (stmt, vars_to_rename);
+}
/* Replaces immediate uses of VAR by REPL. */
@@ -718,6 +764,7 @@ replace_immediate_uses (tree var, tree repl)
dataflow_t df;
tree stmt;
stmt_ann_t ann;
+ bool mark_new_vars;
df = get_immediate_uses (SSA_NAME_DEF_STMT (var));
n = num_immediate_uses (df);
@@ -742,12 +789,22 @@ replace_immediate_uses (tree var, tree repl)
}
get_stmt_operands (stmt);
+ mark_new_vars = false;
if (is_gimple_reg (SSA_NAME_VAR (var)))
{
+ if (TREE_CODE (stmt) == MODIFY_EXPR)
+ {
+ propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 0), repl);
+ propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 1), repl);
+ }
+
uses = USE_OPS (ann);
for (j = 0; j < (int) NUM_USES (uses); j++)
if (USE_OP (uses, j) == var)
- propagate_value (USE_OP_PTR (uses, j), repl);
+ {
+ propagate_value (USE_OP_PTR (uses, j), repl);
+ mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl));
+ }
}
else
{
@@ -762,15 +819,15 @@ replace_immediate_uses (tree var, tree repl)
propagate_value (V_MAY_DEF_OP_PTR (v_may_defs, j), repl);
}
- modify_stmt (stmt);
-
/* If REPL is a pointer, it may have different memory tags associated
with it. For instance, VAR may have had a name tag while REPL
only had a type tag. In these cases, the virtual operands (if
any) in the statement will refer to different symbols which need
to be renamed. */
- if (POINTER_TYPE_P (TREE_TYPE (repl)))
+ if (mark_new_vars)
mark_new_vars_to_rename (stmt, vars_to_rename);
+ else
+ modify_stmt (stmt);
}
}
@@ -788,23 +845,6 @@ raise_value (tree phi, tree val, tree *eq_to)
if (eq_to[ver] == var)
return;
- switch (TREE_CODE (val))
- {
- case SSA_NAME:
- case REAL_CST:
- case COMPLEX_CST:
- break;
- case INTEGER_CST:
- if (TREE_CODE (TREE_TYPE (var)) != POINTER_TYPE)
- break;
-
- default:
- /* Do not propagate pointer constants. This might require folding
- things like *&foo and rewriting the ssa, which is not worth the
- trouble. */
- val = var;
- }
-
if (eq_to[ver])
{
if (operand_equal_p (eq_to[ver], val, 0))