From patchwork Fri Oct 1 11:43:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 66338 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 11691B7102 for ; Fri, 1 Oct 2010 21:43:09 +1000 (EST) Received: (qmail 32463 invoked by alias); 1 Oct 2010 11:43:03 -0000 Received: (qmail 32442 invoked by uid 22791); 1 Oct 2010 11:43:01 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 01 Oct 2010 11:42:54 +0000 Received: (qmail 1305 invoked from network); 1 Oct 2010 11:42:52 -0000 Received: from unknown (HELO ?84.152.240.2?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 1 Oct 2010 11:42:52 -0000 Message-ID: <4CA5C96D.7070407@codesourcery.com> Date: Fri, 01 Oct 2010 13:43:41 +0200 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.9) Gecko/20100911 Lightning/1.0b3pre Thunderbird/3.1.3 MIME-Version: 1.0 To: GCC Patches CC: "Vladimir N. Makarov" Subject: PR45445 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 We have an insn that has an earlyclobber output, and an input operand that is a SImode subreg of a DImode pseudo. The latter is live through the insn. In make_pseudo_conflict, we create artificial lifetimes, but we do it for entire pseudo registers. With the subword-tracking changes, this causes a problem, because it leaves all involved registers in a "dead" state, relying on other code to mark whatever is used in the insn as live. Thus, the entire reg gets marked as dead, but only the part actually used gets marked as live again, leaving us with incorrect life information. The patch below allows us to track exactly the pieces used in the insn in make_pseudo_conflict. Mikael Pettersson has verified that it fixes his bootstrap. Ok after I also test on i686-linux? Bernd * ira-lives.c (mark_pseudo_reg_live, mark_pseudo_reg_dead): New static functions. (mark_ref_live, mark_ref_dead): Use them. (make_pseudo_conflict): New arg ORIG_DREG. All callers changed. Save the original reg, and use the new functions. (check_and_make_def_use_conflict): New arg ORIG_DREG. All callers changed. (check_and_make_def_conflict): Save the original reg. Index: ira-lives.c =================================================================== --- ira-lives.c (revision 164551) +++ ira-lives.c (working copy) @@ -329,6 +329,21 @@ mark_hard_reg_live (rtx reg) } } +/* Mark a pseudo, or one of its subwords, as live. REGNO is the pseudo's + register number; ORIG_REG is the access in the insn, which may be a + subreg. */ +static void +mark_pseudo_reg_live (rtx orig_reg, unsigned regno) +{ + if (df_read_modify_subreg_p (orig_reg)) + { + mark_pseudo_regno_subword_live (regno, + subreg_lowpart_p (orig_reg) ? 0 : 1); + } + else + mark_pseudo_regno_live (regno); +} + /* Mark the register referenced by use or def REF as live. */ static void mark_ref_live (df_ref ref) @@ -340,15 +355,7 @@ mark_ref_live (df_ref ref) reg = SUBREG_REG (reg); if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) - { - if (df_read_modify_subreg_p (orig_reg)) - { - mark_pseudo_regno_subword_live (REGNO (reg), - subreg_lowpart_p (orig_reg) ? 0 : 1); - } - else - mark_pseudo_regno_live (REGNO (reg)); - } + mark_pseudo_reg_live (orig_reg, REGNO (reg)); else mark_hard_reg_live (reg); } @@ -445,6 +452,21 @@ mark_hard_reg_dead (rtx reg) } } +/* Mark a pseudo, or one of its subwords, as dead. REGNO is the pseudo's + register number; ORIG_REG is the access in the insn, which may be a + subreg. */ +static void +mark_pseudo_reg_dead (rtx orig_reg, unsigned regno) +{ + if (df_read_modify_subreg_p (orig_reg)) + { + mark_pseudo_regno_subword_dead (regno, + subreg_lowpart_p (orig_reg) ? 0 : 1); + } + else + mark_pseudo_regno_dead (regno); +} + /* Mark the register referenced by definition DEF as dead, if the definition is a total one. */ static void @@ -466,26 +488,22 @@ mark_ref_dead (df_ref def) return; if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) - { - if (df_read_modify_subreg_p (orig_reg)) - { - mark_pseudo_regno_subword_dead (REGNO (reg), - subreg_lowpart_p (orig_reg) ? 0 : 1); - } - else - mark_pseudo_regno_dead (REGNO (reg)); - } + mark_pseudo_reg_dead (orig_reg, REGNO (reg)); else mark_hard_reg_dead (reg); } -/* Make pseudo REG conflicting with pseudo DREG, if the 1st pseudo - class is intersected with class CL. Advance the current program - point before making the conflict if ADVANCE_P. Return TRUE if we - will need to advance the current program point. */ +/* If REG is a pseudo or a subreg of it, and the class of its allocno + intersects CL, make a conflict with pseudo DREG. ORIG_DREG is the + rtx actually accessed, it may be indentical to DREG or a subreg of it. + Advance the current program point before making the conflict if + ADVANCE_P. Return TRUE if we will need to advance the current + program point. */ static bool -make_pseudo_conflict (rtx reg, enum reg_class cl, rtx dreg, bool advance_p) +make_pseudo_conflict (rtx reg, enum reg_class cl, rtx dreg, rtx orig_dreg, + bool advance_p) { + rtx orig_reg = reg; ira_allocno_t a; if (GET_CODE (reg) == SUBREG) @@ -501,29 +519,31 @@ make_pseudo_conflict (rtx reg, enum reg_ if (advance_p) curr_point++; - mark_pseudo_regno_live (REGNO (reg)); - mark_pseudo_regno_live (REGNO (dreg)); - mark_pseudo_regno_dead (REGNO (reg)); - mark_pseudo_regno_dead (REGNO (dreg)); + mark_pseudo_reg_live (orig_reg, REGNO (reg)); + mark_pseudo_reg_live (orig_dreg, REGNO (dreg)); + mark_pseudo_reg_dead (orig_reg, REGNO (reg)); + mark_pseudo_reg_dead (orig_dreg, REGNO (dreg)); return false; } /* Check and make if necessary conflicts for pseudo DREG of class DEF_CL of the current insn with input operand USE of class USE_CL. - Advance the current program point before making the conflict if - ADVANCE_P. Return TRUE if we will need to advance the current - program point. */ + ORIG_DREG is the rtx actually accessed, it may be indentical to + DREG or a subreg of it. Advance the current program point before + making the conflict if ADVANCE_P. Return TRUE if we will need to + advance the current program point. */ static bool -check_and_make_def_use_conflict (rtx dreg, enum reg_class def_cl, - int use, enum reg_class use_cl, - bool advance_p) +check_and_make_def_use_conflict (rtx dreg, rtx orig_dreg, + enum reg_class def_cl, int use, + enum reg_class use_cl, bool advance_p) { if (! reg_classes_intersect_p (def_cl, use_cl)) return advance_p; advance_p = make_pseudo_conflict (recog_data.operand[use], - use_cl, dreg, advance_p); + use_cl, dreg, orig_dreg, advance_p); + /* Reload may end up swapping commutative operands, so you have to take both orderings into account. The constraints for the two operands can be completely @@ -534,12 +554,12 @@ check_and_make_def_use_conflict (rtx dre && recog_data.constraints[use][0] == '%') advance_p = make_pseudo_conflict (recog_data.operand[use + 1], - use_cl, dreg, advance_p); + use_cl, dreg, orig_dreg, advance_p); if (use >= 1 && recog_data.constraints[use - 1][0] == '%') advance_p = make_pseudo_conflict (recog_data.operand[use - 1], - use_cl, dreg, advance_p); + use_cl, dreg, orig_dreg, advance_p); return advance_p; } @@ -554,6 +574,7 @@ check_and_make_def_conflict (int alt, in enum reg_class use_cl, acl; bool advance_p; rtx dreg = recog_data.operand[def]; + rtx orig_dreg = dreg; if (def_cl == NO_REGS) return; @@ -599,8 +620,8 @@ check_and_make_def_conflict (int alt, in if (alt1 < recog_data.n_alternatives) continue; - advance_p = check_and_make_def_use_conflict (dreg, def_cl, use, - use_cl, advance_p); + advance_p = check_and_make_def_use_conflict (dreg, orig_dreg, def_cl, + use, use_cl, advance_p); if ((use_match = recog_op_alt[use][alt].matches) >= 0) { @@ -611,8 +632,8 @@ check_and_make_def_conflict (int alt, in use_cl = ALL_REGS; else use_cl = recog_op_alt[use_match][alt].cl; - advance_p = check_and_make_def_use_conflict (dreg, def_cl, use, - use_cl, advance_p); + advance_p = check_and_make_def_use_conflict (dreg, orig_dreg, def_cl, + use, use_cl, advance_p); } } }