impl load32

This means we can write a memset32 (load32 -> store32),
tested explicitly with the new unit test.

Slightly changes to the type protocol,
  - load and splat now generate scalars or vectors
    depending on how `scalar` is set
  - store should no longer have to pay attention to `scalar`;
    it's input values will already be the right size

Clean up some of the type declarations where we don't
actually need the subclass types, holding llvm::Type* instead.
This makes using ?: easier.

Change-Id: I2f98701ebdeead0513d355b2666b024794b90193
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/273781
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Klein 2020-02-27 12:04:37 -06:00 committed by Skia Commit-Bot
parent 15c98cbfef
commit 11efa18eca
2 changed files with 47 additions and 18 deletions

View File

@ -1912,12 +1912,12 @@ namespace skvm {
K = 16;
}
llvm::Type *ptr = llvm::Type::getInt8Ty(ctx)->getPointerTo();
//llvm::Type *f32 = llvm::Type::getFloatTy(ctx);
llvm::IntegerType *i32 = llvm::Type::getInt32Ty(ctx),
*i64 = llvm::Type::getInt64Ty(ctx);
//llvm::VectorType *I32 = llvm::VectorType::get(i32, K),
// *F32 = llvm::VectorType::get(f32, K);
llvm::Type *ptr = llvm::Type::getInt8Ty(ctx)->getPointerTo(),
*i64 = llvm::Type::getInt64Ty(ctx),
// *f32 = llvm::Type::getFloatTy(ctx),
// *F32 = llvm::VectorType::get(f32, K),
*i32 = llvm::Type::getInt32Ty(ctx),
*I32 = llvm::VectorType::get(i32, K);
std::vector<llvm::Type*> arg_types = { i64 };
for (size_t i = 0; i < fStrides.size(); i++) {
@ -1950,21 +1950,28 @@ namespace skvm {
SkDebugf("can't llvm %s (%d)\n", name(op), op);
return false;
case Op::store32: {
llvm::Value* v = vals[x];
if (scalar) {
v = b->CreateExtractElement(v, (uint64_t)0);
}
case Op::load32: {
llvm::Value* ptr = b->CreateBitCast(args[immy],
v->getType()->getPointerTo());
vals[i] = b->CreateAlignedStore(v, ptr, 1);
(scalar ? i32 : I32)->getPointerTo());
vals[i] = b->CreateAlignedLoad(ptr, 1);
} break;
// Ops below this line shouldn't need to consider `scalar`... they're Just Math.
case Op::splat:
vals[i] = llvm::ConstantVector::getSplat(K, llvm::ConstantInt::get(i32, immy));
case Op::splat: {
llvm::ConstantInt* imm = b->getInt32(immy);
vals[i] = scalar ? imm
: llvm::ConstantVector::getSplat(K, imm);
break;
}
case Op::store32: {
llvm::Value* ptr = b->CreateBitCast(args[immy],
vals[x]->getType()->getPointerTo());
vals[i] = b->CreateAlignedStore(vals[x], ptr, 1);
} break;
// Ops below this line shouldn't need to consider `scalar`... they're Just Math.
}
return true;

View File

@ -281,7 +281,7 @@ DEF_TEST(SkVM_Pointless, r) {
}
#if defined(SKVM_LLVM)
DEF_TEST(SkVM_LLVM, r) {
DEF_TEST(SkVM_LLVM_memset, r) {
skvm::Builder b;
b.store32(b.varying<int>(), b.splat(42));
@ -297,6 +297,28 @@ DEF_TEST(SkVM_LLVM, r) {
}
REPORTER_ASSERT(r, buf[17] == 47);
}
DEF_TEST(SkVM_LLVM_memcpy, r) {
skvm::Builder b;
{
auto src = b.varying<int>(),
dst = b.varying<int>();
b.store32(dst, b.load32(src));
}
skvm::Program p = b.done();
REPORTER_ASSERT(r, p.hasJIT());
int src[] = {1,2,3,4,5,6,7,8,9},
dst[] = {0,0,0,0,0,0,0,0,0};
p.eval(SK_ARRAY_COUNT(src)-1, src, dst);
for (size_t i = 0; i < SK_ARRAY_COUNT(src)-1; i++) {
REPORTER_ASSERT(r, dst[i] == src[i]);
}
size_t i = SK_ARRAY_COUNT(src)-1;
REPORTER_ASSERT(r, dst[i] == 0);
}
#endif
DEF_TEST(SkVM_LoopCounts, r) {