<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;
      charset=windows-1252">
  </head>
  <body>
    <p>Jingu,</p>
    <p>I'm not fluent in AArch64 assembly, sorry.  If you want more
      meaningful commentary, you'll need to reduce your c++ example
      further, and give a better explanation of what you expect the
      unroller to do for you.  <br>
    </p>
    <p>Philip<br>
    </p>
    <div class="moz-cite-prefix">On 7/16/21 12:09 PM, Jingu Kang wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:VE1PR08MB467078B15A8CD691095F345699119@VE1PR08MB4670.eurprd08.prod.outlook.com">
      <meta http-equiv="Content-Type" content="text/html;
        charset=windows-1252">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:Batang;
        panose-1:2 3 6 0 0 1 1 1 1 1;}@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:"Malgun Gothic";
        panose-1:2 11 5 3 2 0 0 2 0 4;}@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}@font-face
        {font-family:"\@Malgun Gothic";}@font-face
        {font-family:"\@Batang";
        panose-1:2 3 6 0 0 1 1 1 1 1;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0cm;
        font-size:10.0pt;
        font-family:"Courier New";}span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:Consolas;}span.EmailStyle21
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}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]-->
      <div class="WordSection1">
        <p class="MsoNormal">Sorry for poor example…<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">The AArch64 assembly output of the example
          from gcc is as below. The loop is unrolled 7 times. I have
          written some comments to explain how the assembly code is
          mapped to C source code. As you can see on `.L3` label, the
          ‘if (*s++ != '\n')’ block is unrolled 7 times. <o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">        stp     x29, x30, [sp, -48]!<o:p></o:p></p>
        <p class="MsoNormal">        mov     x29, sp<o:p></o:p></p>
        <p class="MsoNormal">        stp     x19, x20, [sp, 16]<o:p></o:p></p>
        <p class="MsoNormal">        mov     x19, x0  --> x19 is char
          *s<o:p></o:p></p>
        <p class="MsoNormal">        mov     x20, x1  --> x20 is char
          *end<o:p></o:p></p>
        <p class="MsoNormal">        str     x21, [sp, 32]<o:p></o:p></p>
        <p class="MsoNormal">        orr     x21, x3, x2  --> x21 is
          check1 | check2<o:p></o:p></p>
        <p class="MsoNormal">.L70:<o:p></o:p></p>
        <p class="MsoNormal">        sub     x0, x20, x19  --> x0 =
          end - s;<o:p></o:p></p>
        <p class="MsoNormal">        add     x1, x0, 1<o:p></o:p></p>
        <p class="MsoNormal">        ands    x2, x1, 7  --> unroll
          count is 7<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L3     --> .L3 is
          inside while loop. if (*s++ != '\n')<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x19, x20  --> while(s
          <= end)<o:p></o:p></p>
        <p class="MsoNormal">        bhi     .L2     --> .L2 is label
          ret1.<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">        ldrb    w3, [x19], 1  --> start
          of remainder<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w3, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x2, 1<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L3<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x2, 2<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L49<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x2, 3<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L50<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x2, 4<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L51<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x2, 5<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L52<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x2, 6<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L53<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w4, [x19], 1<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w4, 10<o:p></o:p></p>
        <p class="MsoNormal">        bne     .L53<o:p></o:p></p>
        <p class="MsoNormal">.L71:<o:p></o:p></p>
        <p class="MsoNormal">        cbz     x21, .L4  --> if(check1
          || check2)<o:p></o:p></p>
        <p class="MsoNormal">        bl      foo()<o:p></o:p></p>
        <p class="MsoNormal">        mov     x19, x0<o:p></o:p></p>
        <p class="MsoNormal">        cbz     x0, .L2   --> if (!s)
          goto ret1;<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">.L4:                      --> if(boo(s))
          goto ret0;<o:p></o:p></p>
        <p class="MsoNormal">        mov     x0, x19<o:p></o:p></p>
        <p class="MsoNormal">        bl      boo(char*)<o:p></o:p></p>
        <p class="MsoNormal">        cbz     w0, .L70<o:p></o:p></p>
        <p class="MsoNormal">        mov     w0, 0<o:p></o:p></p>
        <p class="MsoNormal">        ldp     x19, x20, [sp, 16]<o:p></o:p></p>
        <p class="MsoNormal">        ldr     x21, [sp, 32]<o:p></o:p></p>
        <p class="MsoNormal">        ldp     x29, x30, [sp], 48<o:p></o:p></p>
        <p class="MsoNormal">        ret<o:p></o:p></p>
        <p class="MsoNormal">.L53:          --> if (*s++ != '\n') for
          remainder<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w5, [x19], 1<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w5, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">.L52:          --> if (*s++ != '\n') for
          remainder<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w6, [x19], 1<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w6, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">.L51:          --> if (*s++ != '\n') for
          remainder<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w7, [x19], 1<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w7, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">.L50:          --> if (*s++ != '\n') for
          remainder<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w8, [x19], 1<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w8, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">.L49:          --> if (*s++ != '\n') for
          remainder<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w9, [x19], 1<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w9, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">.L3:                          --> if
          (*s++ != '\n'), 7 times unrolled<o:p></o:p></p>
        <p class="MsoNormal">        cmp     x19, x20<o:p></o:p></p>
        <p class="MsoNormal">        bhi     .L2<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w10, [x19]<o:p></o:p></p>
        <p class="MsoNormal">        add     x19, x19, 1<o:p></o:p></p>
        <p class="MsoNormal">        mov     x11, x19<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w10, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w12, [x19], 1<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w12, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w13, [x11, 1]<o:p></o:p></p>
        <p class="MsoNormal">        add     x19, x11, 2<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w13, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w14, [x11, 2]<o:p></o:p></p>
        <p class="MsoNormal">        add     x19, x11, 3<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w14, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w15, [x11, 3]<o:p></o:p></p>
        <p class="MsoNormal">        add     x19, x11, 4<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w15, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w16, [x11, 4]<o:p></o:p></p>
        <p class="MsoNormal">        add     x19, x11, 5<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w16, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w17, [x11, 5]<o:p></o:p></p>
        <p class="MsoNormal">        add     x19, x11, 6<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w17, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        ldrb    w18, [x11, 6]<o:p></o:p></p>
        <p class="MsoNormal">        add     x19, x11, 7<o:p></o:p></p>
        <p class="MsoNormal">        cmp     w18, 10<o:p></o:p></p>
        <p class="MsoNormal">        beq     .L71<o:p></o:p></p>
        <p class="MsoNormal">        b       .L3<o:p></o:p></p>
        <p class="MsoNormal">.L2:                      --> label ret1<o:p></o:p></p>
        <p class="MsoNormal">        mov     w0, 1<o:p></o:p></p>
        <p class="MsoNormal">        ldp     x19, x20, [sp, 16]<o:p></o:p></p>
        <p class="MsoNormal">        ldr     x21, [sp, 32]<o:p></o:p></p>
        <p class="MsoNormal">        ldp     x29, x30, [sp], 48<o:p></o:p></p>
        <p class="MsoNormal">        ret<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">I am sorry for showing you assembly output
          directly… It looks like the rtl level’s unroll pass of gcc
          unrolls above loop and I need to check it next week. Once I
          have clear idea about above unrolling from gcc, let me reduce
          the example more and let you know. <o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">Thanks<o:p></o:p></p>
        <p class="MsoNormal">JinGu Kang<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <div style="border:none;border-left:solid blue 1.5pt;padding:0cm
          0cm 0cm 4.0pt">
          <div>
            <div style="border:none;border-top:solid #E1E1E1
              1.0pt;padding:3.0pt 0cm 0cm 0cm">
              <p class="MsoNormal"><b>From:</b> llvm-dev
                <a class="moz-txt-link-rfc2396E" href="mailto:llvm-dev-bounces@lists.llvm.org"><llvm-dev-bounces@lists.llvm.org></a> <b>On Behalf Of
                </b>Philip Reames via llvm-dev<br>
                <b>Sent:</b> 16 July 2021 18:27<br>
                <b>To:</b> Jingu Kang <a class="moz-txt-link-rfc2396E" href="mailto:Jingu.Kang@arm.com"><Jingu.Kang@arm.com></a><br>
                <b>Cc:</b> <a class="moz-txt-link-abbreviated" href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br>
                <b>Subject:</b> Re: [llvm-dev] Question about Unrolling
                Loop with Multiple Exits<o:p></o:p></p>
            </div>
          </div>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p><o:p> </o:p></p>
          <div>
            <p class="MsoNormal">On 7/16/21 9:29 AM, Jingu Kang wrote:<o:p></o:p></p>
          </div>
          <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
            <p>Hi Philip,<o:p></o:p></p>
            <p>Thanks for your kind reply.<o:p></o:p></p>
            <p>> A) Are you measuring on tip of tree?� There were
              changes for multiple exit unrolling which landed very
              recently.<o:p></o:p></p>
            <p>Yep, I am investigating benchmarks with llvm tip and I
              can see the llvm fails to unroll some loops with multiple
              exits.<o:p></o:p></p>
            <p class="MsoNormal">> B) One of your exits does not
              dominate your latch.� Those are generally hard<o:p></o:p></p>
            <p class="MsoNormal">> C) This example does not seem to
              require gotos.� I strongly suggest reducing your test
              cases if you want more informed commentary.�<o:p></o:p></p>
            <p class="MsoNormal">�<o:p></o:p></p>
            <p class="MsoNormal">I am looking at perlbench recently and
              it has `goto` statements inside loop. The example is a
              reduced case.
              <o:p></o:p></p>
          </blockquote>
          <p class="MsoNormal">Right, but the gotos aren't relevant for
            your reduced test.� You can reduce further.<br>
            <br>
            <o:p></o:p></p>
          <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
            <p class="MsoNormal">When I look at the gcc�s output of
              the example, it looks like gcc unrolls only the below `if`
              statement block�<o:p></o:p></p>
            <p class="MsoNormal">�<o:p></o:p></p>
            <p class="MsoNormal">��� if (*s++ != '\n')<o:p></o:p></p>
            <p class="MsoNormal">����� continue;<o:p></o:p></p>
          </blockquote>
          <p class="MsoNormal">Your phrasing here does not parse for
            me.� Can you restate this with different wording and maybe
            a fully worked example?<br>
            <br>
            <o:p></o:p></p>
          <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
            <p class="MsoNormal">�<o:p></o:p></p>
            <p class="MsoNormal">Thanks<o:p></o:p></p>
            <p class="MsoNormal">JinGu Kang<o:p></o:p></p>
            <p class="MsoNormal">�<o:p></o:p></p>
            <div style="border:none;border-left:solid blue
              1.5pt;padding:0cm 0cm 0cm 4.0pt">
              <div>
                <div style="border:none;border-top:solid #E1E1E1
                  1.0pt;padding:3.0pt 0cm 0cm 0cm">
                  <p class="MsoNormal"><b>From:</b> llvm-dev <a
                      href="mailto:llvm-dev-bounces@lists.llvm.org"
                      moz-do-not-send="true">
                      <llvm-dev-bounces@lists.llvm.org></a> <b>On
                      Behalf Of </b>Philip Reames via llvm-dev<br>
                    <b>Sent:</b> 16 July 2021 15:52<br>
                    <b>To:</b> Jingu Kang <a
                      href="mailto:Jingu.Kang@arm.com"
                      moz-do-not-send="true"><Jingu.Kang@arm.com></a>;
                    <a href="mailto:llvm-dev@lists.llvm.org"
                      moz-do-not-send="true">llvm-dev@lists.llvm.org</a><br>
                    <b>Subject:</b> Re: [llvm-dev] Question about
                    Unrolling Loop with Multiple Exits<o:p></o:p></p>
                </div>
              </div>
              <p class="MsoNormal">�<o:p></o:p></p>
              <p>A) Are you measuring on tip of tree?� There were
                changes for multiple exit unrolling which landed very
                recently.<o:p></o:p></p>
              <p>B) One of your exits does not dominate your latch.�
                Those are generally hard.�
                <o:p></o:p></p>
              <p>C) This example does not seem to require gotos.� I
                strongly suggest reducing your test cases if you want
                more informed commentary.�
                <o:p></o:p></p>
              <p>Philip<o:p></o:p></p>
              <div>
                <p class="MsoNormal">On 7/16/21 7:42 AM, Jingu Kang via
                  llvm-dev wrote:<o:p></o:p></p>
              </div>
              <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
                <p class="MsoNormal">Hi All,<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">While I am investigating
                  benchmarks, I have found loops which llvm fails to
                  unroll because the loops have multiple exits.<o:p></o:p></p>
                <p class="MsoNormal">For example, <o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">char *foo(void);<o:p></o:p></p>
                <p class="MsoNormal">int boo(char *s);<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">int test(char *s, char *end, char
                  *check1, char *check2) {<o:p></o:p></p>
                <p class="MsoNormal">� while (s <= end) {<o:p></o:p></p>
                <p class="MsoNormal">��� if (*s++ != '\n')<o:p></o:p></p>
                <p class="MsoNormal">����� continue;<o:p></o:p></p>
                <p class="MsoNormal">��� if (check1 || check2) {<o:p></o:p></p>
                <p class="MsoNormal">����� s = foo();<o:p></o:p></p>
                <p class="MsoNormal">����� if (!s)<o:p></o:p></p>
                <p class="MsoNormal">������� goto ret1;<o:p></o:p></p>
                <p class="MsoNormal">��� }�� <o:p></o:p></p>
                <p class="MsoNormal">����if (boo(s))<o:p></o:p></p>
                <p class="MsoNormal">����� goto ret0;<o:p></o:p></p>
                <p class="MsoNormal">� }<o:p></o:p></p>
                <p class="MsoNormal">� goto ret1;<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">ret0:<o:p></o:p></p>
                <p class="MsoNormal">� return 0;<o:p></o:p></p>
                <p class="MsoNormal">ret1:<o:p></o:p></p>
                <p class="MsoNormal">� return 1;<o:p></o:p></p>
                <p class="MsoNormal">}<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">Above code causes below messages
                  from LoopUnroll pass.<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">Bailout for multi-exit handling
                  when latch exit has >1 predecessor.<o:p></o:p></p>
                <p class="MsoNormal">Multiple exit/exiting blocks in
                  loop and multi-exit unrolling not enabled!<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">I can see the option
                  `unroll-runtime-multi-exit` and comments about it. I
                  wonder there are already reviews for the work on
                  phabriactor or some people are working on it.<o:p></o:p></p>
                <p class="MsoNormal">If someone knows information about
                  it, please share it.<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">Thanks<o:p></o:p></p>
                <p class="MsoNormal">JinGu Kang<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal">�<o:p></o:p></p>
                <p class="MsoNormal"><br>
                  <br>
                  <br>
                  <o:p></o:p></p>
                <pre>_______________________________________________<o:p></o:p></pre>
                <pre>LLVM Developers mailing list<o:p></o:p></pre>
                <pre><a href="mailto:llvm-dev@lists.llvm.org" moz-do-not-send="true">llvm-dev@lists.llvm.org</a><o:p></o:p></pre>
                <pre><a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><o:p></o:p></pre>
              </blockquote>
            </div>
          </blockquote>
        </div>
      </div>
    </blockquote>
  </body>
</html>