/space/rguenther/install/gcc-4.1.0/bin/gcc -O -fomit-frame-pointer -march=i586 -S nvl160095.3-2.min.i -v Using built-in specs. Target: i686-pc-linux-gnu Configured with: /space/rguenther/src/svn/gcc-4_1-branch/configure --enable-cxa_at_exit --enable-threads=posix --enable-languages=c,c++,fortran --enable-checking=release --prefix=/space/rguenther/install/gcc-4.1.0 Thread model: posix gcc version 4.1.0 /space/rguenther/install/gcc-4.1.0/libexec/gcc/i686-pc-linux-gnu/4.1.0/cc1 -fpreprocessed nvl160095.3-2.min.i -quiet -dumpbase nvl160095.3-2.min.i -march=i586 -auxbase nvl160095.3-2.min -O -version -fomit-frame-pointer -o nvl160095.3-2.min.s GNU C version 4.1.0 (i686-pc-linux-gnu) compiled by GNU C version 4.1.0. GGC heuristics: --param ggc-min-expand=99 --param ggc-min-heapsize=129574 Compiler executable checksum: 7939d08ae804c1d1531a5f156c80434a nvl160095.3-2.min.i: In function ‘AppPlci_hold_reply’: nvl160095.3-2.min.i:29: warning: assignment makes pointer from integer without a cast nvl160095.3-2.min.i: At top level: nvl160095.3-2.min.i:46: warning: initialization from incompatible pointer type nvl160095.3-2.min.i: In function ‘plci_cc_hold_rej’: nvl160095.3-2.min.i:44: internal compiler error: in reg_or_subregno, at jump.c:2011 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions. adding -mtune=pentiumpro or removing -march=i586 fixes the problem
Created attachment 11104 [details] testcase
#1 0x08450df9 in reg_or_subregno (reg=0xb7d87780) at /space/rguenther/src/svn/gcc-4_1-branch/gcc/jump.c:2011 2011 gcc_assert (REG_P (reg)); (gdb) call debug_rtx(reg) (mem/c:SI (plus:SI (reg/f:SI 7 sp) (const_int 24 [0x18])) [0 S4 A8]) so... #2 0x0849f961 in push_reload (in=0xb7d8778c, out=0x0, inloc=0xb7d77a4c, outloc=0x0, class=Q_REGS, inmode=QImode, outmode=VOIDmode, strict_low=0, optional=1, opnum=2, type=RELOAD_FOR_INPUT) at /space/rguenther/src/svn/gcc-4_1-branch/gcc/reload.c:1332 #3 0x084a70d3 in find_reloads (insn=0xb7d6d320, replace=0, ind_levels=0, live_known=1, reload_reg_p=0x8802d40) at /space/rguenther/src/svn/gcc-4_1-branch/gcc/reload.c:4006 #4 0x084b2325 in calculate_needs_all_insns (global=1) at /space/rguenther/src/svn/gcc-4_1-branch/gcc/reload1.c:1476 #5 0x084b06d4 in reload (first=0xb7cf2dc0, global=1) at /space/rguenther/src/svn/gcc-4_1-branch/gcc/reload1.c:967 #6 0x08639227 in global_alloc (file=0x0) at /space/rguenther/src/svn/gcc-4_1-branch/gcc/global.c:628 we're reloading (gdb) call debug_rtx (insn) (insn 43 42 44 2 (parallel [ (set (reg:QI 3 bx [72]) (minus:QI (subreg:QI (reg:SI 3 bx [71]) 0) (subreg:QI (reg/f:SI 67) 0))) (clobber (reg:CC 17 flags)) ]) 178 {*subqi_1} (insn_list:REG_DEP_TRUE 33 (insn_list:REG_DEP_TRUE 42 (nil))) (expr_list:REG_UNUSED (reg:CC 17 flags) (expr_list:REG_DEAD (reg:SI 3 bx [71]) (expr_list:REG_DEAD (reg/f:SI 67) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil))))))
Reduced testcase: typedef struct { unsigned short FacilitySelector; } _cmsg; typedef struct _AppPlci { int *appl; } AppPlci_t; void AppPlci_hold_reply(AppPlci_t *aplci, unsigned short SuppServiceReason) { _cmsg *cmsg; unsigned char tmp[10], *p; if (aplci->appl) { if (!(cmsg = _kd_cmsg_alloc())) return; p = &tmp[1]; p += capiEncodeFacIndSuspend(p); tmp[0] = p - &tmp[1]; cmsg->FacilitySelector = 0x0003; } if (SuppServiceReason == 0) mISDN_FsmEvent(&aplci->appl); }
Looks like we have a (subreg (mem)) which this guard misses: /* If a memory location is needed for the copy, make one. */ if (in != 0 && (REG_P (in) || GET_CODE (in) == SUBREG) && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)), class, inmode)) get_secondary_mem (in, inmode, opnum, type); And there is a similar occurrence for output reloads some 30 lines below.
I have a patch in testing.
The sequence of what happens is a bit involved, and breaks a very old invariant in reload.c which doesn't seem to hold anyway since a long time, as there is already much code handling this non-holding, namely that subreg's of MEM only happen for paradoxical subregs, except on WORD_REGISTER_OPERATIONS machines. OTOH there is also other code in reload*.c which still seem to rely on this invariant (like this asserting code here), or tries to make sure it's true (e.g. in eliminate_regs_1). So, what happens is this: * pseudo 64 doesn't get a hardreg, and we are faced with (subreg:QI (reg:SI 64)) in some operand * the first time through the reload loop, reg_equiv_memory_loc[64] is still zero, hence no elimination is run on it, and no stackslot is created for it yet. * first time in calculate_needs_all_insns() it does an eliminate_regs call on the insn in question. As reg_equiv_memory_loc[64] is not yet filled in it goes down until eliminate_regs_1((reg:SI 64)), which then allocates the stack-slot for pseudo 64 in alter_reg. [this already is strange design, that stackslots are created sort of by accident in random order by trying to eliminate other regs] * now reg_equiv_memory_loc[64] _is_ set up to that new stack slot. But we are still deep down in the calculate_needs_all_insns() activation, not in the outer reload loop. Hence reg_equiv_mem[64] or reg_equiv_address[64] are not yet filled (they are normally setup from reg_equiv_memory_loc[64] just before the whole insn scanning). * now the insn in question is scanned further, and eventually goes into find_reloads(), which, before scanning constraints, tries to reload operand addresses. When it sees a SUBREG in an operand (as here), it uses find_reloads_toplev on that one. * find_reloads_toplev tries to handle SUBREGs sensible, i.e. tries to avoid creating (subreg (mem ...)), but can only do that if either reg_equiv_address[regno] or reg_equiv_mem[regno] are set up. See above for why this normally, but not here, is the case. * So it happily creates the problematic (subreg:QI (mem:SI stackslot)) which is stored into recog_data.operand[i] in find_reloads, so that further on we see that subreg-mem as operand (for this run in find_reloads). * Further down the road it checks constraints, which all are fine, but then comes optional reloads. * find_reloads tries to be nice to reload inheritance and creates an optional reload for each MEM operand (or subreg thereof), i.e. also for this one, so push_reload() is called on it. * push_reload doesn't expect a SUBREG of MEM which isn't paradoxical, and has even some gcc_assert to that effect in some of it's conditional blocks. * OTOH it also has code to explicitely handle SUBREGs where the inner reg is not REG_P, but perhaps that is supposed to only handle subregs of constants, not (subreg(mem)). And it has to expect some non-paradoxical (subreg(mem)) on WORD_REGISTER_OPERATIONS machines anyway. If either the stackslots would have been set up already by the time calculate_needs_all_insns runs, or find_reloads_toplev would also deal with only reg_equiv_memory_loc being set (which it can't) this problem wouldn't have occured. Sooo, the easiest solution for this I believe is that patch which Richard already mentioned (perhaps attach it here?), which simply also tests REG_P (SUBREG_REG (in/out)) in both places. The other solution would be to reinstate the invariant of subreg(mem) never occuring except on some machines, but that would be much harder to prove correct.
Shorter testcase: ======================================= void foo(char* p, char c, int i) { char a[2], *q=a+1; if (p && i) *p = q-a+bar(i); if (c) bar(i); } =======================================
Subject: Bug number PR26826 A patch for this bug has been added to the patch tracker. The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-03/msg01454.html
Subject: Bug 26826 Author: rguenth Date: Mon Apr 17 13:53:19 2006 New Revision: 113007 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=113007 Log: 2006-04-17 Richard Guenther <rguenther@suse.de> PR target/26826 * reload.c (push_reload): Guard calls to get_secondary_mem for memory subregs. Modified: trunk/gcc/ChangeLog trunk/gcc/reload.c
Fixed on the mainline.
Subject: Bug 26826 Author: rguenth Date: Fri Apr 28 14:36:14 2006 New Revision: 113348 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=113348 Log: 2006-04-28 Richard Guenther <rguenther@suse.de> PR target/26826 * gcc.target/i386/pr26826.c: New testcase. Added: trunk/gcc/testsuite/gcc.target/i386/pr26826.c Modified: trunk/gcc/testsuite/ChangeLog
Subject: Bug 26826 Author: rguenth Date: Fri Apr 28 14:40:51 2006 New Revision: 113349 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=113349 Log: 2006-04-28 Richard Guenther <rguenther@suse.de> PR target/26826 * reload.c (push_reload): Guard calls to get_secondary_mem for memory subregs. * gcc.target/i386/pr26826.c: New testcase. Added: branches/gcc-4_1-branch/gcc/testsuite/gcc.target/i386/pr26826.c - copied unchanged from r113348, trunk/gcc/testsuite/gcc.target/i386/pr26826.c Modified: branches/gcc-4_1-branch/gcc/ChangeLog branches/gcc-4_1-branch/gcc/reload.c branches/gcc-4_1-branch/gcc/testsuite/ChangeLog
Fixed.