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

Wrong GEP emission for tuple containing VecElement #32414

Closed
chriselrod opened this issue Jun 25, 2019 · 9 comments · Fixed by #34473
Closed

Wrong GEP emission for tuple containing VecElement #32414

chriselrod opened this issue Jun 25, 2019 · 9 comments · Fixed by #34473
Labels
bug Indicates an unexpected problem or unintended behavior compiler:codegen Generation of LLVM IR and native code compiler:simd instruction-level vectorization
Milestone

Comments

@chriselrod
Copy link
Contributor

chriselrod commented Jun 25, 2019

julia> @noinline function foo(a)
           v = ntuple(Val(8)) do w Core.VecElement(Float64(10w)) end
           a, (v, (a,(1e6,1e9)))
       end
foo (generic function with 1 method)

julia> foo(-35.0)
(10.0, ((VecElement{Float64}(30.0), VecElement{Float64}(40.0), VecElement{Float64}(50.0), VecElement{Float64}(60.0), VecElement{Float64}(70.0), VecElement{Float64}(80.0), VecElement{Float64}(-35.0), VecElement{Float64}(1.0e6)), (1.0e9, (1.2353556789225747e-307, 6.9513596813479e-310))))

julia> versioninfo()
Julia Version 1.3.0-DEV.428
Commit 863e03fbb1* (2019-06-19 15:07 UTC)
Platform Info:
  OS: Linux (x86_64-generic-linux)
  CPU: Intel(R) Core(TM) i9-7900X CPU @ 3.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.0 (ORCJIT, skylake)

The answer should be:

(-35.0, ((VecElement{Float64}(10.0), VecElement{Float64}(20.0), VecElement{Float64}(30.0), VecElement{Float64}(40.0), VecElement{Float64}(50.0), VecElement{Float64}(60.0), VecElement{Float64}(70.0), VecElement{Float64}(80.0), VecElement{Float64}(-35.0), VecElement{Float64}(1.0e6)), (-35.0, (1.0e6, 1.0e9))))

That is, the incorrect answer we received is shifted to the left by 16 bytes, and there appears to be an 8-byte gap between the first float and the following vector.

If we replace the tuple of VecElements with a standard tuple, that is what we get:

julia> @noinline function bar(a)
           v = ntuple(Val(8)) do w Float64(10w) end
           a, (v, (a,(1e6,1e9)))
       end
bar (generic function with 1 method)

julia> bar(-35.0)
(-35.0, ((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0), (-35.0, (1.0e6, 1.0e9))))

This silently corrupts data -- not the easiest problem to track down!

I referenced the issue here, where vtjnash said:

Seems like a new issue: it looks like we're specifying the wrong sort of vector to LLVM for our desired alignment for Julia.

@chriselrod
Copy link
Contributor Author

Is this more than just an alignment problem? On the latest master:

julia> @noinline function foo(a)
           v = ntuple(Val(8)) do w Core.VecElement(Float64(10w)) end
           (v, (a,(1e6,1e9))), a
       end
foo (generic function with 1 method)

julia> foo(-35.0)
(((VecElement{Float64}(-35.0), VecElement{Float64}(20.0), VecElement{Float64}(30.0), VecElement{Float64}(40.0), VecElement{Float64}(50.0), VecElement{Float64}(60.0), VecElement{Float64}(70.0), VecElement{Float64}(80.0)), (-35.0, (1.0e6, 1.0e9))), 4.65313481751076e-310)

Somehow a replaced the first element of v while the a at the end was replaced with uninitialized data. Turning the a into a tuple eats further into the vector:

julia> @noinline function foo(a)
           v = ntuple(Val(8)) do w Core.VecElement(Float64(10w)) end
           (v, (a,(1e6,1e9))), (a,a)
       end
foo (generic function with 1 method)

julia> foo(-35.0)
(((VecElement{Float64}(-35.0), VecElement{Float64}(-35.0), VecElement{Float64}(30.0), VecElement{Float64}(40.0), VecElement{Float64}(50.0), VecElement{Float64}(60.0), VecElement{Float64}(70.0), VecElement{Float64}(80.0)), (-35.0, (1.0e6, 1.0e9))), (4.65313472422326e-310, 6.939755661418e-310))

