<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=utf-8">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 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:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";
        color:black;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p
        {mso-style-priority:99;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";
        color:black;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";
        color:black;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
        {mso-style-priority:99;
        mso-style-link:"Balloon Text Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";
        color:black;}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:Consolas;
        color:black;}
span.phui-handle
        {mso-style-name:phui-handle;}
span.EmailStyle21
        {mso-style-type:personal;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.EmailStyle22
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";
        color:black;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></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 bgcolor="white" lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Philip,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">For naming convention, dump.txt contains the LLVM IR dump before induction simplification pass and after induction simplification pass with my patch disabled.
 dump.txt.patch contains the LLVM IR dump before induction simplification pass and after induction simplification pass with my patch enabled (i.e. current llvm trunk).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">For now, I address the main concern which is 
</span>*Why* is shifting the extend to the load operand profitable<span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> and you also mention below  </span>Why should we believe that the widened-bin-op + *ext form is profitable over
 the trunc form *in general*: <span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">
My patch adds an extend to the load, and removes a truncate (or more precisely avoids adding a truncate) but this happens only when it also removes an extend instruction (See widenWithVariantLoadUseCodegen near LLVM_DEBUG…). So, my code adds an extend instruction
 to the Load but also removes an extend instruction (which is the user of the operation whose one of the operand is a load)  and a truncate instruction. The end result is that we end up with one less instruction which is a truncate instruction. You can see
 we have 3 fewer truncate instructions in dump.txt.patch than in dump.txt while the number of extend instructions is the same. What we observe in those dump files is what is also happening in general.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">.
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Note that I used to have this comment in the code, but I lost it by mistake while updating the code after one of the reviews. It could have helped with understanding
 the code.   </span><o:p></o:p></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:11.0pt;font-family:"Courier New";color:windowtext">+  // Profitability: Check if widening the use eliminates sign/zero extend<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:windowtext">+  // instructions.</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">The next question that you may have (and I had it before doing this) is: we avoided adding a truncate instruction but we changed where extend instruction occur
 (added one and removed one); Will the latter affect performance negatively even with less truncate instructions? I do not think so but I cannot prove. This optimization is old and I am just extending it to work on more cases.    <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">This discussion obviously points to that I should have explained the changes better in the comment. Also, may need to extend this beyond load.
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">I stop here before discussing the other points mentioned below because we need to agree first on the core which is “how is it profitable?”. I hope I made things
 a little bit clearer.  <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Abderrazek<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext"> Philip Reames [mailto:listmail@philipreames.com]
<br>
<b>Sent:</b> Thursday, September 13, 2018 3:33 PM<br>
<b>To:</b> Abderrazek Zaafrani; llvm-commits@lists.llvm.org; Sebastian Pop<br>
<b>Subject:</b> Re: [llvm] r341726 - [SimplifyIndVar] Avoid generating truncate instructions with non-hoisted Laod operand.<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">Adrerrazek,<br>
<br>
Thank for you for the fairly lengthy follow up.  <br>
<br>
I've replied to few specific points inline, but the macro concern I have is the same one I expressed in my previous email.  *Why* is shifting the extend to the load operand profitable?  Why do we believe this is a generally profitable transformation?  Your
 answer to date has been specific to one particular example.  That does not address the core concern which is about generality. 
<br>
<br>
Fair warning: I will revert this patch in a day or so unless we've come to a satisfactory conclusion.  That doesn't prevent us from continuing the conversation and then reintroducing it later.  It's just to avoid having trunk potentially (performance wise)
 broken in the mean time.  <br>
<br>
Philip<o:p></o:p></p>
<div>
<p class="MsoNormal">On 09/12/2018 03:56 PM, Abderrazek Zaafrani wrote:<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Philip,</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">This is a continuation of my previous reply and the main intent is to show some generated code.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">The context of this work is to try to improve llvm to be on par with gcc. A well-known benchmark used for phones show a gap between gcc and llvm. I cannot share
 the proprietary code but I tried to reconstruct my own test (see test.cpp attached). The other two files attached are llvm IR dump without the patch and with the patch. I am only including the dump before and after Induction Variable Simplification pass as
 it is the only pass I am modifying. </span><o:p></o:p></p>
</blockquote>
<p class="MsoNormal">Am I correct in interpreting dump.txt to be the before IR and dump,.txt.patch to the after IR?  I'd probably have named these before-indvars.ll and after-indvars.ll for clarity. 
<br>
<br>
<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">If you compare these two files, you can see that there are less truncate instructions with my patch. Current Induction simplification pass , among other things,
 tries to avoid creating truncate instructions while widening the induction variables. My patch does not  bring any new idea or optimization. It just tries harder to avoid creating truncate instructions.</span><o:p></o:p></p>
<p class="MsoNormal">I disagree here.  You may be extending an existing approach, but the specifics of how to "avoid a truncate" in this case is new and needs to be justified.  Why should we believe that the widened-bin-op + *ext form is profitable over the
 trunc form *in general*?  (Not just this one example.)<br>
<br>
<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Let’s examine the effect of having clean code without unnecessary truncate instructions on the final generated code.
</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Here is the ARM assembly for test.cpp  without the patch:</span><o:p></o:p></p>
<p class="MsoNormal">Unfortunately, I'm not fluent in ARM assembly, so this doesn't help me much.  Comments on key pieces and changes would have gone a long way.  Alternatively, I am much more familiar with X86 if you'd prefer.<br>
<br>
<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   .cfi_startproc</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">// %bb.0:                               // %entry</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   ldr w9, [x0]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add x11, x1, w3, sxtw #2</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  mov w8, wzr</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  neg w10, w9</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  lsl w12, w9, #1</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  orr w13, wzr, #0x4</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">.LBB0_1:                                // %for.body</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">                                               // =>This Inner Loop Header: Depth=1</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add w14, w12, w8</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  ldrb  w14, [x2, w14, sxtw]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  ldrb  w15, [x2, w8, sxtw]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add w16, w10, w8</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  ldrb  w16, [x2, w16, sxtw]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add w8, w8, w9</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  sub w14, w14, w15</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add w14, w14, w16</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  str w14, [x11, x13]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add x13, x13, #4            // =4</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> cmp x13, #400               // =400</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  b.ne  .LBB0_1</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">// %bb.2:              
</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">And with the patch:</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">    .cfi_startproc</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">// %bb.0:                               // %entry</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   ldrsw x8, [x0]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   add x10, x1, w3, sxtw #2</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   neg x9, x8</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   lsl x11, x8, #1</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   orr w12, wzr, #0x4</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">.LBB0_1:                                // %for.body</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">                                               // =>This Inner Loop Header: Depth=1</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  ldrb  w13, [x2, x11]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  ldrb  w14, [x2]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  ldrb  w15, [x2, x9]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">   add x2, x2, x8</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  sub w13, w13, w14</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add w13, w13, w15</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  str w13, [x10, x12]</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  add x12, x12, #4            // =4</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">  cmp x12, #400               // =400</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">b.ne  .LBB0_1</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">// %bb.2:                               // %for.cond.cleanup</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">If you look at the load instructions ldrb inside the loop for both versions, you can see that the offsets are computed more efficiently with the patched version
 than non-patched version (offset is  computed inside the loop for non-patch version and outside the loop for patched version).
</span><o:p></o:p></p>
<p class="MsoNormal">Your framing here really confuses me.  What does extending the load have to do with the addressing form used?  *Why* is there a connection here? 
<br>
<br>
<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Experiment on ARM A72 shows an improvement of close to 10% for one application in the benchmark.
</span><o:p></o:p></p>
<p class="MsoNormal">This is a single benchmark.  I'm asking about the set of all possible benchmarks. 
<br>
<br>
<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Abderrazek</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"> </span><o:p></o:p></p>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext"> Philip Reames [<a href="mailto:listmail@philipreames.com">mailto:listmail@philipreames.com</a>]
<br>
<b>Sent:</b> Monday, September 10, 2018 4:41 PM<br>
<b>To:</b> Abderrazek Zaafrani; <a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>; Sebastian Pop<br>
<b>Subject:</b> Re: [llvm] r341726 - [SimplifyIndVar] Avoid generating truncate instructions with non-hoisted Laod operand.</span><o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"> <o:p></o:p></p>
<p>I have serious concerns with this patch.  I don't believe this patch meets our usual standards.  I believe this patch warrants being reverted, and then re-reviewed from scratch. 
<o:p></o:p></p>
<p>@<span class="phui-handle">sebpop</span>, I don't think it was appropriate to approve this patch given the public history.  I wouldn't normally call that out, but this seems like a really clear cut case.<o:p></o:p></p>
<p>@Abderrazek, please don't let me scare you off here.  While I think this patch does need reverted, I think this can be adjusted into something clearly worthwhile, and I encourage you to do so.  I'm happy to help as well.  (Fair warning, my time is very limited,
 so my help will only go so far.)<o:p></o:p></p>
<p>Philip<o:p></o:p></p>
<div>
<p class="MsoNormal">On 09/07/2018 03:41 PM, Abderrazek Zaafrani via llvm-commits wrote:<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<pre>Author: az<o:p></o:p></pre>
<pre>Date: Fri Sep  7 15:41:57 2018<o:p></o:p></pre>
<pre>New Revision: 341726<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=341726&view=rev">http://llvm.org/viewvc/llvm-project?rev=341726&view=rev</a><o:p></o:p></pre>
<pre>Log:<o:p></o:p></pre>
<pre>[SimplifyIndVar] Avoid generating truncate instructions with non-hoisted Laod operand.<o:p></o:p></pre>
</blockquote>
<p class="MsoNormal">(For the future, you had a nice comment in the review about the reasoning.  The submit comment should include that too.)<br>
<br>
Your reasoning here is explained purely in terms of what we do for loop-invariant loads.  You don't state what this is, or provide a clear description of what the code generation should be.  I've read over the review and the code, and can reverse engineer what
 you're going for, but it is your responsibility to make this clear from the submitted code.  This patch does not achieve that objective.<br>
<br>
Reverse engineering the code, here's what I *think* you're trying to accomplish:<br>
If we find a binary operator where we need to extend one side, check to see if we can cheaply extend the other operand and widen the load instead.  Many architectures can efficiently generate an extending load, so we consider loads to be one such cheaply extensible
 case.<br>
<br>
(I can't connect this understanding of the code to your comments in the review though, so maybe I'm missing something still?)<br>
<br>
In terms of the review discussion, I am concerned that you appear to be mixing TBAA and AliasSet terminology.  You appear to have rejected an approach based on a possibly flawed understanding.  Your reviewers should have asked for a reference w.r.t. the rejected
 approach (e.g. email discussion, review, or rejected patch).  <br>
<br>
<br>
<br>
<br>
<o:p></o:p></p>
<pre> <o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>Differential Revision: <a href="https://reviews.llvm.org/D49151">https://reviews.llvm.org/D49151</a><o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>Modified:<o:p></o:p></pre>
<pre>    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<o:p></o:p></pre>
<pre>    llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<o:p></o:p></pre>
<pre>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=341726&r1=341725&r2=341726&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=341726&r1=341725&r2=341726&view=diff</a><o:p></o:p></pre>
<pre>==============================================================================<o:p></o:p></pre>
<pre>--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)<o:p></o:p></pre>
<pre>+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Fri Sep  7 15:41:57 2018<o:p></o:p></pre>
<pre>@@ -1017,6 +1017,8 @@ protected:<o:p></o:p></pre>
<pre>   Instruction *widenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter);<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>   bool widenLoopCompare(NarrowIVDefUse DU);<o:p></o:p></pre>
<pre>+  bool widenWithVariantLoadUse(NarrowIVDefUse DU);<o:p></o:p></pre>
<pre>+  void widenWithVariantLoadUseCodegen(NarrowIVDefUse DU);<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>   void pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef);<o:p></o:p></pre>
<pre> };<o:p></o:p></pre>
<pre>@@ -1361,6 +1363,146 @@ bool WidenIV::widenLoopCompare(NarrowIVD<o:p></o:p></pre>
<pre>   return true;<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>+/// If the narrow use is an instruction whose two operands are the defining<o:p></o:p></pre>
<pre>+/// instruction of DU and a load instruction, then we have the following:<o:p></o:p></pre>
<pre>+/// if the load is hoisted outside the loop, then we do not reach this function<o:p></o:p></pre>
<pre>+/// as scalar evolution analysis works fine in widenIVUse with variables<o:p></o:p></pre>
<pre>+/// hoisted outside the loop and efficient code is subsequently generated by<o:p></o:p></pre>
<pre>+/// not emitting truncate instructions. But when the load is not hoisted<o:p></o:p></pre>
<pre>+/// (whether due to limitation in alias analysis or due to a true legality),<o:p></o:p></pre>
<pre>+/// then scalar evolution can not proceed with loop variant values and<o:p></o:p></pre>
<pre>+/// inefficient code is generated. This function handles the non-hoisted load<o:p></o:p></pre>
<pre>+/// special case by making the optimization generate the same type of code for<o:p></o:p></pre>
<pre>+/// hoisted and non-hoisted load (widen use and eliminate sign extend<o:p></o:p></pre>
<pre>+/// instruction). This special case is important especially when the induction<o:p></o:p></pre>
<pre>+/// variables are affecting addressing mode in code generation.<o:p></o:p></pre>
<p class="MsoNormal">This comment really tells me nothing about what this function does, or what it's goal is. 
<br>
<br>
<br>
<o:p></o:p></p>
<pre> <o:p></o:p></pre>
<pre>+bool WidenIV::widenWithVariantLoadUse(NarrowIVDefUse DU) {<o:p></o:p></pre>
<pre>+  Instruction *NarrowUse = DU.NarrowUse;<o:p></o:p></pre>
<pre>+  Instruction *NarrowDef = DU.NarrowDef;<o:p></o:p></pre>
<pre>+  Instruction *WideDef = DU.WideDef;<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  // Handle the common case of add<nsw/nuw><o:p></o:p></pre>
<pre>+  const unsigned OpCode = NarrowUse->getOpcode();<o:p></o:p></pre>
<pre>+  // Only Add/Sub/Mul instructions are supported.<o:p></o:p></pre>
<p class="MsoNormal">Why?<br>
<br>
<br>
<o:p></o:p></p>
<pre> <o:p></o:p></pre>
<pre>+  if (OpCode != Instruction::Add && OpCode != Instruction::Sub &&<o:p></o:p></pre>
<pre>+      OpCode != Instruction::Mul)<o:p></o:p></pre>
<pre>+    return false;<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  // The operand that is not defined by NarrowDef of DU. Let's call it the<o:p></o:p></pre>
<pre>+  // other operand.<o:p></o:p></pre>
<pre>+  unsigned ExtendOperIdx = DU.NarrowUse->getOperand(0) == NarrowDef ? 1 : 0;<o:p></o:p></pre>
<pre>+  assert(DU.NarrowUse->getOperand(1 - ExtendOperIdx) == DU.NarrowDef &&<o:p></o:p></pre>
<pre>+         "bad DU");<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  const SCEV *ExtendOperExpr = nullptr;<o:p></o:p></pre>
<pre>+  const OverflowingBinaryOperator *OBO =<o:p></o:p></pre>
<pre>+    cast<OverflowingBinaryOperator>(NarrowUse);<o:p></o:p></pre>
<pre>+  ExtendKind ExtKind = getExtendKind(NarrowDef);<o:p></o:p></pre>
<pre>+  if (ExtKind == SignExtended && OBO->hasNoSignedWrap())<o:p></o:p></pre>
<pre>+    ExtendOperExpr = SE->getSignExtendExpr(<o:p></o:p></pre>
<pre>+      SE->getSCEV(NarrowUse->getOperand(ExtendOperIdx)), WideType);<o:p></o:p></pre>
<pre>+  else if (ExtKind == ZeroExtended && OBO->hasNoUnsignedWrap())<o:p></o:p></pre>
<pre>+    ExtendOperExpr = SE->getZeroExtendExpr(<o:p></o:p></pre>
<pre>+      SE->getSCEV(NarrowUse->getOperand(ExtendOperIdx)), WideType);<o:p></o:p></pre>
<pre>+  else<o:p></o:p></pre>
<pre>+    return false;<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  // We are interested in the other operand being a load instruction.<o:p></o:p></pre>
<pre>+  // But, we should look into relaxing this restriction later on.<o:p></o:p></pre>
<pre>+  auto *I = dyn_cast<Instruction>(NarrowUse->getOperand(ExtendOperIdx));<o:p></o:p></pre>
<pre>+  if (I && I->getOpcode() != Instruction::Load)<o:p></o:p></pre>
<pre>+    return false;<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  // Verifying that Defining operand is an AddRec<o:p></o:p></pre>
<pre>+  const SCEV *Op1 = SE->getSCEV(WideDef);<o:p></o:p></pre>
<pre>+  const SCEVAddRecExpr *AddRecOp1 = dyn_cast<SCEVAddRecExpr>(Op1);<o:p></o:p></pre>
<pre>+  if (!AddRecOp1 || AddRecOp1->getLoop() != L)<o:p></o:p></pre>
<pre>+    return false;<o:p></o:p></pre>
<pre>+  // Verifying that other operand is an Extend.<o:p></o:p></pre>
<pre>+  if (ExtKind == SignExtended) {<o:p></o:p></pre>
<pre>+    if (!isa<SCEVSignExtendExpr>(ExtendOperExpr))<o:p></o:p></pre>
<pre>+      return false;<o:p></o:p></pre>
<pre>+  } else {<o:p></o:p></pre>
<pre>+    if (!isa<SCEVZeroExtendExpr>(ExtendOperExpr))<o:p></o:p></pre>
<pre>+      return false;<o:p></o:p></pre>
<pre>+  }<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  if (ExtKind == SignExtended) {<o:p></o:p></pre>
<pre>+    for (Use &U : NarrowUse->uses()) {<o:p></o:p></pre>
<pre>+      SExtInst *User = dyn_cast<SExtInst>(U.getUser());<o:p></o:p></pre>
<pre>+      if (!User || User->getType() != WideType)<o:p></o:p></pre>
<pre>+        return false;<o:p></o:p></pre>
<pre>+    }<o:p></o:p></pre>
<pre>+  } else { // ExtKind == ZeroExtended<o:p></o:p></pre>
<pre>+    for (Use &U : NarrowUse->uses()) {<o:p></o:p></pre>
<pre>+      ZExtInst *User = dyn_cast<ZExtInst>(U.getUser());<o:p></o:p></pre>
<pre>+      if (!User || User->getType() != WideType)<o:p></o:p></pre>
<pre>+        return false;<o:p></o:p></pre>
<pre>+    }<o:p></o:p></pre>
<pre>+  }<o:p></o:p></pre>
<p class="MsoNormal">This and the previous block of restrictions seem awfully narrow with no clear reasoning of why they need to be.<br>
<br>
<br>
<o:p></o:p></p>
<pre> <o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  return true;<o:p></o:p></pre>
<pre>+}<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+/// Special Case for widening with variant Loads (see<o:p></o:p></pre>
<pre>+/// WidenIV::widenWithVariantLoadUse). This is the code generation part.<o:p></o:p></pre>
<pre>+void WidenIV::widenWithVariantLoadUseCodegen(NarrowIVDefUse DU) {<o:p></o:p></pre>
<pre>+  Instruction *NarrowUse = DU.NarrowUse;<o:p></o:p></pre>
<pre>+  Instruction *NarrowDef = DU.NarrowDef;<o:p></o:p></pre>
<pre>+  Instruction *WideDef = DU.WideDef;<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  ExtendKind ExtKind = getExtendKind(NarrowDef);<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  LLVM_DEBUG(dbgs() << "Cloning arithmetic IVUser: " << *NarrowUse << "\n");<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  // Generating a widening use instruction.<o:p></o:p></pre>
<pre>+  Value *LHS = (NarrowUse->getOperand(0) == NarrowDef)<o:p></o:p></pre>
<pre>+                   ? WideDef<o:p></o:p></pre>
<pre>+                   : createExtendInst(NarrowUse->getOperand(0), WideType,<o:p></o:p></pre>
<pre>+                                      ExtKind, NarrowUse);<o:p></o:p></pre>
<pre>+  Value *RHS = (NarrowUse->getOperand(1) == NarrowDef)<o:p></o:p></pre>
<pre>+                   ? WideDef<o:p></o:p></pre>
<pre>+                   : createExtendInst(NarrowUse->getOperand(1), WideType,<o:p></o:p></pre>
<pre>+                                      ExtKind, NarrowUse);<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  auto *NarrowBO = cast<BinaryOperator>(NarrowUse);<o:p></o:p></pre>
<pre>+  auto *WideBO = BinaryOperator::Create(NarrowBO->getOpcode(), LHS, RHS,<o:p></o:p></pre>
<pre>+                                        NarrowBO->getName());<o:p></o:p></pre>
<pre>+  IRBuilder<> Builder(NarrowUse);<o:p></o:p></pre>
<pre>+  Builder.Insert(WideBO);<o:p></o:p></pre>
<pre>+  WideBO->copyIRFlags(NarrowBO);<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  if (ExtKind == SignExtended)<o:p></o:p></pre>
<pre>+    ExtendKindMap[NarrowUse] = SignExtended;<o:p></o:p></pre>
<pre>+  else<o:p></o:p></pre>
<pre>+    ExtendKindMap[NarrowUse] = ZeroExtended;<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+  // Update the Use.<o:p></o:p></pre>
<pre>+  if (ExtKind == SignExtended) {<o:p></o:p></pre>
<pre>+    for (Use &U : NarrowUse->uses()) {<o:p></o:p></pre>
<pre>+      SExtInst *User = dyn_cast<SExtInst>(U.getUser());<o:p></o:p></pre>
<pre>+      if (User && User->getType() == WideType) {<o:p></o:p></pre>
<pre>+        LLVM_DEBUG(dbgs() << "INDVARS: eliminating " << *User << " replaced by "<o:p></o:p></pre>
<pre>+                          << *WideBO << "\n");<o:p></o:p></pre>
<pre>+        ++NumElimExt;<o:p></o:p></pre>
<pre>+        User->replaceAllUsesWith(WideBO);<o:p></o:p></pre>
<pre>+        DeadInsts.emplace_back(User);<o:p></o:p></pre>
<pre>+      }<o:p></o:p></pre>
<pre>+    }<o:p></o:p></pre>
<pre>+  } else { // ExtKind == ZeroExtended<o:p></o:p></pre>
<pre>+    for (Use &U : NarrowUse->uses()) {<o:p></o:p></pre>
<pre>+      ZExtInst *User = dyn_cast<ZExtInst>(U.getUser());<o:p></o:p></pre>
<pre>+      if (User && User->getType() == WideType) {<o:p></o:p></pre>
<pre>+        LLVM_DEBUG(dbgs() << "INDVARS: eliminating " << *User << " replaced by "<o:p></o:p></pre>
<pre>+                          << *WideBO << "\n");<o:p></o:p></pre>
<pre>+        ++NumElimExt;<o:p></o:p></pre>
<pre>+        User->replaceAllUsesWith(WideBO);<o:p></o:p></pre>
<pre>+        DeadInsts.emplace_back(User);<o:p></o:p></pre>
<pre>+      }<o:p></o:p></pre>
<pre>+    }<o:p></o:p></pre>
<pre>+  }<o:p></o:p></pre>
<pre>+}<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre> /// Determine whether an individual user of the narrow IV can be widened. If so,<o:p></o:p></pre>
<pre> /// return the wide clone of the user.<o:p></o:p></pre>
<pre> Instruction *WidenIV::widenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) {<o:p></o:p></pre>
<pre>@@ -1458,6 +1600,16 @@ Instruction *WidenIV::widenIVUse(NarrowI<o:p></o:p></pre>
<pre>     if (widenLoopCompare(DU))<o:p></o:p></pre>
<pre>       return nullptr;<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>+    // We are here about to generate a truncate instruction that may hurt<o:p></o:p></pre>
<pre>+    // performance because the scalar evolution expression computed earlier<o:p></o:p></pre>
<pre>+    // in WideAddRec.first does not indicate a polynomial induction expression.<o:p></o:p></pre>
<pre>+    // In that case, look at the operands of the use instruction to determine<o:p></o:p></pre>
<pre>+    // if we can still widen the use instead of truncating its operand.<o:p></o:p></pre>
<pre>+    if (widenWithVariantLoadUse(DU)) {<o:p></o:p></pre>
<pre>+      widenWithVariantLoadUseCodegen(DU);<o:p></o:p></pre>
<pre>+      return nullptr;<o:p></o:p></pre>
<pre>+    }<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>     // This user does not evaluate to a recurrence after widening, so don't<o:p></o:p></pre>
<pre>     // follow it. Instead insert a Trunc to kill off the original use,<o:p></o:p></pre>
<pre>     // eventually isolating the original narrow IV so it can be removed.<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>Modified: llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll<o:p></o:p></pre>
<pre>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll?rev=341726&r1=341725&r2=341726&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll?rev=341726&r1=341725&r2=341726&view=diff</a><o:p></o:p></pre>
<pre>==============================================================================<o:p></o:p></pre>
<pre>--- llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll (original)<o:p></o:p></pre>
<pre>+++ llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll Fri Sep  7 15:41:57 2018<o:p></o:p></pre>
<pre>@@ -273,3 +273,87 @@ for.end:<o:p></o:p></pre>
<pre>   %call = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))<o:p></o:p></pre>
<pre>   ret i32 0<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<p class="MsoNormal">The testing included here is insufficient.  Specifically:<br>
1) The tests do not appear to be maximally reduced.<br>
2) The tests do not clearly show what the expected output is.  (i.e. positive check)<br>
3) It includes only minimal negative tests (i.e. exercising cases which shouldn't trigger).  Clearly missing cases include: non-load RHS, other binary op types, missing nsw/nuw, etc...<br>
<br>
<br>
<br>
<o:p></o:p></p>
<pre> <o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+%struct.image = type {i32, i32}<o:p></o:p></pre>
<pre>+define i32 @foo4(%struct.image* %input, i32 %length, i32* %in) {<o:p></o:p></pre>
<pre>+entry:<o:p></o:p></pre>
<pre>+  %stride = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 1<o:p></o:p></pre>
<pre>+  %0 = load i32, i32* %stride, align 4<o:p></o:p></pre>
<pre>+  %cmp17 = icmp sgt i32 %length, 1<o:p></o:p></pre>
<pre>+  br i1 %cmp17, label %for.body.lr.ph, label %for.cond.cleanup<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+for.body.lr.ph:                                   ; preds = %entry<o:p></o:p></pre>
<pre>+  %channel = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 0<o:p></o:p></pre>
<pre>+  br label %for.body<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+for.cond.cleanup.loopexit:                        ; preds = %for.body<o:p></o:p></pre>
<pre>+  %1 = phi i32 [ %6, %for.body ]<o:p></o:p></pre>
<pre>+  br label %for.cond.cleanup<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit, %entry<o:p></o:p></pre>
<pre>+  %2 = phi i32 [ 0, %entry ], [ %1, %for.cond.cleanup.loopexit ]<o:p></o:p></pre>
<pre>+  ret i32 %2<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+; mul instruction below is widened instead of generating a truncate instruction for it<o:p></o:p></pre>
<pre>+; regardless if Load operand of mul is inside or outside the loop (we have both cases).<o:p></o:p></pre>
<pre>+; CHECK: for.body:<o:p></o:p></pre>
<pre>+; CHECK-NOT: trunc<o:p></o:p></pre>
<pre>+for.body:                                         ; preds = %for.body.lr.ph, %for.body<o:p></o:p></pre>
<pre>+  %x.018 = phi i32 [ 1, %for.body.lr.ph ], [ %add, %for.body ]<o:p></o:p></pre>
<pre>+  %add = add nuw nsw i32 %x.018, 1<o:p></o:p></pre>
<pre>+  %3 = load i32, i32* %channel, align 8<o:p></o:p></pre>
<pre>+  %mul = mul nsw i32 %3, %add<o:p></o:p></pre>
<pre>+  %idx.ext = sext i32 %mul to i64<o:p></o:p></pre>
<pre>+  %add.ptr = getelementptr inbounds i32, i32* %in, i64 %idx.ext<o:p></o:p></pre>
<pre>+  %4 = load i32, i32* %add.ptr, align 4<o:p></o:p></pre>
<pre>+  %mul1 = mul nsw i32 %0, %add<o:p></o:p></pre>
<pre>+  %idx.ext1 = sext i32 %mul1 to i64<o:p></o:p></pre>
<pre>+  %add.ptr1 = getelementptr inbounds i32, i32* %in, i64 %idx.ext1<o:p></o:p></pre>
<pre>+  %5 = load i32, i32* %add.ptr1, align 4<o:p></o:p></pre>
<pre>+  %6 = add i32 %4, %5<o:p></o:p></pre>
<pre>+  %cmp = icmp slt i32 %add, %length<o:p></o:p></pre>
<pre>+  br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit<o:p></o:p></pre>
<pre>+}<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+define i32 @foo5(%struct.image* %input, i32 %length, i32* %in) {<o:p></o:p></pre>
<pre>+entry:<o:p></o:p></pre>
<pre>+  %stride = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 1<o:p></o:p></pre>
<pre>+  %0 = load i32, i32* %stride, align 4<o:p></o:p></pre>
<pre>+  %cmp17 = icmp sgt i32 %length, 1<o:p></o:p></pre>
<pre>+  br i1 %cmp17, label %for.body.lr.ph, label %for.cond.cleanup<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+for.body.lr.ph:                                   ; preds = %entry<o:p></o:p></pre>
<pre>+  %channel = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 0<o:p></o:p></pre>
<pre>+  br label %for.body<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+for.cond.cleanup.loopexit:                        ; preds = %for.body<o:p></o:p></pre>
<pre>+  %1 = phi i32 [ %7, %for.body ]<o:p></o:p></pre>
<pre>+  br label %for.cond.cleanup<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit, %entry<o:p></o:p></pre>
<pre>+  %2 = phi i32 [ 0, %entry ], [ %1, %for.cond.cleanup.loopexit ]<o:p></o:p></pre>
<pre>+  ret i32 %2<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre>+; This example is the same as above except that the first mul is used in two places<o:p></o:p></pre>
<pre>+; and this may result in having two versions of the multiply: an i32 and i64 version.<o:p></o:p></pre>
<pre>+; In this case, keep the trucate instructions to avoid this redundancy.<o:p></o:p></pre>
<pre>+; CHECK: for.body:<o:p></o:p></pre>
<pre>+; CHECK: trunc<o:p></o:p></pre>
<pre>+for.body:                                         ; preds = %for.body.lr.ph, %for.body<o:p></o:p></pre>
<pre>+  %x.018 = phi i32 [ 1, %for.body.lr.ph ], [ %add, %for.body ]<o:p></o:p></pre>
<pre>+  %add = add nuw nsw i32 %x.018, 1<o:p></o:p></pre>
<pre>+  %3 = load i32, i32* %channel, align 8<o:p></o:p></pre>
<pre>+  %mul = mul nsw i32 %3, %add<o:p></o:p></pre>
<pre>+  %idx.ext = sext i32 %mul to i64<o:p></o:p></pre>
<pre>+  %add.ptr = getelementptr inbounds i32, i32* %in, i64 %idx.ext<o:p></o:p></pre>
<pre>+  %4 = load i32, i32* %add.ptr, align 4<o:p></o:p></pre>
<pre>+  %mul1 = mul nsw i32 %0, %add<o:p></o:p></pre>
<pre>+  %idx.ext1 = sext i32 %mul1 to i64<o:p></o:p></pre>
<pre>+  %add.ptr1 = getelementptr inbounds i32, i32* %in, i64 %idx.ext1<o:p></o:p></pre>
<pre>+  %5 = load i32, i32* %add.ptr1, align 4<o:p></o:p></pre>
<pre>+  %6 = add i32 %4, %5<o:p></o:p></pre>
<pre>+  %7 = add i32 %6, %mul<o:p></o:p></pre>
<pre>+  %cmp = icmp slt i32 %add, %length<o:p></o:p></pre>
<pre>+  br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit<o:p></o:p></pre>
<pre>+}<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>_______________________________________________<o:p></o:p></pre>
<pre>llvm-commits mailing list<o:p></o:p></pre>
<pre><a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><o:p></o:p></pre>
<pre><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><o:p></o:p></pre>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>