Skip to content

Commit

Permalink
Fix casting (static and dynamic) arrays to vectors
Browse files Browse the repository at this point in the history
  • Loading branch information
kinke committed May 2, 2020
1 parent 734d849 commit 87f2a6f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
44 changes: 38 additions & 6 deletions gen/toir.cpp
Expand Up @@ -2593,18 +2593,24 @@ class ToElemVisitor : public Visitor {
//////////////////////////////////////////////////////////////////////////////

static DLValue *emitVector(VectorExp *e, LLValue *dstMem) {
TypeVector *type = static_cast<TypeVector *>(e->to->toBasetype());
assert(e->type->ty == Tvector);
TypeVector *type = e->to->toBasetype()->isTypeVector();
assert(type);

const unsigned N = e->dim;

Type *elementType = type->elementType();
if (elementType->ty == Tvoid)
elementType = Type::tuns8;

// Array literals are assigned element-wise, other expressions are cast and
// splat across the vector elements. This is what DMD does.
const auto getCastElement = [e, elementType](DValue *element) {
return DtoRVal(DtoCast(e->loc, element, elementType));
};

Type *tsrc = e->e1->type->toBasetype();
if (auto lit = e->e1->isArrayLiteralExp()) {
// Optimization for array literals: check for a fully static literal and
// store a vector constant in that case, otherwise emplace element-wise
// into destination memory.
Logger::println("array literal expression");
assert(lit->elements->length == N &&
"Array literal vector initializer "
Expand All @@ -2616,7 +2622,7 @@ class ToElemVisitor : public Visitor {
llElementConstants.reserve(N);
for (unsigned i = 0; i < N; ++i) {
DValue *val = toElem(indexArrayLiteral(lit, i));
LLValue *llVal = DtoRVal(DtoCast(e->loc, val, elementType));
LLValue *llVal = getCastElement(val);
llElements.push_back(llVal);
if (auto llConstant = isaConstant(llVal))
llElementConstants.push_back(llConstant);
Expand All @@ -2630,10 +2636,36 @@ class ToElemVisitor : public Visitor {
DtoStore(llElements[i], DtoGEP(dstMem, 0, i));
}
}
} else if (tsrc->ty == Tarray || tsrc->ty == Tsarray) {
// Arrays: prefer a memcpy if the LL element types match, otherwise cast
// and store element-wise.
if (auto ts = tsrc->isTypeSArray()) {
Logger::println("static array expression");
assert(ts->dim->toInteger() == N &&
"Static array vector initializer length mismatch, should have "
"been handled in frontend.");
} else {
// TODO: bounds check?
Logger::println("dynamic array expression, assume matching length");
}

LLValue *arrayPtr = DtoArrayPtr(toElem(e->e1));
Type *srcElementType = tsrc->nextOf();

if (DtoMemType(elementType) == DtoMemType(srcElementType)) {
DtoMemCpy(dstMem, arrayPtr);
} else {
for (unsigned i = 0; i < N; ++i) {
DLValue srcElement(srcElementType, DtoGEP1(arrayPtr, i));
LLValue *llVal = getCastElement(&srcElement);
DtoStore(llVal, DtoGEP(dstMem, 0, i));
}
}
} else {
// Try a splat vector constant, otherwise store element-wise.
Logger::println("normal (splat) expression");
DValue *val = toElem(e->e1);
LLValue *llElement = DtoRVal(DtoCast(e->loc, val, elementType));
LLValue *llElement = getCastElement(val);
if (auto llConstant = isaConstant(llElement)) {
auto vectorConstant = llvm::ConstantVector::getSplat(N, llConstant);
DtoStore(vectorConstant, dstMem);
Expand Down
22 changes: 22 additions & 0 deletions tests/codegen/vector_init.d
Expand Up @@ -37,3 +37,25 @@ void foo()
short8 s8 = [1, 2, 3, 4, 5, 6, 7, 8];
D2 d2 = 1.5;
}

// https://github.com/ldc-developers/ldc/issues/3418
// CHECK: define {{.*}}_D11vector_init3bar
void bar(const ref float[4] floats, const(int)[] ints)
{
alias float4 = __vector(float[4]);
alias int4 = __vector(int[4]);

// CHECK: %[[f:[0-9]+]] = bitcast <4 x float>* %f to i8*
// CHECK: call void @llvm.memcpy{{.*}}(i8*{{[^,]*}} %[[f]]
auto f = cast(float4) floats;

// CHECK: %[[i:[0-9]+]] = bitcast <4 x i32>* %i to i8*
// CHECK: call void @llvm.memcpy{{.*}}(i8*{{[^,]*}} %[[i]]
auto i = cast(int4) ints;

// CHECK: fptosi
// CHECK: fptosi
// CHECK: fptosi
// CHECK: fptosi
auto converted = cast(int4) floats;
}

0 comments on commit 87f2a6f

Please sign in to comment.