Or maybe this is the exact sample problem, and the compiler changed the order of the returned values?

@chriselrod-lilly
Copy link

(I'm the same person as above, just on a different account.)

julia> @noinline function foo(a)
       v = ntuple(Val(4)) do w Core.VecElement(Float64(10w)) end
       a, (v, (a,(1e6,1e9)))
   end
foo (generic function with 1 method)

julia> foo(-35.)
(10.0, ((VecElement{Float64}(30.0), VecElement{Float64}(40.0), VecElement{Float64}(-35.0), VecElement{Float64}(1.0e6)), (1.0e9, (0.0, 0.0))))

julia> versioninfo()
Julia Version 1.1.0
Commit 80516ca202 (2019-01-21 21:24 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, haswell)

I did confirm that this bug affects avx2 machines as well.
If no one else has the time to look at it, is there any chance the problem code is accessible enough for someone unfamiliar with Julia's internals (ie, me) to fix? If so, can someone point me to where relevant values are defined?

@KristofferC
Copy link
Member

julia/src/datatype.c

Lines 184 to 224 in b451d55

// Determine if homogeneous tuple with fields of type t will have
// a special alignment beyond normal Julia rules.
// Return special alignment if one exists, 0 if normal alignment rules hold.
// A non-zero result *must* match the LLVM rules for a vector type <nfields x t>.
// For sake of Ahead-Of-Time (AOT) compilation, this routine has to work
// without LLVM being available.
unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
{
if (!jl_is_vecelement_type(t))
return 0;
// LLVM 3.7 and 3.8 either crash or generate wrong code for many
// SIMD vector sizes N. It seems the rule is that N can have at
// most 2 non-zero bits. (This is true at least for N<=100.) See
// also <https://llvm.org/bugs/show_bug.cgi?id=27708>.
size_t mask = nfields;
// See e.g.
// <https://graphics.stanford.edu/%7Eseander/bithacks.html> for an
// explanation of this bit-counting algorithm.
mask &= mask-1; // clear least-significant 1 if present
mask &= mask-1; // clear another 1
if (mask)
return 0; // nfields has more than two 1s
assert(jl_datatype_nfields(t)==1);
jl_value_t *ty = jl_field_type((jl_datatype_t*)t, 0);
if (!jl_is_primitivetype(ty))
// LLVM requires that a vector element be a primitive type.
// LLVM allows pointer types as vector elements, but until a
// motivating use case comes up for Julia, we reject pointers.
return 0;
size_t elsz = jl_datatype_size(ty);
if (elsz>8 || (1<<elsz & 0x116) == 0)
// Element size is not 1, 2, 4, or 8.
return 0;
size_t size = nfields*elsz;
// LLVM's alignment rule for vectors seems to be to round up to
// a power of two, even if that's overkill for the target hardware.
size_t alignment=1;
for( ; size>alignment; alignment*=2 )
continue;
return alignment;
}
might be useful to look at.

@chriselrod
Copy link
Contributor Author

chriselrod commented Oct 6, 2019

Is it possible for me to pay someone to fix this?
If so, how, and how much is it likely to cost?

This issue is a constant aggravation, but I think solving it is beyond me.

a magically jumps to the front, replacing the first element of the vector:

julia> @noinline function foo(a)
                  v = ntuple(Val(8)) do w Core.VecElement(Float64(10w)) end
                  (v, (a,(1e6,1e9))), a
              end
foo (generic function with 1 method)

julia> foo(23.4)
(((VecElement{Float64}(23.4), VecElement{Float64}(20.0), VecElement{Float64}(30.0), VecElement{Float64}(40.0), VecElement{Float64}(50.0), VecElement{Float64}(60.0), VecElement{Float64}(70.0), VecElement{Float64}(80.0)), (23.4, (1.0e6, 1.0e9))), 4.67707705511027e-310)

@vchuravy
Copy link
Member

vchuravy commented Oct 6, 2019

To me this looks like an LLVM bug before optimization:

julia> @code_llvm optimize=false foo(23.4)

;  @ REPL[1]:2 within `foo'
; Function Attrs: noinline
define void @julia_foo_15969({ { <8 x double>, { double, [2 x double] } }, double }* noalias nocapture sret, double) #0 {
top:
  %2 = alloca { double, [2 x double] }
  %3 = alloca { <8 x double>, { double, [2 x double] } }
  %4 = alloca { { <8 x double>, { double, [2 x double] } }, double }
  %5 = call %jl_value_t*** @julia.ptls_states()
  %6 = bitcast %jl_value_t*** %5 to %jl_value_t addrspace(10)**
  %7 = getelementptr inbounds %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %6, i64 4
  %8 = bitcast %jl_value_t addrspace(10)** %7 to i64**
  %9 = load i64*, i64** %8
;  @ REPL[1]:3 within `foo'
  %10 = getelementptr inbounds { double, [2 x double] }, { double, [2 x double] }* %2, i32 0, i32 0
  store double %1, double* %10
  %11 = getelementptr inbounds { double, [2 x double] }, { double, [2 x double] }* %2, i32 0, i32 1
  store [2 x double] [double 1.000000e+06, double 1.000000e+09], [2 x double]* %11
  %12 = getelementptr inbounds { <8 x double>, { double, [2 x double] } }, { <8 x double>, { double, [2 x double] } }* %3, i32 0, i32 0
  store <8 x double> <double 1.000000e+01, double 2.000000e+01, double 3.000000e+01, double 4.000000e+01, double 5.000000e+01, double 6.000000e+01, double 7.000000e+01, double 8.000000e+01>, <8 x double>* %12
  %13 = getelementptr inbounds { <8 x double>, { double, [2 x double] } }, { <8 x double>, { double, [2 x double] } }* %3, i32 0, i32 1
  %14 = bitcast { double, [2 x double] }* %13 to i8*
  %15 = bitcast { double, [2 x double] }* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %14, i8* %15, i64 24, i32 8, i1 false)
  %16 = getelementptr inbounds { { <8 x double>, { double, [2 x double] } }, double }, { { <8 x double>, { double, [2 x double] } }, double }* %4, i32 0, i32 0
  %17 = bitcast { <8 x double>, { double, [2 x double] } }* %16 to i8*
  %18 = bitcast { <8 x double>, { double, [2 x double] } }* %3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %17, i8* %18, i64 96, i32 16, i1 false)
  %19 = getelementptr inbounds { { <8 x double>, { double, [2 x double] } }, double }, { { <8 x double>, { double, [2 x double] } }, double }* %4, i32 0, i32 0
  %20 = bitcast { <8 x double>, { double, [2 x double] } }* %19 to double*
  store double %1, double* %20
  %21 = bitcast { { <8 x double>, { double, [2 x double] } }, double }* %0 to i8*
  %22 = bitcast { { <8 x double>, { double, [2 x double] } }, double }* %4 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %21, i8* %22, i64 112, i32 16, i1 false)
  ret void
}

