From patchwork Thu Feb 10 14:31:18 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 82609 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 05C37B70E3 for ; Fri, 11 Feb 2011 01:32:04 +1100 (EST) Received: (qmail 6790 invoked by alias); 10 Feb 2011 14:32:01 -0000 Received: (qmail 6782 invoked by uid 22791); 10 Feb 2011 14:32:00 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, TW_TJ, TW_TM, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 10 Feb 2011 14:31:55 +0000 Received: (qmail 15925 invoked from network); 10 Feb 2011 14:31:52 -0000 Received: from unknown (HELO ?84.152.197.202?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 10 Feb 2011 14:31:52 -0000 Message-ID: <4D53F6B6.3020006@codesourcery.com> Date: Thu, 10 Feb 2011 15:31:18 +0100 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101211 Lightning/1.0b3pre Thunderbird/3.1.7 MIME-Version: 1.0 To: GCC Patches Subject: Avoid ivopts when loop contains vfork 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 When a loop contains vfork, certain loop optimizations can be incorrect. This was seen with an unreleased port in the LTP testcase waitpid03, with the relevant part of the code looking like this: while (++ikids < MAXUPRC) { if ((pid[ikids] = FORK_OR_VFORK()) > 0) { This was transformed into an autoinc, i.e. something like while (ikids < MAXUPRC - 1) { if ((pid[ikids++] = FORK_OR_VFORK()) > 0) { ikids did not get a hard register, which means that the copy on the stack was incremented twice, once for each return from vfork. In our tree, I fixed it with the following patch. Note that, despite the name, setjmp_call_p really tests ECF_RETURNS_TWICE, which is true for vfork as well. Bootstrapped and regression tested on i686-linux. Ok? Bernd * tree-ssa-loop-ivopts.c (loop_body_includes_call): Change return value to integer. Check whether the loop calls special functions. (tree_ssa_iv_optimize_loop): Return if we find it does. Index: tree-ssa-loop-ivopts.c =================================================================== --- tree-ssa-loop-ivopts.c (revision 169892) +++ tree-ssa-loop-ivopts.c (working copy) @@ -6325,9 +6325,12 @@ tree_ssa_iv_optimize_finalize (struct iv htab_delete (data->inv_expr_tab); } -/* Returns true if the loop body BODY includes any function calls. */ +/* Returns a nonzero value if the loop body BODY includes any function + calls. For normal calls, we return a positive value; if there is + something special (like a call to vfork) that should prevent us from + optimizing the loop, we return a negative value. */ -static bool +static int loop_body_includes_call (basic_block *body, unsigned num_nodes) { gimple_stmt_iterator gsi; @@ -6337,11 +6340,16 @@ loop_body_includes_call (basic_block *bo for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); - if (is_gimple_call (stmt) - && !is_inexpensive_builtin (gimple_call_fndecl (stmt))) - return true; + if (is_gimple_call (stmt)) + { + tree callee_t = gimple_call_fndecl (stmt); + if (setjmp_call_p (callee_t)) + return -1; + if (!is_inexpensive_builtin (callee_t)) + return 1; + } } - return false; + return 0; } /* Optimizes the LOOP. Returns true if anything changed. */ @@ -6353,6 +6361,7 @@ tree_ssa_iv_optimize_loop (struct ivopts struct iv_ca *iv_ca; edge exit; basic_block *body; + int t; gcc_assert (!data->niters); data->current_loop = loop; @@ -6375,7 +6384,14 @@ tree_ssa_iv_optimize_loop (struct ivopts } body = get_loop_body (loop); - data->body_includes_call = loop_body_includes_call (body, loop->num_nodes); + t = loop_body_includes_call (body, loop->num_nodes); + if (t >= 0) + data->body_includes_call = t > 0; + else + { + free (body); + goto finish; + } renumber_gimple_stmt_uids_in_blocks (body, loop->num_nodes); free (body);