aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 698aefcfc45..c1d05b52756 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1617,6 +1617,7 @@ canonicalize_addr_expr (tree *expr_p)
static enum gimplify_status
gimplify_conversion (tree *expr_p)
{
+ tree tem;
gcc_assert (TREE_CODE (*expr_p) == NOP_EXPR
|| TREE_CODE (*expr_p) == CONVERT_EXPR);
@@ -1627,6 +1628,17 @@ gimplify_conversion (tree *expr_p)
if (tree_ssa_useless_type_conversion (*expr_p))
*expr_p = TREE_OPERAND (*expr_p, 0);
+ /* Attempt to avoid NOP_EXPR by producing reference to a subtype.
+ For example this fold (subclass *)&A into &A->subclass avoiding
+ a need for statement. */
+ if (TREE_CODE (*expr_p) == NOP_EXPR
+ && POINTER_TYPE_P (TREE_TYPE (*expr_p))
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
+ && (tem = maybe_fold_offset_to_reference
+ (TREE_OPERAND (*expr_p, 0),
+ integer_zero_node, TREE_TYPE (TREE_TYPE (*expr_p)))))
+ *expr_p = build_fold_addr_expr_with_type (tem, TREE_TYPE (*expr_p));
+
/* If we still have a conversion at the toplevel,
then canonicalize some constructs. */
if (TREE_CODE (*expr_p) == NOP_EXPR || TREE_CODE (*expr_p) == CONVERT_EXPR)
@@ -5859,6 +5871,21 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
ret = GS_ALL_DONE;
break;
+ case PLUS_EXPR:
+ /* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
+ The second is gimple immediate saving a need for extra statement.
+ */
+ if (POINTER_TYPE_P (TREE_TYPE (*expr_p))
+ && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
+ && (tmp = maybe_fold_offset_to_reference
+ (TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
+ TREE_TYPE (TREE_TYPE (*expr_p)))))
+ {
+ *expr_p = build_fold_addr_expr_with_type (tmp,
+ TREE_TYPE (*expr_p));
+ break;
+ }
+ /* FALLTHRU */
default:
switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
{