From: Richard Guenther Date: Fri, 21 Jan 2011 14:05:00 +0000 (+0000) Subject: re PR tree-optimization/47365 (wrong code with -O -ftree-pre) X-Git-Tag: releases/gcc-4.5.3~285 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0650b854221d78e9da737d0c353c58048ce7f12c;p=thirdparty%2Fgcc.git re PR tree-optimization/47365 (wrong code with -O -ftree-pre) 2011-01-21 Richard Guenther PR tree-optimization/47365 * tree-ssa-sccvn.h (vn_lookup_kind): Declare. (vn_reference_lookup_pieces): Adjust. (vn_reference_lookup): Likewise. * tree-ssa-sccvn.c (vn_walk_kind): New static global. (vn_reference_lookup_3): Only look through kills if in VN_WALKREWRITE mode. (vn_reference_lookup_pieces): Adjust. (vn_reference_lookup): Likewise. (visit_reference_op_load): Likewise. (visit_reference_op_store): Likewise. * tree-ssa-pre.c (phi_translate_1): Use VN_WALK mode. (compute_avail): Likewise. (eliminate): Likewise. * gcc.dg/torture/pr47365.c: New testcase. * gcc.dg/tree-ssa/pr47392.c: Likewise. From-SVN: r169090 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00d949d7c7c8..3ba8544c3890 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2011-01-21 Richard Guenther + + PR tree-optimization/47365 + * tree-ssa-sccvn.h (vn_lookup_kind): Declare. + (vn_reference_lookup_pieces): Adjust. + (vn_reference_lookup): Likewise. + * tree-ssa-sccvn.c (vn_walk_kind): New static global. + (vn_reference_lookup_3): Only look through kills if in + VN_WALKREWRITE mode. + (vn_reference_lookup_pieces): Adjust. + (vn_reference_lookup): Likewise. + (visit_reference_op_load): Likewise. + (visit_reference_op_store): Likewise. + * tree-ssa-pre.c (phi_translate_1): Use VN_WALK mode. + (compute_avail): Likewise. + (eliminate): Likewise. + 2011-01-20 Richard Guenther PR tree-optimization/47167 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 77d642169a95..42cd7a220609 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-01-21 Richard Guenther + + PR tree-optimization/47365 + * gcc.dg/torture/pr47365.c: New testcase. + * gcc.dg/tree-ssa/pr47392.c: Likewise. + 2011-01-21 Rainer Orth * g++.dg/other/anon5.C: Skip on mips-sgi-irix*. diff --git a/gcc/testsuite/gcc.dg/torture/pr47365.c b/gcc/testsuite/gcc.dg/torture/pr47365.c new file mode 100644 index 000000000000..e3bc55011a5b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr47365.c @@ -0,0 +1,39 @@ +/* { dg-do run } */ + +struct A +{ + int i; +}; + +struct B +{ + struct A a[2]; +}; + +int i = 1; +struct B b = { 0, 3 }; + +static void +test () +{ + if (b.a[0].i != i) + { + int t = b.a[0].i; + b.a[0] = b.a[1]; + b.a[1].i = t; + } + + if (b.a[1].i == i) + __builtin_abort (); + + if (b.a[0].i == 0) + __builtin_abort (); +} + +int +main () +{ + test (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c b/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c new file mode 100644 index 000000000000..9092ddddc0e7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c @@ -0,0 +1,42 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +struct A +{ + int i; +}; + +struct B +{ + struct A a[2]; +}; + +int i = 1; +struct B b = { 0, 3 }; + +static void +test () +{ + if (b.a[0].i != i) + { + int t = b.a[0].i; + b.a[0] = b.a[1]; + b.a[1].i = t; + } + + if (b.a[1].i == i) + __builtin_abort (); + + if (b.a[0].i == 0) + __builtin_abort (); +} + +int +main () +{ + test (); + return 0; +} + +/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 1cf78c776dde..7b117a81f6fe 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -1701,7 +1701,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, tree result = vn_reference_lookup_pieces (newvuse, ref->set, ref->type, newoperands, - &newref, true); + &newref, VN_WALK); if (newref) VEC_free (vn_reference_op_s, heap, newoperands); @@ -2558,6 +2558,10 @@ compute_antic (void) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Starting iteration %d\n", num_iterations); + /* ??? We need to clear our PHI translation cache here as the + ANTIC sets shrink and we restrict valid translations to + those having operands with leaders in ANTIC. Same below + for PA ANTIC computation. */ num_iterations++; changed = false; for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--) @@ -3965,7 +3969,7 @@ compute_avail (void) copy_reference_ops_from_call (stmt, &ops); vn_reference_lookup_pieces (gimple_vuse (stmt), 0, gimple_expr_type (stmt), - ops, &ref, false); + ops, &ref, VN_NOWALK); VEC_free (vn_reference_op_s, heap, ops); if (!ref) continue; @@ -4035,7 +4039,7 @@ compute_avail (void) vn_reference_lookup (gimple_assign_rhs1 (stmt), gimple_vuse (stmt), - true, &ref); + VN_WALK, &ref); if (!ref) continue; @@ -4265,7 +4269,7 @@ eliminate (void) tree rhs = gimple_assign_rhs1 (stmt); tree val; val = vn_reference_lookup (gimple_assign_lhs (stmt), - gimple_vuse (stmt), true, NULL); + gimple_vuse (stmt), VN_WALK, NULL); if (TREE_CODE (rhs) == SSA_NAME) rhs = VN_INFO (rhs)->valnum; if (val diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 9b2638f10904..886f215bb1b8 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -988,6 +988,7 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult) } static tree *last_vuse_ptr; +static vn_lookup_kind vn_walk_kind; /* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_ with the current VUSE and performs the expression lookup. */ @@ -1103,7 +1104,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_) /* For aggregate copies translate the reference through them if the copy kills ref. */ - else if (gimple_assign_single_p (def_stmt) + else if (vn_walk_kind == VN_WALKREWRITE + && gimple_assign_single_p (def_stmt) && (DECL_P (gimple_assign_rhs1 (def_stmt)) || INDIRECT_REF_P (gimple_assign_rhs1 (def_stmt)) || handled_component_p (gimple_assign_rhs1 (def_stmt)))) @@ -1193,7 +1195,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_) tree vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type, VEC (vn_reference_op_s, heap) *operands, - vn_reference_t *vnresult, bool maywalk) + vn_reference_t *vnresult, vn_lookup_kind kind) { struct vn_reference_s vr1; vn_reference_t tmp; @@ -1218,10 +1220,11 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type, vn_reference_lookup_1 (&vr1, vnresult); if (!*vnresult - && maywalk + && kind != VN_NOWALK && vr1.vuse) { ao_ref r; + vn_walk_kind = kind; if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands)) *vnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, @@ -1244,7 +1247,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type, stored in the hashtable if one exists. */ tree -vn_reference_lookup (tree op, tree vuse, bool maywalk, +vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, vn_reference_t *vnresult) { VEC (vn_reference_op_s, heap) *operands; @@ -1259,12 +1262,13 @@ vn_reference_lookup (tree op, tree vuse, bool maywalk, vr1.set = get_alias_set (op); vr1.hashcode = vn_reference_compute_hash (&vr1); - if (maywalk + if (kind != VN_NOWALK && vr1.vuse) { vn_reference_t wvnresult; ao_ref r; ao_ref_init (&r, op); + vn_walk_kind = kind; wvnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, vn_reference_lookup_2, @@ -1983,14 +1987,14 @@ visit_reference_op_load (tree lhs, tree op, gimple stmt) last_vuse = gimple_vuse (stmt); last_vuse_ptr = &last_vuse; - result = vn_reference_lookup (op, gimple_vuse (stmt), true, NULL); + result = vn_reference_lookup (op, gimple_vuse (stmt), VN_WALKREWRITE, NULL); last_vuse_ptr = NULL; /* If we have a VCE, try looking up its operand as it might be stored in a different type. */ if (!result && TREE_CODE (op) == VIEW_CONVERT_EXPR) result = vn_reference_lookup (TREE_OPERAND (op, 0), gimple_vuse (stmt), - true, NULL); + VN_WALKREWRITE, NULL); /* We handle type-punning through unions by value-numbering based on offset and size of the access. Be prepared to handle a @@ -2101,7 +2105,7 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt) Otherwise, the vdefs for the store are used when inserting into the table, since the store generates a new memory state. */ - result = vn_reference_lookup (lhs, gimple_vuse (stmt), false, NULL); + result = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_NOWALK, NULL); if (result) { diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h index c60c28ac11a5..dd237fc6cdda 100644 --- a/gcc/tree-ssa-sccvn.h +++ b/gcc/tree-ssa-sccvn.h @@ -185,10 +185,11 @@ void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **); void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **); bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, tree, VEC (vn_reference_op_s, heap) *); +typedef enum { VN_NOWALK, VN_WALK, VN_WALKREWRITE } vn_lookup_kind; tree vn_reference_lookup_pieces (tree, alias_set_type, tree, VEC (vn_reference_op_s, heap) *, - vn_reference_t *, bool); -tree vn_reference_lookup (tree, tree, bool, vn_reference_t *); + vn_reference_t *, vn_lookup_kind); +tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *); vn_reference_t vn_reference_insert (tree, tree, tree); vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree, VEC (vn_reference_op_s, heap) *,