Use an unordered map for intrinsics in the IR generator.

Several small tweaks:
- Replace std::pair<> with a struct (IRIntrinsic) so we can use names
  (fIntrinsic/fAlreadyIncluded) instead of .first and .second.
- Replace std::map<String, std::pair<...>> with a name (IRIntrinsicMap).
- Replace map with unordered_map, since we don't rely on order anywhere.

Change-Id: I508eb3cde5bd4fddcc0b3d02d6ce21d33f9a5421
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313523
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
John Stiles 2020-08-26 19:46:27 -04:00 committed by Skia Commit-Bot
parent aba6b93dfb
commit 810c8cf519
5 changed files with 42 additions and 29 deletions

View File

@ -70,7 +70,7 @@ static const char SKSL_PIPELINE_INCLUDE[] = "sksl_pipeline.sksl";
namespace SkSL {
static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>>* target) {
IRIntrinsicMap* target) {
for (auto iter = src->begin(); iter != src->end(); ) {
std::unique_ptr<ProgramElement>& element = *iter;
switch (element->fKind) {
@ -79,7 +79,7 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
SkASSERT(f.fDeclaration.fBuiltin);
String key = f.fDeclaration.description();
SkASSERT(target->find(key) == target->end());
(*target)[key] = std::make_pair(std::move(element), false);
(*target)[key] = IRIntrinsic{std::move(element), /*fAlreadyIncluded=*/false};
iter = src->erase(iter);
break;
}
@ -87,7 +87,7 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
Enum& e = element->as<Enum>();
StringFragment name = e.fTypeName;
SkASSERT(target->find(name) == target->end());
(*target)[name] = std::make_pair(std::move(element), false);
(*target)[name] = IRIntrinsic{std::move(element), /*fAlreadyIncluded=*/false};
iter = src->erase(iter);
break;
}
@ -99,8 +99,10 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
}
Compiler::Compiler(Flags flags)
: fFlags(flags)
, fContext(new Context())
: fGPUIntrinsics(std::make_unique<IRIntrinsicMap>())
, fInterpreterIntrinsics(std::make_unique<IRIntrinsicMap>())
, fFlags(flags)
, fContext(std::make_shared<Context>())
, fErrorCount(0) {
auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(this));
fIRGenerator = new IRGenerator(fContext.get(), symbols, *this);
@ -236,7 +238,7 @@ Compiler::Compiler(Flags flags)
std::make_unique<Variable>(/*offset=*/-1, Modifiers(), skCapsName,
*fContext->fSkCaps_Type, Variable::kGlobal_Storage));
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
std::vector<std::unique_ptr<ProgramElement>> gpuIntrinsics;
std::vector<std::unique_ptr<ProgramElement>> interpIntrinsics;
#if SKSL_STANDALONE
@ -266,8 +268,8 @@ Compiler::Compiler(Flags flags)
fFragmentInclude = rehydrator.elements();
}
#endif
grab_intrinsics(&gpuIntrinsics, &fGPUIntrinsics);
grab_intrinsics(&interpIntrinsics, &fInterpreterIntrinsics);
grab_intrinsics(&gpuIntrinsics, fGPUIntrinsics.get());
grab_intrinsics(&interpIntrinsics, fInterpreterIntrinsics.get());
}
Compiler::~Compiler() {
@ -1548,20 +1550,20 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
case Program::kVertex_Kind:
inherited = &fVertexInclude;
fIRGenerator->fSymbolTable = fVertexSymbolTable;
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
fIRGenerator->start(&settings, inherited);
break;
case Program::kFragment_Kind:
inherited = &fFragmentInclude;
fIRGenerator->fSymbolTable = fFragmentSymbolTable;
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
fIRGenerator->start(&settings, inherited);
break;
case Program::kGeometry_Kind:
this->loadGeometryIntrinsics();
inherited = &fGeometryInclude;
fIRGenerator->fSymbolTable = fGeometrySymbolTable;
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
fIRGenerator->start(&settings, inherited);
break;
case Program::kFragmentProcessor_Kind: {
@ -1575,14 +1577,14 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
}
inherited = &fFPInclude;
fIRGenerator->fSymbolTable = fFPSymbolTable;
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
fIRGenerator->start(&settings, inherited);
break;
#else
inherited = nullptr;
fIRGenerator->fSymbolTable = fGpuSymbolTable;
fIRGenerator->start(&settings, /*inherited=*/nullptr, /*builtin=*/true);
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
std::ifstream in(SKSL_FP_INCLUDE);
std::string stdText{std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>()};
@ -1601,14 +1603,14 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
this->loadPipelineIntrinsics();
inherited = &fPipelineInclude;
fIRGenerator->fSymbolTable = fPipelineSymbolTable;
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
fIRGenerator->start(&settings, inherited);
break;
case Program::kGeneric_Kind:
this->loadInterpreterIntrinsics();
inherited = &fInterpreterInclude;
fIRGenerator->fSymbolTable = fInterpreterSymbolTable;
fIRGenerator->fIntrinsics = &fInterpreterIntrinsics;
fIRGenerator->fIntrinsics = fInterpreterIntrinsics.get();
fIRGenerator->start(&settings, inherited);
break;
}

