Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting MARCH=i686 causes dates test to fail on 32 bit #9039

Closed
tkelman opened this issue Nov 17, 2014 · 10 comments
Closed

Setting MARCH=i686 causes dates test to fail on 32 bit #9039

tkelman opened this issue Nov 17, 2014 · 10 comments
Labels
system:32-bit Affects only 32-bit systems

Comments

@tkelman
Copy link
Contributor

tkelman commented Nov 17, 2014

Found over at staticfloat/julia-vagrant#2 (comment) by @staticfloat, should probably move conversation here and cc @quinnj

julia> versioninfo()
Julia Version 0.4.0-dev+1627
Commit 74b8a6b (2014-11-15 17:04 UTC)
Platform Info:
  System: Windows (i686-w64-mingw32)
  CPU: Intel(R) Core(TM)2 Duo CPU     E8400  @ 3.00GHz
  WORD_SIZE: 32
  BLAS: libopenblas (DYNAMIC_ARCH NO_AFFINITY Penryn)
  LAPACK: libopenblas
  LIBM: libopenlibm
  LLVM: libLLVM-3.3

julia> df = Dates.DateFormat("[HH:MM:SS.sss]")
DateFormat(Slot[DelimitedSlot{Hour}(1,Hour,2,0,"english"),DelimitedSlot{Minute}(
2,Minute,2,0,"english"),DelimitedSlot{Second}(3,Second,2,0,"english"),DelimitedS
lot{Millisecond}(4,Millisecond,3,0,"english")],"[",Any[":",":",".","]"])

julia> Dates.slotparse(df.slots[4], "118")
ERROR: InexactError()
 in slotparse at dates/io.jl:99

Oddly if I run the code from

slotparse(slot::Slot{Millisecond},x) = !ismatch(r"[^0-9\s]",x) ? slot.period(parsefloat("."*x)*1000.0) : throw(SLOTERROR)
at the REPL it works fine, but putting that same code inside a new function it gives an InexactError.

Might not be Windows-specific, would need testing on 32-bit Linux to be sure.

@tkelman tkelman added system:windows Affects only Windows system:32-bit Affects only 32-bit systems and removed system:windows Affects only Windows labels Nov 17, 2014
@tkelman
Copy link
Contributor Author

tkelman commented Nov 17, 2014

Oh right, I (mostly) fixed compiling 32-bit Julia on 64-bit Linux a couple weeks ago. This happens on 32 bit Linux too, as far as I can tell.

@tkelman tkelman changed the title Setting MARCH=i686 causes dates test to fail on win32 Setting MARCH=i686 causes dates test to fail on 32 bit Nov 17, 2014
@quinnj
Copy link
Member

quinnj commented Nov 17, 2014

Does the output of @code_llvm give any clues as to what's changing because of architecture here?

@tkelman
Copy link
Contributor Author

tkelman commented Nov 18, 2014

