From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 95409 invoked by alias); 21 Oct 2015 12:56:10 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 95399 invoked by uid 89); 21 Oct 2015 12:56:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00,KAM_ASCII_DIVIDERS,RP_MATCHES_RCVD,SPF_PASS autolearn=no version=3.3.2 X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Wed, 21 Oct 2015 12:56:08 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 6D381AAC8; Wed, 21 Oct 2015 12:56:04 +0000 (UTC) Date: Wed, 21 Oct 2015 12:57:00 -0000 From: Richard Biener To: gcc-patches@gcc.gnu.org cc: Dominik Vogt Subject: [PATCH] Fix PR67443 Message-ID: User-Agent: Alpine 2.11 (LSU 23 2013-08-11) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2015-10/txt/msg02069.txt.bz2 The following patch fixes PR67443, ao_ref_from_mem's special handling of some negative MEM_OFFSET cases being wrong in general. The patch removes the special-casing and places an additional safety net for MEM_EXPR handlings that rely on component bounds being honored. The patch might pessimize the mentioned "promoted subreg parameter" handling as for negative MEM_OFFSET we now run into /* If MEM_OFFSET and MEM_SIZE get us outside of the base object of the MEM_EXPR punt. This happens for STRICT_ALIGNMENT targets a lot. */ if (MEM_EXPR (mem) != get_spill_slot_decl (false) && (ref->offset < 0 || (DECL_P (ref->base) && (DECL_SIZE (ref->base) == NULL_TREE || TREE_CODE (DECL_SIZE (ref->base)) != INTEGER_CST || wi::ltu_p (wi::to_offset (DECL_SIZE (ref->base)), ref->offset + ref->size))))) return false; but I can't see how the previous handling was correct with regard to overlaps in the parameter area. Bootstrapped and tested on x86_64-unknown-linux-gnu and powerpc64-linux-gnu by me and on s390[x]-linux by Dominik. Eventually we'll get another testcase so I'll leave this for comments a while and will commit somewhen later this week. Thanks, Richard. 2015-10-21 Richard Biener Dominik Vogt PR middle-end/67443 * alias.c (ao_ref_from_mem): Remove promoted subreg handling. Properly prune ref->ref for accesses outside of ref. Index: gcc/alias.c =================================================================== *** gcc/alias.c (revision 229119) --- gcc/alias.c (working copy) *************** ao_ref_from_mem (ao_ref *ref, const_rtx *** 339,353 **** || !MEM_SIZE_KNOWN_P (mem)) return true; ! /* If the base decl is a parameter we can have negative MEM_OFFSET in ! case of promoted subregs on bigendian targets. Trust the MEM_EXPR ! here. */ if (MEM_OFFSET (mem) < 0 ! && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size) ! return true; ! /* Otherwise continue and refine size and offset we got from analyzing ! MEM_EXPR by using MEM_SIZE and MEM_OFFSET. */ ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT; ref->size = MEM_SIZE (mem) * BITS_PER_UNIT; --- 339,354 ---- || !MEM_SIZE_KNOWN_P (mem)) return true; ! /* If MEM_OFFSET/MEM_SIZE get us outside of ref->offset/ref->max_size ! drop ref->ref. */ if (MEM_OFFSET (mem) < 0 ! || (ref->max_size != -1 ! && ((MEM_OFFSET (mem) + MEM_SIZE (mem)) * BITS_PER_UNIT ! > ref->max_size))) ! ref->ref = NULL_TREE; ! /* Refine size and offset we got from analyzing MEM_EXPR by using ! MEM_SIZE and MEM_OFFSET. */ ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT; ref->size = MEM_SIZE (mem) * BITS_PER_UNIT; Index: gcc/testsuite/gcc.target/s390/pr67443.c =================================================================== *** gcc/testsuite/gcc.target/s390/pr67443.c (revision 0) --- gcc/testsuite/gcc.target/s390/pr67443.c (working copy) *************** *** 0 **** --- 1,49 ---- + /* Test case for PR/67443. */ + + /* { dg-do run { target s390*-*-* } } */ + /* { dg-prune-output "call-clobbered register used for global register variable" } */ + /* { dg-options "-march=z900 -fPIC -fomit-frame-pointer -O3" } */ + + #include + + /* Block all registers except the first three argument registers. */ + register long r0 asm ("r0"); + register long r1 asm ("r1"); + register long r5 asm ("r5"); + register long r6 asm ("r6"); + register long r7 asm ("r7"); + register long r8 asm ("r8"); + register long r9 asm ("r9"); + register long r10 asm ("r10"); + register long r11 asm ("r11"); + + struct s_t + { + unsigned f1 : 8; + unsigned f2 : 24; + }; + + __attribute__ ((noinline)) + void foo (struct s_t *ps, int c, int i) + { + /* Uses r2 as address register. */ + ps->f1 = c; + /* The calculation of the value is so expensive that it's cheaper to spill ps + to the stack and reload it later (into a different register). + ==> Uses r4 as address register.*/ + ps->f2 = i + i % 3; + /* If dead store elimination fails to detect that the address in r2 during + the first assignment is an alias of the address in r4 during the second + assignment, it eliminates the first assignment and the f1 field is not + written (bug). */ + } + + int main (void) + { + struct s_t s = { 0x01u, 0x020304u }; + + foo (&s, 0, 0); + assert (s.f1 == 0&& s.f2 == 0); + + return 0; + }