<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:"Courier New";
        mso-fareast-language:RU;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0cm;
        mso-margin-bottom-alt:auto;
        margin-left:0cm;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
span.EmailStyle21
        {mso-style-type:personal;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
span.EmailStyle22
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:2.0cm 42.5pt 2.0cm 3.0cm;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:79959171;
        mso-list-type:hybrid;
        mso-list-template-ids:634000450 68747279 68747289 68747291 68747279 68747289 68747291 68747279 68747289 68747291;}
@list l0:level1
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l1
        {mso-list-id:1084378136;
        mso-list-type:hybrid;
        mso-list-template-ids:-207465610 68747279 68747289 68747291 68747279 68747289 68747291 68747279 68747289 68747291;}
@list l1:level1
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l1:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l1:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
ol
        {margin-bottom:0cm;}
ul
        {margin-bottom:0cm;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="RU" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal"><span lang="EN-US">Hello Everyone,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">I want to raise a discussion about </span>
<span lang="EN-US" style="font-family:"Courier New"">@llvm.experimental.guard</span><span lang="EN-US"> intrinsic and reasons why we should give up using it. Here is an alternative approach to representation of guards that resolves some of fundamental flaws
 that the current guards have.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Basically, this intrinsic was introduced to model the following situation: we want to check that some condition is true, and if it's not, we should deoptimize at this point and quit execution of the compiled code. According
 to <a href="http://llvm.org/docs/LangRef.html#llvm-experimental-guard-intrinsic">
<span style="color:windowtext">http://llvm.org/docs/LangRef.html#llvm-experimental-guard-intrinsic</span></a>, the guard looks like this:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<div style="border:solid #CCCCCC 1.0pt;padding:6.0pt 6.0pt 6.0pt 6.0pt">
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">define void @llvm.experimental.guard(i1 %pred, <args...>) {<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">  %realPred = and i1 %pred, undef<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">  br i1 %realPred, label %continue, label %leave [, !make.implicit !{}]<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU"><o:p> </o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">leave:<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">  call void @llvm.experimental.deoptimize(<args...>) [ "deopt"() ]<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">  ret void<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU"><o:p> </o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">continue:<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">  ret void<o:p></o:p></span></p>
<p class="MsoNormal" style="line-height:11.95pt;background:#F8F8F8"><span style="font-size:11.5pt;font-family:Consolas;mso-fareast-language:RU">}<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Since guard's </span><span lang="EN-US" style="font-family:"Courier New"">leave</span><span lang="EN-US"> branch has a semantics of deoptimize, it is *always* legal to go to this branch, even if the condition is true.
 It means that guard conditions can be widened with any other conditions without loss of correctness. In other words, if the following code is correct:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">    call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">    <some operations><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">The following code will also be correct, no matter what
