Date: Fri, 26 Feb 2016 09:26:27 -0500
On Fri, Feb 26, 2016 at 7:12 AM, Robert Haberlach <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. 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]
> http://www.open-std.org/mailman/listinfo/ub
>
> 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. 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]
> http://www.open-std.org/mailman/listinfo/ub
>
Received on 2016-02-26 15:26:36