[LLVMbugs] [Bug 24343] New: After r228826, fdiv can be hoisted incorrectly on i386

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Mon Aug 3 11:01:09 PDT 2015


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

            Bug ID: 24343
           Summary: After r228826, fdiv can be hoisted incorrectly on i386
           Product: new-bugs
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: dimitry at andric.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

During a mass test build of the FreeBSD ports collection with a recent clang
trunk snapshot, we ran into strange libpng failures on i386:

http://package18.nyi.freebsd.org/data/headi386PR201377-default/2015-07-31_12h04m22s/logs/errors/png-1.6.17_1.log

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

-- 
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/20150803/bf2618a3/attachment.html>


More information about the llvm-bugs mailing list