Commit e52201b6 by Richard Guenther Committed by Richard Biener

tree-ssa.c (useless_type_conversion_p_1): Make function and array type…

tree-ssa.c (useless_type_conversion_p_1): Make function and array type comparisons frontend independent.

2009-08-06  Richard Guenther  <rguenther@suse.de>

	* tree-ssa.c (useless_type_conversion_p_1): Make function and
	array type comparisons frontend independent.
	* Makefile.in (tree-ssa.o): Add $(TARGET_H) dependency.
	* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Always fill
	out array reference lower bound and element size operands.
	(ao_ref_init_from_vn_reference): Properly compute the offset
	for ARRAY_RANGE_REF.
	(vn_reference_fold_indirect): Fill out array reference lower
	bound and element size operands.
	* tree-ssa-pre.c (phi_translate_1): Fail if we have to translate
	a non gimple valued reference operand which can happen for
	array reference lower bound or element size.
	(create_component_ref_by_pieces_1): Properly generate the
	element size operand for array references.

From-SVN: r150519
parent b92fbdd7
2009-08-06 Richard Guenther <rguenther@suse.de>
* tree-ssa.c (useless_type_conversion_p_1): Make function and
array type comparisons frontend independent.
* Makefile.in (tree-ssa.o): Add $(TARGET_H) dependency.
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Always fill
out array reference lower bound and element size operands.
(ao_ref_init_from_vn_reference): Properly compute the offset
for ARRAY_RANGE_REF.
(vn_reference_fold_indirect): Fill out array reference lower
bound and element size operands.
* tree-ssa-pre.c (phi_translate_1): Fail if we have to translate
a non gimple valued reference operand which can happen for
array reference lower bound or element size.
(create_component_ref_by_pieces_1): Properly generate the
element size operand for array references.
2009-08-06 Richard Guenther <rguenther@suse.de>
PR tree-optimization/40964
* tree.c (iterative_hash_host_wide_int): Export.
* tree.h (iterative_hash_host_wide_int): Declare.
......
......@@ -2193,7 +2193,7 @@ tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(TOPLEV_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
$(TREE_DUMP_H) langhooks.h $(TREE_PASS_H) $(BASIC_BLOCK_H) $(BITMAP_H) \
$(FLAGS_H) $(GGC_H) hard-reg-set.h $(HASHTAB_H) pointer-set.h \
$(GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H)
$(GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H) $(TARGET_H)
tree-into-ssa.o : tree-into-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
$(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
......
......@@ -1600,6 +1600,9 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
else if (!opresult)
break;
}
/* We can't possibly insert these. */
else if (op1 && !is_gimple_min_invariant (op1))
break;
changed |= op1 != oldop1;
if (op2 && TREE_CODE (op2) == SSA_NAME)
{
......@@ -1617,6 +1620,9 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
else if (!opresult)
break;
}
/* We can't possibly insert these. */
else if (op2 && !is_gimple_min_invariant (op2))
break;
changed |= op2 != oldop2;
if (!newoperands)
......@@ -2742,7 +2748,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
pre_expr op1expr;
tree genop2 = currop->op1;
pre_expr op2expr;
tree genop3;
tree genop3 = currop->op2;
pre_expr op3expr;
genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
stmts, domstmt);
if (!genop0)
......@@ -2759,8 +2766,17 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
if (!genop2)
return NULL_TREE;
}
genop3 = currop->op2;
if (genop3)
{
tree elmt_type = TREE_TYPE (TREE_TYPE (genop0));
genop3 = size_binop (EXACT_DIV_EXPR, genop3,
size_int (TYPE_ALIGN_UNIT (elmt_type)));
op3expr = get_or_alloc_expr_for (genop3);
genop3 = find_or_generate_expression (block, op3expr, stmts,
domstmt);
if (!genop3)
return NULL_TREE;
}
return build4 (currop->opcode, currop->type, genop0, genop1,
genop2, genop3);
}
......
......@@ -561,18 +561,9 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
case ARRAY_REF:
/* Record index as operand. */
temp.op0 = TREE_OPERAND (ref, 1);
/* Record even constant lower bounds. */
if (TREE_OPERAND (ref, 2))
temp.op1 = TREE_OPERAND (ref, 2);
else
{
tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
if (domain
&& TYPE_MIN_VALUE (domain)
&& !integer_zerop (TYPE_MIN_VALUE (domain)))
temp.op1 = TYPE_MIN_VALUE (domain);
}
temp.op2 = TREE_OPERAND (ref, 3);
/* Always record lower bounds and element size. */
temp.op1 = array_ref_low_bound (ref);
temp.op2 = array_ref_element_size (ref);
break;
case STRING_CST:
case INTEGER_CST:
......@@ -731,19 +722,17 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
case ARRAY_RANGE_REF:
case ARRAY_REF:
/* Same for ARRAY_REFs. We do not have access to the array
type here, but we recorded the lower bound in op1. */
if (op->op2
|| !host_integerp (op->op0, 0)
|| (op->op1 && !host_integerp (op->op1, 0))
|| !host_integerp (TYPE_SIZE (op->type), 1))
/* We recorded the lower bound and the element size. */
if (!host_integerp (op->op0, 0)
|| !host_integerp (op->op1, 0)
|| !host_integerp (op->op2, 0))
max_size = -1;
else
{
HOST_WIDE_INT hindex = TREE_INT_CST_LOW (op->op0);
if (op->op1)
hindex -= TREE_INT_CST_LOW (op->op1);
hindex *= TREE_INT_CST_LOW (TYPE_SIZE (op->type));
hindex -= TREE_INT_CST_LOW (op->op1);
hindex *= TREE_INT_CST_LOW (op->op2);
hindex *= BITS_PER_UNIT;
offset += hindex;
}
break;
......@@ -863,8 +852,8 @@ vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **ops,
if ((dom = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (op->op0, 0))))
&& TYPE_MIN_VALUE (dom))
aref.op0 = TYPE_MIN_VALUE (dom);
aref.op1 = NULL_TREE;
aref.op2 = NULL_TREE;
aref.op1 = aref.op0;
aref.op2 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (op->op0)));
VEC_safe_push (vn_reference_op_s, heap, mem, &aref);
}
copy_reference_ops_from_ref (TREE_OPERAND (op->op0, 0), &mem);
......
......@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "rtl.h"
#include "tm_p.h"
#include "target.h"
#include "ggc.h"
#include "langhooks.h"
#include "hard-reg-set.h"
......@@ -871,8 +872,10 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
&& TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type))
return true;
/* Changes in machine mode are never useless conversions. */
if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type))
/* Changes in machine mode are never useless conversions unless we
deal with aggregate types in which case we defer to later checks. */
if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type)
&& !AGGREGATE_TYPE_P (inner_type))
return false;
/* If both the inner and outer types are integral types, then the
......@@ -919,6 +922,11 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
&& TYPE_VOLATILE (TREE_TYPE (outer_type)))
return false;
/* We require explicit conversions from incomplete target types. */
if (!COMPLETE_TYPE_P (TREE_TYPE (inner_type))
&& COMPLETE_TYPE_P (TREE_TYPE (outer_type)))
return false;
/* Do not lose casts between pointers that when dereferenced access
memory with different alias sets. */
if (get_deref_alias_set (inner_type) != get_deref_alias_set (outer_type))
......@@ -948,33 +956,129 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
return useless_type_conversion_p (TREE_TYPE (outer_type),
TREE_TYPE (inner_type));
/* For aggregates we may need to fall back to structural equality
checks. */
else if (AGGREGATE_TYPE_P (inner_type)
&& AGGREGATE_TYPE_P (outer_type))
else if (TREE_CODE (inner_type) == ARRAY_TYPE
&& TREE_CODE (outer_type) == ARRAY_TYPE)
{
/* Different types of aggregates are incompatible. */
if (TREE_CODE (inner_type) != TREE_CODE (outer_type))
/* Preserve string attributes. */
if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
return false;
/* Conversions from array types with unknown extent to
array types with known extent are not useless. */
if (TREE_CODE (inner_type) == ARRAY_TYPE
&& !TYPE_DOMAIN (inner_type)
if (!TYPE_DOMAIN (inner_type)
&& TYPE_DOMAIN (outer_type))
return false;
/* Nor are conversions from array types with non-constant size to
array types with constant size or to different size. */
if (TYPE_SIZE (outer_type)
&& TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
&& (!TYPE_SIZE (inner_type)
|| TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
|| !tree_int_cst_equal (TYPE_SIZE (outer_type),
TYPE_SIZE (inner_type))))
return false;
/* Check conversions between arrays with partially known extents.
If the array min/max values are constant they have to match.
Otherwise allow conversions to unknown and variable extents.
In particular this declares conversions that may change the
mode to BLKmode as useless. */
if (TYPE_DOMAIN (inner_type)
&& TYPE_DOMAIN (outer_type)
&& TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
{
tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));
/* After gimplification a variable min/max value carries no
additional information compared to a NULL value. All that
matters has been lowered to be part of the IL. */
if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
inner_min = NULL_TREE;
if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
outer_min = NULL_TREE;
if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
inner_max = NULL_TREE;
if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
outer_max = NULL_TREE;
/* Conversions NULL / variable <- cst are useless, but not
the other way around. */
if (outer_min
&& (!inner_min
|| !tree_int_cst_equal (inner_min, outer_min)))
return false;
if (outer_max
&& (!inner_max
|| !tree_int_cst_equal (inner_max, outer_max)))
return false;
}
/* Recurse on the element check. */
return useless_type_conversion_p (TREE_TYPE (outer_type),
TREE_TYPE (inner_type));
}
else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
|| TREE_CODE (inner_type) == METHOD_TYPE)
&& TREE_CODE (inner_type) == TREE_CODE (outer_type))
{
tree outer_parm, inner_parm;
/* If the return types are not compatible bail out. */
if (!useless_type_conversion_p (TREE_TYPE (outer_type),
TREE_TYPE (inner_type)))
return false;
/* Method types should belong to a compatible base class. */
if (TREE_CODE (inner_type) == METHOD_TYPE
&& !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
TYPE_METHOD_BASETYPE (inner_type)))
return false;
/* A conversion to an unprototyped argument list is ok. */
if (!TYPE_ARG_TYPES (outer_type))
return true;
/* If the argument types are compatible the conversion is useless. */
if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
return true;
for (outer_parm = TYPE_ARG_TYPES (outer_type),
inner_parm = TYPE_ARG_TYPES (inner_type);
outer_parm && inner_parm;
outer_parm = TREE_CHAIN (outer_parm),
inner_parm = TREE_CHAIN (inner_parm))
if (!useless_type_conversion_p (TREE_VALUE (outer_parm),
TREE_VALUE (inner_parm)))
return false;
/* If there is a mismatch in the number of arguments the functions
are not compatible. */
if (outer_parm || inner_parm)
return false;
/* Defer to the target if necessary. */
if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
return targetm.comp_type_attributes (outer_type, inner_type) != 0;
return true;
}
/* For aggregates we may need to fall back to structural equality
checks. */
else if (AGGREGATE_TYPE_P (inner_type)
&& TREE_CODE (inner_type) == TREE_CODE (outer_type))
{
/* ??? This seems to be necessary even for aggregates that don't
have TYPE_STRUCTURAL_EQUALITY_P set. */
/* ??? This should eventually just return false. */
return lang_hooks.types_compatible_p (inner_type, outer_type);
}
/* Also for functions and possibly other types with
TYPE_STRUCTURAL_EQUALITY_P set. */
else if (TYPE_STRUCTURAL_EQUALITY_P (inner_type)
&& TYPE_STRUCTURAL_EQUALITY_P (outer_type))
return lang_hooks.types_compatible_p (inner_type, outer_type);
return false;
}
......
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