>>>>> «Martin», Martin von Loewis wrote: Martin> First I found this quite convincing. However, you'll have to keep the Martin> C++ storage model in mind. In order to modify an object through a Martin> pointer, you need to take the address of the object. In you second Martin> example, g++ knows that the address of a, b, and c is never taken, so Martin> it knows that no store operation might modify them (at least not in a Martin> compliant program, non-compliant ones might exhibit unexpected Martin> results). Quite right. Martin> So I modified your last test case to read Martin> inline double& nth_element(double* data, unsigned i) Martin> { return data[i]; } Martin> inline double nth_element(const double* data, unsigned i) Martin> { return data[i]; } Martin> int main() Martin> { Martin> const unsigned n = 1000; Martin> double* a = new double[n]; Martin> double* b = new double[n]; Martin> double* c = new double[n]; Martin> extern void f(double **); Martin> f(&a); Martin> f(&b); Martin> f(&c); Martin> for (unsigned i=0; i nth_element(a, i) = nth_element(static_cast(b), i) Martin> + nth_element(static_cast(c), i); Martin> return 0; Martin> } Martin> That way, g++ has no way of knowing what ::f does with the pointers Martin> it gets. In turn, it generates for the loop: Martin> .LL6: Martin> cmp %o3,999 Martin> bgu .LL7 Martin> ld [%fp-24],%o1 Martin> ld [%fp-28],%o2 Martin> sll %o3,3,%o0 Martin> ldd [%o1+%o0],%f4 Martin> ldd [%o2+%o0],%f2 Martin> faddd %f4,%f2,%f4 Martin> ld [%fp-20],%o1 Martin> add %o3,1,%o3 Martin> b .LL6 Martin> std %f4,[%o1+%o0] Martin> As you can see, it generates these superfluous (sp? sem?) loads. Now, Martin> in C++, the address of almost every object is taken, as it is an Martin> implicit parameter of non-static member functions. So in your first Martin> case, it doesn't know that *this is a loop invariant for a,b, or c. Yep. But, we (and g++ as well) know that the execution of f(&c); is completed before entering the for-loop which doesn't included any other function call whose sided effect is unknown. So my point is: in the for-loop a, b, and c are loop invariants (because, function calls involved are inlined, and the arguments aren't modified); how the semantic could be affected if the loads of a, b, and c were moved out of the loop ? What about this proposal: members functions declared *const*, *inlined* (i.e. g++ does see their definitions) which are *leaf* functions should be subject to code-motion optimization ? -- Gaby