<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - After r345814, IndVars regression causing infinite loop"
   href="https://bugs.llvm.org/show_bug.cgi?id=41998">41998</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>After r345814, IndVars regression causing infinite loop
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>8.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>dimitry@andric.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>As reported in <a href="https://bugs.freebsd.org/237515">https://bugs.freebsd.org/237515</a> and
<a href="https://github.com/michaelrsweet/htmldoc/issues/349">https://github.com/michaelrsweet/htmldoc/issues/349</a>, the HTMLDOC program
compiled with clang 8.0 hangs (and eventually causes a stack overflow)
when processing a PDF.

Bisection shows this is a regression caused by
<a href="https://reviews.llvm.org/rL345814">https://reviews.llvm.org/rL345814</a> ("[IndVars] Smart hard uses
detection").

I attempted to minimize the test case as much as possible; the following
is a small self-contained program showing the issue:

========================================================================
#include <stdio.h>

__attribute__((__noinline__)) void parse_pre(const char *dataptr) {
  int col;
  char line[1024];
  char *lineptr;

  for (col = 0, lineptr = line; *dataptr != '\0'; dataptr++) {
    printf("before inner loop: col=%d, diff=%td\n", col, lineptr - line);
    do {
      printf("inside inner loop: col=%d, diff=%td\n", col, lineptr - line);
      *lineptr++ = ' ';
      col++;
    } while (col & 7);
  }
}

int main(void) {
  parse_pre("a");

  return 0;
}
========================================================================

What appears to happen is that IndVars pulls the (col & 7) test out of
the inner loop, but it precalculates the iteration count incorrectly,
causing that inner loop to never exit.  It will keep on overwriting the
line[] buffer until it crashes.

With clang trunk r345813, the inner loop looks like:

.LBB0_3:                                # %do.body
                                        #   Parent Loop BB0_2 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
        #DEBUG_VALUE: parse_pre:lineptr <- [DW_OP_constu 48, DW_OP_minus]
[$rbp+0]
        #DEBUG_VALUE: parse_pre:dataptr <- [DW_OP_constu 56, DW_OP_minus]
[$rbp+0]
        #DEBUG_VALUE: parse_pre:col <- $r15d
        #DEBUG_VALUE: parse_pre:col <- $ebx
        #DEBUG_VALUE: parse_pre:lineptr <- $r13
        .loc    1 11 68 is_stmt 1       # ps-pdf-min.c:11:68
        movq    %r13, %rdx
        subq    %r12, %rdx
        .loc    1 11 7 is_stmt 0        # ps-pdf-min.c:11:7
        movl    $.L.str.1, %edi
        xorl    %eax, %eax
        movl    %ebx, %esi
        callq   printf
        .loc    1 12 18 is_stmt 1       # ps-pdf-min.c:12:18
        movb    $32, (%r13)
        .loc    1 12 15 is_stmt 0       # ps-pdf-min.c:12:15
        addq    $1, %r13
.Ltmp9:
        .loc    1 13 10 is_stmt 1       # ps-pdf-min.c:13:10
        addl    $1, %ebx
.Ltmp10:
        #DEBUG_VALUE: parse_pre:col <- $ebx
        .loc    1 14 5                  # ps-pdf-min.c:14:5
        testb   $7, %bl
        jne     .LBB0_3

E.g., %ebx contains 'col', is increased by 'addl $1, %ebx', and is then
tested with 'testb $7, %bl'.  This works correctly.

With clang trunk r345814, the inner loop becomes:

        .loc    1 10 5 is_stmt 1        # ps-pdf-min.c:10:5
        movl    %r12d, %r13d
        negl    %r13d
        andl    $7, %r13d
        leaq    (%rbx,%r13), %rax
.Ltmp6:
        #DEBUG_VALUE: parse_pre:lineptr <- [DW_OP_constu 48, DW_OP_minus]
[$rbp+0]
        .loc    1 0 5 is_stmt 0         # ps-pdf-min.c:0:5
        movq    %rax, -48(%rbp)         # 8-byte Spill
.Ltmp7:
        .p2align        4, 0x90
.LBB0_3:                                # %do.body
                                        #   Parent Loop BB0_2 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
        #DEBUG_VALUE: parse_pre:lineptr <- [DW_OP_constu 48, DW_OP_minus]
[$rbp+0]
        #DEBUG_VALUE: parse_pre:col <- $r12d
        #DEBUG_VALUE: parse_pre:dataptr <- $r14
        #DEBUG_VALUE: parse_pre:col <- $r12d
        #DEBUG_VALUE: parse_pre:lineptr <- $rbx
        .loc    1 11 68 is_stmt 1       # ps-pdf-min.c:11:68
        movq    %rbx, %rdx
        subq    %r15, %rdx
        .loc    1 11 7 is_stmt 0        # ps-pdf-min.c:11:7
        movl    $.L.str.1, %edi
        xorl    %eax, %eax
        movl    %r12d, %esi
        callq   printf
        .loc    1 12 18 is_stmt 1       # ps-pdf-min.c:12:18
        movb    $32, (%rbx)
        .loc    1 12 15 is_stmt 0       # ps-pdf-min.c:12:15
        addq    $1, %rbx
.Ltmp8:
        .loc    1 13 10 is_stmt 1       # ps-pdf-min.c:13:10
        addl    $1, %r12d
.Ltmp9:
        #DEBUG_VALUE: parse_pre:col <- $r12d
        .loc    1 14 5                  # ps-pdf-min.c:14:5
        addq    $-1, %r13
        jne     .LBB0_3

Here, %r12d contains 'col', which is first stored in %r13d, negated,
then anded with $7.  Unfortunately, on the first loop, 'col' is zero, so
negation doesn't do anything, and neither does 'andl $7'.  So at the end
of the loop, %r13 is decremented to -1, and the loop effectively
executes 2^64 times... :-/</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>