https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121685
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Jonathan Wakely from comment #4) > (In reply to Richard Biener from comment #3) > > So even though m_mcowner cannot possibly be bound to nullptr it might still > > bind to a released object? Likewise may it bind to an object of > > insufficient size? > > Not in a correct program. If you access an object through a > std::vector<int>& reference then there must be a valid object of that type > at that location, or you have UB. > > It's OK to form the reference, e.g. via a cast, but not to access the object > through the reference. The usual TBAA rules for pointers. It's OK for a > reference to outlive the object it refers to, but you can't access the > object after its lifetime ends. > > > > So, consider > > > > int *p = new int; > > int &q = *p; > > delete p; > > fun (q, 0); > > > > with > > > > int fun(int &q, int released) { if (!released) return q; return 0; } > > The `return q` statement is undefined behaviour within the f(q,0) call, > because there is no object within its lifetime at that location. > > > or > > > > char c; > > int &q = *(char *)&c; > > The cast is OK, but reading from or writing to q is undefined. > > > alternatively > > > > int *p = (int *)malloc (1); > > int &q = *p; > > The cast is OK, and forming the reference is OK, but reading/writing through > the reference would not be. There is no object of type int at that location, > and the storage is not suitably sized for an int (but malloc does guarantee > it's suitably aligned for an int ... but that's not sufficient to make it > correct). [...] thanks for clarifying, so for the case in question we cannot hoist the access to m_mcowner._M_impl._M_start and make it unconditionally accessed because the access might invoke UB (and thus even trap). For reference, we're talking about the following: void fun(std::vector<int>& blacksq, std::vector<int>& m_mcowner) { for (unsigned int i = 0; i < blacksq.size(); i++) { if (blacksq[i]) { m_mcowner[i]++; } } } apart from the peeling idea DR analysis could still treat the load as invariant for the purpose of analyzing the data access. But the load would have to be materialized conditional somehow. With the intended use of a masked load for m_mcowner[i] that will be a somewhat difficult feat, we'll have to implement the after-the-fact conditionalizing of regions masked with all-zeros directly during vector code gen. Note that if-conversion is unhelpful here in turning the m_mcowner_11(D)->D.27774._M_impl.D.27089._M_start load into a .MASK_LOAD. Note that LLVM happily hoists this load, creating wrong-code.