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:
Mike Klein 2020-03-02 15:46:36 -06:00 committed by Skia Commit-Bot
parent 6a63365fee
commit 89c995c196

View File

@ -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;
}
}