Commit fe9821b8 by Jan Hubicka Committed by Jan Hubicka

tree.h (maybe_fold_offset_to_component_ref): Remove.


	* tree.h (maybe_fold_offset_to_component_ref): Remove.
	(maybe_fold_offset_to_reference): Declare.
	* fold-const.c (fold_unary): Do not fold
	(type *)&A into &A->field_of_type_and_offset_0
	* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): When base type
	size is unknown, give up.
	(maybe_fold_offset_to_component_ref): Ignore firelds with unknown
	offsets.
	(maybe_fold_offset_to_reference): New.
	(maybe_fold_stmt_indirect): Use it.
	(fold_stmt_r): Fold (type *)&A+offset into A->field_if_type_and_offset.
	* gimplify.c (gimplify_conversion): Canonicalize conversions to
	field references.
	(gimplify_expr): Likewise for plus_expr.

From-SVN: r124323
parent 8b11009b
2007-05-01 Jan Hubicka <jh@suse.cz>
* tree.h (maybe_fold_offset_to_component_ref): Remove.
(maybe_fold_offset_to_reference): Declare.
* fold-const.c (fold_unary): Do not fold
(type *)&A into &A->field_of_type_and_offset_0
* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): When base type
size is unknown, give up.
(maybe_fold_offset_to_component_ref): Ignore firelds with unknown
offsets.
(maybe_fold_offset_to_reference): New.
(maybe_fold_stmt_indirect): Use it.
(fold_stmt_r): Fold (type *)&A+offset into A->field_if_type_and_offset.
* gimplify.c (gimplify_conversion): Canonicalize conversions to
field references.
(gimplify_expr): Likewise for plus_expr.
2007-05-01 Zdenek Dvorak <dvorakz@suse.cz> 2007-05-01 Zdenek Dvorak <dvorakz@suse.cz>
* tree-ssa-loop-ivopts.c (rewrite_use_nonlinear_expr): Use * tree-ssa-loop-ivopts.c (rewrite_use_nonlinear_expr): Use
......
...@@ -7748,13 +7748,6 @@ fold_unary (enum tree_code code, tree type, tree op0) ...@@ -7748,13 +7748,6 @@ fold_unary (enum tree_code code, tree type, tree op0)
return fold_convert (type, build_fold_addr_expr (base)); return fold_convert (type, build_fold_addr_expr (base));
} }
/* Convert (type *)&A into &A->field_of_type_and_offset_0. */
if (TREE_CODE (op0) == ADDR_EXPR && POINTER_TYPE_P (type)
&& (tem = maybe_fold_offset_to_component_ref
(TREE_TYPE (TREE_OPERAND (op0, 0)), TREE_OPERAND (op0, 0),
integer_zero_node, TREE_TYPE (type), false)))
return build_fold_addr_expr_with_type (tem, type);
if ((TREE_CODE (op0) == MODIFY_EXPR if ((TREE_CODE (op0) == MODIFY_EXPR
|| TREE_CODE (op0) == GIMPLE_MODIFY_STMT) || TREE_CODE (op0) == GIMPLE_MODIFY_STMT)
&& TREE_CONSTANT (GENERIC_TREE_OPERAND (op0, 1)) && TREE_CONSTANT (GENERIC_TREE_OPERAND (op0, 1))
......
...@@ -1617,6 +1617,7 @@ canonicalize_addr_expr (tree *expr_p) ...@@ -1617,6 +1617,7 @@ canonicalize_addr_expr (tree *expr_p)
static enum gimplify_status static enum gimplify_status
gimplify_conversion (tree *expr_p) gimplify_conversion (tree *expr_p)
{ {
tree tem;
gcc_assert (TREE_CODE (*expr_p) == NOP_EXPR gcc_assert (TREE_CODE (*expr_p) == NOP_EXPR
|| TREE_CODE (*expr_p) == CONVERT_EXPR); || TREE_CODE (*expr_p) == CONVERT_EXPR);
...@@ -1627,6 +1628,17 @@ gimplify_conversion (tree *expr_p) ...@@ -1627,6 +1628,17 @@ gimplify_conversion (tree *expr_p)
if (tree_ssa_useless_type_conversion (*expr_p)) if (tree_ssa_useless_type_conversion (*expr_p))
*expr_p = TREE_OPERAND (*expr_p, 0); *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, /* If we still have a conversion at the toplevel,
then canonicalize some constructs. */ then canonicalize some constructs. */
if (TREE_CODE (*expr_p) == NOP_EXPR || TREE_CODE (*expr_p) == CONVERT_EXPR) if (TREE_CODE (*expr_p) == NOP_EXPR || TREE_CODE (*expr_p) == CONVERT_EXPR)
...@@ -5857,6 +5869,21 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, ...@@ -5857,6 +5869,21 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
ret = GS_ALL_DONE; ret = GS_ALL_DONE;
break; 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: default:
switch (TREE_CODE_CLASS (TREE_CODE (*expr_p))) switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
{ {
......
...@@ -1587,6 +1587,8 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type) ...@@ -1587,6 +1587,8 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
Otherwise, compute the offset as an index by using a division. If the Otherwise, compute the offset as an index by using a division. If the
division isn't exact, then don't do anything. */ division isn't exact, then don't do anything. */
elt_size = TYPE_SIZE_UNIT (elt_type); elt_size = TYPE_SIZE_UNIT (elt_type);
if (!elt_size)
return NULL;
if (integer_zerop (offset)) if (integer_zerop (offset))
{ {
if (TREE_CODE (elt_size) != INTEGER_CST) if (TREE_CODE (elt_size) != INTEGER_CST)
...@@ -1647,12 +1649,11 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type) ...@@ -1647,12 +1649,11 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
} }
/* A subroutine of fold_stmt_r. Attempts to fold *(S+O) to S.X. /* Attempt to fold *(S+O) to S.X.
BASE is a record type. OFFSET is a byte displacement. ORIG_TYPE BASE is a record type. OFFSET is a byte displacement. ORIG_TYPE
is the desired result type. */ is the desired result type. */
/* ??? This doesn't handle class inheritance. */
tree static tree
maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset, maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
tree orig_type, bool base_is_ptr) tree orig_type, bool base_is_ptr)
{ {
...@@ -1679,6 +1680,8 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset, ...@@ -1679,6 +1680,8 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
if (DECL_BIT_FIELD (f)) if (DECL_BIT_FIELD (f))
continue; continue;
if (!DECL_FIELD_OFFSET (f))
continue;
field_offset = byte_position (f); field_offset = byte_position (f);
if (TREE_CODE (field_offset) != INTEGER_CST) if (TREE_CODE (field_offset) != INTEGER_CST)
continue; continue;
...@@ -1766,6 +1769,69 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset, ...@@ -1766,6 +1769,69 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
orig_type, false); orig_type, false);
} }
/* Attempt to express (ORIG_TYPE)BASE+OFFSET as BASE->field_of_orig_type
or BASE[index] or by combination of those.
Before attempting the conversion strip off existing ADDR_EXPRs and
handled component refs. */
tree
maybe_fold_offset_to_reference (tree base, tree offset, tree orig_type)
{
tree ret;
tree type;
bool base_is_ptr = true;
STRIP_NOPS (base);
if (TREE_CODE (base) == ADDR_EXPR)
{
base_is_ptr = false;
base = TREE_OPERAND (base, 0);
/* Handle case where existing COMPONENT_REF pick e.g. wrong field of union,
so it needs to be removed and new COMPONENT_REF constructed.
The wrong COMPONENT_REF are often constructed by folding the
(type *)&object within the expression (type *)&object+offset */
if (handled_component_p (base) && 0)
{
HOST_WIDE_INT sub_offset, size, maxsize;
tree newbase;
newbase = get_ref_base_and_extent (base, &sub_offset,
&size, &maxsize);
gcc_assert (newbase);
gcc_assert (!(sub_offset & (BITS_PER_UNIT - 1)));
if (size == maxsize)
{
base = newbase;
if (sub_offset)
offset = int_const_binop (PLUS_EXPR, offset,
build_int_cst (TREE_TYPE (offset),
sub_offset / BITS_PER_UNIT), 1);
}
}
if (lang_hooks.types_compatible_p (orig_type, TREE_TYPE (base))
&& integer_zerop (offset))
return base;
type = TREE_TYPE (base);
}
else
{
base_is_ptr = true;
if (!POINTER_TYPE_P (TREE_TYPE (base)))
return NULL_TREE;
type = TREE_TYPE (TREE_TYPE (base));
}
ret = maybe_fold_offset_to_component_ref (type, base, offset,
orig_type, base_is_ptr);
if (!ret)
{
if (base_is_ptr)
base = build1 (INDIRECT_REF, type, base);
ret = maybe_fold_offset_to_array_ref (base, offset, orig_type);
}
return ret;
}
/* A subroutine of fold_stmt_r. Attempt to simplify *(BASE+OFFSET). /* A subroutine of fold_stmt_r. Attempt to simplify *(BASE+OFFSET).
Return the simplified expression, or NULL if nothing could be done. */ Return the simplified expression, or NULL if nothing could be done. */
...@@ -1802,6 +1868,8 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset) ...@@ -1802,6 +1868,8 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
if (TREE_CODE (base) == ADDR_EXPR) if (TREE_CODE (base) == ADDR_EXPR)
{ {
tree base_addr = base;
/* Strip the ADDR_EXPR. */ /* Strip the ADDR_EXPR. */
base = TREE_OPERAND (base, 0); base = TREE_OPERAND (base, 0);
...@@ -1810,24 +1878,11 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset) ...@@ -1810,24 +1878,11 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
&& ccp_decl_initial_min_invariant (DECL_INITIAL (base))) && ccp_decl_initial_min_invariant (DECL_INITIAL (base)))
return DECL_INITIAL (base); return DECL_INITIAL (base);
/* Try folding *(&B+O) to B[X]. */
t = maybe_fold_offset_to_array_ref (base, offset, TREE_TYPE (expr));
if (t)
return t;
/* Try folding *(&B+O) to B.X. */ /* Try folding *(&B+O) to B.X. */
t = maybe_fold_offset_to_component_ref (TREE_TYPE (base), base, offset, t = maybe_fold_offset_to_reference (base_addr, offset,
TREE_TYPE (expr), false); TREE_TYPE (expr));
if (t) if (t)
return t; return t;
/* Fold *&B to B. We can only do this if EXPR is the same type
as BASE. We can't do this if EXPR is the element type of an array
and BASE is the array. */
if (integer_zerop (offset)
&& lang_hooks.types_compatible_p (TREE_TYPE (base),
TREE_TYPE (expr)))
return base;
} }
else else
{ {
...@@ -1856,9 +1911,8 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset) ...@@ -1856,9 +1911,8 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
/* Try folding *(B+O) to B->X. Still an improvement. */ /* Try folding *(B+O) to B->X. Still an improvement. */
if (POINTER_TYPE_P (TREE_TYPE (base))) if (POINTER_TYPE_P (TREE_TYPE (base)))
{ {
t = maybe_fold_offset_to_component_ref (TREE_TYPE (TREE_TYPE (base)), t = maybe_fold_offset_to_reference (base, offset,
base, offset, TREE_TYPE (expr));
TREE_TYPE (expr), true);
if (t) if (t)
return t; return t;
} }
...@@ -2020,6 +2074,21 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) ...@@ -2020,6 +2074,21 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
integer_zero_node); integer_zero_node);
break; break;
case NOP_EXPR:
t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
if (t)
return t;
*walk_subtrees = 0;
if (POINTER_TYPE_P (TREE_TYPE (expr))
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
&& (t = maybe_fold_offset_to_reference
(TREE_OPERAND (expr, 0),
integer_zero_node,
TREE_TYPE (TREE_TYPE (expr)))))
t = build_fold_addr_expr_with_type (t, TREE_TYPE (expr));
break;
/* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF. /* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF.
We'd only want to bother decomposing an existing ARRAY_REF if We'd only want to bother decomposing an existing ARRAY_REF if
the base array is found to have another offset contained within. the base array is found to have another offset contained within.
......
...@@ -4422,8 +4422,7 @@ extern void fold_defer_overflow_warnings (void); ...@@ -4422,8 +4422,7 @@ extern void fold_defer_overflow_warnings (void);
extern void fold_undefer_overflow_warnings (bool, tree, int); extern void fold_undefer_overflow_warnings (bool, tree, int);
extern void fold_undefer_and_ignore_overflow_warnings (void); extern void fold_undefer_and_ignore_overflow_warnings (void);
extern bool fold_deferring_overflow_warnings_p (void); extern bool fold_deferring_overflow_warnings_p (void);
extern tree maybe_fold_offset_to_component_ref (tree, tree, tree, extern tree maybe_fold_offset_to_reference (tree, tree, tree);
tree, bool);
extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT, extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT,
int, bool); int, bool);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment