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.c95
1 files changed, 89 insertions, 6 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 0a59dd20..cf6e764 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1275,21 +1275,48 @@ non_rewritable_lvalue_p (tree lhs)
&& DECL_P (TREE_OPERAND (lhs, 0)))
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
+ /* ??? 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_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR)
{
tree decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
- if (DECL_P (decl)
+
+ /* A decl that is wrapped inside a MEM-REF that covers
+ it full is also rewritable. */
+ if (integer_zerop (TREE_OPERAND (lhs, 1))
+ && DECL_P (decl)
&& DECL_SIZE (decl) == TYPE_SIZE (TREE_TYPE (lhs))
&& (TREE_THIS_VOLATILE (decl) == TREE_THIS_VOLATILE (lhs)))
return false;
+
+ /* A vector-insert using a MEM_REF or ARRAY_REF is rewritable
+ using a BIT_INSERT_EXPR. */
+ if (DECL_P (decl)
+ && VECTOR_TYPE_P (TREE_TYPE (decl))
+ && TYPE_MODE (TREE_TYPE (decl)) != BLKmode
+ && types_compatible_p (TREE_TYPE (lhs),
+ TREE_TYPE (TREE_TYPE (decl)))
+ && tree_fits_uhwi_p (TREE_OPERAND (lhs, 1))
+ && tree_int_cst_lt (TREE_OPERAND (lhs, 1),
+ TYPE_SIZE_UNIT (TREE_TYPE (decl)))
+ && (tree_to_uhwi (TREE_OPERAND (lhs, 1))
+ % tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) == 0)
+ return false;
}
+ /* A vector-insert using a BIT_FIELD_REF is rewritable using
+ BIT_INSERT_EXPR. */
+ if (TREE_CODE (lhs) == BIT_FIELD_REF
+ && DECL_P (TREE_OPERAND (lhs, 0))
+ && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0)))
+ && TYPE_MODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != BLKmode
+ && types_compatible_p (TREE_TYPE (lhs),
+ TREE_TYPE (TREE_TYPE (TREE_OPERAND (lhs, 0))))
+ && (tree_to_uhwi (TREE_OPERAND (lhs, 2))
+ % tree_to_uhwi (TYPE_SIZE (TREE_TYPE (lhs)))) == 0)
+ return false;
+
return true;
}
@@ -1511,6 +1538,62 @@ execute_update_addresses_taken (void)
continue;
}
+ /* Rewrite a vector insert via a BIT_FIELD_REF on the LHS
+ into a BIT_INSERT_EXPR. */
+ if (TREE_CODE (lhs) == BIT_FIELD_REF
+ && DECL_P (TREE_OPERAND (lhs, 0))
+ && bitmap_bit_p (suitable_for_renaming,
+ DECL_UID (TREE_OPERAND (lhs, 0)))
+ && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0)))
+ && TYPE_MODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != BLKmode
+ && types_compatible_p (TREE_TYPE (lhs),
+ TREE_TYPE (TREE_TYPE
+ (TREE_OPERAND (lhs, 0))))
+ && (tree_to_uhwi (TREE_OPERAND (lhs, 2))
+ % tree_to_uhwi (TYPE_SIZE (TREE_TYPE (lhs))) == 0))
+ {
+ tree var = TREE_OPERAND (lhs, 0);
+ tree val = gimple_assign_rhs1 (stmt);
+ tree bitpos = TREE_OPERAND (lhs, 2);
+ gimple_assign_set_lhs (stmt, var);
+ gimple_assign_set_rhs_with_ops
+ (&gsi, BIT_INSERT_EXPR, var, val, bitpos);
+ stmt = gsi_stmt (gsi);
+ unlink_stmt_vdef (stmt);
+ update_stmt (stmt);
+ continue;
+ }
+
+ /* Rewrite a vector insert using a MEM_REF on the LHS
+ into a BIT_INSERT_EXPR. */
+ if (TREE_CODE (lhs) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
+ && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0))
+ && DECL_P (sym)
+ && bitmap_bit_p (suitable_for_renaming, DECL_UID (sym))
+ && VECTOR_TYPE_P (TREE_TYPE (sym))
+ && TYPE_MODE (TREE_TYPE (sym)) != BLKmode
+ && types_compatible_p (TREE_TYPE (lhs),
+ TREE_TYPE (TREE_TYPE (sym)))
+ && tree_fits_uhwi_p (TREE_OPERAND (lhs, 1))
+ && tree_int_cst_lt (TREE_OPERAND (lhs, 1),
+ TYPE_SIZE_UNIT (TREE_TYPE (sym)))
+ && (tree_to_uhwi (TREE_OPERAND (lhs, 1))
+ % tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) == 0)
+ {
+ tree val = gimple_assign_rhs1 (stmt);
+ tree bitpos
+ = wide_int_to_tree (bitsizetype,
+ mem_ref_offset (lhs) * BITS_PER_UNIT);
+ gimple_assign_set_lhs (stmt, sym);
+ gimple_assign_set_rhs_with_ops
+ (&gsi, BIT_INSERT_EXPR, sym, val, bitpos);
+ stmt = gsi_stmt (gsi);
+ unlink_stmt_vdef (stmt);
+ update_stmt (stmt);
+ continue;
+ }
+
/* We shouldn't have any fancy wrapping of
component-refs on the LHS, but look through
VIEW_CONVERT_EXPRs as that is easy. */