<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-01-31 6:56 GMT+01:00 Hal Finkel <span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"><div><div class="h5">
<p><br>
</p>
<div class="m_9181507380244513006moz-cite-prefix">On 01/28/2017 10:36 AM, Piotr Padlewski
wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr"><br>
<div class="gmail_extra"><br>
<div class="gmail_quote">2017-01-26 15:41 GMT+01:00 Hal Finkel
<span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div bgcolor="#FFFFFF"><span class="m_9181507380244513006gmail-">
<p><br>
</p>
<div class="m_9181507380244513006gmail-m_3802625087396114044moz-cite-prefix">On
01/26/2017 06:44 AM, Piotr Padlewski wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr"><br>
<div class="gmail_extra"><br>
<div class="gmail_quote">2017-01-26 3:28
GMT+01:00 Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote"><span>On 25
January 2017 at 15:03, Hal Finkel
via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div bgcolor="#FFFFFF">
<p>Hi Piotr,</p>
<p>I think makes sense. Modulo
bitcasts, the invariant is
identified by a particular
pointer SSA value. Given that
you can't sensibly have two
nonequivalent invariants
associated with the same
pointer SSA value
simultaneously, there's no
need to also identify the
invariant with a metadata
string as well. When we need a
new "identifier" for the
pointed-to value, we get one
using invariant.group.barrier.</p>
</div>
</blockquote>
<div><br>
</div>
</span>
<div>As I recall, the original
motivation for the identifier was to
support cases where the "invariant"
region's value changes and then
changes back (remember that
invariant.group does not imply the
storage doesn't change, just that a
particular set of loads and stores
witness the same value):</div>
<div><br>
</div>
<div>struct A { void *vptr; /*...*/ };</div>
<div>struct B { void *vptr; /*...*/ };</div>
<div>union U { A a; B b; };</div>
<div><br>
</div>
<div>void f(U *u) {</div>
<div> // #1, load A vptr</div>
<div> load u->a.vptr, !invariant
"A::vptr"</div>
<div> // #2, change union member to B
...</div>
<div> store u->b.vptr, !invariant
"B::vptr"</div>
<div> // #3, change union member back
to A ...</div>
<div> f(u); // performs: store
u->a.vptr, !invariant "A::vptr"</div>
<div> // #4, load A vptr again, can
be forwarded from #1 but not from #2</div>
<div> load u->a.vptr, !invariant
"A::vptr"</div>
<div>}</div>
<div><br>
</div>
</div>
</div>
</div>
</blockquote>
<div>Excellent point, I forgot that one don't
have to call placement new in order to
emplace different type.</div>
<div>I discussed it with Krzysztof and we
belive the best way to solve it is to
introduce barriers before every use of union
if it contains any polymorphic class
(recursively for each class in union). This
might look very bad, but assuming we will be
able skip barrier for optimizations not
relying on !invariant.group, then it will
not pessimize anything. <br>
</div>
</div>
</div>
</div>
</blockquote>
<br>
</span> In light of this, can we go back and reevaluate
your list of proposed solutions? You pointed out two
problems:<br>
1. "This works well if the pointer type doesn’t change,
but when it does, devirtualization might not happen"
(e.g. a conversion to a base-class pointer/reference).<br>
2. "The other problem is that when we combine 2
instructions with different invariant.group metadata,
then we pick one of them, because for now we can have
only single !invariant.group metadata."<br>
<br>
Given what's been said, I'm leaning toward favoring
solution (b), "having sub invariant groups - like
inheritance, so we could figure out that one group is
subgroup of another" because 1) it seems to solve both
problems and 2) it seems like we could get all of the
non-trivial logic (for generation, comparison, and
merging) from our TBAA implementation (we might even be
able to directly reuse the same metadata).<span class="m_9181507380244513006gmail-HOEnZb"><font color="#888888"><br>
<br>
-Hal</font></span>
<div>
<div class="m_9181507380244513006gmail-h5"><br>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>I was thinking about this, and as long as I think about
it I am convincing myself that different groups, or even
sub groups that you have mentioned,</div>
<div>will have no use for const memory propagation. In the
future we probably would like to decorate const member
loads and </div>
<div>stores with<b> !invariant.group</b> (or <b>!invariant</b>
if groups will be removed [if name will change :P]). </div>
<div><br>
</div>
<div>In order to decorate const members, we will need to
insert barrier before <b>every</b> use of union member.</div>
<div>So I was thinking about this example: <a href="https://godbolt.org/g/iSUjKD" target="_blank">https://godbolt.org/g/iSUjKD</a>
but it doesn't compile, but Krzysztof figured out this
one:</div>
<div><a href="https://godbolt.org/g/lYQFBd" target="_blank">https://godbolt.org/g/lYQFBd</a>
(BTW it seems that clang is pretty bad at cleaning out
iostreams)<br>
</div>
<div><font face="monospace, monospace"><br>
</font></div>
<div>
<div>
<pre style="color:rgb(51,51,51);margin-top:0px;margin-bottom:0px;line-height:16.25px"><font face="monospace, monospace"><span style="color:rgb(0,136,0);font-weight:bold">struct</span> A {
<span style="color:rgb(0,136,0);font-weight:bold">const</span> <span style="color:rgb(51,51,153);font-weight:bold">int</span> x;
};
<span style="color:rgb(0,136,0);font-weight:bold">union</span> B {
A a1;
A a2;
B() : a1{<span style="color:rgb(0,0,221);font-weight:bold">42</span>} { }
<span style="color:rgb(51,51,153);font-weight:bold">void</span> switch2(<span style="color:rgb(51,51,153);font-weight:bold">int</span> x) {
a1.~A();
<span style="color:rgb(0,136,0);font-weight:bold">new</span> (&a2) A{x};
}
};
<span style="color:rgb(51,51,153);font-weight:bold">int</span> <span style="color:rgb(0,102,187);font-weight:bold">main</span>() {
B b;
std::cout << b.a1.x << std::endl;
b.switch2(<span style="color:rgb(0,0,221);font-weight:bold">50</span>);
std::cout << b.a2.x << std::endl;
}</font></pre>
<pre style="color:rgb(51,51,51);margin-top:0px;margin-bottom:0px;line-height:16.25px"><font face="monospace, monospace">
</font></pre>
</div>
</div>
<div>As he checked in standard, it seems to be valid C++11
code by <b>9.5.4</b>. </div>
<div>So as you can see different groups won't gonna work in
case of const members inside union, like:</div>
<div><br>
</div>
<div>
<pre style="color:rgb(51,51,51);margin-top:0px;margin-bottom:0px;line-height:16.25px"><font face="monospace, monospace"><span style="color:rgb(51,51,153);font-weight:bold">int</span> <span style="color:rgb(0,102,187);font-weight:bold">main</span>() {
B b;
std::cout << b.a1.x << std::endl;
b.switch2(<span style="color:rgb(0,0,221);font-weight:bold">50</span>);
std::cout << b.a2.x << std::endl;
b.switch2(<span style="color:rgb(0,0,221);font-weight:bold">51</span>);
std::cout << b.a2.x << std::end; <span style="color:rgb(136,136,136)">// This is not 50, as we would thought based on invariant.groups</span>
}</font></pre>
</div>
<div><br>
</div>
<div><br>
</div>
<div>I am not familiar with the TBAA implementation, but
after digging more int MSSA, I have other reason to not
like the sub groups. </div>
<div>It might be pretty hard to handle them efficiently in
many algorithms including MSSA.</div>
</div>
</div>
</div>
</blockquote>
<br></div></div>
I don't see why. TBAA is handled just fine (including in MSSA); it
is just a more-complicated pair-compatibility rule.<span class=""><br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div><br>
</div>
<div>Hal, what are the things that you dislike about the
emitting barriers everywhere for unions?</div>
</div>
</div>
</div>
</blockquote>
<br></span>
I was thinking about Richard's point about the
changing-and-then-changing-<wbr>back scenario, plus I wonder how these
barriers affect optimizations. We don't seem to look through
invariant_group_barrier in stripPointerCasts, BasicAA, etc. because
int_invariant_group_barrier does not have Returned<0> on the
definition in include/llvm/IR/Intrinsics.td. We can fix that, but we
need to be very careful not to remove the dependence on the
barrier's return value, and maybe that's the right solution, but
even so, it just makes me wonder if there's a way without the
barriers. <br>
<br>
Thanks again,<br>
Hal<div><div class="h5"><br></div></div></div></blockquote><div>So we need barriers anyway, and the different groups are not sufficient for optimizations like const propagation of const member (like in Krzysztof's example with unions).</div><div>Right now no optimization skips invariant barriers (no optimizations uses the fact that barrier returns the same pointer), but many treat barrier as function not modyfing any memory.</div><div>I am working on the patch for MSSA to use the same memory use as the dominating load/store etc. With this it will skip the invariant.groups at least for MSSA. <br></div><div>We will still need to handle it in many passes, but I am sure we will be able to make it work so it won't pesimize anything. I don't see the <b>-fstrict-vtable-pointes</b> being default option without it.</div><div><br></div><div>Piotr </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div bgcolor="#FFFFFF" text="#000000"><div><div class="h5">
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div>It only seems to be very heavy, but I am pretty sure we
can get to the point where we will be able to</div>
<div>delete barriers when we can, and teach optimizations
and analysis how to skip them, so they will not pesimize
any code.</div>
<div><br>
</div>
<div><br>
</div>
<div><b>TL;DR </b></div>
<div>different groups works for devirtualization, but it is
seem to not be a general way to go with "invariant"
things.</div>
<div><br>
</div>
<div>Piotr</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div bgcolor="#FFFFFF">
<div>
<div class="m_9181507380244513006gmail-h5"> <br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div><br>
</div>
<div> <br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div>However, I don't immediately
see a way in which the C++ object
model would require us to track
multiple distinct groups of loads
and stores, so if it isn't useful
to be able to do that outside of
C++ vptr / const member invariant
tracking, I think we can remove
it.</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>It should not make optimizations in
LLVM any harder with group or without, so
I will postpone the removal of groups for
some time.</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845h5">
<div bgcolor="#FFFFFF">
<p> -Hal<br>
</p>
<div>
<div class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-h5">
<br>
<div class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-m_8071376148364838946moz-cite-prefix">On
01/24/2017 01:39 PM,
Piotr Padlewski via
llvm-dev wrote:<br>
</div>
</div>
</div>
<blockquote type="cite">
<div>
<div class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-h5">
<div dir="ltr">Hi,
<div>I would really
like to hear some
feedback about
this.</div>
<div><br>
</div>
<div>Piotr</div>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">2017-01-20
17:07 GMT+01:00
Piotr Padlewski <span dir="ltr"><<a href="mailto:piotr.padlewski@gmail.com" target="_blank">piotr.padlewski@gmail.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr"><span id="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-m_8071376148364838946m_3685817574736257236gmail-docs-internal-guid-f4b3e122-bc9b-30cb-5204-c95e1095750e">
<p dir="ltr" style="text-align:left;line-height:1.38;margin-top:0pt;margin-bottom:3pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:arial;font-size:14.6667px;white-space:pre-wrap">Hi all,</span></p>
<p dir="ltr" style="text-align:left;line-height:1.38;margin-top:0pt;margin-bottom:3pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:arial;font-size:14.6667px;white-space:pre-wrap">I would like to propose a new way clang would decorate vtable loads in order to handle devirtualization better.</span></p>
<p dir="ltr" style="text-align:left;line-height:1.38;margin-top:0pt;margin-bottom:3pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:arial;font-size:14.6667px;white-space:pre-wrap">I've added <b>llvm-dev</b> also, because this can start a discussion about changing invariant.group to just invariant. </span></p>
<p dir="ltr" style="text-align:left;line-height:1.38;margin-top:0pt;margin-bottom:3pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:arial;font-size:14.6667px;white-space:pre-wrap">PDF version of this RFC can be found here:</span></p>
<p dir="ltr" style="text-align:left;line-height:1.38;margin-top:0pt;margin-bottom:3pt"><a href="https://drive.google.com/file/d/0B72TmzNsY6Z8ZmpOUnB5dDZfSFU/view?usp=sharing" style="font-size:14.6667px;white-space:pre-wrap;font-family:arial;background-color:transparent" target="_blank">https://drive.google.com/file/<wbr>d/0B72TmzNsY6Z8ZmpOUnB5dDZfSFU<wbr>/view?usp=sharing</a></p><h2 style="line-height:1.38;margin-top:18pt;margin-bottom:6pt"><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:arial;font-size:21.3333px;font-weight:400;white-space:pre-wrap">
</span></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="background-color:transparent;color:rgb(0,0,0);font-family:arial;font-size:21.3333px;font-weight:400;white-space:pre-wrap">Background:</span>
</p></h2><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">Initial old design:</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><a href="http://lists.llvm.org/pipermail/cfe-dev/2015-July/044227.html" style="text-decoration:none" target="_blank"><span style="font-size:14.6667px;font-family:arial;background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">http://lists.llvm.org/pipermai<wbr>l/cfe-dev/2015-July/044227.htm<wbr>l</span></a></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">My talk from LLVM Dev Meeting</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"><a href="http://llvm.org/devmtg/2016-11/#talk6" target="_blank">http://llvm.org/devmtg/2016-11<wbr>/#talk6</a></span></p>
<h2 dir="ltr" style="line-height:1.38;margin-top:18pt;margin-bottom:6pt"><span style="font-size:21.3333px;font-family:arial;color:rgb(0,0,0);background-color:transparent;font-weight:400;vertical-align:baseline;white-space:pre-wrap">The problem</span></h2><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">Clang with </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">-fstrict-vtable-pointers </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">decorates vtable loads with metadata corresponding to mangled pointer type name like:</span></p>
<p dir="ltr" style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,102,187);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">g</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">(A& a){</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> a.foo();</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">}</span></p>
<p dir="ltr" style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">define </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(255,0,0);background-color:rgb(255,170,170);vertical-align:baseline;white-space:pre-wrap">@</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">_Z1gR1A(%</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A* dereferenceable(</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">8</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">) %a) local_unnamed_addr </span><span style="font-size:14.6667px;font-family:arial;color:rgb(255,0,0);background-color:rgb(255,170,170);vertical-align:baseline;white-space:pre-wrap">#</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">0</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> {</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(153,119,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">entry:</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> %</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">0</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> = bitcast %</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A* %a to </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> (%</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A*)***</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> %vtable = load </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> (%</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A*)**, </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> (%</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A*)*** %</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">0</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">, !invariant.group !</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">7</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> %</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">1</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> = load </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> (%</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A*)*, </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> (%</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A*)** %vtable</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> tail call </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> %</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">1</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">(%</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">.A* nonnull %a)</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> ret </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">}</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">!</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,221);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">7</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> = !{!</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:rgb(255,240,240);vertical-align:baseline;white-space:pre-wrap">"_ZTS1A"</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">}</span></p>
<p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">This works well if the pointer type doesn’t change, but when it does, devirtualization might not happen like here:</span></p>
<p dir="ltr" style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> A {</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> A();</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">virtual</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,102,187);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">foo</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">();</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">};</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> B : A{</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> B();</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,136,0);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">virtual</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,102,187);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">foo</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">();</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">};</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,102,187);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">g</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">(A& a){</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> a.foo();</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> a.foo();</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">}</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,102,187);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">clobber</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">(A&);</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:14.6667px;font-family:arial;color:rgb(0,102,187);background-color:transparent;font-weight:700;vertical-align:baseline;white-space:pre-wrap">f</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">() {</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> B b;</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> clobber(b);</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"> g(b);</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span><span style="font-size:14.6667px;font-family:arial;color:rgb(51,51,51);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">}</span></p>
<p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">The other problem is that when we combine 2 instructions with different invariant.group metadata, then we pick one of them, because for now we can have only single !invariant.group metadata.</span></p>
<h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:26.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;font-weight:400;vertical-align:baseline;white-space:pre-wrap">The solution</span></h1><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">I had some initial ideas how it can be solved, like </span></p><ol style="margin-top:0pt;margin-bottom:0pt"><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap">introducing multi invariant groups</span></p></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap">having sub invariant groups - like inheritance, so we could figure out that one group is subgroup of another</span></p></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap">decorating all loads with base pointer MD (doesn’t work with multiple inheritance)</span></p></li></ol>
<p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">I consulted my ideas with Krzysztof Pszeniczny, and he proposed something much simpler: we can decorate every invariant.group md with empty metadata.</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">This should work because the lifetime of the object is strictly defined by invariant.group.barrier.</span></p>
<p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">If this holds, we can start discussion about if it makes sense to keep invariant groups, and instead have just “invariant”, that would be equivalent to having invariant.group with the same metadata.</span></p>
<p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">Do you have some thoughts about this approach? I don’t have a mathematical proof, but I am confident that it should be valid.</span></p><div><span style="font-size:14.6667px;font-family:arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap">
</span></div></span></div>
</blockquote></div>
</div>
<fieldset class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-m_8071376148364838946mimeAttachmentHeader"></fieldset>
</div></div><pre>______________________________<wbr>_________________
LLVM Developers mailing list
<a class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-m_8071376148364838946moz-txt-link-abbreviated" href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>
<a class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-m_8071376148364838946moz-txt-link-freetext" href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-dev</a><span class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-HOEnZb"><font color="#888888">
</font></span></pre><span class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-HOEnZb"><font color="#888888">
</font></span></blockquote><span class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-HOEnZb"><font color="#888888">
<pre class="m_9181507380244513006gmail-m_3802625087396114044m_2260526803923265845m_-5474282151935520877gmail-m_8071376148364838946moz-signature" cols="72">--
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre></font></span></div>
</div></div>______________________________<wbr>_________________
cfe-dev mailing list
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a>
</blockquote></div>
</div></div>
</blockquote></div>
</div></div>
</blockquote>
<pre class="m_9181507380244513006gmail-m_3802625087396114044moz-signature" cols="72">--
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre></div></div></div></blockquote></div>
</div></div>
</blockquote>
<pre class="m_9181507380244513006moz-signature" cols="72">--
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre></div></div></div></blockquote></div><br></div></div>