</span><span lang="EN-US" style="font-family:"Courier New"">%other_cond</span><span lang="EN-US"> is:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">    %wider_cond = and i1 %cond, %other_cond<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">    call void (i1, ...) @llvm.experimental.guard(i1 %wider_cond) [ "deopt"() ]<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">    <do some useful stuff><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">More formally, if </span><span lang="EN-US" style="font-family:"Courier New"">%cond_a</span><span lang="EN-US"> implies
</span><span lang="EN-US" style="font-family:"Courier New"">%cond_b</span><span lang="EN-US">, it is always valid to replace
</span><span lang="EN-US" style="font-family:"Courier New"">guard(%cond_b)</span><span lang="EN-US"> with
</span><span lang="EN-US" style="font-family:"Courier New"">guard(%cond_a)</span><span lang="EN-US">. We use this fact to make some optimizations, for example Loop Predication and Guard Widening passes.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Given this semantics, all optimizations may assume that at every point dominated by a guard its condition is true, as well as they do when they derive this fact from explicit branch instructions. And it would work fine
 if it had a full support.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Unfortunately, hiding this implicit control flow semantics within the intrinsic has some significant downsides. And the biggest one is that all transform and analysis passes that can derive conditions from explicit branches
 should also be taught about the semantics of guards, otherwise they will be interpreted as regular calls. We've spent a lot of time teaching that passes about the guards, but at some point it appeared that:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"><![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">1.<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">There are still places in optimizer which are not aware about the guards and can only use conditions of explicit branches. Such are: exact look taken count calculation in SCEV, new loop unswitching, some transforms
 in EarlyCSE and potentially some others;<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"><![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">2.<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">Support of guards is mostly code duplication that makes it harder to read. In some cases (as in SCEV taken count calculation), the code needs massive refactoring to work with guard conditions, while branch conditions
 fit in easily.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"><![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">3.<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">Finding all guards in a block is expensive. While every block has at most 1 branch condition, it can have an arbitrary amount of guards. There is no easy way to get the nearest dominating guard. We need to iterate
 through instructions to collect them all, which may turn some O(1) algorithms to O(N). It costs us compile time.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"><![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">4.<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">The biggest problem is that whenever a new transform appears, we should make sure that it supports guards if it needs to. The maintenance cost of it is unreasonably high.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"><![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">5.<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">In the past, we had numerous bugs because of incomplete support of guards. Current situation with them is quite healthy, however we don't know what happens when we add guard support to every new pass which could
 be not ready for that. More complex logic is potentially more broken.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:35.4pt"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">And we have all this overhead only because we want to be able to widen guards. There is no other differences between guards and regular branches to deopt blocks. So cheap and easy guard
 widening costs us hard and ugly support over the rest of LLVM code. Instead of this, we want to have something that will allow us to use full power of LLVM optimizer to employ guard conditions for free, even if it makes guard widening more complicated.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Previously, there was a discussion about using invokes of guard intrinsic instead of calls to solve some of these problems. However this approach doesn't solve the biggest problem: we still
 need to and teach every single pass that may need it about the semantics of this intrinsic, and keep an eye on all new passes to make sure they can use it.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">I have a proposal how it can be done relatively easily and with minimum overhead. Let us inline the guard according to the specification:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    %guard_cond = and i1 %cond, %undef<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    br i1 %guard_cond, label %guarded, label %deopt<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">  guarded:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    <do some useful stuff><o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">  deopt:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    <deoptimize and leave the compiled code><o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Let's notice two important facts:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l0 level1 lfo4"><![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">1.<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">In guarded block, </span><span lang="EN-US" style="font-family:"Courier New"">%cond</span><span lang="EN-US"> is
</span><span lang="EN-US" style="font-family:"Courier New"">true</span><span lang="EN-US"> because it is implied by
</span><span lang="EN-US" style="font-family:"Courier New"">%guard_cond</span><span lang="EN-US"> being
</span><span lang="EN-US" style="font-family:"Courier New"">true</span><span lang="EN-US">.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l0 level1 lfo4"><![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">2.<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">In </span><span lang="EN-US" style="font-family:"Courier New"">deopt</span><span lang="EN-US"> block, we cannot assume that
</span><span lang="EN-US" style="font-family:"Courier New"">%cond </span><span lang="EN-US">is false because it is not implied by
</span><span lang="EN-US" style="font-family:"Courier New"">%guard_cond</span><span lang="EN-US"> being
</span><span lang="EN-US" style="font-family:"Courier New"">false</span><span lang="EN-US">. Thus, we cannot make transforms that would need to be discarded after we widen the guard.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">So from optimization perspective, all optimizations that were valid for branch by
</span><span lang="EN-US" style="font-family:"Courier New"">%cond </span><span lang="EN-US">are also valid for branch by
</span><span lang="EN-US" style="font-family:"Courier New"">%guard_cond</span><span lang="EN-US"> in the
</span><span lang="EN-US" style="font-family:"Courier New"">guarded</span><span lang="EN-US"> block. Luckily, most passes I've checked can deduce
</span><span lang="EN-US" style="font-family:"Courier New"">%a = true</span><span lang="EN-US"> from
</span><span lang="EN-US" style="font-family:"Courier New"">%a & %b = true</span><span lang="EN-US"> (and if a pass cannot do it, it's a good general improvement to teach it to). And this invariant remains, no matter how many other conditions we attach to the
</span><span lang="EN-US" style="font-family:"Courier New"">%guard_cond</span><span lang="EN-US"> through
</span><span lang="EN-US" style="font-family:"Courier New"">and</span><span lang="EN-US">.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Guard widening for such representation is done trivially: whenever we want to widen
</span><span lang="EN-US" style="font-family:"Courier New"">%guard_cond</span><span lang="EN-US">, we just attach the new condition to it through and, without loss of optimization opportunity and correctness.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">The only thing we should be able to do is to distinguish guards from regular branches (that don't have this semantics that "it is always legal to go to non-taken branch"). We could say that
 any branch by condition </span><span lang="EN-US" style="font-family:"Courier New"">and i1 %cond, undef</span><span lang="EN-US"> and deopt in non-taken branch can be seen as a guard. And it would be a good solution if it wasn't for a nasty fact that any other
 transform (like instcombine) can kill this </span><span lang="EN-US" style="font-family:"Courier New"">undef</span><span lang="EN-US"> and replace "</span><span lang="EN-US" style="font-family:"Courier New"">and i1 %cond, undef</span><span lang="EN-US"> "
 with "</span><span lang="EN-US" style="font-family:"Courier New"">%cond</span><span lang="EN-US">" (or with "</span><span lang="EN-US" style="font-family:"Courier New"">false</span><span lang="EN-US">", which is even worse). So basically, the only thing we
 need to distinguish the guard is a special type of undef value which will not be optimized away by other transforms (at least not before we are done with widening-based transforms).<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">To solve that, we can introduce a special intrinsic that is called
</span><span lang="EN-US" style="font-family:"Courier New"">widenable_condition()</span><span lang="EN-US">. And we can just use it instead of the
</span><span lang="EN-US" style="font-family:"Courier New"">undef</span><span lang="EN-US"> here like this:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    %wc = call i1 widenable_condition()<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    %guard_cond = and i1 %cond, %wc<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    br i1 %guard_cond, label %guarded, label %deopt<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">  guarded:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    <do some useful stuff><o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">  deopt:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US" style="font-family:"Courier New"">    <deoptimize and leave the compiled code><o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Now we can distinguish a guard from a regular conditional branch: a guard is a conditional branch whose condition is an
</span><span lang="EN-US" style="font-family:"Courier New"">and</span><span lang="EN-US"> tree with a
</span><span lang="EN-US" style="font-family:"Courier New"">widenable_condition()</span><span lang="EN-US"> as one of its leaves, and its non-taken branch goes straight to deoptimize intrinsic call without any side-effecting instructions before it. We no longer
 need the </span><span lang="EN-US" style="font-family:"Courier New"">@llvm.experimental.guard</span><span lang="EN-US"> instinsic and can use its modified inlined version instead.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">We also consider usage of a read from a global field instead of
</span><span lang="EN-US" style="font-family:"Courier New"">widenable_condition()
</span><span lang="EN-US">call to emulate this special condition, but the fundamental idea is the same.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Formally, when we no longer need it, we should lower this
</span><span lang="EN-US" style="font-family:"Courier New"">widenable_condition()
</span><span lang="EN-US">into </span><span lang="EN-US" style="font-family:"Courier New"">undef</span><span lang="EN-US">, but actually it is better to lower it into
</span><span lang="EN-US" style="font-family:"Courier New"">true</span><span lang="EN-US"> value because we want to stay in compiled code and not go to deoptimize without reasons.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Currently I have a working prototype of this new guards form, as well as Loop Predication and Guard Widening implementations for them. This implementation is still in process of evaluation,
 but so far it seems that this new form is at least as powerful as the old one, besides, it doesn't require any special actions to maintain it in all passes and analyzes and opens up new optimization opportunities (which are currently missed because of incomplete
 support of guard intrinsic). The patches are not in reviewable condition yet, but I am working to make them ready for review.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">What do you guys think about it? If someone has proposals or ideas on this problem and the suggested solution, please don't hesitate to share!<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Best regards,<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:0cm"><span lang="EN-US">Max<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>