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.c83
1 files changed, 39 insertions, 44 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 7bd01f8..90fb5dd 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1885,6 +1885,34 @@ non_rewritable_mem_ref_base (tree ref)
return NULL_TREE;
}
+/* For an lvalue tree LHS return true if it cannot be rewritten into SSA form.
+ Otherwise return true. */
+
+static bool
+non_rewritable_lvalue_p (tree lhs)
+{
+ /* A plain decl is always rewritable. */
+ if (DECL_P (lhs))
+ return false;
+
+ /* A decl that is wrapped inside a MEM-REF that covers
+ it full is also rewritable.
+ ??? The following could be relaxed allowing component
+ references that do not change the access size. */ ;
+ if (TREE_CODE (lhs) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
+ && integer_zerop (TREE_OPERAND (lhs, 1)))
+ {
+ tree decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
+ if (DECL_P (decl)
+ && DECL_SIZE (decl) == TYPE_SIZE (TREE_TYPE (lhs))
+ && (TREE_THIS_VOLATILE (decl) == TREE_THIS_VOLATILE (lhs)))
+ return false;
+ }
+
+ return true;
+}
+
/* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and
mark the variable VAR for conversion into SSA. Return true when updating
stmts is required. */
@@ -1978,29 +2006,13 @@ execute_update_addresses_taken (void)
if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
{
tree lhs = gimple_get_lhs (stmt);
-
- /* A plain decl does not need it set. */
- if (lhs && !DECL_P (lhs))
+ if (lhs
+ && TREE_CODE (lhs) != SSA_NAME
+ && non_rewritable_lvalue_p (lhs))
{
- tree orig_lhs = lhs;
-
- while (handled_component_p (lhs))
- lhs = TREE_OPERAND (lhs, 0);
-
- if (DECL_P (lhs))
- bitmap_set_bit (not_reg_needs, DECL_UID (lhs));
- else if (TREE_CODE (lhs) == MEM_REF
- && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR)
- {
- decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
- if (DECL_P (decl)
- && (!integer_zerop (TREE_OPERAND (lhs, 1))
- || (DECL_SIZE (decl)
- != TYPE_SIZE (TREE_TYPE (orig_lhs)))
- || (TREE_THIS_VOLATILE (lhs)
- != TREE_THIS_VOLATILE (decl))))
- bitmap_set_bit (not_reg_needs, DECL_UID (decl));
- }
+ decl = get_base_address (lhs);
+ if (DECL_P (decl))
+ bitmap_set_bit (not_reg_needs, DECL_UID (decl));
}
}
@@ -2027,29 +2039,12 @@ execute_update_addresses_taken (void)
{
tree link = gimple_asm_output_op (stmt, i);
tree lhs = TREE_VALUE (link);
-
- /* A plain decl does not need it set. */
- if (!DECL_P (lhs))
+ if (TREE_CODE (lhs) != SSA_NAME
+ && non_rewritable_lvalue_p (lhs))
{
- tree orig_lhs = lhs;
-
- while (handled_component_p (lhs))
- lhs = TREE_OPERAND (lhs, 0);
-
- if (DECL_P (lhs))
- bitmap_set_bit (not_reg_needs, DECL_UID (lhs));
- else if (TREE_CODE (lhs) == MEM_REF
- && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR)
- {
- decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
- if (DECL_P (decl)
- && (!integer_zerop (TREE_OPERAND (lhs, 1))
- || (TYPE_MAIN_VARIANT (TREE_TYPE (decl))
- != TYPE_MAIN_VARIANT (TREE_TYPE (orig_lhs)))
- || (TREE_THIS_VOLATILE (lhs)
- != TREE_THIS_VOLATILE (decl))))
- bitmap_set_bit (not_reg_needs, DECL_UID (decl));
- }
+ decl = get_base_address (lhs);
+ if (DECL_P (decl))
+ bitmap_set_bit (not_reg_needs, DECL_UID (decl));
}
}
for (i = 0; i < gimple_asm_ninputs (stmt); ++i)