Skip to content

Commit

Permalink
work on fixing vector load/store alignment to be compatible with juli…
Browse files Browse the repository at this point in the history
…a (16 byte) and C (assume 1 byte) as needed
  • Loading branch information
vtjnash committed Jun 16, 2015
1 parent dadf243 commit 7eae9b0
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 23 deletions.
12 changes: 7 additions & 5 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ Value *llvm_type_rewrite(Value *v, Type *from_type, Type *target_type, bool toju
if (v->getType() != ptarget_type) {
v = builder.CreatePointerCast(v, ptarget_type);
}
return builder.CreateLoad(v);
return builder.CreateAlignedLoad(v, 1); // unknown alignment from C
}
}
else {
Expand All @@ -267,10 +267,11 @@ Value *llvm_type_rewrite(Value *v, Type *from_type, Type *target_type, bool toju
}

if (v->getType() != from_type) { // this is already be a pointer in the codegen
unsigned align = v->getType() == jl_pvalue_llvmt ? 16 : 0;
if (v->getType() != ptarget_type) {
v = builder.CreatePointerCast(v, ptarget_type);
}
return builder.CreateLoad(v);
return builder.CreateAlignedLoad(v, align);
}
}
assert(v->getType() == from_type);
Expand Down Expand Up @@ -340,7 +341,7 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv,
if (vt != jl_pvalue_llvmt) {
// argument value is unboxed
if (vt != jv->getType())
jv = builder.CreateLoad(jv);
jv = builder.CreateLoad(jv); // something stack allocated
if (addressOf || (byRef && inReg)) {
if (ty->isPointerTy() && ty->getContainedType(0) == vt) {
// pass the address of an alloca'd thing, not a box
Expand Down Expand Up @@ -1409,7 +1410,8 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
Value *newst = emit_new_struct(rt,1,NULL,ctx);
assert(newst != NULL && "Type was not concrete");
assert(newst->getType()->isPointerTy());
builder.CreateStore(result, builder.CreateBitCast(newst, prt->getPointerTo()));
// julia gc is aligned 16, otherwise use default alignment for alloca pointers
builder.CreateAlignedStore(result, builder.CreateBitCast(newst, prt->getPointerTo()), newst->getType()==jl_pvalue_llvmt ? 16 : 0);
result = newst;
}
else {
Expand All @@ -1430,7 +1432,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
}
else {
if (result->getType() != jl_pvalue_llvmt && !lrt->isAggregateType())
result = builder.CreateLoad(result);
result = builder.CreateLoad(result); // something alloca'd above
}

return mark_or_box_ccall_result(result, args[2], rt, static_rt, ctx);
Expand Down
6 changes: 5 additions & 1 deletion src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,8 @@ static Value *typed_load(Value *ptr, Value *idx_0based, jl_value_t *jltype,
// elt = data;
//}
//else {
if (data->getType()->getContainedType(0)->isVectorTy() && !alignment)
alignment = ((jl_datatype_t*)jltype)->alignment; // prevent llvm from assuming 32 byte alignment of vectors
Instruction *load = builder.CreateAlignedLoad(data, alignment, false);
if (tbaa) {
elt = tbaa_decorate(tbaa, load);
Expand Down Expand Up @@ -1194,6 +1196,8 @@ static void typed_store(Value *ptr, Value *idx_0based, Value *rhs,
data = builder.CreateBitCast(ptr, PointerType::get(elty, 0));
else
data = ptr;
if (data->getType()->getContainedType(0)->isVectorTy() && !alignment)
alignment = ((jl_datatype_t*)jltype)->alignment; // prevent llvm from assuming 32 byte alignment of vectors
Instruction *store = builder.CreateAlignedStore(rhs, builder.CreateGEP(data, idx_0based), alignment);
if (tbaa)
tbaa_decorate(tbaa, store);
Expand Down Expand Up @@ -1618,7 +1622,7 @@ static Value *tpropagate(Value *a, Value *b)
static Value *init_bits_value(Value *newv, Value *jt, Type *t, Value *v)
{
builder.CreateStore(jt, builder.CreateBitCast(emit_typeptr_addr(newv), jl_ppvalue_llvmt));
builder.CreateStore(v, builder.CreateBitCast(data_pointer(newv), PointerType::get(t,0)));
builder.CreateAlignedStore(v, builder.CreateBitCast(data_pointer(newv), PointerType::get(t,0)), 16); // Julia's gc-alignment is 16-bytes
return newv;
}

Expand Down
4 changes: 2 additions & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3792,7 +3792,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
else {
Type *t = julia_type_to_llvm(jargty);
val = builder.CreatePointerCast(val, t->getPointerTo());
val = builder.CreateLoad(val, false);
val = builder.CreateAlignedLoad(val, 1); // make no alignment assumption about pointer from C
}
}
else {
Expand All @@ -3816,7 +3816,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
Value *mem = emit_allocobj(jl_datatype_size(jargty));
builder.CreateStore(literal_pointer_val((jl_value_t*)jargty),
emit_typeptr_addr(mem));
builder.CreateStore(val, builder.CreateBitCast(mem, val->getType()->getPointerTo()));
builder.CreateAlignedStore(val, builder.CreateBitCast(mem, val->getType()->getPointerTo()), 16); // julia's gc gives 16-byte aligned addresses
val = mem;
}
if (specsig)
Expand Down
10 changes: 5 additions & 5 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static Value *emit_unbox(Type *to, Value *x, jl_value_t *jt)
}
if (ty != jl_pvalue_llvmt) {
if (to->isAggregateType()) {
x = builder.CreateLoad(x);
x = builder.CreateLoad(x); // something stack allocated
ty = x->getType();
}
else {
Expand All @@ -287,20 +287,20 @@ static Value *emit_unbox(Type *to, Value *x, jl_value_t *jt)
}
return x;
}
Value *p = data_pointer(x);
Value *p = x;
if (to == T_int1) {
// bools stored as int8, so an extra Trunc is needed to get an int1
return builder.CreateTrunc(builder.
CreateLoad(builder.
CreateBitCast(p, T_pint8), false),
CreateBitCast(p, T_pint8)),
T_int1);
}
if (to->isStructTy() && !to->isSized()) {
// empty struct - TODO - is this a good way to represent it?
assert(to != T_void);
return UndefValue::get(to);
}
return builder.CreateLoad(builder.CreateBitCast(p, to->getPointerTo()), false);
return builder.CreateAlignedLoad(builder.CreateBitCast(p, to->getPointerTo()), 16); // julia's gc gives 16-byte aligned addresses
}

// unbox trying to determine type automatically
Expand Down Expand Up @@ -488,7 +488,7 @@ static Value *generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx)

