This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR25130, too hard for me :-(


Hi people,

Consider the following C++ program, which is my test case for PR25130,
a wrong-code issue seen on x86 and powerpc (with a different test case)
but it can probably be triggered anywhere under the right, well wrong,
circumstances if I understand the bug properly (and that's a Big If).

// g++ -O -fgcse t.C -fno-exceptions -fno-tree-dominator-opts -mtune=pentiumpro
// Should print two different pointers, but we break something somewhere.
inline void* operator new(unsigned, void* __p) throw() { return __p; }

extern "C"
{
int printf (...);
inline int __attribute__((noinline)) foo (int) { asm volatile ("" : : : "memory"); }
extern void __attribute ((noreturn)) abort (void);
}

struct _Deque_base
{
  _Deque_base()
  {
    _M_impl._M_start_cur = new int;
    _M_impl._M_finish_cur = _M_impl._M_start_cur;
    foo (0);
  }

  ~_Deque_base() {
    foo (_M_impl._M_start_node);
  }

  struct _Deque_impl
  {
    int* _M_start_cur;
    int _M_start_node;
    int* _M_finish_cur;
  };
  _Deque_impl _M_impl;
};

struct deque : public _Deque_base {};

struct ClusterContainerStandard
{
  deque _clusters;
  virtual void add_cluster() { }
};

int main( )
{
  {
    ClusterContainerStandard box;
  }
  asm volatile ("" : : : "memory");

  {
    deque clusters;
    if (clusters._M_impl._M_start_cur)
    {
      void *__p;
      __p = clusters._M_impl._M_finish_cur;
      if (__p)
	*(int *)__p = 0;
      ++clusters._M_impl._M_finish_cur;
    }

    printf ("%p %p\n",
            clusters._M_impl._M_start_cur, clusters._M_impl._M_finish_cur);
  }
  return 0;
}


The problem seems to be that the variables "box" and "clusters" share
some stack space.  So we have for box at one point a memory reference
in RTL that looks like this:

(insn 27 22 28 0 (set (reg:SI 68 [ <variable>._M_impl._M_start_node ])
        (mem/s/j:SI (plus:SI (reg/f:SI 20 frame)
                (const_int -8 [0xfffffff8])) [0 <variable>._M_impl._M_start_node+0 S4 A32])) 34 {*movsi_1} (nil)
    (nil))

and one for "clusters" that is also (mem (plus (frame) (const_int -8)))
later on:

(insn 39 37 41 0 (set (mem/s/j/c:SI (plus:SI (reg/f:SI 20 frame)
                (const_int -8 [0xfffffff8])) [0 clusters.D.1846._M_impl._M_finish_cur+0 S4 A32])
        (reg:SI 60 [ D.2070 ])) 34 {*movsi_1} (nil)
    (nil))

In gcse we then decide that these are the same expression, and (for
some reason even with -fno-gcse-lm) we apply load PRE to it.  But we
get it wrong.  When inserting the expression, we insert,

(insn 94 56 57 2 (set (reg:SI 73)
        (mem/s/j:SI (plus:SI (reg/f:SI 20 frame)
                (const_int -8 [0xfffffff8])) [0 <variable>._M_impl._M_start_node+0 S4 A32])) -1 (nil)
    (nil))

where we want to insert something for clusters._M_impl._M_finish_cur
if we're going to insert anything at all.

I have no real good idea how to attack this.  It seems to me that the
results of alias analysis are good (i.e. nonoverlapping_memrefs_p says
the two MEMs don't overlap, and they don't), and that GCSE should just
treat these two MEMs as different expressions.  But...
1) I'm not really sure my analysis of the problem is right.  This is
   still RTL, after all, and I've come to the conclusion that I'll
   never learn enough RTL to be sure about anything.
2) Iff I am right at least, then I still wouldn't know how to make
   GCSE handle these two MEMs differently.


So in short, I could use some help here, please :-)

Gr.
Steven


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]