after optimization:

julia> @code_llvm optimize=true foo(23.4)

;  @ REPL[1]:2 within `foo'
; Function Attrs: noinline
define void @julia_foo_15969({ { <8 x double>, { double, [2 x double] } }, double }* noalias nocapture sret, double) #0 {
top:
;  @ REPL[1]:3 within `foo'
  %.sroa.0.0..sroa_idx = getelementptr inbounds { { <8 x double>, { double, [2 x double] } }, double }, { { <8 x double>, { double, [2 x double] } }, double }* %0, i64 0, i32 0, i32 0, i64 0
  store double %1, double* %.sroa.0.0..sroa_idx, align 64
  %.sroa.3.sroa.0.0..sroa.3.0..sroa_cast.sroa_idx = getelementptr inbounds { { <8 x double>, { double, [2 x double] } }, double }, { { <8 x double>, { double, [2 x double] } }, double }* %0, i64 0, i32 0, i32 0, i64 1
  %.sroa.3.sroa.0.0..sroa.3.0..sroa_cast.sroa_cast = bitcast double* %.sroa.3.sroa.0.0..sroa.3.0..sroa_cast.sroa_idx to <7 x double>*
  store <7 x double> <double 2.000000e+01, double 3.000000e+01, double 4.000000e+01, double 5.000000e+01, double 6.000000e+01, double 7.000000e+01, double 8.000000e+01>, <7 x double>* %.sroa.3.sroa.0.0..sroa.3.0..sroa_cast.sroa_cast, align 8
  %.sroa.3.sroa.2.sroa.0.0..sroa.3.sroa.2.0..sroa.3.0..sroa_cast.sroa_cast.sroa_idx = getelementptr inbounds { { <8 x double>, { double, [2 x double] } }, double }, { { <8 x double>, { double, [2 x double] } }, double }* %0, i64 0, i32 0, i32 1, i32 0
  store double %1, double* %.sroa.3.sroa.2.sroa.0.0..sroa.3.sroa.2.0..sroa.3.0..sroa_cast.sroa_cast.sroa_idx, align 64
  %.sroa.3.sroa.2.sroa.2.0..sroa.3.sroa.2.0..sroa.3.0..sroa_cast.sroa_cast.sroa_idx11 = getelementptr inbounds { { <8 x double>, { double, [2 x double] } }, double }, { { <8 x double>, { double, [2 x double] } }, double }* %0, i64 0, i32 0, i32 1, i32 1, i64 0
  %2 = bitcast double* %.sroa.3.sroa.2.sroa.2.0..sroa.3.sroa.2.0..sroa.3.0..sroa_cast.sroa_cast.sroa_idx11 to <2 x double>*
  store <2 x double> <double 1.000000e+06, double 1.000000e+09>, <2 x double>* %2, align 8
  ret void
}

