From patchwork Mon Mar 12 14:09:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 146111 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 CB1D6B6FA3 for ; Tue, 13 Mar 2012 01:14:25 +1100 (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=1332166466; h=Comment: DomainKey-Signature:Received:Received:Received:Received: Resent-From:Resent-Date:Resent-Message-ID:Resent-To:Message-Id: User-Agent:Date:From:To:Cc:Subject:References: Content-Disposition:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=D0ZmltpT5RkzDpMY1CqliZCp/fM=; b=GYRJFO6GH31d4oI LEQceZH44ixd1wrqQT2jZna0Q2plen0dxD7E6LcQ8NvUXuuSEbHDvdXzPRuDp0R8 xccVrDx8tkVzCY2kziKkVatW1mqAsYdirQIdDvtpyQ5ACTO1mxl/jguOKseCvNX2 vWjYPR1FXNyFV6e4sngLc+RZPCUU= 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:Resent-From:Resent-Date:Resent-Message-ID:Resent-To:Message-Id:User-Agent:Date:From:To:Cc:Subject:References:Content-Disposition:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=Ey2Y0p+/1j68yTvW+kBxVGzl3hXQth45FzyDNj2mVXUE98YlmF++ECUH3kLDBL muntPUERFnh5/gpFESjJu7UK7mwRPn0NzQAAmtDgvelvyKh2KaevLtmcKCpx95mS 3q8k7RAiYOEWxfPUVCQbw0oL9Gfl5Kgie0mHjQC741ZNE=; Received: (qmail 13457 invoked by alias); 12 Mar 2012 14:13:44 -0000 Received: (qmail 13276 invoked by uid 22791); 12 Mar 2012 14:13:40 -0000 X-SWARE-Spam-Status: No, hits=-5.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI 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; Mon, 12 Mar 2012 14:13:21 +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 AA8F49393C for ; Mon, 12 Mar 2012 15:13:19 +0100 (CET) Resent-From: Martin Jambor Resent-Date: Mon, 12 Mar 2012 15:13:19 +0100 Resent-Message-ID: <20120312141319.GC2177@virgil.arch.suse.de> Resent-To: GCC Patches Message-Id: <20120312140918.117967027@virgil.suse.cz> User-Agent: quilt/0.48-20.3.1 Date: Mon, 12 Mar 2012 15:09:03 +0100 From: Martin Jambor To: GCC Patches Cc: Richard Guenther Subject: [PATCH 2/3] Move MEM_REF expansion to a new function References: <20120312140901.004541946@virgil.suse.cz> Content-Disposition: inline; filename=unify_mem_ref_base_expansion.diff 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, when we expand a misaligned MEM_REF on the LHS, we must not call the code in expand_expr_real_1 if the subsequent patch is applied, because the code generates code extracting the contents of the memory to a register, which is of course bad if the intent is to write into that memory. Therefore expand_assignment should expand MEM_REFs itself, just as it do when it encounters naked misaligned ones. In order not to have nearly identical code twice in expand_assignment and once more in expand_expr_real_1, I put it into a separate function expand_mem_ref_to_mem_rtx (I'll be happy to change the name to anything more correct or fitting). Nevertheless, the existing code pieces in expand_assignment and expand_expr_real_1 sre not exactly identical, the differences are: - expand_expr_real_1 handles a special case when the defining statement of the MEM_REF base is a BIT_AND_EXPR, expand_assignment does not. The changelog introducing the change says "TER BIT_AND_EXPRs into MEM_REFs" which I suspect is a good thing for LHSs as well, so I kept the code. - When expanding the base, the two functions differ in the expand_modifier they pass down to expand_expr. expand_assignment uses EXPAND_NORMAL while expand_expr_real_1 passes EXPAND_SUM. According to the comment in expr.h the latter seemed more permissive and so I used that, even though I admit I do not really know what the implications of this modifier are. Is it OK to use EXPAND_SUM also on a LHS? - expand_expr_real_1 calls memory_address_addr_space twice, whereas expand_assignment replaces the first call with convert_memory_address_addr_space. Looking at the two functions I thought it might be OK to call memory_address_addr_space (which itself calls convert_memory_address_addr_space) only once. But again, my expertise in this area is limited, I'll be happy to be shown I'm wrong here. So far I have bootstrapped and tested this patch separately on x86_64-linx and i686-linux. Additionally, it has also passed bootstrap and testing on usparc64-linux and ia64-linux. Thanks in advance for any comments, Martin 2012-03-09 Martin Jambor * expr.c (expand_mem_ref_to_mem_rtx): New function. (expand_assignment): Call it when expanding a MEM_REF on the LHS. (expand_expr_real_1): Likewise. Index: src/gcc/expr.c =================================================================== --- src.orig/gcc/expr.c +++ src/gcc/expr.c @@ -4565,6 +4565,47 @@ mem_ref_refers_to_non_mem_p (tree ref) && !MEM_P (DECL_RTL (base))); } +/* Expand a MEM_REF referring an object in memory to a MEM RTX. Any spacial + treatment of misalignment must be handled on top of the returned result. */ + +static rtx +expand_mem_ref_to_mem_rtx (tree ref) +{ + enum machine_mode address_mode, mode = TYPE_MODE (TREE_TYPE (ref)); + tree base = TREE_OPERAND (ref, 0); + addr_space_t as + = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref, 0)))); + gimple def_stmt; + rtx mem, op0; + + gcc_checking_assert (!mem_ref_refers_to_non_mem_p (ref)); + + address_mode = targetm.addr_space.address_mode (as); + + if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR))) + { + tree mask = gimple_assign_rhs2 (def_stmt); + base = build2 (BIT_AND_EXPR, TREE_TYPE (base), + gimple_assign_rhs1 (def_stmt), mask); + TREE_OPERAND (ref, 0) = base; + } + op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM); + op0 = convert_memory_address_addr_space (address_mode, op0, as); + if (!integer_zerop (TREE_OPERAND (ref, 1))) + { + rtx off + = immed_double_int_const (mem_ref_offset (ref), address_mode); + op0 = simplify_gen_binary (PLUS, address_mode, op0, off); + } + op0 = memory_address_addr_space (mode, op0, as); + mem = gen_rtx_MEM (mode, op0); + set_mem_attributes (mem, ref, 0); + set_mem_addr_space (mem, as); + if (TREE_THIS_VOLATILE (ref)) + MEM_VOLATILE_P (mem) = 1; + return mem; +} + /* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL is true, try generating a nontemporal store. */ @@ -4600,46 +4641,31 @@ expand_assignment (tree to, tree from, b != CODE_FOR_nothing) || SLOW_UNALIGNED_ACCESS (mode, align))) { - addr_space_t as - = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (to, 0)))); struct expand_operand ops[2]; - enum machine_mode address_mode; - rtx reg, op0, mem; + rtx reg, mem; reg = expand_expr (from, NULL_RTX, VOIDmode, EXPAND_NORMAL); reg = force_not_mem (reg); if (TREE_CODE (to) == MEM_REF) - { - tree base = TREE_OPERAND (to, 0); - address_mode = targetm.addr_space.address_mode (as); - op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL); - op0 = convert_memory_address_addr_space (address_mode, op0, as); - if (!integer_zerop (TREE_OPERAND (to, 1))) - { - rtx off - = immed_double_int_const (mem_ref_offset (to), address_mode); - op0 = simplify_gen_binary (PLUS, address_mode, op0, off); - } - op0 = memory_address_addr_space (mode, op0, as); - mem = gen_rtx_MEM (mode, op0); - set_mem_attributes (mem, to, 0); - set_mem_addr_space (mem, as); - } + mem = expand_mem_ref_to_mem_rtx (to); else if (TREE_CODE (to) == TARGET_MEM_REF) { + addr_space_t as + = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (to, 0)))); struct mem_address addr; + rtx op0; get_address_description (to, &addr); op0 = addr_for_mem_ref (&addr, as, true); op0 = memory_address_addr_space (mode, op0, as); mem = gen_rtx_MEM (mode, op0); set_mem_attributes (mem, to, 0); set_mem_addr_space (mem, as); + if (TREE_THIS_VOLATILE (to)) + MEM_VOLATILE_P (mem) = 1; } else gcc_unreachable (); - if (TREE_THIS_VOLATILE (to)) - MEM_VOLATILE_P (mem) = 1; if (icode != CODE_FOR_nothing) { @@ -4737,7 +4763,11 @@ expand_assignment (tree to, tree from, b else { misalignp = false; - to_rtx = expand_normal (tem); + if (TREE_CODE (tem) == MEM_REF + && !mem_ref_refers_to_non_mem_p (tem)) + to_rtx = expand_mem_ref_to_mem_rtx (tem); + else + to_rtx = expand_normal (tem); } /* If the bitfield is volatile, we want to access it in the @@ -9395,17 +9425,12 @@ expand_expr_real_1 (tree exp, rtx target case MEM_REF: { - addr_space_t as - = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); - enum machine_mode address_mode; - tree base = TREE_OPERAND (exp, 0); - gimple def_stmt; enum insn_code icode; - unsigned align; /* Handle expansion of non-aliased memory with non-BLKmode. That might end up in a register. */ if (mem_ref_refers_to_non_mem_p (exp)) { + tree base = TREE_OPERAND (exp, 0); HOST_WIDE_INT offset = mem_ref_offset (exp).low; tree bit_offset; tree bftype; @@ -9437,32 +9462,9 @@ expand_expr_real_1 (tree exp, rtx target bit_offset), target, tmode, modifier); } - address_mode = targetm.addr_space.address_mode (as); - base = TREE_OPERAND (exp, 0); - if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR))) - { - tree mask = gimple_assign_rhs2 (def_stmt); - base = build2 (BIT_AND_EXPR, TREE_TYPE (base), - gimple_assign_rhs1 (def_stmt), mask); - TREE_OPERAND (exp, 0) = base; - } - align = get_object_or_type_alignment (exp); - op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM); - op0 = memory_address_addr_space (address_mode, op0, as); - if (!integer_zerop (TREE_OPERAND (exp, 1))) - { - rtx off - = immed_double_int_const (mem_ref_offset (exp), address_mode); - op0 = simplify_gen_binary (PLUS, address_mode, op0, off); - } - op0 = memory_address_addr_space (mode, op0, as); - temp = gen_rtx_MEM (mode, op0); - set_mem_attributes (temp, exp, 0); - set_mem_addr_space (temp, as); - if (TREE_THIS_VOLATILE (exp)) - MEM_VOLATILE_P (temp) = 1; + temp = expand_mem_ref_to_mem_rtx (exp); if (mode != BLKmode - && align < GET_MODE_ALIGNMENT (mode) + && get_object_or_type_alignment (exp) < GET_MODE_ALIGNMENT (mode) /* If the target does not have special handling for unaligned loads of mode then it can use regular moves for them. */ && ((icode = optab_handler (movmisalign_optab, mode))