From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16414 invoked by alias); 13 Mar 2004 20:10:15 -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 16407 invoked from network); 13 Mar 2004 20:10:14 -0000 Received: from unknown (HELO main.gmane.org) (80.91.224.249) by sources.redhat.com with SMTP; 13 Mar 2004 20:10:14 -0000 Received: from root by main.gmane.org with local (Exim 3.35 #1 (Debian)) id 1B2FSY-0001Ny-00 for ; Sat, 13 Mar 2004 21:10:14 +0100 Received: from panic.cs.bris.ac.uk ([137.222.103.158]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 13 Mar 2004 21:10:14 +0100 Received: from brown by panic.cs.bris.ac.uk with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 13 Mar 2004 21:10:14 +0100 To: gcc@gcc.gnu.org From: Julian Brown Subject: Bad mode-change inside subreg: DImode to SImode Date: Sat, 13 Mar 2004 20:10:00 -0000 Organization: University of Bristol Message-ID: Reply-To: brown@cs.bris.ac.uk X-Complaints-To: usenet@sea.gmane.org X-Gmane-NNTP-Posting-Host: panic.cs.bris.ac.uk User-Agent: slrn/0.9.8.0 (Linux) X-SW-Source: 2004-03/txt/msg00617.txt.bz2 Hi, I am working on a port of GCC to a custom architecture, and I have hit a problem recently (possibly since starting working against newer versions of GCC) which I am having particular difficulty in solving. I am working against the gcc-3_4-branch, but the same thing happens with other recent branches. The following code refuses to compile: -- typedef struct { long long rem; long long quot; } lldiv_t; lldiv_t divlong (long long numer, long long denom) { lldiv_t retval; if (numer >= 0) { retval.quot++; } return (retval); } -- giving the error: divbug.c: In function `divlong': divbug.c:14: internal compiler error: in simplify_subreg, at simplify-rtx.c:3236 I have tracked this down for starters to the cse pass: beforehand, the offending rtx looks like (from divbug.c.04.jump): (insn 12 6 13 0 (set (reg:SI 137) (lt:SI (subreg:SI (reg/v:DI 135 [ numer ]) 4) (const_int 0 [0x0]))) -1 (nil) (nil)) and afterwards (divbug.c.06.cse): (insn 12 6 13 0 (set (reg:SI 137) (lt:SI (subreg:SI (reg/f:SI 134) 4) (const_int 0 [0x0]))) 60 {*slt_insn} (nil) (nil)) The problem is that that substitution is invalid, since (reg/f:SI 134) doesn't have a second word. Now, I found where the bad substitution is happening, in canon_reg() in cse.c, which is line 2805 in my version of the code, the "else" part of: -- /* If replacing pseudo with hard reg or vice versa, ensure the insn remains valid. Likewise if the insn has MATCH_DUPs. */ if (insn != 0 && new != 0 && GET_CODE (new) == REG && GET_CODE (XEXP (x, i)) == REG && (((REGNO (new) < FIRST_PSEUDO_REGISTER) != (REGNO (XEXP (x, i)) < FIRST_PSEUDO_REGISTER)) || (insn_code = recog_memoized (insn)) < 0 || insn_data[insn_code].n_dups > 0)) validate_change (insn, &XEXP (x, i), new, 1); else XEXP (x, i) = new; -- Now though, I am totally stuck trying to figure out why gcc would believe the substitution to be a sensible thing to do. My speculations are: (1) There is a structure-sharing violation somehow, and the whole (subreg...) should have been changed to the (reg...) rather than just the child pointer changing. (2) There's a random bug somewhere in my machine description, etc. which is triggering this behaviour. I can compile the code with an ARM cross-compiler, and the equivalent substitution doesn't appear to happen (the rtl isn't identical though, since my arch has significant differences to the ARM). I don't have much belief in my ability to decipher exactly what's going on in cse.c, since it's big & complicated & I'm not that smart. Can anyone lend any pointers as to what might be happening here? (My machine description files are at: http://panic.cs.bris.ac.uk/~jules/dop{.md,.c,.h,-protos.h}) Cheers, Julian