<div dir="ltr">Hi Shulin,<div><br></div><div>Sorry for the late reply. The quick answer is: The first one will be generated when optimizations are on and the second one when not. What follows is peeling off the levels of detail in case you want to know more.</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">I wonder when the llvm will generate the former one, and when it will generate the later one?</blockquote><div><br></div><div>"llvm" is a very vague term here. We should define what high-level component we're talking about. </div><div><br></div><div>I guess you mean Clang, i.e., the C/C++ front-end, whose job we can assume ends with the generation of LLVM IR (then comes the "middle-end" which does a bunch of, let's say, target-independent optimizations in this LLVM IR</div><div>and then comes the back-end which does a bunch more target-dependent optimizations and finally generates assembly).</div><div><br></div><div>Clang generally generates the simplest IR possible. So, Clang will generate the second version because it is simple and it goes something like this. This `<span style="font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap;color:rgb(102,102,102)">&</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">s</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">[</span><span style="font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap;color:rgb(64,160,112)">1</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">].</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">Z</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">.</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">B</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">[</span><span style="font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap;color:rgb(64,160,112)">5</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">][</span><span style="font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap;color:rgb(64,160,112)">13</span><span style="background-color:rgb(248,248,248);color:rgb(0,0,0);font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;white-space:pre-wrap">];`</span> is actually broken into many small expressions in the Abstract Syntax Tree (AST). Every dereference is basically one expression. When Clang generates code, for every sub-expression generates a getelementptr (GEP), which is used as input to the next expression and that's about it. So, Clang doesn't go one step further</div><div>to understand all these small sub-expressions as one big expression and create only one GEP.</div><div><br></div><div>Now, when optimizations are turned on, all these GEPs are folded into one [1].</div><div><br></div><div>You can even go one step further and try to find which transformation does the job, by using `opt`, the tool which helps experimenting with optimizations. You literally just copy and paste the LLVM IR you got from Clang again into Godbolt,</div><div>add -O1 and add the argument -print-changed=quiet [2]. This will show you the LLVM IR only after the passes that succeeded to do some change. You can see that the real work was done by Instruction Combining.</div><div>You can run it on its own to see the effect [3].</div><div><br></div><div>Finally, you can even go one step further and see where in the code of the pass this happens. That would require downloading LLVM, inspecting the debug output and setting a bunch of breakpoints</div><div>but after doing all that, you could find this [4].</div><div><br></div><div>Hope this helps!</div><div><br></div><div>Best,</div><div>Stefanos</div><div><br></div><div>[1] <a href="https://godbolt.org/z/51cs6656o">https://godbolt.org/z/51cs6656o</a></div><div>[2] <a href="https://godbolt.org/z/T1v4MfrGW">https://godbolt.org/z/T1v4MfrGW</a></div><div>[3] <a href="https://godbolt.org/z/sTehE7eo1">https://godbolt.org/z/sTehE7eo1</a></div><div>[4] <a href="https://github.com/llvm/llvm-project/blob/6b9524a05bab21c6b0ba4fe025864cb613605b99/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp#L2031">https://github.com/llvm/llvm-project/blob/6b9524a05bab21c6b0ba4fe025864cb613605b99/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp#L2031</a></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Στις Κυρ, 30 Μαΐ 2021 στις 10:13 π.μ., ο/η 周书林 via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> έγραψε:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi everyone, <div><br></div><div>I am learning llvm IR from official documents, especially the GEP instruction. </div><div><br></div><div>Now I have a problem about the GEP instructions generated by llvm.</div><div><br></div><div>As the example in 

<a href="https://llvm.org/docs/LangRef.html#getelementptr-instruction" target="_blank">https://llvm.org/docs/LangRef.html#getelementptr-instruction</a> say, for the function "<b>foo" </b>in the following code example:</div><div><pre style="overflow:auto hidden;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;line-height:16.625px;padding:0.5em;border:1px solid rgb(204,204,204);background-color:rgb(248,248,248);color:rgb(0,0,0)"><span style="color:rgb(0,112,32);font-weight:bold">struct</span> <span style="color:rgb(14,132,181);font-weight:bold">RT</span> <span>{</span>
  <span style="color:rgb(144,32,0)">char</span> <span>A</span><span>;</span>
  <span style="color:rgb(144,32,0)">int</span> <span>B</span><span>[</span><span style="color:rgb(64,160,112)">10</span><span>][</span><span style="color:rgb(64,160,112)">20</span><span>];</span>
  <span style="color:rgb(144,32,0)">char</span> <span>C</span><span>;</span>
<span>};</span>
<span style="color:rgb(0,112,32);font-weight:bold">struct</span> <span style="color:rgb(14,132,181);font-weight:bold">ST</span> <span>{</span>
  <span style="color:rgb(144,32,0)">int</span> <span>X</span><span>;</span>
  <span style="color:rgb(144,32,0)">double</span> <span>Y</span><span>;</span>
  <span style="color:rgb(0,112,32);font-weight:bold">struct</span> <span style="color:rgb(14,132,181);font-weight:bold">RT</span> <span>Z</span><span>;</span>
<span>};</span>

