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