To break this up a bit:

  • %0 is the return value; %retvalue
  • %1 is the argument; %arg
%retvalue[0][0][0][0] = %arg
%retvalue[0][0][0][1:7] = <20, 30, 40, 50, 60, 70, 80>
%retvalue[0][0][1][0] = %arg
%retvalue[0][0][1][1][0:1] = (1e6,1e9)

Which matches what we get when we run the code, even down to the fact that the store of arg to the last element of the tuple is missing and we are getting random memory.
I should mention that the generated IR looks fine to me and that LLVM trunk still has this issue https://godbolt.org/z/x79YbH

@vchuravy
Copy link
Member

vchuravy commented Oct 6, 2019

Oh no, I misread something:

  %19 = getelementptr inbounds { { <8 x double>, { double, [2 x double] } }, double }, { { <8 x double>, { double, [2 x double] } }, double }* %4, i32 0, i32 0
  %20 = bitcast { <8 x double>, { double, [2 x double] } }* %19 to double*
  store double %1, double* %20

This is probably meant to be be the store (x, a), but instead it is overwriting the first element of the vector. So it is a codegen issue.

@vchuravy vchuravy added bug Indicates an unexpected problem or unintended behavior compiler:codegen Generation of LLVM IR and native code labels Oct 6, 2019
@vchuravy vchuravy changed the title Wrong LLVM vector allignment Wrong GEP emission for tuple containing VecElement Oct 6, 2019
@vchuravy
Copy link
Member

vchuravy commented Oct 6, 2019

It boils down to an alignment issue in

julia/src/cgutils.cpp

Lines 2528 to 2529 in 0aa59a0

unsigned offs = jl_field_offset(sty, i);
unsigned llvm_idx = (i > 0 && isa<StructType>(lt)) ? convert_struct_offset(ctx, lt, offs) : i;

Julia believes that the second field is at offset 96 and that the struct has alignment 16, whereas LLVM believes that the offset of the field is 128 and that the struct alignment is 64.

@vtjnash
Copy link
Member

vtjnash commented Oct 19, 2019

FWIW, I think the relevant assert was disabled in #21980, while this issue should be addressed by #21959 — they, coincidentally, being by the same author

@chriselrod
Copy link
Contributor Author

Is it possible for me to pay someone to fix this?
If so, how, and how much is it likely to cost?

Not as nice as paying vchuravy or any developers directly, but I did just donate some money to Julia through NumFocus.

