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]

[PATCH] Fix PR optimization/11198


Hi,

This is a regression from GCC 3.2.1 present on the 3.3 branch only (but 
latent on mainline). See http://gcc.gnu.org/ml/gcc/2003-07/msg00368.html
for an analysis.

Richard proposed to say that two objects conflict for the purpose of stack 
slots reuse if they have the same alias set. This ensures that distinct 
aggregate types don't conflict, without dwelling on the members of the 
aggregates.

Big thanks to Volker and Wolfgang for reducing the original testcase (1.9 MB) 
to something usable from a debugging viewpoint.

Bootstrapped/regtested on i586-redhat-linux-gnu (3.3 branch except Ada). Ok 
for mainline and 3.3 branch?

-- 
Eric Botcazou


2003-07-06  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
            Eric Botcazou  <ebotcazou@libertysurf.fr>

        PR optimization/11198
	* alias.c (objects_must_conflict_p): Return 1 if the types have
	the same alias set, not if the alias sets only conflict.

2003-07-06  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
            Eric Botcazou  <ebotcazou@libertysurf.fr>

        * g++.dg/opt/stack1.C: New test.
Index: alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/alias.c,v
retrieving revision 1.181.2.1
diff -c -p -r1.181.2.1 alias.c
*** alias.c	7 Jan 2003 20:58:20 -0000	1.181.2.1
--- alias.c	5 Jul 2003 16:01:57 -0000
*************** int
*** 323,328 ****
--- 323,330 ----
  objects_must_conflict_p (t1, t2)
       tree t1, t2;
  {
+   HOST_WIDE_INT set1, set2;
+ 
    /* If neither has a type specified, we don't know if they'll conflict
       because we may be using them to store objects of various types, for
       example the argument and local variables areas of inlined functions.  */
*************** objects_must_conflict_p (t1, t2)
*** 343,357 ****
        || (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2)))
      return 1;
  
!   /* If one is aggregate and the other is scalar then they may not
!      conflict.  */
!   if ((t1 != 0 && AGGREGATE_TYPE_P (t1))
!       != (t2 != 0 && AGGREGATE_TYPE_P (t2)))
!     return 0;
  
!   /* Otherwise they conflict only if the alias sets conflict.  */
!   return alias_sets_conflict_p (t1 ? get_alias_set (t1) : 0,
! 				t2 ? get_alias_set (t2) : 0);
  }
  
  /* T is an expression with pointer type.  Find the DECL on which this
--- 345,359 ----
        || (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2)))
      return 1;
  
!   set1 = t1 ? get_alias_set (t1) : 0;
!   set2 = t2 ? get_alias_set (t2) : 0;
  
!   /* Otherwise they conflict if they have no alias set or the same. We
!      can't simply use alias_sets_conflict_p here, because we must make
!      sure that every subtype of t1 will conflict with every subtype of
!      t2 for which a pair of subobjects of these respective subtypes
!      overlaps on the stack.  */
!   return set1 == 0 || set2 == 0 || set1 == set2;
  }
  
  /* T is an expression with pointer type.  Find the DECL on which this
// PR optimization/11198
// Origin: Joerg Walter <jhr.walter@t-online.de>
// Reduced testcase by: Volker Reichelt <reichelt@igpm.rwth-aachen.de>
//                      Wolfgang Bangerth <bangerth@ticam.utexas.edu>

// The compiler used to allocate the same stack slot for two aggregates,
// overlooking that assignments to members given the same address on the
// stack may not alias and thus may be reordered by the scheduling passes.

// { dg-do run }
// { dg-options "-O2 -frename-registers" }


double zero_;

inline const int&
min(const int& a, const int& b) {
  if (b < a) return b; return a;
}

struct barrier { barrier () {} };

template <typename=void> struct unbounded_array {
    inline unbounded_array (): data_ (new double [9]) {}
    inline double& operator [] (int i) { return data_ [i]; }
    double* data_;
};

inline int element (int i, int j) {
  return i + j;
}

template <typename=void>
struct matrix {
    inline matrix () : size2_ (3) {}

    inline unbounded_array<> &data () { return data_; }

    inline double& el (int i, int j) {
      int dead1 = j;
      int dead2 = 1 + i - j;
      if (j < size2_ && i-j < 2)
	return data () [element (j,i-j+1)];
      barrier ();
      return zero_;
    }

    struct iterator2;

    inline iterator2 find () {
      return iterator2 (*this);
    }

    struct iterator1 {
        inline iterator1 (matrix *m):
			dead1 (m), i (0) {}
	void *dead1;
        int i;
        int dead2;
    };

    const int size2_;
    unbounded_array<> data_;
};


template<typename=void>
struct adaptor {
    adaptor (matrix<> &m) : m(&m), upper_ (1) {}

    int size1 () const     { return m->size1 (); }
    int size2 () const     { return 3; }
    int lower () const     { return 1; }
    int upper () const     { return upper_; }
    matrix<> &data () { return *m; }

    double& el (int i, int j) {
      int dead1, dead2;
      if (j < size2 () && i-j < 1)
	return data ().el (i, j);

      barrier ();
      return zero_;
    }

    struct a_iterator2;

    struct a_iterator1 {
        a_iterator1 (adaptor &a, const matrix<>::iterator1 &it1):
			a (&a), dead1 (it1) {}

        a_iterator2 begin () const {
	  return a_iterator2(*a);
        }
	adaptor *a;	
        matrix<>::iterator1 dead1;
    };

    struct a_iterator2 {
        a_iterator2 (adaptor &a) : a (&a) {}

        double& f () const {
	  int i = 0;
	  int l = a->upper () + i;
	  int q = a->size2 ();
	  if (0 < q &&
	      l < a->lower () + 1 + a->upper ())
	    return a->m->el(0,0);

	  return a->el (i, 0);
        }

	adaptor *a;
    };

    matrix<> *m;
    int upper_;
};

void matrix_swap (adaptor<> &bam1, adaptor<> &bam2)
{
  adaptor<>::a_iterator1 it1 (bam1,matrix<>::iterator1(bam1.m)),
                         it2 (bam2,matrix<>::iterator1(bam2.m));
  int dead;
  double x = it1.begin().f();
  it2.begin().f() = x;
}

int main ()
{
  matrix<> m1,m2;
  adaptor<> bam1 (m1), bam2 (m2);
  matrix_swap (bam1, bam2);
  return 0;
}

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