From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18802 invoked by alias); 11 Apr 2003 18:09:01 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 18780 invoked from network); 11 Apr 2003 18:08:59 -0000 Received: from unknown (HELO nikam.ms.mff.cuni.cz) (195.113.18.106) by sources.redhat.com with SMTP; 11 Apr 2003 18:08:59 -0000 Received: from camelot.ms.mff.cuni.cz (kampanus.ms.mff.cuni.cz [195.113.18.107]) by nikam.ms.mff.cuni.cz (Postfix) with SMTP id 2F45A4DE86; Fri, 11 Apr 2003 20:09:00 +0200 (CEST) Received: by camelot.ms.mff.cuni.cz (sSMTP sendmail emulation); Fri, 11 Apr 2003 20:09:01 +0200 Date: Fri, 11 Apr 2003 19:01:00 -0000 From: Jan Hubicka To: Eric Botcazou Cc: Jan Hubicka , gcc@gcc.gnu.org Subject: Re: Reload bug Message-ID: <20030411180901.GL15771@kam.mff.cuni.cz> References: <200304081937.16859.ebotcazou@libertysurf.fr> <200304102200.35188.ebotcazou@libertysurf.fr> <20030410202612.GI9319@kam.mff.cuni.cz> <200304111356.23415.ebotcazou@libertysurf.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200304111356.23415.ebotcazou@libertysurf.fr> User-Agent: Mutt/1.3.28i X-SW-Source: 2003-04/txt/msg00557.txt.bz2 > > The code is wrong for post-SUBREG_BYTE patch as it checks that the > > partial regs have exactly size of one word, but we do allow subregs on > > registers of different sizes. We need to verify that offset can > > represent the register exactly. > > Is it really wrong or is it incomplete now, in the post-SUBREG_BYTE era? Hi, this is the patch I am currently playing with. The subreg_offset_representable_p should return false when we can't represent the subreg and should abort in the cases I believe current implemetnation would get entirely confused. I am not quite sure I got it right, but you may want to take a look :) Index: emit-rtl.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v retrieving revision 1.318 diff -c -3 -p -r1.318 emit-rtl.c *** emit-rtl.c 4 Apr 2003 22:44:02 -0000 1.318 --- emit-rtl.c 11 Apr 2003 18:06:01 -0000 *************** subreg_hard_regno (x, check_mode) *** 1080,1086 **** abort (); if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg))) abort (); ! /* Catch non-congruent offsets too. */ byte_offset = SUBREG_BYTE (x); if ((byte_offset % GET_MODE_SIZE (mode)) != 0) --- 1080,1090 ---- abort (); if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg))) abort (); ! #ifdef ENABLE_CHECKING ! if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg), ! SUBREG_BYTE (x), mode)) ! abort (); ! #endif /* Catch non-congruent offsets too. */ byte_offset = SUBREG_BYTE (x); if ((byte_offset % GET_MODE_SIZE (mode)) != 0) Index: reload.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.c,v retrieving revision 1.211 diff -c -3 -p -r1.211 reload.c *** reload.c 26 Mar 2003 07:48:13 -0000 1.211 --- reload.c 11 Apr 2003 18:06:01 -0000 *************** find_reloads (insn, replace, ind_levels, *** 2880,2885 **** --- 2880,2891 ---- if (GET_CODE (SUBREG_REG (operand)) == REG && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER) { + if (!subreg_offset_representable_p + (REGNO (SUBREG_REG (operand)), + GET_MODE (SUBREG_REG (operand)), + SUBREG_BYTE (operand), + GET_MODE (operand))) + force_reload = 1; offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)), GET_MODE (SUBREG_REG (operand)), SUBREG_BYTE (operand), *************** find_reloads (insn, replace, ind_levels, *** 2935,2960 **** ) #endif ) - /* This following hunk of code should no longer be - needed at all with SUBREG_BYTE. If you need this - code back, please explain to me why so I can - fix the real problem. -DaveM */ - #if 0 - /* Subreg of a hard reg which can't handle the subreg's mode - or which would handle that mode in the wrong number of - registers for subregging to work. */ - || (GET_CODE (operand) == REG - && REGNO (operand) < FIRST_PSEUDO_REGISTER - && ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD - && (GET_MODE_SIZE (GET_MODE (operand)) - > UNITS_PER_WORD) - && ((GET_MODE_SIZE (GET_MODE (operand)) - / UNITS_PER_WORD) - != HARD_REGNO_NREGS (REGNO (operand), - GET_MODE (operand)))) - || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset, - operand_mode[i]))) - #endif ) force_reload = 1; } --- 2941,2946 ---- *************** find_reloads_address_1 (mode, x, context *** 5271,5276 **** --- 5257,5275 ---- GET_MODE (SUBREG_REG (orig_op1)), SUBREG_BYTE (orig_op1), GET_MODE (orig_op1)))); + } + /* Plus in the index register may be created only as a result of + register remateralization for expresion like &localvar*4. Reload it. + It may be possible to combine the displacement on the outer level, + but it is probably not worthwhile to do so. */ + if (context) + { + find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0), + opnum, ADDR_TYPE (type), ind_levels, insn); + push_reload (*loc, NULL_RTX, loc, (rtx*) 0, + (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)), + GET_MODE (x), VOIDmode, 0, 0, opnum, type); + return 1; } if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE + nregs_ymode = HARD_REGNO_NREGS (xregno, ymode); + + /* paradoxical subregs are always valid. */ + if (offset == 0 + && nregs_ymode > nregs_xmode + && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD + ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN)) + return true; + + /* Lowpart subregs are always valid. */ + if (offset == subreg_lowpart_offset (ymode, xmode)) + return true; + + #ifdef ENABLE_CHECKING + /* This should always pass, otherwise we don't know how to verify the + constraint. + + These conditions may be relaxed but subreg_offset would need to be + redesigned. */ + if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode) + || GET_MODE_SIZE (ymode) % nregs_ymode + || mode_for_size (GET_MODE_SIZE (ymode) / nregs_ymode, + MODE_INT, 0) == VOIDmode + || nregs_xmode % nregs_ymode) + abort (); + #endif + + /* The XMODE value can be seen as an vector of NREGS_XMODE + values. The subreg must represent an lowpart of given field. + Compute what field it is. */ + offset -= subreg_lowpart_offset (mode_for_size (GET_MODE_SIZE (ymode) + / nregs_ymode, + MODE_INT, 0), xmode); + + /* size of ymode must not be greater than the size of xmode. */ + mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode); + if (mode_multiple == 0) + abort (); + + y_offset = offset / GET_MODE_SIZE (ymode); + nregs_multiple = nregs_xmode / nregs_ymode; + #ifdef ENABLE_CHECKING + if (offset % GET_MODE_SIZE (ymode) + || mode_multiple % nregs_multiple) + abort (); + #endif + return (!(y_offset % (mode_multiple / nregs_multiple))); + } + /* Return the final regno that a subreg expression refers to. */ unsigned int subreg_regno (x)