<html>
<head>
<base href="https://llvm.org/bugs/" />
</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 r228826, fdiv can be hoisted incorrectly on i386" href="https://urldefense.proofpoint.com/v2/url?u=https-3A__llvm.org_bugs_show-5Fbug.cgi-3Fid-3D24343&d=AwMBaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=pF93YEPyB-J_PERP4DUZOJDzFVX5ZQ57vQk33wu0vio&m=UjsiDHFMDWdc5bT3Yq69RDZtx9dnlU6KYjHwxlL0sj4&s=GHssC_9dnZhHStPlm44w3EMIc70z_4A3WEw_Lrq4DPo&e=">24343</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>After r228826, fdiv can be hoisted incorrectly on i386
</td>
</tr>
<tr>
<th>Product</th>
<td>new-bugs
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</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>llvmbugs@cs.uiuc.edu
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>During a mass test build of the FreeBSD ports collection with a recent clang
trunk snapshot, we ran into strange libpng failures on i386:
<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__package18.nyi.freebsd.org_data_headi386PR201377-2Ddefault_2015-2D07-2D31-5F12h04m22s_logs_errors_png-2D1.6.17-5F1.log&d=AwMBaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=pF93YEPyB-J_PERP4DUZOJDzFVX5ZQ57vQk33wu0vio&m=UjsiDHFMDWdc5bT3Yq69RDZtx9dnlU6KYjHwxlL0sj4&s=8wEgguhyFYBdc74VAK7TtVpkjQls6tMouKW-Tn6w1qk&e=">http://package18.nyi.freebsd.org/data/headi386PR201377-default/2015-07-31_12h04m22s/logs/errors/png-1.6.17_1.log</a>
After some digging, it turned out that the failing tests get a 'division by
zero' floating point exception, when calling pow() with a 0 first argument.
Note that all libpng tests enable such floating point exceptions using
feenableexcept(3).
The FPE occurs in the following part of pow()'s FreeBSD implementation, on line
166:
161 /* special value of x */
162 if(lx==0) {
163 if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
164 z = ax; /*x is +-0,+-inf,+-1*/
165 if(hy<0)
166 z = 1.0/z; /* z = (1/|x|) */
167 if(hx<0) {
168 if(((ix-0x3ff00000)|yisint)==0) {
169 z = (z-z)/(z-z); /* (-1)**non-int is NaN */
170 } else if(yisint==1)
171 z = -z; /* (x<0)**odd = -(|x|**odd) */
172 }
173 return z;
174 }
175 }
However, for the particular tests, at line 165 'hy' is zero, so line 166 should
really have been skipped. But inspection of the assembly (in this case
produced by trunk r241361) shows that the fdiv has been incorrectly hoisted
above the conditional jump (js .LBB_024):
.Ltmp96:
#DEBUG_VALUE: pow:ix <- ESI
#DEBUG_VALUE: pow:yisint <- 0
#DEBUG_VALUE: pow:z <- FP3
#DEBUG_VALUE: pow:ax <- FP3
.loc 1 165 8 is_stmt 1 # e_pow.c:165:8
cmpl $0, 36(%esp) # 4-byte Folded Reload
.loc 1 166 14 # e_pow.c:166:14
fld1
fdiv %st(1)
.Ltmp97:
#DEBUG_VALUE: pow:z <- FP1
js .LBB0_24
.Ltmp98:
# BB#23: # %if.then.107
fstp %st(0)
Compare this with the correct output of clang 3.6.1, where the fdiv is only
done in case the conditional fails:
.Ltmp101:
#DEBUG_VALUE: pow:ix <- ESI
#DEBUG_VALUE: pow:yisint <- 0
#DEBUG_VALUE: pow:z <- FP1
#DEBUG_VALUE: pow:ax <- FP1
.loc 1 165 6 is_stmt 1 # e_pow.c:165:6
cmpl $0, 36(%esp) # 4-byte Folded Reload
jns .LBB0_24
.Ltmp102:
# BB#23: # %if.then108
#DEBUG_VALUE: pow:ix <- ESI
#DEBUG_VALUE: pow:yisint <- 0
#DEBUG_VALUE: pow:z <- FP1
#DEBUG_VALUE: pow:ax <- FP1
fld1
.loc 1 166 11 # e_pow.c:166:11
.Ltmp103:
fdivp %st(1)
.Ltmp104:
.LBB0_24: # %if.end110
Bisecting showed that this invalid hoisting has been introduced by r228826,
"[SimplifyCFG] Swap to using TargetTransformInfo for cost analysis". I am
unsure why, though; it does not seem to touch i387 FP code directly?
Here is a minimal C test case to show the issue; it can also be run to show the
FPE:
#include <fenv.h>
__attribute__((__noinline__)) double foo(int n, double d)
{
if (n > 0)
d = 1.0 / d;
return d;
}
int main(void)
{
feenableexcept(FE_DIVBYZERO);
return (int)foo(0, 0.0);
}
Compile this with: clang -target i386-freebsd -O2 -S bad-hoist.c
Correct result with clang at r228825:
foo: # @foo
# BB#0: # %entry
pushl %ebp
movl %esp, %ebp
fldl 12(%ebp)
cmpl $0, 8(%ebp)
jle .LBB0_2
# BB#1: # %if.then
fld1
fdivp %st(1)
.LBB0_2: # %if.end
Bad result with clang at r228826:
foo: # @foo
# BB#0: # %entry
pushl %ebp
movl %esp, %ebp
fldl 12(%ebp)
cmpl $0, 8(%ebp)
fld1
fdiv %st(1)
jg .LBB0_2
# BB#1: # %entry
fstp %st(0)
fldz
fxch %st(1)
.LBB0_2: # %entry</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>