From patchwork Wed Jul 21 14:37:39 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 59444 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 A6AEEB70A6 for ; Thu, 22 Jul 2010 00:35:49 +1000 (EST) Received: (qmail 24749 invoked by alias); 21 Jul 2010 14:35:45 -0000 Received: (qmail 24687 invoked by uid 22791); 21 Jul 2010 14:35:44 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 21 Jul 2010 14:35:38 +0000 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6LEZaA5018234 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 21 Jul 2010 10:35:36 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6LEZZfV031276 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 21 Jul 2010 10:35:36 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id o6LEbegN022688; Wed, 21 Jul 2010 16:37:40 +0200 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id o6LEbdqq022686; Wed, 21 Jul 2010 16:37:39 +0200 Date: Wed, 21 Jul 2010 16:37:39 +0200 From: Jakub Jelinek To: Richard Guenther Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix var-tracking.c (adjust_insn) on inline-asm with multiple outputs (PR debug/45015) Message-ID: <20100721143739.GN19172@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-12-10) 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 Hi! adjust_insns doesn't handle correctly inline-asm with multiple sets. In that case PATTERN is a PARALLEL with a bunch of SETs from ASM_OPERANDS (and optionally some CLOBBERs), but the 3 vector operands of ASM_OPERANDS rtx must be shared between all of them in the same insn. adjust_insn would instead walk the inputs and do any needed changes in all of them separately. This means the vectors weren't shared and, if any of the operands had any side-effects, the side-effects would be accounted several times (which leads to ICEs). The following patch fixes that by only ever changing operands of ASM_OPERANDS for the first ASM_OPERANDS in the instruction, and by ensuring the vectors are shared afterwards as well in adjust_insn. Bootstrapped/regtested on x86_64-linux and i686-linux (and tested with the testcase on m68k-linux cross). Ok for trunk? What about 4.5, which has the same bug? 2010-07-21 Jakub Jelinek PR debug/45015 * var-tracking.c (adjust_mems): Ignore ASM_OPERANDS with non-zero ASM_OPERANDS_OUTPUT_IDX. (adjust_insn): For inline asm with multiple sets ensure first ASM_OPERANDS vectors are used by all following ASM_OPERANDS in the insn. * gcc.target/m68k/pr45015.c: New test. Jakub --- gcc/var-tracking.c.jj 2010-07-21 09:53:10.000000000 +0200 +++ gcc/var-tracking.c 2010-07-21 14:04:26.000000000 +0200 @@ -910,6 +910,16 @@ adjust_mems (rtx loc, const_rtx old_rtx, return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem), GET_MODE (SUBREG_REG (tem))); return tem; + case ASM_OPERANDS: + /* Don't do any replacements in second and following + ASM_OPERANDS of inline-asm with multiple sets. + ASM_OPERANDS_INPUT_VEC, ASM_OPERANDS_INPUT_CONSTRAINT_VEC + and ASM_OPERANDS_LABEL_VEC need to be equal between + all the ASM_OPERANDs in the insn and adjust_insn will + fix this up. */ + if (ASM_OPERANDS_OUTPUT_IDX (loc) != 0) + return loc; + break; default: break; } @@ -960,7 +970,57 @@ adjust_insn (basic_block bb, rtx insn) note_stores (PATTERN (insn), adjust_mem_stores, &amd); amd.store = false; - note_uses (&PATTERN (insn), adjust_mem_uses, &amd); + if (GET_CODE (PATTERN (insn)) == PARALLEL + && asm_noperands (PATTERN (insn)) > 0 + && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET) + { + rtx body, set0; + int i; + + /* inline-asm with multiple sets is tiny bit more complicated, + because the 3 vectors in ASM_OPERANDS need to be shared between + all ASM_OPERANDS in the instruction. adjust_mems will + not touch ASM_OPERANDS other than the first one, asm_noperands + test above needs to be called before that (otherwise it would fail) + and afterwards this code fixes it up. */ + note_uses (&PATTERN (insn), adjust_mem_uses, &amd); + body = PATTERN (insn); + set0 = XVECEXP (body, 0, 0); +#ifdef ENABLE_CHECKING + gcc_assert (GET_CODE (set0) == SET + && GET_CODE (SET_SRC (set0)) == ASM_OPERANDS + && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set0)) == 0); +#endif + for (i = 1; i < XVECLEN (body, 0); i++) + if (GET_CODE (XVECEXP (body, 0, i)) != SET) + break; + else + { + set = XVECEXP (body, 0, i); +#ifdef ENABLE_CHECKING + gcc_assert (GET_CODE (SET_SRC (set)) == ASM_OPERANDS + && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set)) == i); +#endif + if (ASM_OPERANDS_INPUT_VEC (SET_SRC (set)) + != ASM_OPERANDS_INPUT_VEC (SET_SRC (set0)) + || ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set)) + != ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0)) + || ASM_OPERANDS_LABEL_VEC (SET_SRC (set)) + != ASM_OPERANDS_LABEL_VEC (SET_SRC (set0))) + { + rtx newsrc = shallow_copy_rtx (SET_SRC (set)); + ASM_OPERANDS_INPUT_VEC (newsrc) + = ASM_OPERANDS_INPUT_VEC (SET_SRC (set0)); + ASM_OPERANDS_INPUT_CONSTRAINT_VEC (newsrc) + = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0)); + ASM_OPERANDS_LABEL_VEC (newsrc) + = ASM_OPERANDS_LABEL_VEC (SET_SRC (set0)); + validate_change (NULL_RTX, &SET_SRC (set), newsrc, true); + } + } + } + else + note_uses (&PATTERN (insn), adjust_mem_uses, &amd); /* For read-only MEMs containing some constant, prefer those constants. */ --- gcc/testsuite/gcc.target/m68k/pr45015.c.jj 2010-07-21 14:28:14.000000000 +0200 +++ gcc/testsuite/gcc.target/m68k/pr45015.c 2010-07-21 14:29:46.000000000 +0200 @@ -0,0 +1,26 @@ +/* PR debug/45015 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +unsigned int +foo (unsigned int *x, const unsigned int *y, int z, unsigned int w) +{ + unsigned int a, b, c, s; + int j; + j = -z; + x -= j; + y -= j; + a = 0; + do + { + __asm__ ("move.l %2, %0; move.l %3, %1" : "=d" (b), "=d" (c) : "g<>" (y[j]), "d" (w)); + c += a; + a = (c < a) + b; + s = x[j]; + c = s + c; + a += (c < s); + x[j] = c; + } + while (++j != 0); + return a; +}