File pr34043-5.diff of Package gcc43
2008-02-29 Richard Guenther <rguenther@suse.de>
PR tree-optimization/34043
PR tree-optimization/33989
* tree-ssa-pre.c (get_sccvn_value): Build a value handle for
to be inserted expressions.
(substitute_leaders_in_expr): New function.
(eliminate): If we do not have a fully redundant leader but
can insert an alternate simplified expression, do so with all
operands replaced with their leader.
* tree-ssa-sccvn.h (struct vn_ssa_aux): Add needs_insertion flag.
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Value-number
union member access based on its size, not type and member.
(visit_reference_op_load): For a weak match from union type
punning create a fake SSA_NAME to attach a value-number for
the result VIEW_CONVERTed to the correct type.
(free_scc_vn): Release fake SSA_NAMEs again.
* gcc.dg/tree-ssa/ssa-fre-7.c: New testcase.
* gcc.dg/tree-ssa/ssa-fre-8.c: Likewise.
Index: gcc-4.3.0-20080306/gcc/tree-ssa-pre.c
===================================================================
*** gcc-4.3.0-20080306.orig/gcc/tree-ssa-pre.c 2008-03-10 11:33:02.000000000 +0100
--- gcc-4.3.0-20080306/gcc/tree-ssa-pre.c 2008-03-10 13:22:17.000000000 +0100
*************** clear_expression_ids (void)
*** 284,290 ****
VEC_free (vuse_vec, heap, expression_vuses);
}
! static bool in_fre = false;
/* An unordered bitmap set. One bitmap tracks values, the other,
expressions. */
--- 284,290 ----
VEC_free (vuse_vec, heap, expression_vuses);
}
! bool in_fre = false;
/* An unordered bitmap set. One bitmap tracks values, the other,
expressions. */
*************** get_sccvn_value (tree name)
*** 3237,3247 ****
bool is_invariant = is_gimple_min_invariant (val);
tree valvh = !is_invariant ? get_value_handle (val) : NULL_TREE;
/* We may end up with situations where SCCVN has chosen a
representative for the equivalence set that we have not
visited yet. In this case, just create the value handle for
it. */
! if (!valvh && !is_invariant)
{
tree defstmt = SSA_NAME_DEF_STMT (val);
--- 3237,3252 ----
bool is_invariant = is_gimple_min_invariant (val);
tree valvh = !is_invariant ? get_value_handle (val) : NULL_TREE;
+ /* In the case SCCVN has created a dummy SSA_NAME to value
+ number a simplified expression, just create a value handle
+ for it. */
+ if (!valvh && !is_invariant && VN_INFO (val)->needs_insertion)
+ valvh = vn_lookup_or_add (VN_INFO (val)->expr);
/* We may end up with situations where SCCVN has chosen a
representative for the equivalence set that we have not
visited yet. In this case, just create the value handle for
it. */
! else if (!valvh && !is_invariant)
{
tree defstmt = SSA_NAME_DEF_STMT (val);
*************** compute_avail (void)
*** 3590,3595 ****
--- 3595,3648 ----
free (worklist);
}
+ /* Substitutes leaders for all operands in EXPR supposed to replace
+ the rhs of STMT in basic-block BB.
+ Returns an available expression if that succeeds, NULL_TREE otherwise. */
+
+ static tree
+ substitute_leaders_in_expr (basic_block bb, tree stmt, tree expr)
+ {
+ switch (TREE_CODE_CLASS (TREE_CODE (expr)))
+ {
+ case tcc_reference:
+ if (TREE_CODE (expr) != VIEW_CONVERT_EXPR
+ && TREE_CODE (expr) != REALPART_EXPR
+ && TREE_CODE (expr) != IMAGPART_EXPR)
+ return NULL_TREE;
+
+ /* Fallthrough. */
+ case tcc_unary:
+ if (is_gimple_min_invariant (TREE_OPERAND (expr, 0)))
+ return expr;
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME)
+ {
+ tree def_stmt;
+ tree tmp = get_value_handle (TREE_OPERAND (expr, 0));
+ tmp = bitmap_find_leader (AVAIL_OUT (bb), tmp);
+ if (!tmp)
+ return NULL_TREE;
+ /* tmp can still be unavailable if it is defined in the same
+ basic-block, but after stmt. libgomp.fortran/retval1.f90:f5 */
+ def_stmt = SSA_NAME_DEF_STMT (tmp);
+ if (def_stmt
+ && TREE_CODE (def_stmt) != PHI_NODE
+ && bb_for_stmt (def_stmt) == bb)
+ {
+ block_stmt_iterator bsi = bsi_start (bb);
+ while (bsi_stmt (bsi) != def_stmt)
+ {
+ if (bsi_stmt (bsi) == stmt)
+ return NULL_TREE;
+ bsi_next (&bsi);
+ }
+ }
+ return build1 (TREE_CODE (expr), TREE_TYPE (expr), tmp);
+ }
+
+ default:;
+ }
+ return NULL_TREE;
+ }
/* Eliminate fully redundant computations. */
*************** eliminate (void)
*** 3622,3627 ****
--- 3675,3696 ----
sprime = bitmap_find_leader (AVAIL_OUT (b),
get_value_handle (lhs));
+ /* If we didn't find a leader but have an expression
+ we can insert, use that as replacement. */
+ if (sprime
+ && sprime == lhs
+ && VN_INFO (lhs)->valnum != VN_TOP
+ /* Instead of VN_TOP we also can end up with a
+ constant value. g++.dg/opt/reload1.C */
+ && TREE_CODE (VN_INFO (lhs)->valnum) == SSA_NAME
+ && VN_INFO (VN_INFO (lhs)->valnum)->needs_insertion)
+ {
+ tree tmp = VN_INFO (VN_INFO (lhs)->valnum)->expr;
+ tmp = substitute_leaders_in_expr (b, stmt, tmp);
+ if (tmp)
+ sprime = tmp;
+ }
+
if (sprime
&& sprime != lhs
&& (TREE_CODE (*rhs_p) != SSA_NAME
Index: gcc-4.3.0-20080306/gcc/tree-ssa-sccvn.c
===================================================================
*** gcc-4.3.0-20080306.orig/gcc/tree-ssa-sccvn.c 2008-03-10 11:33:02.000000000 +0100
--- gcc-4.3.0-20080306/gcc/tree-ssa-sccvn.c 2008-03-10 13:22:50.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 103,108 ****
--- 103,110 ----
structure copies.
*/
+ extern bool in_fre;
+
/* The set of hashtables and alloc_pool's for their items. */
typedef struct vn_tables_s
*************** copy_reference_ops_from_ref (tree ref, V
*** 538,545 ****
temp.op1 = TREE_OPERAND (ref, 2);
break;
case COMPONENT_REF:
! /* Record field as operand. */
! temp.op0 = TREE_OPERAND (ref, 1);
break;
case ARRAY_RANGE_REF:
case ARRAY_REF:
--- 540,558 ----
temp.op1 = TREE_OPERAND (ref, 2);
break;
case COMPONENT_REF:
! /* If this is a reference to a union member, record the union
! member size as operand. */
! if (in_fre
! && TREE_CODE (DECL_CONTEXT (TREE_OPERAND (ref, 1))) == UNION_TYPE
! && integer_zerop (DECL_FIELD_OFFSET (TREE_OPERAND (ref, 1)))
! && integer_zerop (DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1))))
! {
! temp.type = NULL_TREE;
! temp.op0 = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (ref, 1)));
! }
! else
! /* Record field as operand. */
! temp.op0 = TREE_OPERAND (ref, 1);
break;
case ARRAY_RANGE_REF:
case ARRAY_REF:
*************** defs_to_varying (tree stmt)
*** 1107,1112 ****
--- 1120,1128 ----
return changed;
}
+ static tree
+ try_to_simplify (tree stmt, tree rhs);
+
/* Visit a copy between LHS and RHS, return true if the value number
changed. */
*************** visit_reference_op_load (tree lhs, tree
*** 1179,1186 ****
bool changed = false;
tree result = vn_reference_lookup (op, shared_vuses_from_stmt (stmt));
! if (result)
! {
changed = set_ssa_val_to (lhs, result);
}
else
--- 1195,1247 ----
bool changed = false;
tree result = vn_reference_lookup (op, shared_vuses_from_stmt (stmt));
! /* We handle type-punning through unions by value-numbering based
! on offset and size of the access. Be prepared to handle a
! type-mismatch here via creating a VIEW_CONVERT_EXPR.
! Do this only after the iteration converged as introducing new
! SSA_NAMEs will let it never finish otherwise. */
! if (result
! && (useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (op))
! || current_info == valid_info))
! {
! if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (op)))
! {
! tree val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op),
! result);
! /* Make sure to simplify with earlier conversions as otherwise
! our dummy SSA_NAMEs start to leak all over. */
! if (TREE_CODE (val) == VIEW_CONVERT_EXPR)
! {
! tree tem = try_to_simplify (stmt, val);
! if (tem)
! val = tem;
! }
! result = val;
! if (result != lhs
! && !is_gimple_min_invariant (val)
! && TREE_CODE (val) != SSA_NAME)
! /* Finally do a lookup to not create redundant conversions. */
! result = vn_unary_op_lookup (val);
! if (!result)
! {
! /* Create a new temporary SSA_NAME to attach the
! conversion expression to. */
! result = make_ssa_name (SSA_NAME_VAR (lhs), NULL_TREE);
! VN_INFO_GET (result)->valnum = result;
! VN_INFO (result)->expr = val;
! VN_INFO (result)->needs_insertion = true;
! /* And insert the conversion so we can find it later. */
! vn_unary_op_insert (val, result);
! if (dump_file && (dump_flags & TDF_DETAILS))
! {
! fprintf (dump_file, "Inserting name ");
! print_generic_expr (dump_file, result, 0);
! fprintf (dump_file, " for expression ");
! print_generic_expr (dump_file, val, 0);
! fprintf (dump_file, "\n");
! }
! }
! }
changed = set_ssa_val_to (lhs, result);
}
else
*************** free_scc_vn (void)
*** 2083,2088 ****
--- 2144,2152 ----
if (SSA_NAME_VALUE (name) &&
TREE_CODE (SSA_NAME_VALUE (name)) == VALUE_HANDLE)
SSA_NAME_VALUE (name) = NULL;
+ if (name
+ && VN_INFO (name)->needs_insertion)
+ release_ssa_name (name);
}
}
Index: gcc-4.3.0-20080306/gcc/tree-ssa-sccvn.h
===================================================================
*** gcc-4.3.0-20080306.orig/gcc/tree-ssa-sccvn.h 2008-02-19 10:55:59.000000000 +0100
--- gcc-4.3.0-20080306/gcc/tree-ssa-sccvn.h 2008-03-10 11:33:02.000000000 +0100
*************** typedef struct vn_ssa_aux
*** 44,49 ****
--- 44,53 ----
once. It cannot be used to avoid visitation for SSA_NAME's
involved in non-singleton SCC's. */
unsigned use_processed : 1;
+
+ /* True, if this SSA_NAME doesn't have a defining statement.
+ Insertion of such with expr or replacement with expr is necessary. */
+ unsigned needs_insertion : 1;
} *vn_ssa_aux_t;
/* Return the value numbering info for an SSA_NAME. */
Index: gcc-4.3.0-20080306/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc-4.3.0-20080306/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c 2008-03-10 11:33:02.000000000 +0100
***************
*** 0 ****
--- 1,30 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre-details -fdump-tree-optimized" } */
+
+ struct X {
+ int i;
+ union {
+ int j;
+ int k;
+ float f;
+ } u;
+ };
+
+ int foo(int j)
+ {
+ struct X a;
+
+ a.u.j = j;
+ a.u.f = a.u.f;
+ a.u.f = a.u.f;
+ a.u.j = a.u.j;
+ a.u.f = a.u.f;
+ return a.u.k;
+ }
+
+ /* { dg-final { scan-tree-dump "Replaced a.u.f with VIEW_CONVERT_EXPR" "fre" } } */
+ /* { dg-final { scan-tree-dump "Replaced a.u.j with j" "fre" } } */
+ /* { dg-final { scan-tree-dump "Replaced a.u.k with j" "fre" } } */
+ /* { dg-final { scan-tree-dump "return j" "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc-4.3.0-20080306/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc-4.3.0-20080306/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c 2008-03-10 11:33:02.000000000 +0100
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre-details" } */
+
+ union U {
+ int i;
+ float f;
+ };
+ int foo(int i, int b)
+ {
+ union U u;
+ if (b)
+ {
+ i = i << 2;
+ u.i = i;
+ return u.f;
+ }
+ else
+ {
+ i = i << 2;
+ u.i = i;
+ return u.f;
+ }
+ }
+
+ /* { dg-final { scan-tree-dump-times "Replaced u.f with VIEW_CONVERT_EXPR" 2 "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */