<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;
      charset=windows-1252">
  </head>
  <body>
    <p>JFYI, <a class="moz-txt-link-freetext" href="https://reviews.llvm.org/D107381">https://reviews.llvm.org/D107381</a> works in this direction,
      and the reduced test case does unroll with that patch and the
      following command line.</p>
    <p>$ opt -loop-unroll  -enable-new-pm=0 < llvm-dev.ll -S
      -unroll-runtime -debug -unroll-runtime-multi-exit
      -unroll-runtime-epilog<br>
    </p>
    <div class="moz-cite-prefix">On 7/20/21 10:17 AM, Philip Reames
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:b3ab6df8-9c6c-f36a-bed3-a914cf7972e3@philipreames.com">
      <meta http-equiv="Content-Type" content="text/html;
        charset=windows-1252">
      ./opt -loop-unroll  -enable-new-pm=0 < llvm-dev.ll -S
      -unroll-runtime -debug<br>
      Args: ./opt -loop-unroll -enable-new-pm=0 -S -unroll-runtime
      -debug <br>
      Loop Unroll: F[test] Loop %while.body.us<br>
        Loop Size = 10<br>
        runtime unrolling with count: 8<br>
        Exiting block %if.end8.us: TripCount=0, TripMultiple=1,
      BreakoutTrip=1<br>
        Exiting block %while.cond.backedge: TripCount=0, TripMultiple=1,
      BreakoutTrip=1<br>
      Trying runtime unrolling on Loop: <br>
      Loop at depth 1 containing:
%while.body.us<header>,%if.end8.us<exiting>,%while.cond.backedge<latch><exiting><br>
      Using prolog remainder.<br>
      Bailout for multi-exit handling when latch exit has >1
      predecessor.<br>
      Multiple exit/exiting blocks in loop and multi-exit unrolling not
      enabled!<br>
      Won't unroll; remainder loop could not be generated when assuming
      runtime trip count<br>
      ; ModuleID = '<stdin>'<br>
      source_filename = "<stdin>"<br>
      <br>
      declare i32 @foo(i8*)<br>
      <br>
      define void @test(i8* %s, i64 %a) {<br>
      entry:<br>
        %s.addr.a = getelementptr i8, i8* %s, i64 %a<br>
        br label %while.body.us<br>
      <br>
      while.body.us:                                    ; preds =
      %while.cond.backedge, %entry<br>
        %s.addr = phi i8* [ %incdec.ptr, %while.cond.backedge ], [ %s,
      %entry ]<br>
        %incdec.ptr = getelementptr inbounds i8, i8* %s.addr, i64 1<br>
        %incdec.val = load i8, i8* %s.addr, align 1<br>
        %cmp1 = icmp eq i8 %incdec.val, 10<br>
        br i1 %cmp1, label %if.end8.us, label %while.cond.backedge<br>
      <br>
      if.end8.us:                                       ; preds =
      %while.body.us<br>
        %call9 = tail call i32 @foo(i8* nonnull %incdec.ptr)<br>
        %cmp2 = icmp ult i32 %call9, 0<br>
        br i1 %cmp2, label %while.cond.backedge, label %return.loopexit<br>
      <br>
      while.cond.backedge:                              ; preds =
      %if.end8.us, %while.body.us<br>
        %cmp3 = icmp eq i8* %incdec.ptr, %s.addr.a<br>
        br i1 %cmp3, label %return.loopexit, label %while.body.us<br>
      <br>
      return.loopexit:                                  ; preds =
      %while.cond.backedge, %if.end8.us<br>
        ret void<br>
      }<br>
      <p>The debug output appears to give a pretty good clue as to where
        you could start if desired.</p>
      <p>Philip<br>
      </p>
      <div class="moz-cite-prefix">On 7/20/21 9:45 AM, Jingu Kang wrote:<br>
      </div>
      <blockquote type="cite"
cite="mid:VE1PR08MB4670A7930765371270AF676F99E29@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:"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:"\@Malgun Gothic";}@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}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">Hi Philip,<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">I have reduced the test case roughly as
            below.<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">declare i32 @foo(i8 *)<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">define void @test(i8* %s, i64 %a) {<o:p></o:p></p>
          <p class="MsoNormal">entry:<o:p></o:p></p>
          <p class="MsoNormal">  %s.addr.a = getelementptr i8, i8* %s,
            i64 %a<o:p></o:p></p>
          <p class="MsoNormal">  br label %while.body.us<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">while.body.us:    <o:p></o:p></p>
          <p class="MsoNormal">  %s.addr = phi i8* [ %incdec.ptr,
            %while.cond.backedge ], [ %s, %entry ]<o:p></o:p></p>
          <p class="MsoNormal">  %incdec.ptr = getelementptr inbounds
            i8, i8* %s.addr, i64 1<o:p></o:p></p>
          <p class="MsoNormal">  %incdec.val = load i8, i8* %s.addr,
            align 1<o:p></o:p></p>
          <p class="MsoNormal">  %cmp1 = icmp eq i8 %incdec.val, 10<o:p></o:p></p>
          <p class="MsoNormal">  br i1 %cmp1, label %if.end8.us, label
            %while.cond.backedge<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">if.end8.us:    <o:p></o:p></p>
          <p class="MsoNormal">  %call9 = tail call i32 @foo(i8* nonnull
            %incdec.ptr)<o:p></o:p></p>
          <p class="MsoNormal">  %cmp2 = icmp ult i32 %call9, 0<o:p></o:p></p>
          <p class="MsoNormal">  br i1 %cmp2, label
            %while.cond.backedge, label %return.loopexit<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">while.cond.backedge:<o:p></o:p></p>
          <p class="MsoNormal">  %cmp3 = icmp eq i8* %incdec.ptr,
            %s.addr.a<o:p></o:p></p>
          <p class="MsoNormal">  br i1 %cmp3, label %return.loopexit,
            label %while.body.us<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">return.loopexit:    <o:p></o:p></p>
          <p class="MsoNormal">  ret void<o:p></o:p></p>
          <p class="MsoNormal">}<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">Roughly, I unrolled the loop manually 2
            times as below and ignored the remaining loop simply.<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">define void @test(i8* %s, i64 %a) {<o:p></o:p></p>
          <p class="MsoNormal">entry:<o:p></o:p></p>
          <p class="MsoNormal">  %s.addr.a = getelementptr i8, i8* %s,
            i64 %a<o:p></o:p></p>
          <p class="MsoNormal">  br label %while.body.us<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">while.body.us:    <o:p></o:p></p>
          <p class="MsoNormal">  %s.addr = phi i8* [ %incdec.ptr,
            %while.cond.backedge ], [ %s, %entry ]<o:p></o:p></p>
          <p class="MsoNormal">  %incdec.ptr = getelementptr inbounds
            i8, i8* %s.addr, i64 1<o:p></o:p></p>
          <p class="MsoNormal">  %incdec.val = load i8, i8* %s.addr,
            align 1<o:p></o:p></p>
          <p class="MsoNormal">  %cmp1 = icmp eq i8 %incdec.val, 10<o:p></o:p></p>
          <p class="MsoNormal">  br i1 %cmp1, label %if.end8.us, label
            %while.body.us.1<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">while.body.us.1:    <o:p></o:p></p>
          <p class="MsoNormal">  %incdec.ptr.1 = getelementptr inbounds
            i8, i8* %incdec.ptr, i64 1<o:p></o:p></p>
          <p class="MsoNormal">  %incdec.val.1 = load i8, i8*
            %incdec.ptr, align 1<o:p></o:p></p>
          <p class="MsoNormal">  %cmp1.1 = icmp eq i8 %incdec.val.1, 10<o:p></o:p></p>
          <p class="MsoNormal">  br i1 %cmp1.1, label %if.end8.us, label
            %while.cond.backedge<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">if.end8.us:    <o:p></o:p></p>
          <p class="MsoNormal">  %incdec.ptr.phi = phi i8* [
            %incdec.ptr, %while.body.us ], [ %incdec.ptr.1,
            %while.body.us.1 ]<o:p></o:p></p>
          <p class="MsoNormal">  %call9 = tail call i32 @foo(i8* nonnull
            %incdec.ptr.phi)<o:p></o:p></p>
          <p class="MsoNormal">  %cmp2 = icmp ult i32 %call9, 0<o:p></o:p></p>
          <p class="MsoNormal">  br i1 %cmp2, label
            %while.cond.backedge, label %return.loopexit<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">while.cond.backedge:<o:p></o:p></p>
          <p class="MsoNormal">  %cmp3 = icmp eq i8* %incdec.ptr.1,
            %s.addr.a<o:p></o:p></p>
          <p class="MsoNormal">  br i1 %cmp3, label %return.loopexit,
            label %while.body.us<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">return.loopexit:    <o:p></o:p></p>
          <p class="MsoNormal">  ret void<o:p></o:p></p>
          <p class="MsoNormal">}<o:p></o:p></p>
          <p class="MsoNormal"><o:p> </o:p></p>
          <p class="MsoNormal">If possible, can we make loop unroll pass
            handle this kind of cases please?<o:p></o:p></p>
          <p class="MsoNormal">If I missed something, please let me
            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"
                    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 20:12<br>
                  <b>To:</b> Jingu Kang <a
                    class="moz-txt-link-rfc2396E"
                    href="mailto:Jingu.Kang@arm.com"
                    moz-do-not-send="true"><Jingu.Kang@arm.com></a><br>
                  <b>Cc:</b> <a class="moz-txt-link-abbreviated"
                    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>Jingu,<o:p></o:p></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.� <o:p></o:p></p>
            <p>Philip<o:p></o:p></p>
            <div>
              <p class="MsoNormal">On 7/16/21 12:09 PM, Jingu Kang
                wrote:<o:p></o:p></p>
            </div>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <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
                        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 18:27<br>
                      <b>To:</b> Jingu Kang <a
                        href="mailto:Jingu.Kang@arm.com"
                        moz-do-not-send="true"><Jingu.Kang@arm.com></a><br>
                      <b>Cc:</b> <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>�<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>
                  <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>
                  <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>
                        <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>
            </blockquote>
          </div>
        </div>
      </blockquote>
    </blockquote>
  </body>
</html>