I'm guessing that this is because of enabling the assertion that Julia and LLVM use the same alignment #33597 (comment)

julia> @noinline function foo(a)
           v = ntuple(Val(8)) do w Core.VecElement(Float64(10w)) end
           a, (v, (a,(1e6,1e9)))
       end
foo (generic function with 1 method)

julia> foo(-4.0)
julia: /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:514: unsigned int convert_struct_offset(llvm::Type*, unsigned int): Assertion `SL->getElementOffset(idx) == byte_offset' failed.

signal (6): Aborted
in expression starting at REPL[2]:1
gsignal at /usr/lib64/haswell/libc.so.6 (unknown line)
abort at /usr/lib64/haswell/libc.so.6 (unknown line)
unknown function (ip: 0x7f165d8bd776)
__assert_fail at /usr/lib64/haswell/libc.so.6 (unknown line)
convert_struct_offset at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:514 [inlined]
convert_struct_offset at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:509
convert_struct_offset at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:520 [inlined]
emit_new_struct at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:2619
emit_builtin_call at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:2594
emit_call at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3329
emit_expr at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:4101
emit_ssaval_assign at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3805
emit_stmtpos at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3998 [inlined]
emit_function at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:6544
jl_compile_linfo at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:1230
jl_compile_method_internal at /home/chriselrod/Documents/languages/julia/src/gf.c:1879
_jl_invoke at /home/chriselrod/Documents/languages/julia/src/gf.c:2135 [inlined]
jl_apply_generic at /home/chriselrod/Documents/languages/julia/src/gf.c:2300
jl_apply at /home/chriselrod/Documents/languages/julia/src/julia.h:1647 [inlined]
do_call at /home/chriselrod/Documents/languages/julia/src/interpreter.c:328
eval_value at /home/chriselrod/Documents/languages/julia/src/interpreter.c:417
eval_stmt_value at /home/chriselrod/Documents/languages/julia/src/interpreter.c:368 [inlined]
eval_body at /home/chriselrod/Documents/languages/julia/src/interpreter.c:760
jl_interpret_toplevel_thunk_callback at /home/chriselrod/Documents/languages/julia/src/interpreter.c:888
Lenter_interpreter_frame_start_val at /home/chriselrod/Documents/languages/julia/usr/bin/../lib/libjulia.so.1 (unknown line)
jl_interpret_toplevel_thunk at /home/chriselrod/Documents/languages/julia/src/interpreter.c:897
jl_toplevel_eval_flex at /home/chriselrod/Documents/languages/julia/src/toplevel.c:814
jl_toplevel_eval_flex at /home/chriselrod/Documents/languages/julia/src/toplevel.c:764
jl_toplevel_eval at /home/chriselrod/Documents/languages/julia/src/toplevel.c:823 [inlined]
jl_toplevel_eval_in at /home/chriselrod/Documents/languages/julia/src/toplevel.c:843
eval at ./boot.jl:331
eval_user_input at /home/chriselrod/Documents/languages/julia/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
run_backend at (null):0
#80 at (null):0
jl_apply at /home/chriselrod/Documents/languages/julia/src/julia.h:1647 [inlined]
start_task at /home/chriselrod/Documents/languages/julia/src/task.c:687
unknown function (ip: (nil))
Allocations: 9469636 (Pool: 9467308; Big: 2328); GC: 11
fish: “/home/chriselrod/Documents/lang…” terminated by signal SIGABRT (Abort)

Definitely an improvement over silently corrupting answers.

I also get an assertion about incorrect alignment in the simpler case of just returning a NTuple{N,Core.VecElement{T}}:

julia> foo() = ntuple(i -> Core.VecElement{Float64}(i), Val(8))
foo (generic function with 1 method)

julia> foo()
(VecElement{Float64}(1.0), VecElement{Float64}(2.0), VecElement{Float64}(3.0), VecElement{Float64}(4.0), VecElement{Float64}(5.0), VecElement{Float64}(6.0), VecElement{Float64}(7.0), VecElement{Float64}(8.0))

julia> using BenchmarkTools

julia> @benchmark foo()
julia: /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:514: unsigned int convert_struct_offset(llvm::Type*, unsigned int): Assertion `SL->getElementOffset(idx) == byte_offset' failed.