Using this binary https://s3.amazonaws.com/julianightlies/bin/winnt/x86/0.4/julia-0.4.0-dev-1f9a5f0-win32.exe built without MARCH set:

  | | |_| | | | (_| |  |  Version 0.4.0-dev+1640 (2014-11-17 03:42 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit 1f9a5f0* (0 days old master)
|__/                   |  i686-w64-mingw32

julia> df = Dates.DateFormat("[HH:MM:SS.sss]");

julia> Dates.slotparse(df.slots[4], "118")
118 milliseconds

julia> @code_llvm Dates.slotparse(df.slots[4], "118")

; Function Attrs: alignstack(8)
define %Millisecond @"julia_slotparse;1197"(%jl_value_t*, %jl_value_t*) #2 {
top:
  %2 = alloca [5 x %jl_value_t*], align 4
  %.sub = getelementptr inbounds [5 x %jl_value_t*]* %2, i32 0, i32 0
  %3 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 2, !dbg !3648
  store %jl_value_t* inttoptr (i32 6 to %jl_value_t*), %jl_value_t** %.sub, alig
n 4
  %4 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 1, !dbg !3648
  %5 = load %jl_value_t*** @jl_pgcstack, align 4, !dbg !3648
  %.c = bitcast %jl_value_t** %5 to %jl_value_t*, !dbg !3648
  store %jl_value_t* %.c, %jl_value_t** %4, align 4, !dbg !3648
  store %jl_value_t** %.sub, %jl_value_t*** @jl_pgcstack, align 4, !dbg !3648
  store %jl_value_t* null, %jl_value_t** %3, align 4, !dbg !3648
  %6 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 3
  store %jl_value_t* null, %jl_value_t** %6, align 4
  %7 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 4
  store %jl_value_t* null, %jl_value_t** %7, align 4
  %8 = call i1 @"julia_ismatch;251"(%jl_value_t* inttoptr (i32 50910288 to %jl_v
alue_t*), %jl_value_t* %1, i32 0), !dbg !3649
  br i1 %8, label %L, label %if, !dbg !3649

if:                                               ; preds = %top
  store %jl_value_t* inttoptr (i32 50358832 to %jl_value_t*), %jl_value_t** %6,
align 4, !dbg !3649
  store %jl_value_t* %1, %jl_value_t** %7, align 4, !dbg !3649
  %9 = call %jl_value_t* @"julia_string;140"(%jl_value_t* inttoptr (i32 63512432
 to %jl_value_t*), %jl_value_t** %6, i32 2), !dbg !3649
  store %jl_value_t* %9, %jl_value_t** %3, align 4, !dbg !3649
  store %jl_value_t* %9, %jl_value_t** %6, align 4, !dbg !3649
  %10 = call %jl_value_t* @"julia_float64;1149"(%jl_value_t* inttoptr (i32 94475
408 to %jl_value_t*), %jl_value_t** %6, i32 1), !dbg !3649
  %11 = getelementptr inbounds %jl_value_t* %10, i32 1, i32 0, !dbg !3649
  %12 = bitcast %jl_value_t** %11 to double*, !dbg !3649
  %13 = load double* %12, align 8, !dbg !3649
  %14 = fmul double %13, 1.000000e+03, !dbg !3649
  %15 = fptosi double %14 to i64, !dbg !3649
  %16 = sitofp i64 %15 to double, !dbg !3649
  %17 = fptosi double %16 to i64, !dbg !3649
  %18 = icmp eq i64 %15, %17, !dbg !3649
  %19 = fcmp oeq double %14, %16, !dbg !3649
  %20 = and i1 %19, %18, !dbg !3649
  br i1 %20, label %pass, label %fail, !dbg !3649

fail:                                             ; preds = %if
  %21 = load %jl_value_t** @jl_inexact_exception, align 4, !dbg !3649, !tbaa %jt
baa_const
  call void @jl_throw_with_superfluous_argument(%jl_value_t* %21, i32 99), !dbg
!3649
  unreachable, !dbg !3649

pass:                                             ; preds = %if
  %22 = insertvalue %Millisecond undef, i64 %15, 0, !dbg !3649, !julia_type !365
3
  %23 = load %jl_value_t** %4, align 4, !dbg !3649
  %24 = getelementptr inbounds %jl_value_t* %23, i32 0, i32 0, !dbg !3649
  store %jl_value_t** %24, %jl_value_t*** @jl_pgcstack, align 4, !dbg !3649
  ret %Millisecond %22, !dbg !3649

L:                                                ; preds = %top
  %25 = load %jl_value_t** inttoptr (i32 50909528 to %jl_value_t**), align 8, !d
bg !3649
  call void @jl_throw_with_superfluous_argument(%jl_value_t* %25, i32 99), !dbg
!3649
  unreachable
}

Using this binary https://s3.amazonaws.com/julianightlies/bin/winnt/x86/0.4/julia-0.4.0-1f9a5f00b8-win32.exe built with MARCH=i686:

  | | |_| | | | (_| |  |  Version 0.4.0-dev+1640 (2014-11-17 03:42 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit 1f9a5f0 (0 days old master)
|__/                   |  i686-w64-mingw32

julia> df = Dates.DateFormat("[HH:MM:SS.sss]");

julia> Dates.slotparse(df.slots[4], "118")
ERROR: InexactError()
 in slotparse at dates/io.jl:99

julia> @code_llvm Dates.slotparse(df.slots[4], "118")

; Function Attrs: alignstack(8)
define %Millisecond @"julia_slotparse;40928"(%jl_value_t*, %jl_value_t*) #2 {
top:
  %2 = alloca [5 x %jl_value_t*], align 4
  %.sub = getelementptr inbounds [5 x %jl_value_t*]* %2, i32 0, i32 0
  %3 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 2, !dbg !319
  store %jl_value_t* inttoptr (i32 6 to %jl_value_t*), %jl_value_t** %.sub, alig
n 4
  %4 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 1, !dbg !319
  %5 = load %jl_value_t*** @jl_pgcstack, align 4, !dbg !319
  %.c = bitcast %jl_value_t** %5 to %jl_value_t*, !dbg !319
  store %jl_value_t* %.c, %jl_value_t** %4, align 4, !dbg !319
  store %jl_value_t** %.sub, %jl_value_t*** @jl_pgcstack, align 4, !dbg !319
  store %jl_value_t* null, %jl_value_t** %3, align 4, !dbg !319
  %6 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 3
  store %jl_value_t* null, %jl_value_t** %6, align 4
  %7 = getelementptr [5 x %jl_value_t*]* %2, i32 0, i32 4
  store %jl_value_t* null, %jl_value_t** %7, align 4
  %8 = call i1 @julia_ismatch3582(%jl_value_t* inttoptr (i32 45752128 to %jl_val
ue_t*), %jl_value_t* %1, i32 0), !dbg !320
  br i1 %8, label %L, label %if, !dbg !320

if:                                               ; preds = %top
  store %jl_value_t* inttoptr (i32 45541864 to %jl_value_t*), %jl_value_t** %6,
align 4, !dbg !320
  store %jl_value_t* %1, %jl_value_t** %7, align 4, !dbg !320
  %9 = call %jl_value_t* @julia_string(%jl_value_t* inttoptr (i32 59562736 to %j
l_value_t*), %jl_value_t** %6, i32 2), !dbg !320
  store %jl_value_t* %9, %jl_value_t** %3, align 4, !dbg !320
  store %jl_value_t* %9, %jl_value_t** %6, align 4, !dbg !320
  %10 = call %jl_value_t* @"julia_float64;40894"(%jl_value_t* inttoptr (i32 1451
09152 to %jl_value_t*), %jl_value_t** %6, i32 1), !dbg !320
  %11 = getelementptr inbounds %jl_value_t* %10, i32 1, i32 0, !dbg !320
  %12 = bitcast %jl_value_t** %11 to double*, !dbg !320
  %13 = load double* %12, align 8, !dbg !320
  %14 = fmul double %13, 1.000000e+03, !dbg !320
  %15 = fptosi double %14 to i64, !dbg !320
  %16 = sitofp i64 %15 to double, !dbg !320
  %17 = fptosi double %16 to i64, !dbg !320
  %18 = icmp eq i64 %15, %17, !dbg !320
  %19 = fcmp oeq double %14, %16, !dbg !320
  %20 = and i1 %19, %18, !dbg !320
  br i1 %20, label %pass, label %fail, !dbg !320

fail:                                             ; preds = %if
  %21 = load %jl_value_t** @jl_inexact_exception, align 4, !dbg !320, !tbaa %jtb
aa_const
  call void @jl_throw_with_superfluous_argument(%jl_value_t* %21, i32 99), !dbg
!320
  unreachable, !dbg !320

pass:                                             ; preds = %if
  %22 = insertvalue %Millisecond undef, i64 %15, 0, !dbg !320, !julia_type !324
  %23 = load %jl_value_t** %4, align 4, !dbg !320
  %24 = getelementptr inbounds %jl_value_t* %23, i32 0, i32 0, !dbg !320
  store %jl_value_t** %24, %jl_value_t*** @jl_pgcstack, align 4, !dbg !320
  ret %Millisecond %22, !dbg !320

L:                                                ; preds = %top
  %25 = load %jl_value_t** inttoptr (i32 45747816 to %jl_value_t**), align 8, !d
bg !320
  call void @jl_throw_with_superfluous_argument(%jl_value_t* %25, i32 99), !dbg
!320
  unreachable
}

Looks pretty close, not sure if there are any hints in there. The @code_native does look quite a bit different between the two: https://gist.github.com/tkelman/a7fd5d9525af3ae03a63

@jakebolewski
Copy link
Member

I can confirm that this happens on 32 bit linux (found when working on LibGit2 Pkg PR). This was in a VM

Julia Version 0.3.3-pre+30
Commit c3666a1* (2014-11-05 18:14 UTC)
Platform Info:
  System: Linux (i686-linux-gnu)
  CPU: Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
  WORD_SIZE: 32
  BLAS: libopenblas (NO_LAPACK NO_LAPACKE DYNAMIC_ARCH NO_AFFINITY Nehalem)
  LAPACK: liblapack
  LIBM: libopenlibm
  LLVM: libLLVM-3.3

@tkelman
Copy link
Contributor Author

tkelman commented Nov 18, 2014

found when working on LibGit2 Pkg PR

Ooh shiny. Let us know if you need any help with that. libgit2, due to cmake, is the only piece that currently doesn't work in compiling from 64 bit linux to 32 bit. But in a 32 bit linux VM it should work fine.

I can't really read LLVM or assembly well enough to tell, but could this possibly be something having to do with 0.118 * 1000.0 not being integer-valued in extended precision? cc @simonbyrne maybe?

@simonbyrne
Copy link
Contributor

Sorry, this is over my head I'm afraid. From what I can tell, the llvm output is identical. @tkelman's idea seems reasonable though: the i686 native code uses an x87 fmul instruction, whereas the other uses the SSE mulsd instruction.

@simonbyrne
Copy link
Contributor

Possibly relevant: #7185

@tkelman
Copy link
Contributor Author

tkelman commented Nov 18, 2014

This exact error did come up in #8731, and in #8812 @staticfloat had some proposed workarounds. I guess we decided "don't use MARCH=i686" and then proceeded to forget that we had made that decision.

@tkelman tkelman closed this as completed Nov 18, 2014
@staticfloat
Copy link
Member

Sigh, yeah, I could had sworn I had seen this before. ;)

@staticfloat
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
system:32-bit Affects only 32-bit systems
Projects
None yet
Development

No branches or pull requests

5 participants