[llvm-bugs] [Bug 41998] New: After r345814, IndVars regression causing infinite loop

via llvm-bugs llvm-bugs at lists.llvm.org
Thu May 23 12:54:03 PDT 2019


https://bugs.llvm.org/show_bug.cgi?id=41998

            Bug ID: 41998
           Summary: After r345814, IndVars regression causing infinite
                    loop
           Product: new-bugs
           Version: 8.0
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: dimitry at andric.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org

As reported in https://bugs.freebsd.org/237515 and
https://github.com/michaelrsweet/htmldoc/issues/349, 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
https://reviews.llvm.org/rL345814 ("[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... :-/

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190523/27f0d04d/attachment.html>


More information about the llvm-bugs mailing list