Bug 26826 - [4.1 Regression] ICE in reg_or_subregno, at jump.c:2011
Summary: [4.1 Regression] ICE in reg_or_subregno, at jump.c:2011
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.1.0
: P1 normal
Target Milestone: 4.1.1
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code, monitored
Depends on:
Blocks:
 
Reported: 2006-03-23 12:59 UTC by Richard Biener
Modified: 2006-04-29 03:29 UTC (History)
4 users (show)

See Also:
Host:
Target: i586-pc-linux-gnu
Build:
Known to work: 4.0.3
Known to fail: 4.1.0 4.2.0
Last reconfirmed: 2006-03-23 14:33:26


Attachments
testcase (656 bytes, text/plain)
2006-03-23 13:00 UTC, Richard Biener
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2006-03-23 12:59:25 UTC
/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
Comment 1 Richard Biener 2006-03-23 13:00:06 UTC
Created attachment 11104 [details]
testcase
Comment 2 Richard Biener 2006-03-23 13:05:23 UTC
#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))))))
Comment 3 Andrew Pinski 2006-03-23 14:33:26 UTC
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);
}
Comment 4 Paolo Bonzini 2006-03-23 14:47:13 UTC
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.
Comment 5 Richard Biener 2006-03-23 15:01:25 UTC
I have a patch in testing.
Comment 6 Michael Matz 2006-03-25 21:10:47 UTC
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.
Comment 7 Volker Reichelt 2006-03-26 14:32:38 UTC
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);
}
=======================================
Comment 8 patchapp@dberlin.org 2006-03-27 04:35:29 UTC
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
Comment 9 Richard Biener 2006-04-17 13:53:23 UTC
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

Comment 10 Richard Biener 2006-04-17 13:54:09 UTC
Fixed on the mainline.
Comment 11 Richard Biener 2006-04-28 14:36:20 UTC
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

Comment 12 Richard Biener 2006-04-28 14:40:57 UTC
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

Comment 13 Andrew Pinski 2006-04-29 03:29:33 UTC
Fixed.