From patchwork Thu Mar 24 10:50:16 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Belevantsev X-Patchwork-Id: 88165 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id C01FA1007D1 for ; Thu, 24 Mar 2011 21:50:29 +1100 (EST) Received: (qmail 10767 invoked by alias); 24 Mar 2011 10:50:28 -0000 Received: (qmail 10758 invoked by uid 22791); 24 Mar 2011 10:50:27 -0000 X-SWARE-Spam-Status: No, hits=-0.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_JMF_BL, TW_CP, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from smtp.ispras.ru (HELO smtp.ispras.ru) (83.149.198.201) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 24 Mar 2011 10:50:21 +0000 Received: from [10.10.3.52] (winnie.ispras.ru [83.149.198.236]) by smtp.ispras.ru (Postfix) with ESMTP id AFF24E489; Thu, 24 Mar 2011 13:37:18 +0300 (MSK) Message-ID: <4D8B21E8.7050402@ispras.ru> Date: Thu, 24 Mar 2011 13:50:16 +0300 From: Andrey Belevantsev User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.15) Gecko/20110303 Thunderbird/3.1.9 MIME-Version: 1.0 To: GCC Patches CC: "Vladimir N. Makarov" Subject: [PATCH] Fix PR 48144 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello, As noted in the PR audit trail, this is a case when we fail to find a transformed insn due to incomplete transformation history attached to it. The earlier fixes of this issue worked only for bookkeeping copies, but now we need a more general mechanism. Fixed by simply picking up additional transformation history from the av sets of basic blocks on the way. The problem can only happen on the bookkeeping blocks which have somewhat newer av sets available. Bootstrapping and testing on x86-64 and ia64 is in progress, ok if it succeeds? Andrey 2011-03-24 Andrey Belevantsev gcc/ PR rtl-optimization/48144 * sel-sched-ir.c (merge_history_vect): Factor out from ... (merge_expr_data): ... here. (av_set_intersect): Rename to av_set_code_motion_filter. Update all callers. Call merge_history_vect when an expression is found in both sets. * sel-sched-ir.h (av_set_code_motion_filter): Add prototype. gcc/testsuite PR rtl-optimization/48144 * gcc.dg/pr48144.c: New test. diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c index b88dad1..61f3ffb 100644 --- a/gcc/sel-sched-ir.c +++ b/gcc/sel-sched-ir.c @@ -1564,6 +1564,20 @@ free_history_vect (VEC (expr_history_def, heap) **pvect) *pvect = NULL; } +/* Merge vector FROM to PVECT. */ +static void +merge_history_vect (VEC (expr_history_def, heap) **pvect, + VEC (expr_history_def, heap) *from) +{ + expr_history_def *phist; + int i; + + /* We keep this vector sorted. */ + for (i = 0; VEC_iterate (expr_history_def, from, i, phist); i++) + insert_in_history_vect (pvect, phist->uid, phist->type, + phist->old_expr_vinsn, phist->new_expr_vinsn, + phist->spec_ds); +} /* Compare two vinsns as rhses if possible and as vinsns otherwise. */ bool @@ -1796,9 +1810,6 @@ update_speculative_bits (expr_t to, expr_t from, insn_t split_point) void merge_expr_data (expr_t to, expr_t from, insn_t split_point) { - int i; - expr_history_def *phist; - /* For now, we just set the spec of resulting expr to be minimum of the specs of merged exprs. */ if (EXPR_SPEC (to) > EXPR_SPEC (from)) @@ -1822,20 +1833,12 @@ merge_expr_data (expr_t to, expr_t from, insn_t split_point) EXPR_ORIG_SCHED_CYCLE (to) = MIN (EXPR_ORIG_SCHED_CYCLE (to), EXPR_ORIG_SCHED_CYCLE (from)); - /* We keep this vector sorted. */ - for (i = 0; - VEC_iterate (expr_history_def, EXPR_HISTORY_OF_CHANGES (from), - i, phist); - i++) - insert_in_history_vect (&EXPR_HISTORY_OF_CHANGES (to), - phist->uid, phist->type, - phist->old_expr_vinsn, phist->new_expr_vinsn, - phist->spec_ds); - EXPR_WAS_SUBSTITUTED (to) |= EXPR_WAS_SUBSTITUTED (from); EXPR_WAS_RENAMED (to) |= EXPR_WAS_RENAMED (from); EXPR_CANT_MOVE (to) |= EXPR_CANT_MOVE (from); + merge_history_vect (&EXPR_HISTORY_OF_CHANGES (to), + EXPR_HISTORY_OF_CHANGES (from)); update_target_availability (to, from, split_point); update_speculative_bits (to, from, split_point); } @@ -2328,16 +2331,24 @@ av_set_split_usefulness (av_set_t av, int prob, int all_prob) } /* Leave in AVP only those expressions, which are present in AV, - and return it. */ + and return it, merging history expressions. */ void -av_set_intersect (av_set_t *avp, av_set_t av) +av_set_code_motion_filter (av_set_t *avp, av_set_t av) { av_set_iterator i; - expr_t expr; + expr_t expr, expr2; FOR_EACH_EXPR_1 (expr, i, avp) - if (av_set_lookup (av, EXPR_VINSN (expr)) == NULL) + if ((expr2 = av_set_lookup (av, EXPR_VINSN (expr))) == NULL) av_set_iter_remove (&i); + else + /* When updating av sets in bookkeeping blocks, we can add more insns + there which will be transformed but the upper av sets will not + reflect those transformations. We then fail to undo those + when searching for such insns. So merge the history saved + in the av set of the block we are processing. */ + merge_history_vect (&EXPR_HISTORY_OF_CHANGES (expr), + EXPR_HISTORY_OF_CHANGES (expr2)); } diff --git a/gcc/sel-sched-ir.h b/gcc/sel-sched-ir.h index 1f3dec4..5516da9 100644 --- a/gcc/sel-sched-ir.h +++ b/gcc/sel-sched-ir.h @@ -1565,7 +1565,7 @@ extern void av_set_leave_one_nonspec (av_set_t *); extern expr_t av_set_element (av_set_t, int); extern void av_set_substract_cond_branches (av_set_t *); extern void av_set_split_usefulness (av_set_t, int, int); -extern void av_set_intersect (av_set_t *, av_set_t); +extern void av_set_code_motion_filter (av_set_t *, av_set_t); extern void sel_save_haifa_priorities (void); diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c index e26ddac..9179249 100644 --- a/gcc/sel-sched.c +++ b/gcc/sel-sched.c @@ -6481,7 +6481,7 @@ code_motion_path_driver (insn_t insn, av_set_t orig_ops, ilist_t path, /* Filter the orig_ops set. */ if (AV_SET_VALID_P (insn)) - av_set_intersect (&orig_ops, AV_SET (insn)); + av_set_code_motion_filter (&orig_ops, AV_SET (insn)); /* If no more original ops, return immediately. */ if (!orig_ops) diff --git a/gcc/testsuite/gcc.dg/pr48144.c b/gcc/testsuite/gcc.dg/pr48144.c new file mode 100644 index 0000000..030202d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr48144.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target powerpc*-*-* ia64-*-* i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O -frerun-cse-after-loop -fschedule-insns2 -fselective-scheduling2 -fno-tree-ch -funroll-loops --param=max-sched-extend-regions-iters=2 --param=max-sched-region-blocks=15" } */ +extern void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n); + +void bar (void *, void *, void *); + +void foo + (void *p, char *data, unsigned data_len) +{ + int buffer[8]; + int buf2[8]; + unsigned i; + for (i = 0; i + 8 <= data_len; i += 8) + bar (p, buffer, data + i); + memcpy (buf2, data + i, data_len); +}