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