<span style="color:rgb(144,32,0)">int</span> <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(6,40,126)">foo</span><span>(</span><span style="color:rgb(0,112,32);font-weight:bold">struct</span> <span style="color:rgb(14,132,181);font-weight:bold">ST</span> <span style="color:rgb(102,102,102)">*</span><span>s</span><span>)</span> <span>{</span>
  <span style="color:rgb(0,112,32);font-weight:bold">return</span> <span style="color:rgb(102,102,102)">&</span><span>s</span><span>[</span><span style="color:rgb(64,160,112)">1</span><span>].</span><span>Z</span><span>.</span><span>B</span><span>[</span><span style="color:rgb(64,160,112)">5</span><span>][</span><span style="color:rgb(64,160,112)">13</span><span>];</span>
<span>}</span></pre></div><div>the IR could be:</div><div><pre style="overflow:auto hidden;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;line-height:16.625px;padding:0.5em;border:1px solid rgb(204,204,204);background-color:rgb(248,248,248);color:rgb(0,0,0)"><span style="color:rgb(0,112,32);font-weight:bold">define</span> <span style="color:rgb(144,32,0)">i32</span><span>*</span> <span style="color:rgb(187,96,213)">@foo</span><span>(</span><span style="color:rgb(187,96,213)">%struct.ST</span><span>*</span> <span style="color:rgb(187,96,213)">%s</span><span>)</span> <span style="color:rgb(0,112,32);font-weight:bold">nounwind</span> <span style="color:rgb(0,112,32);font-weight:bold">uwtable</span> <span style="color:rgb(0,112,32);font-weight:bold">readnone</span> <span style="color:rgb(0,112,32);font-weight:bold">optsize</span> <span style="color:rgb(0,112,32);font-weight:bold">ssp</span> <span>{</span>
<span style="color:rgb(0,32,112);font-weight:bold">entry:</span>
  <span style="color:rgb(187,96,213)">%arrayidx</span> <span>=</span> <span style="color:rgb(0,112,32);font-weight:bold">getelementptr</span> <span style="color:rgb(0,112,32);font-weight:bold">inbounds</span> <span style="color:rgb(187,96,213)">%struct.ST</span><span>,</span> <span style="color:rgb(187,96,213)">%struct.ST</span><span>*</span> <span style="color:rgb(187,96,213)">%s</span><span>,</span> <span style="color:rgb(144,32,0)">i64</span> <span style="color:rgb(64,160,112)">1</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">2</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">1</span><span>,</span> <span style="color:rgb(144,32,0)">i64</span> <span style="color:rgb(64,160,112)">5</span><span>,</span> <span style="color:rgb(144,32,0)">i64</span> <span style="color:rgb(64,160,112)">13</span>
  <span style="color:rgb(0,112,32);font-weight:bold">ret</span> <span style="color:rgb(144,32,0)">i32</span><span>*</span> <span style="color:rgb(187,96,213)">%arrayidx</span>
<span>}</span></pre></div><div>or </div><div><pre style="overflow:auto hidden;font-family:Consolas,"Deja Vu Sans Mono","Bitstream Vera Sans Mono",monospace;font-size:0.95em;line-height:16.625px;padding:0.5em;border:1px solid rgb(204,204,204);background-color:rgb(248,248,248);color:rgb(0,0,0)"><span style="color:rgb(0,112,32);font-weight:bold">define</span> <span style="color:rgb(144,32,0)">i32</span><span>*</span> <span style="color:rgb(187,96,213)">@foo</span><span>(</span><span style="color:rgb(187,96,213)">%struct.ST</span><span>*</span> <span style="color:rgb(187,96,213)">%s</span><span>)</span> <span>{</span>
  <span style="color:rgb(187,96,213)">%t1</span> <span>=</span> <span style="color:rgb(0,112,32);font-weight:bold">getelementptr</span> <span style="color:rgb(187,96,213)">%struct.ST</span><span>,</span> <span style="color:rgb(187,96,213)">%struct.ST</span><span>*</span> <span style="color:rgb(187,96,213)">%s</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">1</span>                        <span style="color:rgb(96,160,176);font-style:italic">; yields %struct.ST*:%t1</span>
  <span style="color:rgb(187,96,213)">%t2</span> <span>=</span> <span style="color:rgb(0,112,32);font-weight:bold">getelementptr</span> <span style="color:rgb(187,96,213)">%struct.ST</span><span>,</span> <span style="color:rgb(187,96,213)">%struct.ST</span><span>*</span> <span style="color:rgb(187,96,213)">%t1</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">0</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">2</span>                <span style="color:rgb(96,160,176);font-style:italic">; yields %struct.RT*:%t2</span>
  <span style="color:rgb(187,96,213)">%t3</span> <span>=</span> <span style="color:rgb(0,112,32);font-weight:bold">getelementptr</span> <span style="color:rgb(187,96,213)">%struct.RT</span><span>,</span> <span style="color:rgb(187,96,213)">%struct.RT</span><span>*</span> <span style="color:rgb(187,96,213)">%t2</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">0</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">1</span>                <span style="color:rgb(96,160,176);font-style:italic">; yields [10 x [20 x i32]]*:%t3</span>
  <span style="color:rgb(187,96,213)">%t4</span> <span>=</span> <span style="color:rgb(0,112,32);font-weight:bold">getelementptr</span> <span>[</span><span style="color:rgb(64,160,112)">10</span> <span>x</span> <span>[</span><span style="color:rgb(64,160,112)">20</span> <span>x</span> <span style="color:rgb(144,32,0)">i32</span><span>]],</span> <span>[</span><span style="color:rgb(64,160,112)">10</span> <span>x</span> <span>[</span><span style="color:rgb(64,160,112)">20</span> <span>x</span> <span style="color:rgb(144,32,0)">i32</span><span>]]*</span> <span style="color:rgb(187,96,213)">%t3</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">0</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">5</span>  <span style="color:rgb(96,160,176);font-style:italic">; yields [20 x i32]*:%t4</span>
  <span style="color:rgb(187,96,213)">%t5</span> <span>=</span> <span style="color:rgb(0,112,32);font-weight:bold">getelementptr</span> <span>[</span><span style="color:rgb(64,160,112)">20</span> <span>x</span> <span style="color:rgb(144,32,0)">i32</span><span>],</span> <span>[</span><span style="color:rgb(64,160,112)">20</span> <span>x</span> <span style="color:rgb(144,32,0)">i32</span><span>]*</span> <span style="color:rgb(187,96,213)">%t4</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">0</span><span>,</span> <span style="color:rgb(144,32,0)">i32</span> <span style="color:rgb(64,160,112)">13</span>               <span style="color:rgb(96,160,176);font-style:italic">; yields i32*:%t5</span>
  <span style="color:rgb(0,112,32);font-weight:bold">ret</span> <span style="color:rgb(144,32,0)">i32</span><span>*</span> <span style="color:rgb(187,96,213)">%t5</span>
<span>}</span></pre></div><div>I wonder when the llvm will generate the former one, and when it will generate the later one?</div><div><br></div><div>Thank you very much!</div><div><br></div><div>Sincerely,</div><div>Shulin</div><div><br></div><div><br></div></div>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>