From patchwork Mon Mar 21 01:43:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 599941 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qSzBH0X7zz9s5M for ; Mon, 21 Mar 2016 12:43:34 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=e9l5tK+v; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:references:mime-version:content-type :in-reply-to; q=dns; s=default; b=JviRDAJ3biiRRgTh4cbXDTcMSlEomv 2dF8Bv6Pm9HbZonTTIrLeW26E9Idc0/BhxpzAycrtWaWve9kGGuVwFC+k6g1+yWz UCUxmHNYhIdqXvEout/fkHeyP32itobS1nF1XfQ+PEPselO1U3eIFg/LD8/I+Rxl 79PzdxiPIV/kY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:references:mime-version:content-type :in-reply-to; s=default; bh=qM90+sNptJYs9RQnRBB+JbIEhKU=; b=e9l5 tK+v6+tudY1LM/331fLFYl83XDJpSm5DwZUASeo+lpwS9CqF1pAAXJ1JYkWxfy0n KZX4qQPBds1Ug61xxV41SdiW5QRt1udZmV5Q7N9tudLt70VztvlnXc+wmFN/E+CZ /djRuwsE0bT/pzDETJzlNtbdhTeo4132kCVG0rk= Received: (qmail 80373 invoked by alias); 21 Mar 2016 01:43:27 -0000 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 Received: (qmail 80310 invoked by uid 89); 21 Mar 2016 01:43:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=validate, rbx, death X-HELO: mail-pf0-f194.google.com Received: from mail-pf0-f194.google.com (HELO mail-pf0-f194.google.com) (209.85.192.194) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Mon, 21 Mar 2016 01:43:17 +0000 Received: by mail-pf0-f194.google.com with SMTP id n5so27460551pfn.1 for ; Sun, 20 Mar 2016 18:43:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=rAzuNZu7Ovm91mZ5OD6yMWOvyQV0SNZrJcGFXbzobps=; b=HnZzp5VxLF5ulkU0dkpdhFAuXDJ1Jd8I4A+EO53AKjz18vksb8X1o+2vS4tccttjAC 28MxrXH5JCIRuYuxfzOXSUvZjNN7UIgnhXYDDlgB6246eKO2iHWKxCZ5/MKTSfjse54B Yz1xqPCci4xWqykj5Et6wgqNU2cR6vtUaugHZAvZ6YE/stYu5pAW80y8boQD5oyx6Bfq QiMkL5rRI/8ZBiz/0qS+aVxnr/IOOnrjW4YjD7e/ebKLFNa5ZgmQtXI53sRyzVXu2MQj o9ew+7h+4SJHbwOyX41254MgT86qZKDt4GzT/eeAaGNF58iXEebzcUigLNyFJJ+aOgJh 0dkw== X-Gm-Message-State: AD7BkJJn7nQNAb1M2MpHyYs5gJJ0kqlkfH7YfBtbZLDKHuGhf+EfRBZkE3Vxrqn6iUqf7w== X-Received: by 10.98.12.153 with SMTP id 25mr41235053pfm.27.1458524595848; Sun, 20 Mar 2016 18:43:15 -0700 (PDT) Received: from bubble.grove.modra.org (CPE-58-160-146-233.sa.bigpond.net.au. [58.160.146.233]) by smtp.gmail.com with ESMTPSA id ey7sm35948263pab.47.2016.03.20.18.43.14 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 20 Mar 2016 18:43:15 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id BD4DEEA0153; Mon, 21 Mar 2016 12:13:11 +1030 (ACDT) Date: Mon, 21 Mar 2016 12:13:11 +1030 From: Alan Modra To: gcc-patches@gcc.gnu.org Subject: [PATCH 7/7] ira.c validate_equiv_mem Message-ID: <20160321014311.GJ22605@bubble.grove.modra.org> References: <20160321013723.GC22605@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20160321013723.GC22605@bubble.grove.modra.org> User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes This function is used to validate REG_EQUIV notes generated by ira, and to validate potential insn combines performed by ira. The two conditions are not exactly the same, with reload being more restrictive. Separate them so more combines/moves can occur. For example, this sequence from cfgexpand.c:expand_gimple_cond callq _Z18update_bb_for_insnP15basic_block_def mov 0x10(%rbx),%rdi mov 0x0(%rip),%rbp # x_rtl+0x34 callq _Z9safe_as_aIP8rtx_insn7rtx_defET_PT0_ mov %r13,%rdx mov %rbp,%rsi mov %rax,%rdi callq _Z18create_basic_blockP7rtx_defS0_P15basic_block_def becomes callq _Z18update_bb_for_insnP15basic_block_def mov 0x10(%rbx),%rdi callq _Z9safe_as_aIP8rtx_insn7rtx_defET_PT0_ mov 0x0(%rip),%rsi # x_rtl+0x34 mov %r13,%rdx mov %rax,%rdi callq _Z18create_basic_blockP7rtx_defS0_P15basic_block_def * ira.c (enum valid_equiv): New. (validate_equiv_mem): Return enum. (update_equiv_mem): Create replacement in more cases. (add_store_equivs): Update validate_equiv_mem call. diff --git a/gcc/ira.c b/gcc/ira.c index aa721fa..ff0b941 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -2951,23 +2951,28 @@ validate_equiv_mem_from_store (rtx dest, const_rtx set ATTRIBUTE_UNUSED, info->equiv_mem_modified = true; } +enum valid_equiv { valid_none, valid_combine, valid_reload }; + /* Verify that no store between START and the death of REG invalidates MEMREF. MEMREF is invalidated by modifying a register used in MEMREF, by storing into an overlapping memory location, or with a non-const CALL_INSN. - Return 1 if MEMREF remains valid. */ -static int + Return VALID_RELOAD if MEMREF remains valid for reload, + VALID_COMBINE if valid for combine_and_move_insns, and + VALID_NONE otherwise. */ +static enum valid_equiv validate_equiv_mem (rtx_insn *start, rtx reg, rtx memref) { rtx_insn *insn; rtx note; struct equiv_mem_data info = { memref, false }; + enum valid_equiv ret = valid_reload; /* If the memory reference has side effects or is volatile, it isn't a valid equivalence. */ if (side_effects_p (memref)) - return 0; + return valid_none; for (insn = start; insn; insn = NEXT_INSN (insn)) { @@ -2975,19 +2980,27 @@ validate_equiv_mem (rtx_insn *start, rtx reg, rtx memref) continue; if (find_reg_note (insn, REG_DEAD, reg)) - return 1; + return ret; - /* This used to ignore readonly memory and const/pure calls. The problem - is the equivalent form may reference a pseudo which gets assigned a - call clobbered hard reg. When we later replace REG with its - equivalent form, the value in the call-clobbered reg has been - changed and all hell breaks loose. */ if (CALL_P (insn)) - return 0; + { + /* We can combine a reg def from one insn into a reg use in + another over a call if the memory is readonly or the call + const/pure. However, we can't set reg_equiv notes up for + reload over any call. The problem is the equivalent form + may reference a pseudo which gets assigned a call + clobbered hard reg. When we later replace REG with its + equivalent form, the value in the call-clobbered reg has + been changed and all hell breaks loose. */ + ret = valid_combine; + if (! MEM_READONLY_P (memref) + && ! RTL_CONST_OR_PURE_CALL_P (insn)) + return valid_none; + } note_stores (PATTERN (insn), validate_equiv_mem_from_store, &info); if (info.equiv_mem_modified) - return 0; + return valid_none; /* If a register mentioned in MEMREF is modified via an auto-increment, we lose the equivalence. Do the same if one @@ -2999,10 +3012,10 @@ validate_equiv_mem (rtx_insn *start, rtx reg, rtx memref) || REG_NOTE_KIND (note) == REG_DEAD) && REG_P (XEXP (note, 0)) && reg_overlap_mentioned_p (XEXP (note, 0), memref)) - return 0; + return valid_none; } - return 0; + return valid_none; } /* Returns zero if X is known to be invariant. */ @@ -3510,24 +3523,32 @@ update_equiv_regs (void) note. */ note = find_reg_note (insn, REG_EQUIV, NULL_RTX); - if (note == NULL_RTX && REG_BASIC_BLOCK (regno) >= NUM_FIXED_BLOCKS - && MEM_P (SET_SRC (set)) - && validate_equiv_mem (insn, dest, SET_SRC (set))) - note = set_unique_reg_note (insn, REG_EQUIV, copy_rtx (SET_SRC (set))); - + rtx replacement = NULL_RTX; if (note) + replacement = XEXP (note, 0); + else if (REG_BASIC_BLOCK (regno) >= NUM_FIXED_BLOCKS + && MEM_P (SET_SRC (set))) { - int regno = REGNO (dest); - rtx x = XEXP (note, 0); + enum valid_equiv validity; + validity = validate_equiv_mem (insn, dest, SET_SRC (set)); + if (validity != valid_none) + { + replacement = copy_rtx (SET_SRC (set)); + if (validity == valid_reload) + note = set_unique_reg_note (insn, REG_EQUIV, replacement); + } + } - /* If we haven't done so, record for reload that this is an - equivalencing insn. */ - if (!reg_equiv[regno].is_arg_equivalence) - ira_reg_equiv[regno].init_insns - = gen_rtx_INSN_LIST (VOIDmode, insn, - ira_reg_equiv[regno].init_insns); + /* If we haven't done so, record for reload that this is an + equivalencing insn. */ + if (note && !reg_equiv[regno].is_arg_equivalence) + ira_reg_equiv[regno].init_insns + = gen_rtx_INSN_LIST (VOIDmode, insn, + ira_reg_equiv[regno].init_insns); - reg_equiv[regno].replacement = x; + if (replacement) + { + reg_equiv[regno].replacement = replacement; reg_equiv[regno].src_p = &SET_SRC (set); reg_equiv[regno].loop_depth = (short) loop_depth; @@ -3536,7 +3557,8 @@ update_equiv_regs (void) { /* Note that the statement below does not affect the priority in local-alloc! */ - REG_LIVE_LENGTH (regno) *= 2; + if (note) + REG_LIVE_LENGTH (regno) *= 2; /* If the register is referenced exactly twice, meaning it is set once and used once, indicate that the reference may be @@ -3548,7 +3570,7 @@ update_equiv_regs (void) calls. */ if (REG_N_REFS (regno) == 2 - && (rtx_equal_p (x, src) + && (rtx_equal_p (replacement, src) || ! equiv_init_varies_p (src)) && NONJUMP_INSN_P (insn) && equiv_init_movable_p (PATTERN (insn), regno)) @@ -3598,7 +3620,7 @@ add_store_equivs (void) For all other cases the luids should be valid. */ && DF_INSN_LUID (init_insn) < DF_INSN_LUID (insn) && ! find_reg_note (init_insn, REG_EQUIV, NULL_RTX) - && validate_equiv_mem (init_insn, src, dest) + && validate_equiv_mem (init_insn, src, dest) == valid_reload && ! memref_used_between_p (dest, init_insn, insn) /* Attaching a REG_EQUIV note will fail if INIT_INSN has multiple sets. */