------- Comment #7 from jakub at gcc dot gnu dot org  2007-08-22 13:27 -------
Actually, to me this doesn't look like missed-optimization at all.
And you should be happy for 4.2.1 generated bigger code, 4.1.1 optimized out
something it shouldn't.
Below is an stripped down testcase, which works on 3.4/4.1/4.2/4.3 with -O0
or -O2 -fno-strict-aliasing, works even with -O2 with 3.4 and 4.2, segfaults
with 4.1 (x86_64 -m64, aborts with x86_64 -m32) and issues a bogus warning
about unitialized common_head and aborts on the trunk.

/* { dg-do run } */
/* { dg-options "-O2" } */

typedef __SIZE_TYPE__ size_t;
extern void exit (int);
extern void *malloc (size_t);
extern void *realloc (void *, size_t);
extern void abort (void);

void *
__attribute__ ((noinline))
xmalloc (size_t size)
{
  void *p = malloc (size);
  if (p == 0)
    exit (0);
  return p;
}

void *
__attribute__ ((noinline))
xrealloc (void *old, size_t size)
{
  void *p = realloc (old, size);
  if (p == 0)
    exit (0);
  return p;
}

struct obj_section
{
  unsigned int sh_type;
  unsigned int sh_flags;
  unsigned int sh_size;
  unsigned int sh_addralign;
  const char *name;
  char *contents;
  struct obj_section *load_next;
  int idx;
};

struct obj_symbol
{
  struct obj_symbol *next;
  unsigned long value;
  unsigned long size;
  int secidx;
};

struct obj_file
{
  unsigned short e_shnum;
  struct obj_section **sections;
  struct obj_symbol *symtab[521];
};

static void
__attribute__((noinline))
obj_allocate_commons (struct obj_file *f)
{
  struct common_entry
  {
    struct common_entry *next;
    struct obj_symbol *sym;
  } *common_head = (void *) 0;
  unsigned long i;

  for (i = 0; i < 521; ++i)
    {
      struct obj_symbol *sym;
      for (sym = f->symtab[i]; sym; sym = sym->next)
        if (sym->secidx == 0xfff2)
          {
            struct common_entry **p, *n;
            for (p = &common_head; *p; p = &(*p)->next)
              if (sym->size <= (*p)->sym->size)
                break;
            n = __builtin_alloca (sizeof (*n));
            n->next = *p;
            n->sym = sym;
            *p = n;
          }
    }

  if (common_head)
    {
      for (i = 0; i < f->e_shnum; ++i)
        if (f->sections[i]->sh_type == 8)
          break;
      if (i == f->e_shnum)
        {
          struct obj_section *sec;
          f->sections = xrealloc (f->sections, (i + 1) * sizeof (sec));
          f->sections[i] = sec = xmalloc (sizeof (struct obj_section));
          f->e_shnum = i + 1;
          __builtin_memset (sec, 0, sizeof (*sec));
          sec->sh_type = 1;
          sec->sh_flags = (1 << 0) | (1 << 1);
          sec->name = ".bss";
          sec->idx = i;
        }
    }
}

int
main (void)
{
  struct obj_file of;
  struct obj_symbol s;
  struct obj_section *sec;
  __builtin_memset (&s, 0, sizeof (s));
  s.value = 4;
  s.size = 4;
  s.secidx = 0xfff2;
  __builtin_memset (&of, 0, sizeof (of));
  of.e_shnum = 2;
  of.sections = xmalloc (2 * sizeof (sec));
  of.sections[0] = sec = xmalloc (sizeof (struct obj_section));
  __builtin_memset (sec, 0, sizeof (*sec));
  sec->sh_type = 4;
  sec->sh_flags = (1 << 0) | (1 << 1);
  sec->name = ".foo";
  sec->idx = 0;
  of.sections[1] = sec = xmalloc (sizeof (struct obj_section));
  __builtin_memset (sec, 0, sizeof (*sec));
  sec->sh_type = 4;
  sec->sh_flags = (1 << 0) | (1 << 1);
  sec->name = ".bar";
  sec->idx = 1;
  of.symtab[0] = &s;
  obj_allocate_commons (&of);
  if (of.e_shnum != 3)
    abort ();
  return 0;
}

Even on the original testcase, obj_allocate_commons is so short because
the whole if (common_head) { ... } huge block has been completely optimized
out (watch for xrealloc call e.g.).

To me the code looks valid, there is no type puning involved.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33136

Reply via email to