2008-01-10 Andreas Krebbel <krebbel1@de.ibm.com>
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jan 2008 16:46:26 +0000 (16:46 +0000)
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jan 2008 16:46:26 +0000 (16:46 +0000)
PR middle-end/34641
* reload.c (push_reload): Add assertions.  All constants from
reg_equiv_constant should have been used for replacing the respective
pseudo earlier.
(find_reloads_address): Invoke find_reloads_address_part for
constant taken from the reg_equiv_constant array.

2008-01-10  Andreas Krebbel  <krebbel1@de.ibm.com>

PR middle-end/34641
* g++.dg/torture/pr34641.C: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131445 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/reload.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr34641.C [new file with mode: 0644]

index 6acc844..62a4cce 100644 (file)
@@ -1,3 +1,12 @@
+2008-01-10  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       PR middle-end/34641
+       * reload.c (push_reload): Add assertions.  All constants from
+       reg_equiv_constant should have been used for replacing the respective
+       pseudo earlier.
+       (find_reloads_address): Invoke find_reloads_address_part for
+       constant taken from the reg_equiv_constant array.
+
 2008-01-10  Steven Bosscher  <stevenb.gcc@gmail.com>
 
        * tree-ssa-sccvn.h (struct vn_ssa_aux): Make the most accessed
index 8f84546..5a0da1d 100644 (file)
@@ -922,29 +922,33 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
   if (outmode == VOIDmode && out != 0)
     outmode = GET_MODE (out);
 
-  /* If IN is a pseudo register everywhere-equivalent to a constant, and
-     it is not in a hard register, reload straight from the constant,
-     since we want to get rid of such pseudo registers.
-     Often this is done earlier, but not always in find_reloads_address.  */
+  /* If find_reloads and friends until now missed to replace a pseudo
+     with a constant of reg_equiv_constant something went wrong
+     beforehand.
+     Note that it can't simply be done here if we missed it earlier
+     since the constant might need to be pushed into the literal pool
+     and the resulting memref would probably need further
+     reloading.  */
   if (in != 0 && REG_P (in))
     {
       int regno = REGNO (in);
 
-      if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
-         && reg_equiv_constant[regno] != 0)
-       in = reg_equiv_constant[regno];
+      gcc_assert (regno < FIRST_PSEUDO_REGISTER
+                 || reg_renumber[regno] >= 0
+                 || reg_equiv_constant[regno] == NULL_RTX);
     }
 
-  /* Likewise for OUT.  Of course, OUT will never be equivalent to
-     an actual constant, but it might be equivalent to a memory location
-     (in the case of a parameter).  */
+  /* reg_equiv_constant only contains constants which are obviously
+     not appropriate as destination.  So if we would need to replace
+     the destination pseudo with a constant we are in real
+     trouble.  */
   if (out != 0 && REG_P (out))
     {
       int regno = REGNO (out);
 
-      if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
-         && reg_equiv_constant[regno] != 0)
-       out = reg_equiv_constant[regno];
+      gcc_assert (regno < FIRST_PSEUDO_REGISTER
+                 || reg_renumber[regno] >= 0
+                 || reg_equiv_constant[regno] == NULL_RTX);
     }
 
   /* If we have a read-write operand with an address side-effect,
@@ -4772,15 +4776,12 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
     {
       regno = REGNO (ad);
 
-      /* If the register is equivalent to an invariant expression, substitute
-        the invariant, and eliminate any eliminable register references.  */
-      tem = reg_equiv_constant[regno];
-      if (tem != 0
-         && (tem = eliminate_regs (tem, mode, insn))
-         && strict_memory_address_p (mode, tem))
+      if (reg_equiv_constant[regno] != 0)
        {
-         *loc = ad = tem;
-         return 0;
+         find_reloads_address_part (reg_equiv_constant[regno], loc,
+                                    base_reg_class (mode, MEM, SCRATCH),
+                                    GET_MODE (ad), opnum, type, ind_levels);
+         return 1;
        }
 
       tem = reg_equiv_memory_loc[regno];
index 496ef45..2f957f0 100644 (file)
@@ -1,3 +1,8 @@
+2008-01-10  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       PR middle-end/34641
+       * g++.dg/torture/pr34641.C: New testcase.
+
 2008-01-10  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/34651
diff --git a/gcc/testsuite/g++.dg/torture/pr34641.C b/gcc/testsuite/g++.dg/torture/pr34641.C
new file mode 100644 (file)
index 0000000..21115b7
--- /dev/null
@@ -0,0 +1,175 @@
+// { dg-require-effective-target fpic }
+// { dg-options "-fPIC" }
+// { dg-do compile }
+
+
+typedef long unsigned int size_t;
+extern "C" void *
+malloc (size_t __size)
+throw () __attribute__ ((__malloc__));
+     namespace std __attribute__ ((__visibility__ ("default")))
+{
+  using::size_t;
+}
+inline void *operator
+new (std::size_t, void *__p)
+throw ()
+{
+  return __p;
+}
+template < class _T1, class _T2 > struct pair
+{
+  _T1 first;
+  _T2 second;
+    pair (const _T1 & __a, const _T2 & __b):first (__a), second (__b)
+  {
+  }
+  template < class _U1, class _U2 >
+    pair (const pair < _U1, _U2 > &__p):first (__p.first), second (__p.second)
+  {
+  }
+};
+
+template < class _T1, class _T2 >
+  inline pair < _T1, _T2 > make_pair (_T1 __x, _T2 __y)
+{
+  return pair < _T1, _T2 > (__x, __y);
+}
+template < typename _Tp > inline const _Tp &
+max (const _Tp & __a, const _Tp & __b)
+{
+}
+typedef unsigned short int uint16_t;
+typedef unsigned long int uintptr_t;
+typedef uint16_t UChar;
+namespace std __attribute__ ((__visibility__ ("default")))
+{
+  struct __numeric_limits_base
+  {
+  };
+  template < typename _Tp > struct numeric_limits:public __numeric_limits_base
+  {
+    static _Tp max () throw ()
+    {
+    }
+  };
+}
+
+template < typename T > class VectorBufferBase
+{
+public:
+  void allocateBuffer (size_t newCapacity)
+  {
+    if (newCapacity > std::numeric_limits < size_t >::max () / sizeof (T))
+      *(int *) (uintptr_t) 0xbbadbeef = 0;
+  }
+};
+
+template < typename T, size_t inlineCapacity > class VectorBuffer;
+template < typename T > class VectorBuffer < T, 0 >:private VectorBufferBase <
+  T >
+{
+  typedef VectorBufferBase < T > Base;
+  using Base::allocateBuffer;
+};
+
+template < typename T, size_t inlineCapacity = 0 > class Vector
+{
+  typedef VectorBuffer < T, inlineCapacity > Impl;
+public:
+  typedef T *iterator;
+  size_t size () const
+  {
+    return m_size;
+  }
+  size_t capacity () const
+  {
+  }
+  iterator begin ()
+  {
+  }
+  iterator end ()
+  {
+    return begin () + m_size;
+  }
+  void shrink (size_t size);
+  void reserveCapacity (size_t newCapacity);
+  void clear ()
+  {
+    shrink (0);
+  }
+  template < typename U > void append (const U &);
+  void expandCapacity (size_t newMinCapacity);
+  template < typename U > U * expandCapacity (size_t newMinCapacity, U *);
+  size_t m_size;
+  Impl m_impl;
+};
+template < typename T, size_t inlineCapacity >
+  void Vector < T, inlineCapacity >::expandCapacity (size_t newMinCapacity)
+{
+  reserveCapacity (max
+                  (newMinCapacity,
+                   max (static_cast < size_t > (16),
+                        capacity () + capacity () / 4 + 1)));
+}
+
+template < typename T, size_t inlineCapacity >
+  template < typename U >
+  inline U * Vector < T,
+  inlineCapacity >::expandCapacity (size_t newMinCapacity, U * ptr)
+{
+  expandCapacity (newMinCapacity);
+}
+template < typename T, size_t inlineCapacity >
+  void Vector < T, inlineCapacity >::reserveCapacity (size_t newCapacity)
+{
+  m_impl.allocateBuffer (newCapacity);
+}
+template < typename T, size_t inlineCapacity >
+  template < typename U >
+  inline void Vector < T, inlineCapacity >::append (const U & val)
+{
+  const U *ptr = &val;
+  if (size () == capacity ())
+    ptr = expandCapacity (size () + 1, ptr);
+  new (end ())T (*ptr);
+}
+
+class Range;
+class TextIterator
+{
+public:
+  explicit TextIterator (const Range *,
+                        bool emitCharactersBetweenAllVisiblePositions =
+                        false);
+  bool atEnd () const
+  {
+  }
+  void advance ();
+  int length () const
+  {
+  }
+};
+UChar *
+plainTextToMallocAllocatedBuffer (const Range * r, unsigned &bufferLength)
+{
+  static const unsigned cMaxSegmentSize = 1 << 16;
+  typedef pair < UChar *, unsigned >TextSegment;
+  Vector < TextSegment > *textSegments = 0;
+  Vector < UChar > textBuffer;
+  for (TextIterator it (r); !it.atEnd (); it.advance ())
+    {
+      if (textBuffer.size ()
+         && textBuffer.size () + it.length () > cMaxSegmentSize)
+       {
+         UChar *newSegmentBuffer =
+           static_cast <
+           UChar * >(malloc (textBuffer.size () * sizeof (UChar)));
+         if (!textSegments)
+           textSegments = new Vector < TextSegment >;
+         textSegments->
+           append (make_pair (newSegmentBuffer, textBuffer.size ()));
+         textBuffer.clear ();
+       }
+    }
+}