// dynamically-determined type; evaluate.
if (llvmt->isAggregateType()) {
vx = builder.CreateLoad(vx);
vx = builder.CreateLoad(vx); // something stack allocated
}
return allocate_box_dynamic(emit_expr(targ, ctx), ConstantInt::get(T_size,nb), vx);
}
Expand Down
34 changes: 24 additions & 10 deletions test/llvmcall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

using Base.llvmcall

#function add1234(x::Tuple{Int32,Int32,Int32,Int32})
# llvmcall("""%3 = add <4 x i32> %1, %0
# ret <4 x i32> %3""",
# Tuple{Int32,Int32,Int32,Int32},
# Tuple{Tuple{Int32,Int32,Int32,Int32},
# Tuple{Int32,Int32,Int32,Int32}},
# (Int32(1),Int32(2),Int32(3),Int32(4)),
# x)
#end
#
#function add1234(x::NTuple{4,Int64})
# llvmcall("""%3 = add <4 x i64> %1, %0
# ret <4 x i64> %3""",NTuple{4,Int64},
# Tuple{NTuple{4,Int64},NTuple{4,Int64}},
# (Int64(1),Int64(2),Int64(3),Int64(4)),
# x)
#end
#
function add1234(x::Tuple{Int32,Int32,Int32,Int32})
llvmcall("""%3 = extractvalue [4 x i32] %0, 0
%4 = extractvalue [4 x i32] %0, 1
Expand All @@ -25,14 +43,6 @@ function add1234(x::Tuple{Int32,Int32,Int32,Int32})
x)
end

# function add1234(x::NTuple{4,Int64})
# llvmcall("""%3 = add <4 x i64> %1, %0
# ret <4 x i64> %3""",NTuple{4,Int64},
# Tuple{NTuple{4,Int64},NTuple{4,Int64}},
# (Int64(1),Int64(2),Int64(3),Int64(4)),
# x)
# end

@test add1234(map(Int32,(2,3,4,5))) === map(Int32,(3,5,7,9))
#@test add1234(map(Int64,(2,3,4,5))) === map(Int64,(3,5,7,9))

Expand All @@ -44,7 +54,11 @@ baremodule PlusTest

function +(x::Int32, y::Int32)
llvmcall("""%3 = add i32 %1, %0
ret i32 %3""", Int32, Tuple{Int32, Int32}, x, y)
ret i32 %3""",
Int32,
Tuple{Int32, Int32},
x,
y)
end
@test Int32(1)+Int32(2)==Int32(3)
@test Int32(1) + Int32(2) == Int32(3)
end

0 comments on commit 7eae9b0

Please sign in to comment.