https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86619
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |alias, missed-optimization Status|UNCONFIRMED |NEW Last reconfirmed| |2018-07-23 CC| |rguenth at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- type-based alias analysis doesn't distinguish between int[2] and int[3]. The issue with operator[] is that the FE produces ;; Function T& ar<T, size>::operator[](size_t) [with T = int; long unsigned int size = 2; size_t = long unsigned int] (null) ;; enabled by -tree-original return <retval> = (int &) &((struct ar *) this)->ar[offset]; and <<cleanup_point <<< Unknown tree: expr_stmt (void) (*ar<int, 3>::operator[] ((struct ar *) a, 0) = 1) >>>>>; <<cleanup_point <<< Unknown tree: expr_stmt (void) (*ar<int, 2>::operator[] ((struct ar *) b, 0) = 2) >>>>>; <<cleanup_point return <retval> = *ar<int, 3>::operator[] ((struct ar *) a, 0)>>; which after inlining is int & _6; int & _9; <bb 2> : _6 = &a_5(D)->ar[0]; *_6 = 1; _9 = &b_8(D)->ar[0]; *_9 = 2; _11 = &a_5(D)->ar[0]; _12 = *_11; return _12; compared to f1 (struct ar & a, struct ar & b) { int _6; <bb 2> : a_2(D)->ar[0] = 1; b_4(D)->ar[0] = 2; _6 = a_2(D)->ar[0]; return _6; here TBAA only sees int & accesses which do conflict and points-to analysis is TBAA agnostic and cannot disambiguate a_5(D) and b_8(D). For f1 TBAA sees structure accesses and can disambiguate. C++ abstraction makes it harder to optimize here. You get two accesses of effective type int vs. one of ar<int, 2> and one of ar<int, 3>. Way in the past points-to had some bits of TBAA, eventually we can re-introduce bits here but the TBAA bits did not play well with the points-to solver and created wrong-code. Note there isn't really a way to tell the middle-end that a pointed to object is of a specific dynamic type. Eventually we can play leeway and make REFERENCE_TYPE parameters behave that way.