Bug 11576 - [3.3 regression] internal error at emit-rtl.c:2017
Summary: [3.3 regression] internal error at emit-rtl.c:2017
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 3.3
: P2 normal
Target Milestone: 3.3.3
Assignee: Kazu Hirata
URL:
Keywords: ice-on-valid-code, patch
Depends on:
Blocks:
 
Reported: 2003-07-18 13:39 UTC by Yoshinori Sato
Modified: 2003-12-23 15:14 UTC (History)
2 users (show)

See Also:
Host: i386-linux
Target: h8300-elf
Build: i386-linux
Known to work:
Known to fail:
Last reconfirmed: 2003-07-18 15:00:45


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yoshinori Sato 2003-07-18 13:39:49 UTC
o Compile command
$ h8300-elf-gcc -O1 -mh -mint32 -Os -S gcc-bug.c

o Result message
gcc-bug.c: In function `add_to_page_cache':
gcc-bug.c:86: internal compiler error: in change_address_1, at emit-rtl.c:2017

o problem source code

struct list_head {
        struct list_head *next, *prev;
};
static inline void __list_add(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next)
{
        next->prev = new;
        new->next = next;
        new->prev = prev;
        prev->next = new;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
        __list_add(new, head, head->next);
}
typedef struct { int counter; } atomic_t;
static __inline__ int atomic_inc_return(atomic_t *v)
{
        int ret,flags;
        do { asm volatile ("sub.l er0,er0\n\tstc ccr,r0l\n\tmov.l er0,%0":"=r" (flags) : : "er0"); asm volatile ("orc  #0x80,ccr"); } while(0);
        v->counter++;
        ret = v->counter;
        asm volatile ("mov.l %0,er0\n\tldc r0l,ccr": :"r" (flags) : "er0");
        return ret;
}
struct address_space {
        struct list_head clean_pages;
        unsigned long nrpages;
};

struct inode {
        unsigned long dummy;

};
typedef struct page {
        struct list_head list;
        struct address_space *mapping;
        unsigned long index;
        atomic_t count;
        unsigned long flags;
} mem_map_t;
extern unsigned int page_hash_bits;
static inline unsigned long _page_hashfn(struct address_space * mapping, unsigned long index)
{
        return (((((unsigned long) mapping)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))+index)+(((((unsigned long) mapping) /(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))+index)>>(page_hash_bits))) & ((1 << (page_hash_bits))-1);
}
atomic_t page_cache_size = { (0) };
unsigned int page_hash_bits;
struct page **page_hash_table;
static void add_page_to_hash_queue(struct page * page, struct page **p)
{
}

static inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
{
        struct list_head *head = &mapping->clean_pages;

        mapping->nrpages++;
        list_add(&page->list, head);
        page->mapping = mapping;
}

static inline void __add_to_page_cache(struct page * page,
        struct address_space *mapping, unsigned long offset,
        struct page **hash)
{
        unsigned long flags;

        flags = page->flags & ~(1 << 3 | 1 << 1 | 1 << 4 | 1 << 2 | 1 << 13 | 1 << 12);
        page->flags = flags | (1 << 0);
        atomic_inc_return(&(page)->count);
        page->index = offset;
        add_page_to_inode_queue(mapping, page);
        add_page_to_hash_queue(page, hash);
}

static void lru_cache_add(struct page *page)
{
}

void add_to_page_cache(struct page * page, struct address_space * mapping, unsigned long offset)
{
        __add_to_page_cache(page, mapping, offset, (page_hash_table+_page_hashfn(mapping,offset)));
        lru_cache_add(page);
}
Comment 1 Andrew Pinski 2003-07-18 14:08:43 UTC
On the mainline (20030718), I cannot reproduce this so this looks like it only effects 3.3, I will try 
3.3.1 (the latest snapshot) unless someone beats me to it.
Comment 2 Andrew Pinski 2003-07-18 15:00:45 UTC
I can reproduce this on 3.3.1 (20030714).
Comment 3 Andrew Pinski 2003-07-18 15:20:36 UTC
It also happens in 3.2.3.
Comment 4 Andrew Pinski 2003-07-18 15:33:08 UTC
It also happens in 3.1.
Comment 5 Yoshinori Sato 2003-07-18 15:50:42 UTC
3.1.1 and 3.2.3 is no problem
Comment 6 Andrew Pinski 2003-07-18 15:52:04 UTC
This is a regression from 3.0.4 where gcc did not ICE.
Comment 7 Yoshinori Sato 2003-07-18 16:18:41 UTC
testing snapshot ...
gcc version 3.3.1 20030714 (prerelease)

Result
gcc-bug.c: In function `add_to_page_cache':
gcc-bug.c:92: internal compiler error: in change_address_1, at emit-rtl.c:2020
Comment 8 Dara Hazeghi 2003-07-18 17:56:43 UTC
Only -mint32 -mh -Os needed to reproduce it. Workaround is to change -Os to -O1 or remove 
one of the other two options.
Comment 9 Kazu Hirata 2003-09-02 10:01:01 UTC
I simplified the testcase a little bit.

struct list_head {
  struct list_head *next, *prev;
};

struct atomic {
  int counter;
};

struct address_space {
  struct list_head clean_pages;
};

struct page {
  struct list_head list;
  struct address_space *mapping;
  unsigned long index;
  struct atomic count;
  unsigned long flags;
};

