Date: Sat, 27 Feb 2016 17:13:26 -0500
On Fri, Feb 26, 2016 at 1:03 PM, Robert Haberlach <rh633_at_[hidden]> wrote:
> On 02/26/2016 02:26 PM, Hubert Tong wrote:
> > On Fri, Feb 26, 2016 at 7:12 AM, Robert Haberlach <rh633_at_[hidden]
> <mailto:rh633_at_[hidden]>> wrote:
> >
> > I apologize in advance if this was discussed before; I didn't check
> the entire archive. Consider
> >
> > static_assert(alignof(float) >= alignof(int) && sizeof(float) >=
> sizeof(int));
> > int foo(float f) {
> > return *std::launder(reinterpret_cast<int*>(&f)); }
> >
> > As it stands, invocation of foo is undefined, as the argument to
> launder is not pointing to an object of type int (or similar) within its
> lifetime,
> > violating launder's requirement.
> >
> > launder is designed to inhibit address propagation analysis, which
> is the only concerning optimization. Moreover, as long as all usual
> conditions are
> > met (alignment, size & trap values), this should be fine on any
> implementation. If so, can we make the above formally well-defined?
> >
> > This is not fine. Type-based aliasing analysis (TBAA) is allowed to
> determine that the write to "f" and the read from the dereference is not
> related.
> > Consider the effects of inlining:
> > int main(void) { return !foo(0.5f); }
> >
> > becomes (loosely):
> >
> > int main(void) {
> > int __ret;
> > {
> > float __f = 0.5f;
> > __ret = *std::launder(reinterpret_cast<int *>(&__f));
> > }
> > return !__ret;
> > }
> >
> > The implementation is allowed to observe that there are no
> TBAA-compatible reads of the value of __f within its lifetime.
>
> Isn't the whole idea that launder's definition is, to some extent,
> intransparent to optimizers? We're passing a pointer to f into launder. As
> long as
> the analyser is told to assume that calls to launder perform what not, it
> cannot elide the initialization, because launder could read.
>
The definition of launder is *not* opaque to optimizers. It is intended
that launder is well-known to not have side-effects.
> Perhaps launder isn't the right function to base such functionality on,
> anyway (I just had the impression it fitted the picture of an "opaque"
> identity function well). Then my question would rather be if it is
> sensible to provide some function (or language construct), e.g. taking a
> glvalue
> and returning one of a given type, s.t. aliasing via the returned glvalue
> can be well-defined. I don't think there would be great technical obstacles
> in adjusting aliasing analysers to treat such calls accordingly, but it
> would allow for a concise way of disabling strict aliasing for an operation
> while still benefiting from powerful optimization everywhere else.
>
Assuming you mean to use that glvalue directly (as opposed to forming a
pointer or reference binding) to perform said access, then such a construct
makes some sense to me.
>
> Robert
>
> > The likely result is that
> > the initialization of __f would be optimized away.
> >
> > -- HT
> >
> > Being able to use launder in such scenarios would render
> circumlocutions via memcpy superfluous.
> >
> > Robert
> > _______________________________________________
> > ub mailing list
> > ub_at_[hidden] <mailto:ub_at_[hidden]>
> > http://www.open-std.org/mailman/listinfo/ub
> >
> >
> >
> >
> > _______________________________________________
> > ub mailing list
> > ub_at_[hidden]
> > http://www.open-std.org/mailman/listinfo/ub
> >
> _______________________________________________
> ub mailing list
> ub_at_[hidden]
> http://www.open-std.org/mailman/listinfo/ub
>
> On 02/26/2016 02:26 PM, Hubert Tong wrote:
> > On Fri, Feb 26, 2016 at 7:12 AM, Robert Haberlach <rh633_at_[hidden]
> <mailto:rh633_at_[hidden]>> wrote:
> >
> > I apologize in advance if this was discussed before; I didn't check
> the entire archive. Consider
> >
> > static_assert(alignof(float) >= alignof(int) && sizeof(float) >=
> sizeof(int));
> > int foo(float f) {
> > return *std::launder(reinterpret_cast<int*>(&f)); }
> >
> > As it stands, invocation of foo is undefined, as the argument to
> launder is not pointing to an object of type int (or similar) within its
> lifetime,
> > violating launder's requirement.
> >
> > launder is designed to inhibit address propagation analysis, which
> is the only concerning optimization. Moreover, as long as all usual
> conditions are
> > met (alignment, size & trap values), this should be fine on any
> implementation. If so, can we make the above formally well-defined?
> >
> > This is not fine. Type-based aliasing analysis (TBAA) is allowed to
> determine that the write to "f" and the read from the dereference is not
> related.
> > Consider the effects of inlining:
> > int main(void) { return !foo(0.5f); }
> >
> > becomes (loosely):
> >
> > int main(void) {
> > int __ret;
> > {
> > float __f = 0.5f;
> > __ret = *std::launder(reinterpret_cast<int *>(&__f));
> > }
> > return !__ret;
> > }
> >
> > The implementation is allowed to observe that there are no
> TBAA-compatible reads of the value of __f within its lifetime.
>
> Isn't the whole idea that launder's definition is, to some extent,
> intransparent to optimizers? We're passing a pointer to f into launder. As
> long as
> the analyser is told to assume that calls to launder perform what not, it
> cannot elide the initialization, because launder could read.
>
The definition of launder is *not* opaque to optimizers. It is intended
that launder is well-known to not have side-effects.
> Perhaps launder isn't the right function to base such functionality on,
> anyway (I just had the impression it fitted the picture of an "opaque"
> identity function well). Then my question would rather be if it is
> sensible to provide some function (or language construct), e.g. taking a
> glvalue
> and returning one of a given type, s.t. aliasing via the returned glvalue
> can be well-defined. I don't think there would be great technical obstacles
> in adjusting aliasing analysers to treat such calls accordingly, but it
> would allow for a concise way of disabling strict aliasing for an operation
> while still benefiting from powerful optimization everywhere else.
>
Assuming you mean to use that glvalue directly (as opposed to forming a
pointer or reference binding) to perform said access, then such a construct
makes some sense to me.
>
> Robert
>
> > The likely result is that
> > the initialization of __f would be optimized away.
> >
> > -- HT
> >
> > Being able to use launder in such scenarios would render
> circumlocutions via memcpy superfluous.
> >
> > Robert
> > _______________________________________________
> > ub mailing list
> > ub_at_[hidden] <mailto:ub_at_[hidden]>
> > http://www.open-std.org/mailman/listinfo/ub
> >
> >
> >
> >
> > _______________________________________________
> > ub mailing list
> > ub_at_[hidden]
> > http://www.open-std.org/mailman/listinfo/ub
> >
> _______________________________________________
> ub mailing list
> ub_at_[hidden]
> http://www.open-std.org/mailman/listinfo/ub
>
Received on 2016-02-27 23:13:36