From patchwork Sun Sep 25 17:00:03 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 116306 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 DC814B6F68 for ; Mon, 26 Sep 2011 03:00:36 +1000 (EST) Received: (qmail 29607 invoked by alias); 25 Sep 2011 17:00:33 -0000 Received: (qmail 29595 invoked by uid 22791); 25 Sep 2011 17:00:31 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-wy0-f175.google.com (HELO mail-wy0-f175.google.com) (74.125.82.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 25 Sep 2011 17:00:10 +0000 Received: by wyh5 with SMTP id 5so5632562wyh.20 for ; Sun, 25 Sep 2011 10:00:09 -0700 (PDT) Received: by 10.216.185.207 with SMTP id u57mr7569540wem.109.1316970009250; Sun, 25 Sep 2011 10:00:09 -0700 (PDT) Received: from localhost (rsandifo.gotadsl.co.uk. [82.133.89.107]) by mx.google.com with ESMTPS id fr18sm26813552wbb.9.2011.09.25.10.00.07 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 25 Sep 2011 10:00:08 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, bonzini@gnu.org, rdsandiford@googlemail.com Cc: bonzini@gnu.org Subject: Always check modes in forward_propagate_and_simplify Date: Sun, 25 Sep 2011 18:00:03 +0100 Message-ID: <87vcsgo8vg.fsf@firetop.home> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 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 While working on a MIPS16 patch, I came across an ICE on code like: (set (reg:DI 64) (unspec:DI BLAH)) (set (reg:SI PSEUDO) (reg:SI 64)) The problem was that fwprop.c:forward_propagate_and_simplify tried to replace (reg:SI 64) with (unspec:DI BLAH), i.e. it tried to replace an SImode value with a DImode one. The function already checks the modes if both the use and def are subregs. I think we should always do that. There was some discussion a while back about whether we should propagate hard regs. But I think that was in the context of propagating a hard-reg SET_SRC. In this case, BLAH only mentions pseudos, and I think propagating for: (set (reg:SI 64) (unspec:SI BLAH)) (set (reg:SI PSEUDO) (reg:SI 64)) should still be allowed. Tested on x86_64-linux-gnu and mips64-linux-gnu. Also tested by making sure that the only .o files to change between the old and new x86_64-linux-gnu stage2 and stage3 compilers were the checksum files and fwprop.o itself. Paolo, does this look OK to you? Richard gcc/ * fwprop.c (forward_propagate_and_simplify): After checking reg/subreg combinations, check whether the modes are the same. Index: gcc/fwprop.c =================================================================== --- gcc/fwprop.c 2011-09-24 13:52:22.000000000 +0100 +++ gcc/fwprop.c 2011-09-24 13:54:50.000000000 +0100 @@ -1232,21 +1232,24 @@ forward_propagate_and_simplify (df_ref u /* If def and use are subreg, check if they match. */ reg = DF_REF_REG (use); - if (GET_CODE (reg) == SUBREG - && GET_CODE (SET_DEST (def_set)) == SUBREG - && (SUBREG_BYTE (SET_DEST (def_set)) != SUBREG_BYTE (reg) - || GET_MODE (SET_DEST (def_set)) != GET_MODE (reg))) - return false; - + if (GET_CODE (reg) == SUBREG && GET_CODE (SET_DEST (def_set)) == SUBREG) + { + if (SUBREG_BYTE (SET_DEST (def_set)) != SUBREG_BYTE (reg)) + return false; + } /* Check if the def had a subreg, but the use has the whole reg. */ - if (REG_P (reg) && GET_CODE (SET_DEST (def_set)) == SUBREG) + else if (REG_P (reg) && GET_CODE (SET_DEST (def_set)) == SUBREG) return false; - /* Check if the use has a subreg, but the def had the whole reg. Unlike the previous case, the optimization is possible and often useful indeed. */ - if (GET_CODE (reg) == SUBREG && REG_P (SET_DEST (def_set))) + else if (GET_CODE (reg) == SUBREG && REG_P (SET_DEST (def_set))) reg = SUBREG_REG (reg); + /* Make sure that we can treat REG as having the same mode as the + source of DEF_SET. */ + if (GET_MODE (SET_DEST (def_set)) != GET_MODE (reg)) + return false; + /* Check if the substitution is valid (last, because it's the most expensive check!). */ src = SET_SRC (def_set);