From 89c995c196ce1ac133b9c545cecd9eef72b77cc3 Mon Sep 17 00:00:00 2001 From: Mike Klein Date: Mon, 2 Mar 2020 15:46:36 -0600 Subject: [PATCH] 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 Commit-Queue: Mike Klein --- src/core/SkVM.cpp | 53 +++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/core/SkVM.cpp b/src/core/SkVM.cpp index 38dfe8cb10..e6a9768702 100644 --- a/src/core/SkVM.cpp +++ b/src/core/SkVM.cpp @@ -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; } }