signal (6): Aborted
in expression starting at REPL[4]:1
gsignal at /usr/lib64/haswell/libc.so.6 (unknown line)
abort at /usr/lib64/haswell/libc.so.6 (unknown line)
unknown function (ip: 0x7f8d89cba776)
__assert_fail at /usr/lib64/haswell/libc.so.6 (unknown line)
convert_struct_offset at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:514 [inlined]
convert_struct_offset at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:509
convert_struct_offset at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:520 [inlined]
emit_new_struct at /home/chriselrod/Documents/languages/julia/src/cgutils.cpp:2619
emit_builtin_call at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:2594
emit_call at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3329
emit_expr at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:4101
emit_ssaval_assign at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3805
emit_stmtpos at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3998 [inlined]
emit_function at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:6544
jl_compile_linfo at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:1230
emit_invoke at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3275
emit_expr at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:4092
emit_ssaval_assign at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3805
emit_stmtpos at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3998 [inlined]
emit_function at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:6544
jl_compile_linfo at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:1230
emit_invoke at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3275
emit_expr at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:4092
emit_ssaval_assign at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3805
emit_stmtpos at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:3998 [inlined]
emit_function at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:6544
jl_compile_linfo at /home/chriselrod/Documents/languages/julia/src/codegen.cpp:1230
jl_compile_method_internal at /home/chriselrod/Documents/languages/julia/src/gf.c:1879
_jl_invoke at /home/chriselrod/Documents/languages/julia/src/gf.c:2135 [inlined]
jl_apply_generic at /home/chriselrod/Documents/languages/julia/src/gf.c:2300
jl_apply at /home/chriselrod/Documents/languages/julia/src/julia.h:1647 [inlined]
do_apply at /home/chriselrod/Documents/languages/julia/src/builtins.c:630
jl_f__apply at /home/chriselrod/Documents/languages/julia/src/builtins.c:642 [inlined]
jl_f__apply_latest at /home/chriselrod/Documents/languages/julia/src/builtins.c:678
#invokelatest#1 at (null):0 [inlined]
invokelatest##kw at ./essentials.jl:710 [inlined]
#run_result#37 at /home/chriselrod/.julia/packages/BenchmarkTools/7aqwe/src/execution.jl:32 [inlined]
run_result##kw at /home/chriselrod/.julia/packages/BenchmarkTools/7aqwe/src/execution.jl:32 [inlined]
#run#39 at /home/chriselrod/.julia/packages/BenchmarkTools/7aqwe/src/execution.jl:46
run##kw at (null):0 [inlined]
run##kw at /home/chriselrod/.julia/packages/BenchmarkTools/7aqwe/src/execution.jl:46 [inlined]
#warmup#42 at /home/chriselrod/.julia/packages/BenchmarkTools/7aqwe/src/execution.jl:79 [inlined]
warmup at /home/chriselrod/.julia/packages/BenchmarkTools/7aqwe/src/execution.jl:79
jl_apply at /home/chriselrod/Documents/languages/julia/src/julia.h:1647 [inlined]
do_call at /home/chriselrod/Documents/languages/julia/src/interpreter.c:328
eval_value at /home/chriselrod/Documents/languages/julia/src/interpreter.c:417
eval_stmt_value at /home/chriselrod/Documents/languages/julia/src/interpreter.c:368 [inlined]
eval_body at /home/chriselrod/Documents/languages/julia/src/interpreter.c:760
jl_interpret_toplevel_thunk_callback at /home/chriselrod/Documents/languages/julia/src/interpreter.c:888
Lenter_interpreter_frame_start_val at /home/chriselrod/Documents/languages/julia/usr/bin/../lib/libjulia.so.1 (unknown line)
jl_interpret_toplevel_thunk at /home/chriselrod/Documents/languages/julia/src/interpreter.c:897
jl_toplevel_eval_flex at /home/chriselrod/Documents/languages/julia/src/toplevel.c:814
jl_toplevel_eval_flex at /home/chriselrod/Documents/languages/julia/src/toplevel.c:764
jl_toplevel_eval at /home/chriselrod/Documents/languages/julia/src/toplevel.c:823 [inlined]
jl_toplevel_eval_in at /home/chriselrod/Documents/languages/julia/src/toplevel.c:843
eval at ./boot.jl:331
eval_user_input at /home/chriselrod/Documents/languages/julia/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
run_backend at (null):0
#80 at (null):0
jl_apply at /home/chriselrod/Documents/languages/julia/src/julia.h:1647 [inlined]
start_task at /home/chriselrod/Documents/languages/julia/src/task.c:687
unknown function (ip: (nil))
Allocations: 12974179 (Pool: 12971223; Big: 2956); GC: 15
fish: “/home/chriselrod/Documents/lang…” terminated by signal SIGABRT (Abort)

