From patchwork Thu Jun 21 12:47:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Michael Matz X-Patchwork-Id: 166302 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 509A8B6FA7 for ; Thu, 21 Jun 2012 22:47:45 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1340887666; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Date: From:To:Cc:Subject:In-Reply-To:Message-ID:References:User-Agent: MIME-Version:Content-Type:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=FRAXrU7DNtu5s0xCDjvYC1xDscM=; b=T9/OsEt2g7BFDs0 A3r6m5rb0tHOa5rTcshpNYX+bvQ98v3wSmM1Kii+OGII2gOfZmQ0wvujuGeibNru E1wp8/FOcCPXSvnLQJkXA2HkoN8T4VkNs42ar36o/FreGLgOBjUmn12i8it0Yc6/ R3iu03nCQQBJSZGrdNdJD8JySiA0= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Date:From:To:Cc:Subject:In-Reply-To:Message-ID:References:User-Agent:MIME-Version:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=tLIHVTSoAPLYyFhHPPd0h+NNFZISjjaaAqnXm3mTA2cOFXbMKikraYt3R0RnnR 1x3xkA+zaJ50TAzIQL6QJ+flU5GF788glWq46+h++/Ykx0eCWRW4oxZtLDAE6Vgw KyWfMWKlCiJidFzvmbnzprww7EHbIqVv8dJWxkMq4yMSA=; Received: (qmail 31632 invoked by alias); 21 Jun 2012 12:47:40 -0000 Received: (qmail 31622 invoked by uid 22791); 21 Jun 2012 12:47:38 -0000 X-SWARE-Spam-Status: No, hits=-6.0 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_THREADED, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 21 Jun 2012 12:47:16 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx2.suse.de (Postfix) with ESMTP id BED05A2111; Thu, 21 Jun 2012 14:47:14 +0200 (CEST) Date: Thu, 21 Jun 2012 14:47:14 +0200 (CEST) From: Michael Matz To: Richard Guenther Cc: gcc-patches@gcc.gnu.org Subject: Re: RFA: Fix PR53688 In-Reply-To: Message-ID: References: User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 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, On Wed, 20 Jun 2012, Richard Guenther wrote: > > Hmm?  The original expression is an address, I have to build a MEM_REF > > out of that, and the is_gimple_mem_ref_addr() just checked that that > > very address (after going through fold) is not acceptable as MEM_REF > > operand. So how could I avoid the massaging of the address to make it > > an acceptable operand? > > Not change get_base_addres and use > > if (!is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)) > && (exp = get_base_address (TREE_OPERAND (orig_exp, 0)))) I see. I can't use orig_exp, as it's still the (now resolved) SAVE_EXPR, but TREE_OPERAND (TREE_OPERAND(exp, 0), 0) contains it still, so I'm using that now. Hence this is what I committed as r188852. Ciao, Michael. PR middle-end/53688 * builtins.c (get_memory_rtx): Always build an all-aliasing MEM_REF with correct size. testsuite/ * gcc.c-torture/execute/pr53688.c: New test. Index: builtins.c =================================================================== --- builtins.c (revision 188772) +++ builtins.c (working copy) @@ -1252,7 +1252,6 @@ get_memory_rtx (tree exp, tree len) { tree orig_exp = exp; rtx addr, mem; - HOST_WIDE_INT off; /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived from its expression, for expr->a.b only .a.b is recorded. */ @@ -1263,120 +1262,38 @@ get_memory_rtx (tree exp, tree len) mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr)); /* Get an expression we can use to find the attributes to assign to MEM. - If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if - we can. First remove any nops. */ + First remove any nops. */ while (CONVERT_EXPR_P (exp) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0)))) exp = TREE_OPERAND (exp, 0); - off = 0; - if (TREE_CODE (exp) == POINTER_PLUS_EXPR - && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR - && host_integerp (TREE_OPERAND (exp, 1), 0) - && (off = tree_low_cst (TREE_OPERAND (exp, 1), 0)) > 0) - exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - else if (TREE_CODE (exp) == ADDR_EXPR) - exp = TREE_OPERAND (exp, 0); - else if (POINTER_TYPE_P (TREE_TYPE (exp))) - exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp); - else - exp = NULL; - - /* Honor attributes derived from exp, except for the alias set - (as builtin stringops may alias with anything) and the size - (as stringops may access multiple array elements). */ - if (exp) + /* Build a MEM_REF representing the whole accessed area as a byte blob, + (as builtin stringops may alias with anything). */ + exp = fold_build2 (MEM_REF, + build_array_type (char_type_node, + build_range_type (sizetype, + size_one_node, len)), + exp, build_int_cst (ptr_type_node, 0)); + + /* If the MEM_REF has no acceptable address, try to get the base object + from the original address we got, and build an all-aliasing + unknown-sized access to that one. */ + if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0))) + set_mem_attributes (mem, exp, 0); + else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR + && (exp = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0), + 0)))) { + exp = build_fold_addr_expr (exp); + exp = fold_build2 (MEM_REF, + build_array_type (char_type_node, + build_range_type (sizetype, + size_zero_node, + NULL)), + exp, build_int_cst (ptr_type_node, 0)); set_mem_attributes (mem, exp, 0); - - if (off) - mem = adjust_automodify_address_nv (mem, BLKmode, NULL, off); - - /* Allow the string and memory builtins to overflow from one - field into another, see http://gcc.gnu.org/PR23561. - Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole - memory accessed by the string or memory builtin will fit - within the field. */ - if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF) - { - tree mem_expr = MEM_EXPR (mem); - HOST_WIDE_INT offset = -1, length = -1; - tree inner = exp; - - while (TREE_CODE (inner) == ARRAY_REF - || CONVERT_EXPR_P (inner) - || TREE_CODE (inner) == VIEW_CONVERT_EXPR - || TREE_CODE (inner) == SAVE_EXPR) - inner = TREE_OPERAND (inner, 0); - - gcc_assert (TREE_CODE (inner) == COMPONENT_REF); - - if (MEM_OFFSET_KNOWN_P (mem)) - offset = MEM_OFFSET (mem); - - if (offset >= 0 && len && host_integerp (len, 0)) - length = tree_low_cst (len, 0); - - while (TREE_CODE (inner) == COMPONENT_REF) - { - tree field = TREE_OPERAND (inner, 1); - gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF); - gcc_assert (field == TREE_OPERAND (mem_expr, 1)); - - /* Bitfields are generally not byte-addressable. */ - gcc_assert (!DECL_BIT_FIELD (field) - || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) - % BITS_PER_UNIT) == 0 - && host_integerp (DECL_SIZE (field), 0) - && (TREE_INT_CST_LOW (DECL_SIZE (field)) - % BITS_PER_UNIT) == 0)); - - /* If we can prove that the memory starting at XEXP (mem, 0) and - ending at XEXP (mem, 0) + LENGTH will fit into this field, we - can keep the COMPONENT_REF in MEM_EXPR. But be careful with - fields without DECL_SIZE_UNIT like flexible array members. */ - if (length >= 0 - && DECL_SIZE_UNIT (field) - && host_integerp (DECL_SIZE_UNIT (field), 0)) - { - HOST_WIDE_INT size - = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field)); - if (offset <= size - && length <= size - && offset + length <= size) - break; - } - - if (offset >= 0 - && host_integerp (DECL_FIELD_OFFSET (field), 0)) - offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field)) - + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) - / BITS_PER_UNIT; - else - { - offset = -1; - length = -1; - } - - mem_expr = TREE_OPERAND (mem_expr, 0); - inner = TREE_OPERAND (inner, 0); - } - - if (mem_expr == NULL) - offset = -1; - if (mem_expr != MEM_EXPR (mem)) - { - set_mem_expr (mem, mem_expr); - if (offset >= 0) - set_mem_offset (mem, offset); - else - clear_mem_offset (mem); - } - } - set_mem_alias_set (mem, 0); - clear_mem_size (mem); } - + set_mem_alias_set (mem, 0); return mem; } Index: testsuite/gcc.c-torture/execute/pr53688.c =================================================================== --- testsuite/gcc.c-torture/execute/pr53688.c (revision 0) +++ testsuite/gcc.c-torture/execute/pr53688.c (revision 0) @@ -0,0 +1,32 @@ +char headline[256]; +struct hdr { + char part1[9]; + char part2[8]; +} p; + +void __attribute__((noinline,noclone)) +init() +{ + __builtin_memcpy (p.part1, "FOOBARFOO", sizeof (p.part1)); + __builtin_memcpy (p.part2, "SPEC CPU", sizeof (p.part2)); +} + +int main() +{ + char *x; + int c; + init(); + __builtin_memcpy (&headline[0], p.part1, 9); + c = 9; + x = &headline[0]; + x = x + c; + __builtin_memset (x, ' ', 245); + __builtin_memcpy (&headline[10], p.part2, 8); + c = 18; + x = &headline[0]; + x = x + c; + __builtin_memset (x, ' ', 238); + if (headline[10] != 'S') + __builtin_abort (); + return 0; +}