This fixes PR53168 - and removes some of the more odd code in phi-translation (I've added a testcase to make sure the intended PREs still happen). There is still some issues in phi translation I believe, but those are for later.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-05-04 Richard Guenther <rguent...@suse.de> PR tree-optimization/53168 * tree-ssa-pre.c (phi_translate_1): Only handle type-punned memory reads when the result is a constant we can pun. * gcc.dg/torture/pr53168.c: New testcase. * gcc.dg/tree-ssa/ssa-pre-30.c: Likewise. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 187148) --- gcc/tree-ssa-pre.c (working copy) *************** phi_translate_1 (pre_expr expr, bitmap_s *** 1659,1665 **** { unsigned int new_val_id; pre_expr constant; - bool converted = false; tree result = vn_reference_lookup_pieces (newvuse, ref->set, ref->type, --- 1659,1664 ---- *************** phi_translate_1 (pre_expr expr, bitmap_s *** 1668,1679 **** if (result) VEC_free (vn_reference_op_s, heap, newoperands); ! if (result ! && !useless_type_conversion_p (ref->type, TREE_TYPE (result))) { ! result = fold_build1 (VIEW_CONVERT_EXPR, ref->type, result); ! converted = true; } else if (!result && newref && !useless_type_conversion_p (ref->type, newref->type)) { --- 1667,1695 ---- if (result) VEC_free (vn_reference_op_s, heap, newoperands); ! /* We can always insert constants, so if we have a partial ! redundant constant load of another type try to translate it ! to a constant of appropriate type. */ ! if (result && is_gimple_min_invariant (result)) { ! tree tem = result; ! if (!useless_type_conversion_p (ref->type, TREE_TYPE (result))) ! { ! tem = fold_unary (VIEW_CONVERT_EXPR, ref->type, result); ! if (tem && !is_gimple_min_invariant (tem)) ! tem = NULL_TREE; ! } ! if (tem) ! return get_or_alloc_expr_for_constant (tem); } + + /* If we'd have to convert things we would need to validate + if we can insert the translated expression. So fail + here for now - we cannot insert an alias with a different + type in the VN tables either, as that would assert. */ + if (result + && !useless_type_conversion_p (ref->type, TREE_TYPE (result))) + return NULL; else if (!result && newref && !useless_type_conversion_p (ref->type, newref->type)) { *************** phi_translate_1 (pre_expr expr, bitmap_s *** 1681,1741 **** return NULL; } - if (result && is_gimple_min_invariant (result)) - { - gcc_assert (!newoperands); - return get_or_alloc_expr_for_constant (result); - } - expr = (pre_expr) pool_alloc (pre_expr_pool); expr->kind = REFERENCE; expr->id = 0; ! if (converted) ! { ! vn_nary_op_t nary; ! tree nresult; ! ! gcc_assert (CONVERT_EXPR_P (result) ! || TREE_CODE (result) == VIEW_CONVERT_EXPR); ! ! nresult = vn_nary_op_lookup_pieces (1, TREE_CODE (result), ! TREE_TYPE (result), ! &TREE_OPERAND (result, 0), ! &nary); ! if (nresult && is_gimple_min_invariant (nresult)) ! return get_or_alloc_expr_for_constant (nresult); ! ! expr->kind = NARY; ! if (nary) ! { ! PRE_EXPR_NARY (expr) = nary; ! constant = fully_constant_expression (expr); ! if (constant != expr) ! return constant; ! ! new_val_id = nary->value_id; ! get_or_alloc_expression_id (expr); ! } ! else ! { ! new_val_id = get_next_value_id (); ! VEC_safe_grow_cleared (bitmap_set_t, heap, ! value_expressions, ! get_max_value_id() + 1); ! nary = vn_nary_op_insert_pieces (1, TREE_CODE (result), ! TREE_TYPE (result), ! &TREE_OPERAND (result, 0), ! NULL_TREE, ! new_val_id); ! PRE_EXPR_NARY (expr) = nary; ! constant = fully_constant_expression (expr); ! if (constant != expr) ! return constant; ! get_or_alloc_expression_id (expr); ! } ! } ! else if (newref) { PRE_EXPR_REFERENCE (expr) = newref; constant = fully_constant_expression (expr); --- 1697,1707 ---- return NULL; } expr = (pre_expr) pool_alloc (pre_expr_pool); expr->kind = REFERENCE; expr->id = 0; ! if (newref) { PRE_EXPR_REFERENCE (expr) = newref; constant = fully_constant_expression (expr); Index: gcc/testsuite/gcc.dg/torture/pr53168.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr53168.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr53168.c (revision 0) *************** *** 0 **** --- 1,28 ---- + /* { dg-do compile } */ + + int a, b, c; + unsigned *d; + int e[1]; + void fn1 (); + int fn2 (); + int + fn3 () + { + int *f = &a; + if (fn2 ()) + { + for (; c; c++) + { + e[a] && (b = 0); + fn1 (); + if (e[a]) + return 0; + } + for (; c <= 0; c++) + for (;;) + ; + } + else + e[0] = 0 != (d = f); + return *d; + } Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c (revision 0) *************** *** 0 **** --- 1,27 ---- + /* { dg-do compile } */ + /* { dg-options "-O2 -fdump-tree-pre-details" } */ + + int f; + int g; + unsigned int + foo (int b, int x) + { + if (b) + x = *(int *)&f; + g = x; + return *(unsigned int*)&f; + } + float + bar (int b, int x) + { + if (b) + x = *(int *)&f; + g = x; + return *(float *)&f; + } + + /* We should see the partial redundant loads of f even though they + are using different types (of the same size). */ + + /* { dg-final { scan-tree-dump-times "Replaced MEM" 2 "pre" } } */ + /* { dg-final { cleanup-tree-dump "pre" } } */