<div dir="ltr">Hi John,<br><div class="gmail_extra"><br><div class="gmail_quote">2018-03-28 23:23 GMT+02:00 John McCall <span dir="ltr"><<a href="mailto:rjmccall@apple.com" target="_blank">rjmccall@apple.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 style="word-wrap:break-word"><br><div><br><blockquote type="cite"><div>On Mar 19, 2018, at 7:27 PM, Piotr Padlewski via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:</div><br class="m_1414337835050969498gmail-m_7271471833428658469Apple-interchange-newline"><div><div dir="ltr">Hi folks,<div><br></div><div>here is a link to the proposal that we've been working on lately:</div><div><a href="https://docs.google.com/document/d/16GVtCpzK8sIHNc2qZz6RN8amICNBtvjWUod2SujZVEo/edit?usp=sharing" target="_blank">https://docs.google.com/docume<wbr>nt/d/16GVtCpzK8sIHNc2qZz6RN8am<wbr>ICNBtvjWUod2SujZVEo/edit?usp=s<wbr>haring</a><br></div><div><br></div><div>But for the record, I also paste it here. Feedback will be really appreciated!</div><div><br></div><div><br></div><div><b style="font-weight:normal" id="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-docs-internal-guid-a43ba0b5-406d-36b9-4e30-86e8c95f392a"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:3pt;text-align:center"><span style="font-size:26pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">RFC: C++ Devirtualization v2</span></p><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:center"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Piotr Padlewski - </span><a href="mailto:piotr.padlewski@gmail.com" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">piotr.padlewski@gmail.com</span></a></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:center"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Krzysztof Pszeniczny - </span><a href="mailto:krzysztof.pszeniczny@gmail.com" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">krzysztof.pszeniczny@gmail.com</span></a></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:center"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Jakub Kuderski - </span><a href="mailto:kubakuderski@gmail.com" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">kubakuderski@gmail.com</span></a></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:center"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Richard Smith - </span><a href="mailto:RichardSmith@google.com" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">RichardSmith@google.com</span></a></div><br><br><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">This proposal describes a new model of representing pointers to dynamic objects as “fat pointers”. It is designed to solve the hole in the previous devirtualization model that could cause miscompilation. We believe that solving this is very important, especially with the mitigation of the recent Spectre vulnerability - retpolines.</span></div><br><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Introduction to previous devirtualization</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">In the previous model we introduced </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">invariant.group </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">to LLVM as a way of saying “this load will produce the same value if given the same argument”, which was  applied on loads from virtual pointer to communicate that virtual pointer (or in other words, dynamic type) does not change during the lifetime of an object. Because virtual pointer might be set multiple times during construction and destruction of derived types, and because it is possible to change the dynamic type of an object using placement new, </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">invariant.group.barrier </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">was introduced. It is used in every place where the dynamic type might change. To turn devirtualization on user had to specify the </span><span style="font-size:11pt;font-family:Consolas;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">-fstrict-vtable-pointers</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> flag for clang. </span></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">If you want to learn more about the previous model, check out [0][1][2][3]. Although the previous model is not sound for C++, languages like Java or Scala can safely use it. This is because virtual pointer in Java is set only once for every dynamic type, and you can’t do things like placement new, which means 2 aliasing pointers will always have the same dynamic type (also because every pointer still points to a valid object).</span></div><br><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">The problem</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">The old model miscompiles on the following example:</span></div><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">A *a = new A;</span></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">a->foo(); </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">A *b = new(a) B;</span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">if (a == b)</span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  b->foo(); // This call could be devirtualized to </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(255,0,0);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">A::foo()</span></div><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">The problem is that GVN and other pass replaces the SSA value of </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">b</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> with </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">a </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">based on the </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">a==b</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> comparison, which is a totally legal optimization in LLVM and we surely still want to do it. In C++ however, If you replaced </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">b </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">with </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">a </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">inside the if statement’s body, then you would introduce UB. The problem arises because after changing %b to %a in LLVM, the load from virtual pointer can be devirtualized to different type. </span></div><br><div style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%vtable_a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">load</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">!invariant.group</span></div><div style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">;;;</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">; %a == %b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%bool</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">icmp</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">br</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%bool</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%if</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%after</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,119,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">if:</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">; if this will be changed to %a, then the optimizer will be able to replace </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">; %vtable_b with %vtable_a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%vtable_b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">load</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">!invariant.group</span></div><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">For other corner cases check out appendix.</span></div><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Solution</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">The proposed solution is to model pointers to dynamic types as “fat pointers”. We can think of them as pointers that also store the current dynamic type. Virtual calls would consist of virtual pointer load from fat pointer. We will still use invariant.groups for the devirtualization. The difference is that accessing class field, or comparing pointers to dynamic objects would require a call to a new intrinsic - </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">i8* llvm.strip.invariant.group(i8* )</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> to firstly get pointer without information about dynamic type. Creation (or reloading) of fat pointer would be done by call to new intrinsic - </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">i8* llvm.launder.invariant.group(i<wbr>8*)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> that </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">replaces </span><span style="font-size:11pt;font-family:Arial;color:rgb(255,0,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">llvm.invariant.group.barrier</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">.</span></div><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">The pointer comparison will now not be an issue, because the optimizer will not be able to replace the operand of a virtual pointer load with another pointer:</span></div><br><br><div style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%vtable_a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">load</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">i8</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">* </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">!invariant.group</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> !{}</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">;;;</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">; %a == %b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%addr_a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = call i8* @</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">llvm.strip.invariant.group</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">(i8<wbr>* %a)</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%addr_b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = call i8* @</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">llvm.strip.invariant.group</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">(i8<wbr>* %b)</span></div><div style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%bool</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">icmp</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%addr_a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%addr_b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">br</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%bool</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%if</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%after</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,119,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">if:</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">; This will not be able to change %b to %a</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%vtable_b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> = </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">load</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(0,136,0);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">i8</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">* </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">%b</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(153,102,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">!invariant.group</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> !{}</span></div><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">It is important to notice that vtable load of %b cannot be replaced with a load of %addr_b Although the optimizer could potentially figure out that %b and %addr_b are aliasing, the aliasing rules are not strong enough to make this transformation valid. One counterexample could be that although both pointers are pointing to the same memory, one could be a pointer to mmap’ed memory with no write/load permission.</span></div><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt;text-align:justify"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">The Solution formalized</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Formally, to virtually mark pointers as optionally belonging to invariant groups subject to the following rules:</span></div><ul style="margin-top:0pt;margin-bottom:0pt"><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">alloca</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> and library </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">malloc</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">-like functions return pointers belonging to fresh invariant groups</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">belonging to an invariant group is preserved by bitcasts</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">an intrinsic, </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">i8* llvm.strip.invariant.group(i8*<wbr>)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> returns its argument with the invariant group virtual metadata stripped</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">an intrinsic, </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">i8* llvm.launder.invariant.group(i<wbr>8*)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> returns its argument with a fresh invariant group virtual metadata, i.e. it starts a new invariant group. This is similar to C++'s </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">std::launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">.</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">every load and store marked </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">!invariant.group</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> from/to pointers belonging to the same invariant group must load/store the same value</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">the behaviour of a load or store marked </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">!invariant.group</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> from/to pointers not belonging to any invariant group (e.g. obtained from </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">llvm.strip.invariant.group</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">) is undefined</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">constructors may assume the </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">this</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> pointer passed to them belongs to a fresh invariant group</span></div></li></ul><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">From those rules one easily gets:</span></div><ul style="margin-top:0pt;margin-bottom:0pt"><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">llvm.strip.invariant.group</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> is a pure function, i.e. its value depends only on its argument. Its llvm attributes include at least: </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">readnone speculatable nounwind</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">. Its results must alias its argument.</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">llvm.launder.invariant.group</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> is </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">not</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> a pure function: it creates a fresh invariant group each time it's called. One may mentally model this as getting a fresh invariant group identifier somewhere from a 'magic' memory inaccessible to no-one else, so its llvm attributes include at least: </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">inaccessiblememonly speculatable nounwind</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">. Its results must alias its argument.</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip({strip,launder}(X)) = strip(X)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">. This is because we do not care which particular invariant group metadata is stripped.</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder({strip,launder}(X))</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> may be replaced with </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder(X)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> by the optimiser. Note that this not mean that </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder(launder(X)) = launder(X)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">in the IR itself, but only on a metalanguage level: </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> is inherently nondeterministic, so no two invocations of it ever return the same value.</span></div></li></ul><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">This allows to compile the following C++ constructs:</span></div><ul style="margin-top:0pt;margin-bottom:0pt"><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">vtable loads required to perform virtual calls are marked with </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">!invariant.group</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, as before</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">constructors of derived classes need to </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> the </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">this</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> pointer before passing it to the constructors of base classes: they may subsequently operate on the original </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">this</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> pointer</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">likewise, destructors of derived classes need to </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> the </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">this</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> pointer before passing it to the destructors of base classes</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">placement </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">new</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> and </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">std::launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> need to call </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">accesses to union members need to call </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, because the active member of the union may have changed since the last visible access</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">whenever two pointers are to be compared, they must be </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">ped first, because we want the comparison to provide information about the address equality, and not about invariant group equality</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">likewise, whenever a pointer is to be cast to an integer type, it must be </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">ped first</span></div></li><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">whenever an integer is cast to a pointer type, the result must be </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">ed before it is used, to prevent reasoning about the equality of integers to provide any information about equality of invariant groups</span></div></li></ul><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Note that adding calls to </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> and </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> related to pointer comparisons and integer<->pointer conversions will not cause any semantic information to be lost: if any piece of information could be inferred by the optimiser about some collection of variables (e.g. that two pointers are equal) can be inferred now about their </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">ped versions, no matter how many </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> and </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">launder</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> calls have been made to obtain them in the IR. As an example, the C++ expression </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">ptr == std::launder(ptr)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> will be optimised to </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">true</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, because it will compare </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip(ptr)</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> with </span><span style="font-size:11pt;font-family:"Courier New";background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip(launder(ptr))</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, which are indeed equal according to our rules.</span></div></b></div></div></div></blockquote><div><br></div><div>This proposal sounds great, even if it still doesn't solve some of the problems I personally need to solve with invariant loads. :)</div><div><br></div><div>I take it that the actual devirtualization here is ultimately still done by forwarding a visible store of the v-table pointer to an invariant load, just by noticing that they occur to the same laundered pointer and therefore must involve the same value.  There's no way of saying "I know what the value of the v-table pointer is even if you can't see a store" when creating a laundered pointer.  For example, in Swift we have constructor functions that are known to return a complete object of a specific type, even if we can't necessarily see the implementation of that function; there's no way for us to say anything about that function pointer</div><blockquote type="cite"><div><div dir="ltr"><div><b style="font-weight:normal" id="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-docs-internal-guid-a43ba0b5-406d-36b9-4e30-86e8c95f392a"><h2 dir="ltr" style="line-height:1.38;margin-top:18pt;margin-bottom:6pt"><span style="font-size:16pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"></span></h2></b></div></div></div></blockquote></div></div></blockquote><div>I think we have already solved that problem with calls to llvm.assume intrinsic. After calling the constructor, we load virtual pointer (with invariant group) and compare it with the vtable it should point to and then pass it to the assume.</div><div><div><br></div><div>  call void @_ZN1AC1Ev(%struct.A* %a) ; call ctor</div><div>  %3 = load {...} %a                  ; Load vptr</div><div>  %4 = icmp eq %3, @_ZTV1A      ; compare vptr with vtable</div><div>  call void @llvm.assume(i1 %4)</div></div><div> </div><div>(from <a href="http://blog.llvm.org/2017/03/devirtualization-in-llvm-and-clang.html" target="_blank">http://blog.llvm.org/<wbr>2017/03/devirtualization-in-<wbr>llvm-and-clang.html</a> )</div><div><br></div><div>If I understand it correctly, you should be able to use the same technique for the constructor-like functions in Swift :)</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div><div dir="ltr"><div><b style="font-weight:normal" id="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-docs-internal-guid-a43ba0b5-406d-36b9-4e30-86e8c95f392a"><h2 dir="ltr" style="line-height:1.38;margin-top:18pt;margin-bottom:6pt"><span style="font-size:16pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">LLVM</span></h2><br><br><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Because LTO between a module with and without devirtualization will be invalid, we will need to break LLVM level ABI. This is however already implemented, because LTO between modules with invariant.group.barriers and without is also invalid. This also means that if we don’t want to break ABI between modules with and without optimizations, we will need to have invariant.barriers and fatpointer.create/strip turned on all the time.  For the users it will means that when switching to new compiler, they will have to recompile all of the generated object files for LTO builds.</span></div></b></div></div></div></blockquote><div><br></div>Is there really no way to have this degrade more gracefully?  I continue to be very concerned about frontend interworking here, either between different versions of a single frontend (e.g. clang 6 vs. clang 8), or between different invocations of a single frontend with different language options set (e.g. clang vs. clang++), or even between different frontends that produce IR that gets linked together (e.g. clang vs. swift).</div><div><br></div><div>How about this approach:</div><div>  - Instead of taking a meaningless !{} argument, invariant.group takes a string argument which identifies a metadata-dependent optimization.  In your case, it would be something like !"clang.cxx_devirtualization".</div><div>  - Functions have a "supported optimizations" list which declares all the metadata-reliant optimizations they promise to have correct metadata for.  So e.g. clang++ would list "clang.cxx_devirtualization" on every single function it compiled, regardless of whether that function actually needed any metadata.  I'm pretty sure metadata are optimized so that identical lists of options like this don't take up more space just because they're added to every single function in the module.</div><div> - Interprocedural optimizations — which mostly means inlining — are required to be aware of the supported-optimizations list.  The inliner would intersect the supported-optimizations lists and then strip metadata/intrinsics that don't belong anymore.</div><div><br></div><div>But the idea that every single metadata-dependent optimization is going to create a new "IR ABI break" just seems unacceptable to me.  Compiler optimization IRs are not stable things; compiler engineers constantly find new things that they want to express.</div><div><br></div><div>John.</div></div></blockquote><div><br></div><div>I haven't thought about LTO between different languages, thanks for bringing that! </div><div>Can you actually use C++ objects without going through C interface? If it is possible, then that is heavy.</div><div>To clarify how it works right now - if you would do LTO between IR compiled with -fstrict-vtable-pointers and without, then the linker would throw an error. I can see it right now, that it pretty much stops you from doing any LTO between different languages. </div><div>The other idea that we had, was to actually strip all the invariant.groups when linking with module that does not have them. This, opposed to the first idea would let us link whatever we want, but we could silently loose some optimizations.</div><div><br></div><div>I like the idea that you proposed - it is somewhere between these two ideas, as you limit the potential loses to only some functions and in the same time you can link whaterver IR you like. </div><div>However, if you agree that the option 2 - stripping invariant.groups from whole modules - addresses all of your concerns, then I would propose to firstly go with this idea and then optimize it if we would find a problem with it. </div><div>I feel that it might be an overkill to implement it on the first go, especially that we are not even in the point of thinking about turing -fstrict-vtable-pointers on by default.</div><div><br></div><div>What do you think about that?</div><div><br></div><div>Piotr</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 style="word-wrap:break-word"><div><blockquote type="cite"><div><div dir="ltr"><div><b style="font-weight:normal" id="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-docs-internal-guid-a43ba0b5-406d-36b9-4e30-86e8c95f392a"><h2 dir="ltr" style="line-height:1.38;margin-top:18pt;margin-bottom:6pt"><span style="font-size:16pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Clang</span></h2><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Clang will require a  couple of minor changes in CodeGen for constructors and destructors.</span></div><br><br><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><b style="font-weight:normal" id="m_1414337835050969498gmail-m_7271471833428658469gmail-docs-internal-guid-62489d1e-4094-c892-40fb-463ebc9fab54"><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Acknowledgment</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Special thanks for the initiators of this idea - Richard Smith, Chandler Carruth and Sanjoy Das and also for all the other people who took a part in helping with devirtualization v1 including: Daniel Berlin, Reid Kleckner, David Majnemer, John McCall.</span></div></b><br class="m_1414337835050969498gmail-m_7271471833428658469gmail-Apple-interchange-newline">References</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">[0] - Devirtualization in LLVM, Proceeding SPLASH Companion 2017 Proceedings Companion of the 2017 ACM SIGPLAN International Conference on Systems, Programming, Languages, and Applications: Software for Humanity - </span><a href="https://dl.acm.org/citation.cfm?id=3135947" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">https://dl.acm.org/citation.cf<wbr>m?id=3135947</span></a></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">[1] - RFC: Devirtualization in LLVM (ver 1) - </span><a href="https://docs.google.com/document/d/1f2SGa4TIPuBGm6y6YO768GrQsA8awNfGEJSBFukLhYA/edit?usp=sharing" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">https://docs.google.com/docume<wbr>nt/d/1f2SGa4TIPuBGm6y6YO768GrQ<wbr>sA8awNfGEJSBFukLhYA/edit?usp=s<wbr>haring</span></a></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">[2] - Devirtualization in LLVM - LLVM Dev meeting 2016 - </span><a href="https://www.youtube.com/watch?v=qMhV6d3B1Vk" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">https://www.youtube.com/watch?<wbr>v=qMhV6d3B1Vk</span></a></div><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">[3] - Devirtualization in LLVM and Clang - llvm blog- </span><a href="http://blog.llvm.org/2017/03/devirtualization-in-llvm-and-clang.html" style="text-decoration:none" target="_blank"><span style="font-size:11pt;font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">http://blog.llvm.org/2017/03/d<wbr>evirtualization-in-llvm-and-cl<wbr>ang.html</span></a></div><br><br><br><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:3pt"><span style="font-size:26pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Appendix</span></p><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Here are some other corner cases that we found.</span></div><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Unions</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;text-align:justify"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Because union can have dynamic types as members, this means that they would have the same address. To solve this we emit launder.invariant.group before getting any dynamic type. It is possible that we could somehow avoid it, but because virtually no one is using unions this way, this should not cause any problems.</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> A {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">virtual</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> foo();</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">};</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">struct</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> B : A {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> foo() </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">override</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">};</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">union</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> U {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   A a;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   B b;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   U() : b() {}</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">};</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> do_call(A &a) {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   a.foo();</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">}</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">__attribute__((noinline)) </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> init_B(U &u) {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">new</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">(&u.b) B;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">}</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> union_test(U &u) {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   do_call(u.b);</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">new</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">(&u.a) A;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   do_call(u.a);</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   init_B(u);</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   do_call(u.b);</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">}</span></div><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">int</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> main() {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   U u;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   union_test(u);</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">}</span></div><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Ptr to int</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">In this example, instead of comparing the pointers we compare the addresses stored in integers. Because ptrtoint conversion will also require call to </span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:700;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">strip.invariant.group</span><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">, this will also work.</span></div><br><br><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> ptr_to_int() {</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   A *a = </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">new</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> A;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   a->foo();</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   A *b = </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">new</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">(a) B;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">auto</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> av = (</span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">uintptr_t</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">)a;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">auto</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> bv = (</span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">uintptr_t</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">)b;</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">   </span><span style="font-size:10.5pt;font-family:Verdana;color:rgb(0,0,255);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">if</span><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> (av == bv)</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">       b->foo();</span></div><div style="line-height:1.62857;margin-top:0pt;margin-bottom:0pt"><span style="font-size:10.5pt;font-family:Verdana;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">}</span></div><br><br><h1 dir="ltr" style="line-height:1.38;margin-top:20pt;margin-bottom:6pt"><span style="font-size:20pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">int to ptr</span></h1><div style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;background-color:transparent;font-weight:400;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-east-asian:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">Here because we are creating a fat pointer from integer, we need to use launder:</span></div><br><div style="line-height:1.32955;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">void</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:Arial;color:rgb(0,102,187);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">foo</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">(Base *base) {</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">uintptr_t</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> base_int = (</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">uintptr_t</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">)base;</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">/* base_int = ptrtoint (strip base) */</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  Base *base_int_ptr = (Base*)base_int;</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">/* base_int_ptr = inttoptr base_int = inttoptr (ptrtoint (strip base)) = strip base */</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  base_int_ptr->vfun();</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  ...</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  Derived *derived = std::launder(base);</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">uintptr_t</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"> derived_int = (</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,153);background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">uintptr_t</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">)derived;</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">/* derived_int = ptrtoint (strip derived) */</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">/* Note: base_int == derived_int */</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  ....</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  Base *derived_int_ptr = (Base*)derived_int;</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">/* derived_int_ptr = inttoptr (ptrtoint (strip derived)) */</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">/* Note: base_int_ptr == derived_int_ptr */</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  derived_int_ptr->vfun();</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">  </span><span style="font-size:11pt;font-family:Arial;color:rgb(136,136,136);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">/* BUG: But it's different than base_int_ptr->vfun()! */</span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap"><br class="m_1414337835050969498gmail-m_7271471833428658469m_-8503527532884566477gmail-kix-line-break"></span><span style="font-size:11pt;font-family:Arial;color:rgb(51,51,51);background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap">}</span></div><br></b><br></div></div>
______________________________<wbr>_________________<br>cfe-dev mailing list<br><a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br></div></blockquote></div><br></div></blockquote></div><br></div></div>