hoist1
Add scalar hoisting too. Nothing tricky. Scalar loop is now good like the vector one: 0x1065c7160: movl %eax, (%rdx) 0x1065c7162: decl %edi 0x1065c7164: addq $0x4, %rdx 0x1065c7168: testl %edi, %edi 0x1065c716a: jg 0x1065c7160 Change-Id: I9352e85bcae8d6be0d9092b2664841fde2c3c7d6 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274587 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
6a63365fee
commit
89c995c196
@ -1920,13 +1920,14 @@ namespace skvm {
|
||||
fn->addParamAttr(i+1, llvm::Attribute::NoAlias);
|
||||
}
|
||||
|
||||
llvm::BasicBlock *enter = llvm::BasicBlock::Create(ctx, "enter", fn),
|
||||
*hoist = llvm::BasicBlock::Create(ctx, "hoist", fn),
|
||||
*testK = llvm::BasicBlock::Create(ctx, "testK", fn),
|
||||
*loopK = llvm::BasicBlock::Create(ctx, "loopK", fn),
|
||||
*test1 = llvm::BasicBlock::Create(ctx, "test1", fn),
|
||||
*loop1 = llvm::BasicBlock::Create(ctx, "loop1", fn),
|
||||
*leave = llvm::BasicBlock::Create(ctx, "leave", fn);
|
||||
llvm::BasicBlock *enter = llvm::BasicBlock::Create(ctx, "enter" , fn),
|
||||
*hoistK = llvm::BasicBlock::Create(ctx, "hoistK", fn),
|
||||
*testK = llvm::BasicBlock::Create(ctx, "testK" , fn),
|
||||
*loopK = llvm::BasicBlock::Create(ctx, "loopK" , fn),
|
||||
*hoist1 = llvm::BasicBlock::Create(ctx, "hoist1", fn),
|
||||
*test1 = llvm::BasicBlock::Create(ctx, "test1" , fn),
|
||||
*loop1 = llvm::BasicBlock::Create(ctx, "loop1" , fn),
|
||||
*leave = llvm::BasicBlock::Create(ctx, "leave" , fn);
|
||||
|
||||
using IRBuilder = llvm::IRBuilder<>;
|
||||
|
||||
@ -2152,14 +2153,14 @@ namespace skvm {
|
||||
|
||||
{
|
||||
IRBuilder b(enter);
|
||||
b.CreateBr(hoist);
|
||||
b.CreateBr(hoistK);
|
||||
}
|
||||
|
||||
// hoist: emit each hoistable vector instruction; goto testK;
|
||||
// hoistK: emit each hoistable vector instruction; goto testK;
|
||||
// LLVM can do this sort of thing itself, but we've got the information cheap,
|
||||
// and pointer aliasing makes it easier to manually hoist than teach LLVM it's safe.
|
||||
{
|
||||
IRBuilder b(hoist);
|
||||
IRBuilder b(hoistK);
|
||||
|
||||
// Hoisted instructions will need args (think, uniforms), so set that up now.
|
||||
// These phi nodes are degenerate... they'll always be the passed-in args from enter.
|
||||
@ -2180,23 +2181,23 @@ namespace skvm {
|
||||
b.CreateBr(testK);
|
||||
}
|
||||
|
||||
// testK: if (N >= K) goto loopK; else goto test1;
|
||||
// testK: if (N >= K) goto loopK; else goto hoist1;
|
||||
{
|
||||
IRBuilder b(testK);
|
||||
|
||||
// New phi nodes for `n` and each pointer argument from hoist; later we'll add loopK.
|
||||
// These also start as the initial function arguments; hoist can't have changed them.
|
||||
// New phi nodes for `n` and each pointer argument from hoistK; later we'll add loopK.
|
||||
// These also start as the initial function arguments; hoistK can't have changed them.
|
||||
llvm::Argument* arg = fn->arg_begin();
|
||||
|
||||
n = b.CreatePHI(arg->getType(), 2);
|
||||
n->addIncoming(arg++, hoist);
|
||||
n->addIncoming(arg++, hoistK);
|
||||
|
||||
for (size_t i = 0; i < fStrides.size(); i++) {
|
||||
args[i] = b.CreatePHI(arg->getType(), 2);
|
||||
args[i]->addIncoming(arg++, hoist);
|
||||
args[i]->addIncoming(arg++, hoistK);
|
||||
}
|
||||
|
||||
b.CreateCondBr(b.CreateICmpSGE(n, b.getInt32(K)), loopK, test1);
|
||||
b.CreateCondBr(b.CreateICmpSGE(n, b.getInt32(K)), loopK, hoist1);
|
||||
}
|
||||
|
||||
// loopK: ... insts on K x T vectors; N -= K, args += K*stride; goto testK;
|
||||
@ -2221,21 +2222,29 @@ namespace skvm {
|
||||
b.CreateBr(testK);
|
||||
}
|
||||
|
||||
// TODO: hoist1
|
||||
// hoist1: emit each hoistable scalar instruction; goto test1;
|
||||
{
|
||||
IRBuilder b(hoist1);
|
||||
for (size_t i = 0; i < instructions.size(); i++) {
|
||||
if (instructions[i].can_hoist && !emit(i, true, &b)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
b.CreateBr(test1);
|
||||
}
|
||||
|
||||
// test1: if (N >= 1) goto loop1; else goto leave;
|
||||
{
|
||||
IRBuilder b(test1);
|
||||
|
||||
// Set up new phi nodes for `n` and each pointer argument, now from testK and loop1.
|
||||
|
||||
// Set up new phi nodes for `n` and each pointer argument, now from hoist1 and loop1.
|
||||
llvm::PHINode* n_new = b.CreatePHI(n->getType(), 2);
|
||||
n_new->addIncoming(n, testK);
|
||||
n_new->addIncoming(n, hoist1);
|
||||
n = n_new;
|
||||
|
||||
for (size_t i = 0; i < fStrides.size(); i++) {
|
||||
llvm::PHINode* arg_new = b.CreatePHI(args[i]->getType(), 2);
|
||||
arg_new->addIncoming(args[i], testK);
|
||||
arg_new->addIncoming(args[i], hoist1);
|
||||
args[i] = arg_new;
|
||||
}
|
||||
|
||||
@ -2246,7 +2255,7 @@ namespace skvm {
|
||||
{
|
||||
IRBuilder b(loop1);
|
||||
for (size_t i = 0; i < instructions.size(); i++) {
|
||||
if (!emit(i, true, &b)) {
|
||||
if (!instructions[i].can_hoist && !emit(i, true, &b)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user