1*c87b03e5Sespie // PR optimization/11198
2*c87b03e5Sespie // Origin: Joerg Walter <jhr.walter@t-online.de>
3*c87b03e5Sespie // Reduced testcase by: Volker Reichelt <reichelt@igpm.rwth-aachen.de>
4*c87b03e5Sespie //                      Wolfgang Bangerth <bangerth@ticam.utexas.edu>
5*c87b03e5Sespie 
6*c87b03e5Sespie // The compiler used to allocate the same stack slot for two aggregates,
7*c87b03e5Sespie // overlooking that assignments to members given the same address on the
8*c87b03e5Sespie // stack may not alias and thus may be reordered by the scheduling passes.
9*c87b03e5Sespie 
10*c87b03e5Sespie // { dg-do run }
11*c87b03e5Sespie // { dg-options "-O2 -frename-registers" }
12*c87b03e5Sespie 
13*c87b03e5Sespie 
14*c87b03e5Sespie double zero_;
15*c87b03e5Sespie 
16*c87b03e5Sespie inline const int&
min(const int & a,const int & b)17*c87b03e5Sespie min(const int& a, const int& b) {
18*c87b03e5Sespie   if (b < a) return b; return a;
19*c87b03e5Sespie }
20*c87b03e5Sespie 
barrierbarrier21*c87b03e5Sespie struct barrier { barrier () {} };
22*c87b03e5Sespie 
23*c87b03e5Sespie template <typename=void> struct unbounded_array {
unbounded_arrayunbounded_array24*c87b03e5Sespie     inline unbounded_array (): data_ (new double [9]) {}
25*c87b03e5Sespie     inline double& operator [] (int i) { return data_ [i]; }
26*c87b03e5Sespie     double* data_;
27*c87b03e5Sespie };
28*c87b03e5Sespie 
element(int i,int j)29*c87b03e5Sespie inline int element (int i, int j) {
30*c87b03e5Sespie   return i + j;
31*c87b03e5Sespie }
32*c87b03e5Sespie 
33*c87b03e5Sespie template <typename=void>
34*c87b03e5Sespie struct matrix {
matrixmatrix35*c87b03e5Sespie     inline matrix () : size2_ (3) {}
36*c87b03e5Sespie 
datamatrix37*c87b03e5Sespie     inline unbounded_array<> &data () { return data_; }
38*c87b03e5Sespie 
elmatrix39*c87b03e5Sespie     inline double& el (int i, int j) {
40*c87b03e5Sespie       int dead1 = j;
41*c87b03e5Sespie       int dead2 = 1 + i - j;
42*c87b03e5Sespie       if (j < size2_ && i-j < 2)
43*c87b03e5Sespie 	return data () [element (j,i-j+1)];
44*c87b03e5Sespie       barrier ();
45*c87b03e5Sespie       return zero_;
46*c87b03e5Sespie     }
47*c87b03e5Sespie 
48*c87b03e5Sespie     struct iterator2;
49*c87b03e5Sespie 
findmatrix50*c87b03e5Sespie     inline iterator2 find () {
51*c87b03e5Sespie       return iterator2 (*this);
52*c87b03e5Sespie     }
53*c87b03e5Sespie 
54*c87b03e5Sespie     struct iterator1 {
iterator1matrix::iterator155*c87b03e5Sespie         inline iterator1 (matrix *m):
56*c87b03e5Sespie 			dead1 (m), i (0) {}
57*c87b03e5Sespie 	void *dead1;
58*c87b03e5Sespie         int i;
59*c87b03e5Sespie         int dead2;
60*c87b03e5Sespie     };
61*c87b03e5Sespie 
62*c87b03e5Sespie     const int size2_;
63*c87b03e5Sespie     unbounded_array<> data_;
64*c87b03e5Sespie };
65*c87b03e5Sespie 
66*c87b03e5Sespie 
67*c87b03e5Sespie template<typename=void>
68*c87b03e5Sespie struct adaptor {
adaptoradaptor69*c87b03e5Sespie     adaptor (matrix<> &m) : m(&m), upper_ (1) {}
70*c87b03e5Sespie 
size1adaptor71*c87b03e5Sespie     int size1 () const     { return m->size1 (); }
size2adaptor72*c87b03e5Sespie     int size2 () const     { return 3; }
loweradaptor73*c87b03e5Sespie     int lower () const     { return 1; }
upperadaptor74*c87b03e5Sespie     int upper () const     { return upper_; }
dataadaptor75*c87b03e5Sespie     matrix<> &data () { return *m; }
76*c87b03e5Sespie 
eladaptor77*c87b03e5Sespie     double& el (int i, int j) {
78*c87b03e5Sespie       int dead1, dead2;
79*c87b03e5Sespie       if (j < size2 () && i-j < 1)
80*c87b03e5Sespie 	return data ().el (i, j);
81*c87b03e5Sespie 
82*c87b03e5Sespie       barrier ();
83*c87b03e5Sespie       return zero_;
84*c87b03e5Sespie     }
85*c87b03e5Sespie 
86*c87b03e5Sespie     struct a_iterator2;
87*c87b03e5Sespie 
88*c87b03e5Sespie     struct a_iterator1 {
a_iterator1adaptor::a_iterator189*c87b03e5Sespie         a_iterator1 (adaptor &a, const matrix<>::iterator1 &it1):
90*c87b03e5Sespie 			a (&a), dead1 (it1) {}
91*c87b03e5Sespie 
beginadaptor::a_iterator192*c87b03e5Sespie         a_iterator2 begin () const {
93*c87b03e5Sespie 	  return a_iterator2(*a);
94*c87b03e5Sespie         }
95*c87b03e5Sespie 	adaptor *a;
96*c87b03e5Sespie         matrix<>::iterator1 dead1;
97*c87b03e5Sespie     };
98*c87b03e5Sespie 
99*c87b03e5Sespie     struct a_iterator2 {
a_iterator2adaptor::a_iterator2100*c87b03e5Sespie         a_iterator2 (adaptor &a) : a (&a) {}
101*c87b03e5Sespie 
fadaptor::a_iterator2102*c87b03e5Sespie         double& f () const {
103*c87b03e5Sespie 	  int i = 0;
104*c87b03e5Sespie 	  int l = a->upper () + i;
105*c87b03e5Sespie 	  int q = a->size2 ();
106*c87b03e5Sespie 	  if (0 < q &&
107*c87b03e5Sespie 	      l < a->lower () + 1 + a->upper ())
108*c87b03e5Sespie 	    return a->m->el(0,0);
109*c87b03e5Sespie 
110*c87b03e5Sespie 	  return a->el (i, 0);
111*c87b03e5Sespie         }
112*c87b03e5Sespie 
113*c87b03e5Sespie 	adaptor *a;
114*c87b03e5Sespie     };
115*c87b03e5Sespie 
116*c87b03e5Sespie     matrix<> *m;
117*c87b03e5Sespie     int upper_;
118*c87b03e5Sespie };
119*c87b03e5Sespie 
matrix_swap(adaptor<> & bam1,adaptor<> & bam2)120*c87b03e5Sespie void matrix_swap (adaptor<> &bam1, adaptor<> &bam2)
121*c87b03e5Sespie {
122*c87b03e5Sespie   adaptor<>::a_iterator1 it1 (bam1,matrix<>::iterator1(bam1.m)),
123*c87b03e5Sespie                          it2 (bam2,matrix<>::iterator1(bam2.m));
124*c87b03e5Sespie   int dead;
125*c87b03e5Sespie   double x = it1.begin().f();
126*c87b03e5Sespie   it2.begin().f() = x;
127*c87b03e5Sespie }
128*c87b03e5Sespie 
main()129*c87b03e5Sespie int main ()
130*c87b03e5Sespie {
131*c87b03e5Sespie   matrix<> m1,m2;
132*c87b03e5Sespie   adaptor<> bam1 (m1), bam2 (m2);
133*c87b03e5Sespie   matrix_swap (bam1, bam2);
134*c87b03e5Sespie   return 0;
135*c87b03e5Sespie }
136