Skip to content

Commit

Permalink
limit maximum vector alignment to heap alignment
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed May 21, 2017
1 parent d762038 commit 87ccf70
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,10 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox
#endif
unsigned llvm_alignment = DL.getABITypeAlignment((Type*)jst->struct_decl);
unsigned julia_alignment = jst->layout->alignment;
assert(llvm_alignment == julia_alignment);
// Check that the alignment adheres to the heap alignment.
assert(julia_alignment <= JL_SMALL_BYTE_ALIGNMENT);
if (llvm_alignment <= JL_SMALL_BYTE_ALIGNMENT)
assert(julia_alignment == llvm_alignment);
}
#endif
}
Expand Down
5 changes: 4 additions & 1 deletion src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,10 @@ void jl_compute_field_offsets(jl_datatype_t *st)
// Some tuples become LLVM vectors with stronger alignment than what was calculated above.
unsigned al = jl_special_vector_alignment(nfields, lastty);
assert(al % alignm == 0);
if (al)
// JL_SMALL_BYTE_ALIGNMENT is the smallest alignment we can guarantee on the heap.
if (al > JL_SMALL_BYTE_ALIGNMENT)
alignm = JL_SMALL_BYTE_ALIGNMENT;
else if (al)
alignm = al;
}
st->size = LLT_ALIGN(sz, alignm);
Expand Down
60 changes: 60 additions & 0 deletions test/vecelement.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ for i=1:20
end
end

# Try various large tuple lengths and element types #20961
for i in (34, 36, 48, 64, 72, 80, 96)
for t in [Bool, Int8, Int16, Int32, Int64, Float32, Float64]
call_iota(i,t)
end
end

# Another crash report for #15244 motivated this test.
struct Bunch{N,T}
elts::NTuple{N,Base.VecElement{T}}
Expand Down Expand Up @@ -65,3 +72,56 @@ a[1] = Gr(5.0, Bunch((VecElement(6.0), VecElement(7.0))), 8.0)
@test a[2] == Gr(1.0, Bunch((VecElement(2.0), VecElement(3.0))), 4.0)

@test isa(VecElement((1,2)), VecElement{Tuple{Int,Int}})

# The following test mimic SIMD.jl
const _llvmtypes = Dict{DataType, String}(
Float64 => "double",
Float32 => "float",
Int32 => "i32",
Int64 => "i64"
)

@generated function vecadd(x::Vec{N, T}, y::Vec{N, T}) where {N, T}
llvmT = _llvmtypes[T]
func = T <: AbstractFloat ? "fadd" : "add"
exp = """
%3 = $(func) <$(N) x $(llvmT)> %0, %1
ret <$(N) x $(llvmT)> %3
"""
return quote
Base.@_inline_meta
Base.llvmcall($exp,
NTuple{N, VecElement{T}},
Tuple{NTuple{N,VecElement{T}},NTuple{N,VecElement{T}}},
x, y)
end
end

function f20961(x::Vector{Vec{N, T}}, y::Vector{Vec{N, T}}) where{N, T}
@inbounds begin
a = x[1]
b = y[1]
return vecadd(a, b)
end
end

# Test various SIMD Vectors with known good sizes
for T in (Float64, Float32, Int64, Int32)
for N in 1:36
# For some vectortypes Julia emits llvm arrays instead of vectors
if N % 7 == 0 || N % 11 == 0 || N % 13 == 0 || N % 15 == 0 ||
N % 19 == 0 || N % 23 == 0 || N % 25 == 0 || N % 27 == 0 ||
N % 29 == 0 || N % 31 == 0
continue
end
a = ntuple(i->VecElement(T(i)), N)
result = ntuple(i-> VecElement(T(i+i)), N)
b = vecadd(a, a)
@test b == result
b = f20961([a], [a])
@test b == result
if N == 36
code_llvm(STDOUT, f20961, (Vector{Vec{N, T}}, Vector{Vec{N, T}}))
end
end
end

0 comments on commit 87ccf70

Please sign in to comment.