extern unsigned int page_hash_bits;

unsigned int page_hash_bits;

struct page **page_hash_table;

void add_page_to_hash_queue (struct page *page, struct page **p);

void lru_cache_add (struct page *page);

void
add_to_page_cache (struct page *page, struct address_space *mapping,
		   unsigned long offset)
{
  unsigned long m = ((unsigned long) mapping) / 4 + offset;
  unsigned long hash_value =
    (m + (m >> page_hash_bits)) & ((1 << page_hash_bits) - 1);
  struct page **hash = page_hash_table + hash_value;
  struct list_head *head;

  page->flags |= 1;

  {
    struct atomic *v = &page->count;
    int flags;

    asm volatile ("" : "=r" (flags) :             : "er0");
    v->counter++;
    asm volatile ("" :              : "r" (flags) : "er0");
  }

  page->index = offset;

  head = &mapping->clean_pages;

  {
    struct list_head *new = &page->list;
    struct list_head *prev = head;
    struct list_head *next = head->next;

    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
  }

  add_page_to_hash_queue (page, hash);

  lru_cache_add (page);
}
Comment 10 Kazu Hirata 2003-09-03 00:38:36 UTC
Backporting the following patch solves the problem.

http://gcc.gnu.org/ml/gcc-cvs/2002-12/msg00640.html

I will talk to the author of the patch to see if it would make sense to have it
on 3.3 branch.
Comment 11 Kazu Hirata 2003-09-06 03:59:17 UTC
Slightly more reduced:

struct list {
  struct list *next, *prev;
};

struct page {
  struct list list;
  int index;
  int counter;
};

int bits, table;

int
foo (struct page *page, struct list *head, int offset)
{
  int value = (offset >> bits) & (1 << bits);
  int hash = table + value;

  page->index |= 1;

  {
    int *v = &page->counter;
    int flags;

    asm volatile ("" : "=r" (flags) :             : "er0");
    (*v)++;
    asm volatile ("" :              : "r" (flags) : "er0");
  }

  page->index = offset;

  {
    struct list *new = &page->list;
    struct list *prev = head;
    struct list *next = head->next;

    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
  }

  return (int) page + hash;
}
Comment 12 Kazu Hirata 2003-09-06 14:42:03 UTC
Slightly more reduced:

struct page {
  struct page *next, *prev;
  int index;
  int counter;
};

int bits, table;

int
foo (struct page *new, struct page *head, int offset)
{
  int value = (offset + bits) & (1 << bits);
  int hash = table + value;

  new->index++;

  {
    int *v = &new->counter;
    int flags;

    asm volatile ("" : "=r" (flags) :             : "er0");
    (*v)++;
    asm volatile ("" :              : "r" (flags) : "er0");
  }

  new->index = offset;

  {
    struct page *prev = head;
    struct page *next = head->next;

    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
  }

  return (int) new + hash;
}

Comment 13 Mark Mitchell 2003-10-16 09:23:16 UTC
Postponed until GCC 3.3.3.
Comment 14 Zack Weinberg 2003-12-01 22:36:34 UTC
since this is a case of "backport this from 3.4 to fix" we should get Gabriel's
opinion.
Comment 15 Gabriel Dos Reis 2003-12-01 22:55:31 UTC
Subject: Re:  [3.3 regression] internal error at emit-rtl.c:2017

"zack at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| since this is a case of "backport this from 3.4 to fix" we should
| get Gabriel's opinion.

It is OK.  I missed the proposed fix for this PR.

Thanks for bringing it to my attention.

-- Gaby
Comment 16 Zack Weinberg 2003-12-01 23:08:45 UTC
Kazu, would you please do the backport, re-test, and commit?
Comment 17 Gabriel Dos Reis 2003-12-21 20:46:37 UTC
Kazu --
Do you think you have plan for this in time for 3.3.x?

-- Gaby
Comment 18 Kazu Hirata 2003-12-21 20:51:16 UTC
I was about to put a comment.  Mid-air comflict!

Whee, the proposed backport does not fix the problem anymore!
I still get the same ICE.
Would you mind giving me a day or two to analyze this?
If it's beyond my capability, I'll give up with WONTFIX.
Comment 19 Gabriel Dos Reis 2003-12-21 20:55:04 UTC
Subject: Re:  [3.3 regression] internal error at emit-rtl.c:2017

"kazu at cs dot umass dot edu" <gcc-bugzilla@gcc.gnu.org> writes:

| Would you mind giving me a day or two to analyze this?

Sure.  You've till the end of the year :-)

| If it's beyond my capability, I'll give up with WONTFIX.

Thanks!

-- Gaby


Comment 20 GCC Commits 2003-12-23 15:10:30 UTC
Subject: Bug 11576

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_3-branch
Changes by:	kazu@gcc.gnu.org	2003-12-23 15:10:26

Modified files:
	gcc            : ChangeLog 
	gcc/config/h8300: h8300.h 

Log message:
	PR target/11576
	* config/h8300/h8300.h (CONSTANT_ADDRESS_P): Allow CONST and
	HIGH on all variants.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.16114.2.858&r2=1.16114.2.859
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/h8300/h8300.h.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.123.2.2&r2=1.123.2.3

Comment 21 Kazu Hirata 2003-12-23 15:14:15 UTC
Just committed a patch.