From patchwork Mon Mar 21 01:42:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 599940 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 3qSz9Q3qwpz9s5M for ; Mon, 21 Mar 2016 12:42:49 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=nAB/wZAC; 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=cONTeir5SX510gHKuMO49zMRmwjqfO /DXO7sqMxf0XHNEYKmVHBYeRIUPmuRwlquUlDtLV1TNTqxTmZfM1kLUtwc9vVYVY GC6qtebyzY1r8FHVWFLkycUU2ELgHC9Z5fK00LmGywaB5lQaXNEc46knAdFnr2bV eN09g3TvAbAz0= 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=MlYe0VXghyGySPXcgFY9delm7YY=; b=nAB/ wZACf2vzY3dOLK8sEkui83IRRsYqoVT0vr8gkip5gOtnN8tnr9LFIFVEuR65h2Kq La/XWGCIA+ItwXKTacP1FkI1/rVHDjj1nHdpqSnECSIe3mjcRVG+5fwO/byqU8Pa WSIIO3O4QjUmty+vAs/CEMJ/VzQDXVfCyfawtJU= Received: (qmail 78668 invoked by alias); 21 Mar 2016 01:42:40 -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 78652 invoked by uid 89); 21 Mar 2016 01:42:39 -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=Rather, Hence, boundaries X-HELO: mail-pf0-f195.google.com Received: from mail-pf0-f195.google.com (HELO mail-pf0-f195.google.com) (209.85.192.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Mon, 21 Mar 2016 01:42:38 +0000 Received: by mail-pf0-f195.google.com with SMTP id u190so27560023pfb.2 for ; Sun, 20 Mar 2016 18:42:37 -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=dN7f+l/7yZQkSaS7hgUPiaOExoTWbEIfAOLtVghBpDk=; b=em/geLNoA13oQqadV8rGbig/RAWzERvotG98ekrukoQk/3T7rAbbHxSORl0KazqEYw 6ijck2ktpxa0jQCBKdDYM3sRuibMprnGPGkPmdCOuKp0kPl0w40IPy/eqAt2MKcUbZag YAyPzzRkpa7yobB8pPk081QjlxsAysKliQxDDvqeNF5J8EjCjL177/NzdrwiVqM6+xh1 vfZvI/JbVaX7WlxOVW3sfFt8cJatGF7eQquEhxERxA3P3IoGdwmQ+yPp0p7kvLb9uw0D 87uNBpL/XgaiIKXRgBTvKlmbZ6g+jmKVq6l2a9mDCRAI0OCb0P4Pry/yJO9FREch9jEM hNug== X-Gm-Message-State: AD7BkJK7LxSwRl3KAfRWYQsD+ynMEAH8rIgDlrLdQVPIg9R7SOU7aFp2iqj5QQvD80vl4Q== X-Received: by 10.98.76.216 with SMTP id e85mr41537753pfj.121.1458524556373; Sun, 20 Mar 2016 18:42:36 -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 f8sm35937206pfj.49.2016.03.20.18.42.35 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 20 Mar 2016 18:42:35 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 63CBEEA0153; Mon, 21 Mar 2016 12:12:32 +1030 (ACDT) Date: Mon, 21 Mar 2016 12:12:32 +1030 From: Alan Modra To: gcc-patches@gcc.gnu.org Subject: [PATCH 6/7] ira.c use DF infrastructure for combine_and_move_insns Message-ID: <20160321014232.GI22605@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 patch actually improves generated code, because REG_DEAD notes used by the old insn scan are not always present. On x86_64, see gcc/wide-int-print.o:print_hex for an example of a function that is smaller and uses one less callee saved reg. * ira.c (combine_and_move_insns): Rather than scanning insns, use DF infrastucture to find use and def insns. diff --git a/gcc/ira.c b/gcc/ira.c index 1cace25..aa721fa 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -3628,137 +3628,113 @@ add_store_equivs (void) static void combine_and_move_insns (void) { - rtx_insn *insn; - basic_block bb; - int loop_depth; bitmap cleared_regs = BITMAP_ALLOC (NULL); + int max = max_reg_num (); - FOR_EACH_BB_REVERSE_FN (bb, cfun) + for (int regno = FIRST_PSEUDO_REGISTER; regno < max; regno++) { - loop_depth = bb_loop_depth (bb); - for (insn = BB_END (bb); - insn != PREV_INSN (BB_HEAD (bb)); - insn = PREV_INSN (insn)) - { - rtx link; + if (!reg_equiv[regno].replace) + continue; - if (! INSN_P (insn)) - continue; + rtx_insn *use_insn = 0; + for (df_ref use = DF_REG_USE_CHAIN (regno); + use; + use = DF_REF_NEXT_REG (use)) + if (DF_REF_INSN_INFO (use)) + { + if (DEBUG_INSN_P (DF_REF_INSN (use))) + continue; + gcc_assert (!use_insn); + use_insn = DF_REF_INSN (use); + } + gcc_assert (use_insn); - /* Don't substitute into jumps. indirect_jump_optimize does - this for anything we are prepared to handle. */ - if (JUMP_P (insn)) - continue; + /* Don't substitute into jumps. indirect_jump_optimize does + this for anything we are prepared to handle. */ + if (JUMP_P (use_insn)) + continue; - for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) - { - if (REG_NOTE_KIND (link) == REG_DEAD - /* Make sure this insn still refers to the register. */ - && reg_mentioned_p (XEXP (link, 0), PATTERN (insn))) - { - int regno = REGNO (XEXP (link, 0)); - rtx equiv_insn; + df_ref def = DF_REG_DEF_CHAIN (regno); + gcc_assert (DF_REG_DEF_COUNT (regno) == 1 && DF_REF_INSN_INFO (def)); + rtx_insn *def_insn = DF_REF_INSN (def); - if (! reg_equiv[regno].replace - || reg_equiv[regno].loop_depth < (short) loop_depth) - continue; + /* We may not move instructions that can throw, since that + changes basic block boundaries and we are not prepared to + adjust the CFG to match. */ + if (can_throw_internal (def_insn)) + continue; - /* reg_equiv[REGNO].replace gets set only when - REG_N_REFS[REGNO] is 2, i.e. the register is set - once and used once. (If it were only set, but - not used, flow would have deleted the setting - insns.) Hence there can only be one insn in - reg_equiv[REGNO].init_insns. */ - gcc_assert (reg_equiv[regno].init_insns - && !XEXP (reg_equiv[regno].init_insns, 1)); - equiv_insn = XEXP (reg_equiv[regno].init_insns, 0); - - /* We may not move instructions that can throw, since - that changes basic block boundaries and we are not - prepared to adjust the CFG to match. */ - if (can_throw_internal (equiv_insn)) - continue; + basic_block use_bb = BLOCK_FOR_INSN (use_insn); + basic_block def_bb = BLOCK_FOR_INSN (def_insn); + if (bb_loop_depth (use_bb) > bb_loop_depth (def_bb)) + continue; - if (asm_noperands (PATTERN (equiv_insn)) < 0 - && validate_replace_rtx (regno_reg_rtx[regno], - *(reg_equiv[regno].src_p), insn)) - { - rtx equiv_link; - rtx last_link; - rtx note; - - /* Find the last note. */ - for (last_link = link; XEXP (last_link, 1); - last_link = XEXP (last_link, 1)) - ; - - /* Append the REG_DEAD notes from equiv_insn. */ - equiv_link = REG_NOTES (equiv_insn); - while (equiv_link) - { - note = equiv_link; - equiv_link = XEXP (equiv_link, 1); - if (REG_NOTE_KIND (note) == REG_DEAD) - { - remove_note (equiv_insn, note); - XEXP (last_link, 1) = note; - XEXP (note, 1) = NULL_RTX; - last_link = note; - } - } + if (asm_noperands (PATTERN (def_insn)) < 0 + && validate_replace_rtx (regno_reg_rtx[regno], + *reg_equiv[regno].src_p, use_insn)) + { + rtx link; + /* Append the REG_DEAD notes from def_insn. */ + for (rtx *p = ®_NOTES (def_insn); (link = *p) != 0; ) + { + if (REG_NOTE_KIND (XEXP (link, 0)) == REG_DEAD) + { + *p = XEXP (link, 1); + XEXP (link, 1) = REG_NOTES (use_insn); + REG_NOTES (use_insn) = link; + } + else + p = &XEXP (link, 1); + } - remove_death (regno, insn); - SET_REG_N_REFS (regno, 0); - REG_FREQ (regno) = 0; - delete_insn (equiv_insn); + SET_REG_N_REFS (regno, 0); + REG_FREQ (regno) = 0; + delete_insn (def_insn); - reg_equiv[regno].init_insns - = reg_equiv[regno].init_insns->next (); + reg_equiv[regno].init_insns = NULL; + ira_reg_equiv[regno].init_insns = NULL; + bitmap_set_bit (cleared_regs, regno); + } - ira_reg_equiv[regno].init_insns = NULL; - bitmap_set_bit (cleared_regs, regno); - } - /* Move the initialization of the register to just before - INSN. Update the flow information. */ - else if (prev_nondebug_insn (insn) != equiv_insn) - { - rtx_insn *new_insn; + /* Move the initialization of the register to just before + USE_INSN. Update the flow information. */ + else if (prev_nondebug_insn (use_insn) != def_insn) + { + rtx_insn *new_insn; - new_insn = emit_insn_before (PATTERN (equiv_insn), insn); - REG_NOTES (new_insn) = REG_NOTES (equiv_insn); - REG_NOTES (equiv_insn) = 0; - /* Rescan it to process the notes. */ - df_insn_rescan (new_insn); + new_insn = emit_insn_before (PATTERN (def_insn), use_insn); + REG_NOTES (new_insn) = REG_NOTES (def_insn); + REG_NOTES (def_insn) = 0; + /* Rescan it to process the notes. */ + df_insn_rescan (new_insn); - /* Make sure this insn is recognized before - reload begins, otherwise - eliminate_regs_in_insn will die. */ - INSN_CODE (new_insn) = INSN_CODE (equiv_insn); + /* Make sure this insn is recognized before reload begins, + otherwise eliminate_regs_in_insn will die. */ + INSN_CODE (new_insn) = INSN_CODE (def_insn); - delete_insn (equiv_insn); + delete_insn (def_insn); - XEXP (reg_equiv[regno].init_insns, 0) = new_insn; + XEXP (reg_equiv[regno].init_insns, 0) = new_insn; - REG_BASIC_BLOCK (regno) = bb->index; - REG_N_CALLS_CROSSED (regno) = 0; - REG_FREQ_CALLS_CROSSED (regno) = 0; - REG_N_THROWING_CALLS_CROSSED (regno) = 0; - REG_LIVE_LENGTH (regno) = 2; + REG_BASIC_BLOCK (regno) = use_bb->index; + REG_N_CALLS_CROSSED (regno) = 0; + REG_FREQ_CALLS_CROSSED (regno) = 0; + REG_N_THROWING_CALLS_CROSSED (regno) = 0; + REG_LIVE_LENGTH (regno) = 2; - if (insn == BB_HEAD (bb)) - BB_HEAD (bb) = PREV_INSN (insn); + if (use_insn == BB_HEAD (use_bb)) + BB_HEAD (use_bb) = new_insn; - ira_reg_equiv[regno].init_insns - = gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX); - bitmap_set_bit (cleared_regs, regno); - } - } - } + ira_reg_equiv[regno].init_insns + = gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX); + bitmap_set_bit (cleared_regs, regno); } } if (!bitmap_empty_p (cleared_regs)) { + basic_block bb; + FOR_EACH_BB_FN (bb, cfun) { bitmap_and_compl_into (DF_LR_IN (bb), cleared_regs); @@ -3771,7 +3747,7 @@ combine_and_move_insns (void) /* Last pass - adjust debug insns referencing cleared regs. */ if (MAY_HAVE_DEBUG_INSNS) - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn)) if (DEBUG_INSN_P (insn)) { rtx old_loc = INSN_VAR_LOCATION_LOC (insn);