View File

@ -8,8 +8,8 @@
#ifndef SKSL_COMPILER
#define SKSL_COMPILER
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "src/sksl/SkSLASTFile.h"
@ -46,6 +46,8 @@ namespace SkSL {
class ByteCode;
class ExternalValue;
class IRGenerator;
struct IRIntrinsic;
using IRIntrinsicMap = std::unordered_map<String, IRIntrinsic>;
struct PipelineStageArgs;
/**
@ -223,8 +225,8 @@ private:
Position position(int offset);
std::shared_ptr<SymbolTable> fGpuSymbolTable;
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fGPUIntrinsics;
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fInterpreterIntrinsics;
std::unique_ptr<IRIntrinsicMap> fGPUIntrinsics;
std::unique_ptr<IRIntrinsicMap> fInterpreterIntrinsics;
std::unique_ptr<ASTFile> fGpuIncludeSource;
std::vector<std::unique_ptr<ProgramElement>> fVertexInclude;
std::shared_ptr<SymbolTable> fVertexSymbolTable;

View File

@ -7,6 +7,8 @@
#include "src/sksl/SkSLDehydrator.h"
#include <map>
#include "src/sksl/SkSLRehydrator.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBreakStatement.h"

View File

@ -192,7 +192,7 @@ void IRGenerator::start(const Program::Settings* settings,
}
SkASSERT(fIntrinsics);
for (auto& pair : *fIntrinsics) {
pair.second.second = false;
pair.second.fAlreadyIncluded = false;
}
}
@ -2398,9 +2398,9 @@ std::unique_ptr<Expression> IRGenerator::inlineCall(
void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
auto found = fIntrinsics->find(function.description());
if (found != fIntrinsics->end() && !found->second.second) {
found->second.second = true;
FunctionDefinition& original = found->second.first->as<FunctionDefinition>();
if (found != fIntrinsics->end() && !found->second.fAlreadyIncluded) {
found->second.fAlreadyIncluded = true;
FunctionDefinition& original = found->second.fIntrinsic->as<FunctionDefinition>();
for (const FunctionDeclaration* f : original.fReferencedIntrinsics) {
this->copyIntrinsicIfNeeded(*f);
}
@ -3061,9 +3061,9 @@ std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type
if (!result) {
auto found = fIntrinsics->find(type.fName);
if (found != fIntrinsics->end()) {
SkASSERT(!found->second.second);
found->second.second = true;
fProgramElements->push_back(found->second.first->clone());
SkASSERT(!found->second.fAlreadyIncluded);
found->second.fAlreadyIncluded = true;
fProgramElements->push_back(found->second.fIntrinsic->clone());
return this->convertTypeField(offset, type, field);
}
fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +

View File

@ -8,7 +8,6 @@
#ifndef SKSL_IRGENERATOR
#define SKSL_IRGENERATOR
#include <map>
#include <unordered_map>
#include <unordered_set>
@ -35,6 +34,15 @@ namespace SkSL {
struct Swizzle;
/**
* Intrinsics are passed between the Compiler and the IRGenerator using IRIntrinsicMaps.
*/
struct IRIntrinsic {
std::unique_ptr<ProgramElement> fIntrinsic;
bool fAlreadyIncluded = false;
};
using IRIntrinsicMap = std::unordered_map<String, IRIntrinsic>;
/**
* Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
* (unoptimized) intermediate representation (IR).
@ -179,9 +187,8 @@ private:
// additional statements that need to be inserted before the one that convertStatement is
// currently working on
std::vector<std::unique_ptr<Statement>> fExtraStatements;
// Symbols which have definitions in the include files. The bool tells us whether this
// intrinsic has been included already.
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>>* fIntrinsics = nullptr;
// Symbols which have definitions in the include files.
IRIntrinsicMap* fIntrinsics = nullptr;
std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics;
int fLoopLevel;
int fSwitchLevel;