tkluck added a commit to tkluck/julia that referenced this issue Jan 3, 2020
It is possible that LLVM and Julia disagree on the offsets of struct
fields. This has been observed in JuliaLang#32414 in cases like

    Tuple{Float64, NTuple{8, VecElement{Float64}}}

where LLVM wants to align the `vec` on 64 bytes (adding 56 bytes
of padding after the first `Float64`) but Julia refusing to
align like that because it can't guarantee that on the heap:

https://github.com/JuliaLang/julia/blob/c7e9d9f8ade647582c6635c8c9a587f2360af404/src/datatype.c#L453

There is no easy solution this I can see, but since this can be
triggered from pure Julia, the least we can do is not abort the program.

For this reason, this commit replaces the assert by jl_error.
To be able to give a sort-of meaningful error message, we return
a sentinel value from `convert_struct_offset` and generate
an error message in the caller.
tkluck added a commit to tkluck/julia that referenced this issue Jan 3, 2020
It is possible that LLVM and Julia disagree on the offsets of struct
fields. This has been observed in JuliaLang#32414 in cases like

    Tuple{Float64, NTuple{8, VecElement{Float64}}}

where LLVM wants to align the `vec` on 64 bytes (adding 56 bytes
of padding after the first `Float64`) but Julia refusing to
align like that because it can't guarantee that on the heap:

https://github.com/JuliaLang/julia/blob/c7e9d9f8ade647582c6635c8c9a587f2360af404/src/datatype.c#L453

There is no easy solution this I can see, but since this can be
triggered from pure Julia, the least we can do is not abort the program.

For this reason, this commit replaces the assert by jl_error.
To be able to give a sort-of meaningful error message, we return
a sentinel value from `convert_struct_offset` and generate
an error message in the caller.
@JeffBezanson JeffBezanson added this to the 1.5 milestone Jan 8, 2020
@JeffBezanson JeffBezanson modified the milestones: 1.5, 1.4 Jan 14, 2020
vtjnash added a commit that referenced this issue Jan 22, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
vtjnash added a commit that referenced this issue Jan 22, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
vtjnash added a commit that referenced this issue Jan 27, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
vtjnash added a commit that referenced this issue Jan 29, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
vtjnash added a commit that referenced this issue Jan 30, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
JeffBezanson pushed a commit that referenced this issue Jan 30, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
vtjnash added a commit that referenced this issue Feb 4, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
KristofferC pushed a commit that referenced this issue Feb 5, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414

(cherry picked from commit 268ac24)
KristofferC pushed a commit that referenced this issue Apr 11, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes #32414
BioTurboNick pushed a commit to BioTurboNick/julia that referenced this issue Apr 13, 2020
Rather than meaning the actual alignment of the object, this now means
the preferred alignment of the object. The actual alignment of any
object is the minimum of this preferred alignment and the alignment
supported by the runtime allocator. This aligns us with how LLVM treats
alignment, and is probably reasonably sensible anyways.

Also tries to audit our existing uses of CreateLoad/CreateStore for
correctness, and upgrade some to include pointer-types.

fixes JuliaLang#32414

(cherry picked from commit 268ac24)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior compiler:codegen Generation of LLVM IR and native code compiler:simd instruction-level vectorization
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants