This is the mail archive of the gcc-patches@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]

Re: [PATCH] 34641: Fix find_reloads_address handling of reg_equiv_constant


Hello Uli,

> Can you try changing push_reload to unconditionally abort if either
> IN or OUT are a register equivalent to a constant?

Sure. Done with the attached patch.

I've verified on s390, s390x and x86-64 that the function sizes in the
cc1 executable don't change except for the modified functions
push_reload and find_reloads_address.

Bootstrapped on s390, s390x and x86-64.
Ok for mainline?

Bye,

-Andreas-

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  Andreas Krebbel  <krebbel1@de.ibm.com>

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


Index: gcc/reload.c
===================================================================
*** gcc/reload.c.orig	2008-01-08 16:54:51.000000000 +0100
--- gcc/reload.c	2008-01-09 16:46:48.000000000 +0100
*************** push_reload (rtx in, rtx out, rtx *inloc
*** 922,950 ****
    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 (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];
      }
  
!   /* 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).  */
    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];
      }
  
    /* If we have a read-write operand with an address side-effect,
--- 922,954 ----
    if (outmode == VOIDmode && out != 0)
      outmode = GET_MODE (out);
  
!   /* 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);
  
!       gcc_assert (regno < FIRST_PSEUDO_REGISTER
! 		  || reg_renumber[regno] >= 0
! 		  || reg_equiv_constant[regno] == NULL_RTX);
      }
  
!   /* 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);
  
!       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,
*************** find_reloads_address (enum machine_mode 
*** 4772,4786 ****
      {
        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))
  	{
! 	  *loc = ad = tem;
! 	  return 0;
  	}
  
        tem = reg_equiv_memory_loc[regno];
--- 4776,4787 ----
      {
        regno = REGNO (ad);
  
!       if (reg_equiv_constant[regno] != 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: gcc/testsuite/g++.dg/torture/pr34641.C
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/g++.dg/torture/pr34641.C	2008-01-09 08:50:47.000000000 +0100
***************
*** 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 ();
+ 	}
+     }
+ }


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