From patchwork Thu Jun 9 16:54:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georg-Johann Lay X-Patchwork-Id: 99784 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 45B96B6FD2 for ; Fri, 10 Jun 2011 03:02:13 +1000 (EST) Received: (qmail 8283 invoked by alias); 9 Jun 2011 17:02:10 -0000 Received: (qmail 8253 invoked by uid 22791); 9 Jun 2011 17:02:08 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE X-Spam-Check-By: sourceware.org Received: from mo-p00-ob.rzone.de (HELO mo-p00-ob.rzone.de) (81.169.146.161) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 09 Jun 2011 17:01:50 +0000 X-RZG-AUTH: :LXoWVUeid/7A29J/hMvvT2k715jHQaJercGObUOFkj18odoYNahU4Q== X-RZG-CLASS-ID: mo00 Received: from [192.168.0.22] (business-188-111-022-002.static.arcor-ip.net [188.111.22.2]) by post.strato.de (mrclete mo48) (RZmta 25.18) with ESMTPA id R0272an59EeXAx ; Thu, 9 Jun 2011 18:54:13 +0200 (MEST) Message-ID: <4DF0FAB5.6070704@gjlay.de> Date: Thu, 09 Jun 2011 18:54:13 +0200 From: Georg-Johann Lay User-Agent: Thunderbird 2.0.0.24 (X11/20100302) MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org CC: Anatoly Sokolov , Denis Chertykov , "Eric B. Weddington" Subject: [Patch, AVR]: Fix PR46779 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 This is a tentative patch to fix PR46779 and hopefully also related issues like PR45291. In the present version of avr_hard_regno_mode_ok, QImode is forbidden in r29/r28. If a 16-bit value or composite is allocated to r28, this can lead to odd subregs like (set (subreg:QI (reg:HI r28) 0) ...) These subregs are produced by IRA and reload treats the subreg with a RELOAD_WRITE. As reload spills r28 to another hard reg that can access QI, there will be no input reload. Therefore, if r29 already contains data that data will get garbaged. See also the discussion around http://gcc.gnu.org/ml/gcc/2011-06/msg00005.html Tested with two regressions less compared to unpatched compiler. Testcases that now pass are: * gcc.target/avr/pr46779-1.c * gcc.target/avr/pr46779-2.c Johann --- PR target/46779 * config/avr/avr.c (avr_hard_regno_mode_ok): Rewrite. In particular, allow 8-bit values in r28 and r29. (avr_hard_regno_scratch_ok): Disallow any register that might be part of the frame pointer. (avr_hard_regno_rename_ok): Same. Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (Revision 174701) +++ config/avr/avr.c (Arbeitskopie) @@ -6276,26 +6276,35 @@ jump_over_one_insn_p (rtx insn, rtx dest int avr_hard_regno_mode_ok (int regno, enum machine_mode mode) { - /* Disallow QImode in stack pointer regs. */ - if ((regno == REG_SP || regno == (REG_SP + 1)) && mode == QImode) + /* Don't allocate data to non-GENERAL_REGS registers. */ + + if (regno >= 32) return 0; - /* The only thing that can go into registers r28:r29 is a Pmode. */ - if (regno == REG_Y && mode == Pmode) + /* Any GENERAL_REGS register can hold 8-bit values. */ + /* FIXME: + 8-bit values must not be disallowed for R28 or R29. Disallowing + QI et al. in these registers might lead to code like + (set (subreg:QI (reg:HI 28)) ...) + which will result in wrong code because reload does not handle + SUBREGs of hard regsisters like this. This could be fixed in reload. + However, it appears that fixing reload is not wanted by reload people. */ + + if (GET_MODE_SIZE (mode) == 1) return 1; + + /* Disallow big registers that overlap the frame pointer. + This will hopefully reduce the number of spill failures. */ + + if (GET_MODE_SIZE (mode) > 2 + && regno <= REG_Y + && regno + GET_MODE_SIZE (mode) >= REG_Y + 1) + { + return 0; + } - /* Otherwise disallow all regno/mode combinations that span r28:r29. */ - if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1)) - return 0; - - if (mode == QImode) - return 1; - - /* Modes larger than QImode occupy consecutive registers. */ - if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER) - return 0; - - /* All modes larger than QImode should start in an even register. */ + /* All modes larger than 8 bits should start in an even register. */ + return !(regno & 1); } @@ -6422,13 +6431,23 @@ avr_hard_regno_scratch_ok (unsigned int && !df_regs_ever_live_p (regno)) return false; + /* Don't allow hard registers that might be part of the frame pointer. + Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM + and don't care for a frame pointer that spans more than one register. */ + + if ((!reload_completed || frame_pointer_needed) + && (regno == REG_Y || regno == REG_Y + 1)) + { + return false; + } + return true; } /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */ int -avr_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED, +avr_hard_regno_rename_ok (unsigned int old_reg, unsigned int new_reg) { /* Interrupt functions can only use registers that have already been @@ -6439,6 +6458,17 @@ avr_hard_regno_rename_ok (unsigned int o && !df_regs_ever_live_p (new_reg)) return 0; + /* Don't allow hard registers that might be part of the frame pointer. + Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM + and don't care for a frame pointer that spans more than one register. */ + + if ((!reload_completed || frame_pointer_needed) + && (old_reg == REG_Y || old_reg == REG_Y + 1 + || new_reg == REG_Y || new_reg == REG_Y + 1)) + { + return 0; + } + return 1; }