<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>