Skip to content

Commit

Permalink
allow vector types in some intrinsics see #18445
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed Sep 13, 2016
1 parent b2f6b1b commit 5b42d81
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 10 deletions.
12 changes: 6 additions & 6 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static Value *FP(Value *v)
// convert float type to same-size int type
static Type *JL_INTT(Type *t)
{
if (t->isIntegerTy())
if (t->isIntegerTy() || t->isVectorTy())
return t;
if (t->isPointerTy())
return T_size;
Expand Down Expand Up @@ -360,7 +360,7 @@ static Value *emit_unbox(Type *to, const jl_cgval_t &x, jl_value_t *jt, Value *d
static Value *auto_unbox(const jl_cgval_t &v, jl_codectx_t *ctx)
{
jl_value_t *bt = v.typ;
if (!jl_is_bitstype(bt)) {
if (!(jl_is_bitstype(bt) || jl_is_vec_type(bt))) {
// This can be reached with a direct invalid call to an Intrinsic, such as:
// Intrinsics.neg_int("")
emit_error("auto_unbox: unable to determine argument type", ctx);
Expand Down Expand Up @@ -392,7 +392,7 @@ static jl_value_t *staticeval_bitstype(jl_value_t *targ, const char *fname, jl_c
jl_value_t *bt = NULL;
if (jl_is_type_type(bt_value.typ))
bt = jl_tparam0(bt_value.typ);
if (!bt || !jl_is_bitstype(bt)) {
if (!(bt && (jl_is_bitstype(bt) || jl_is_vec_type(bt)))) {
emit_error("expected bits type as first argument", ctx);
return NULL;
}
Expand All @@ -401,7 +401,7 @@ static jl_value_t *staticeval_bitstype(jl_value_t *targ, const char *fname, jl_c

static Type *staticeval_bitstype(jl_value_t *bt)
{
assert(jl_is_bitstype(bt));
assert(jl_is_bitstype(bt) || jl_is_vec_type(bt));
bool isboxed;
Type *to = julia_type_to_llvm(bt, &isboxed);
if (to == NULL || isboxed) {
Expand Down Expand Up @@ -429,7 +429,7 @@ static jl_cgval_t generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx
if (jl_is_type_type(bt_value.typ))
bt = jl_tparam0(bt_value.typ);

if (!bt || !jl_is_bitstype(bt)) {
if (!(bt && (jl_is_bitstype(bt) || jl_is_vec_type(bt)))) {
// it's easier to throw a good error from C than llvm
Value *arg1 = boxed(bt_value, ctx);
Value *arg2 = boxed(v, ctx);
Expand All @@ -454,7 +454,7 @@ static jl_cgval_t generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx
|| !jl_is_bitstype(v.typ)
|| jl_datatype_size(v.typ) != nb) {
Value *typ = emit_typeof_boxed(v, ctx);
if (!jl_is_bitstype(v.typ)) {
if (!(jl_is_bitstype(v.typ) || jl_is_vec_type(v.typ))) {
if (isboxed) {
Value *isbits = emit_datatype_isbitstype(typ);
error_unless(isbits, "reinterpret: expected bitstype value for second argument", ctx);
Expand Down
18 changes: 18 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,24 @@ STATIC_INLINE int jl_is_vecelement_type(jl_value_t* t)
((jl_datatype_t*)(t))->name == jl_vecelement_typename);
}

STATIC_INLINE int jl_is_vec_type(jl_value_t* t)
{
if (!jl_is_tuple_type(t))
return 0;

jl_value_t* ft0 = jl_field_type(t, 0);
if (!jl_is_vecelement_type(ft0))
return 0;

size_t nf = jl_datatype_nfields(t);
for (size_t i = 1; i < nf; ++i)
if (jl_field_type(t, i) != ft0)
// Not homogeneous
return 0;

return 1;
}

STATIC_INLINE int jl_is_type_type(jl_value_t *v)
{
return (jl_is_datatype(v) &&
Expand Down
9 changes: 5 additions & 4 deletions src/runtime_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ const unsigned int host_char_bit = 8;
JL_DLLEXPORT jl_value_t *jl_reinterpret(jl_value_t *ty, jl_value_t *v)
{
JL_TYPECHK(reinterpret, datatype, ty);
if (!jl_is_leaf_type(ty) || !jl_is_bitstype(ty))
if (!jl_is_leaf_type(ty) || !(jl_is_bitstype(ty) || jl_is_vec_type(ty)))
jl_error("reinterpret: target type not a leaf bitstype");
if (!jl_is_bitstype(jl_typeof(v)))
jl_value_t* dt = jl_typeof(v);
if (!(jl_is_bitstype(dt) || jl_is_vec_type(dt)))
jl_error("reinterpret: value not a bitstype");
if (jl_datatype_size(jl_typeof(v)) != jl_datatype_size(ty))
if (jl_datatype_size(dt) != jl_datatype_size(ty))
jl_error("reinterpret: argument size does not match size of target type");
if (ty == jl_typeof(v))
if (ty == dt)
return v;
if (ty == (jl_value_t*)jl_bool_type)
return *(uint8_t*)jl_data_ptr(v) & 1 ? jl_true : jl_false;
Expand Down
13 changes: 13 additions & 0 deletions test/vecelement.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,16 @@ 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}})

import Core.Intrinsics
# Test intrinsics for #18445
# Explicit form
function trunc_vec{T1 <: Vec, T2 <: Vec}(::Type{T1}, x :: T2)
Intrinsics.box(T1, Intrinsics.trunc_int(T1, Intrinsics.unbox(T2, x)))
end

@test trunc_vec(Vec{4, UInt8}, Vec((0xff00, 0xff01, 0x00ff, 0xf0f0))) == Vec((0x00, 0x01, 0xff, 0xf0))
@test Intrinsics.zext_int(Vec{4, UInt16}, Vec((0x00, 0x01, 0xff, 0xf0))) == Vec((0x0000, 0x0001, 0x00ff, 0x00f0))
@test Intrinsics.sext_int(Vec{4, UInt16}, Vec((0x00, 0x01, 0xff, 0xf0))) == Vec((0x0000, 0x0001, 0xffff, 0xfff0))
@test Intrinsics.add_int(Vec((1,2,3,4)), Vec((1,2,3,4))) == Vec((2,4,6,8))
# @test Intrinsics.mul_float(Vec((1.0, 2.0, 1.0, 2.0)), Vec((0.5, 0.5, 1.5, 1.5))) == Vec((0.5, 1.0, 1.5, 3.0))

0 comments on commit 5b42d81

Please sign in to comment.