diff options
author | 2018-03-26 14:24:27 -0400 | |
---|---|---|
committer | 2018-03-26 19:03:44 +0000 | |
commit | 8f7e28f3ae262450c5b04deded9fa23041757868 (patch) | |
tree | ca5007c4dce793ee1841a5a2d27d1a865a5f85ff /src/sksl/ir | |
parent | 19d311b1e3f48d0f04585ce199c377956af52be4 (diff) |
added frexp support to SkSL
This includes an optimizer fix for the situation:
int i;
float f = frexp(foo, i);
If we don't read the variable i, it is considered dead and eliminated -
which then causes an error when we try to write the expression
frexmp(foo, i).
Bug: skia:
Change-Id: Iac385e38e215455346fab62e1f4ec46fa65b3c21
Reviewed-on: https://skia-review.googlesource.com/116521
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src/sksl/ir')
-rw-r--r-- | src/sksl/ir/SkSLVariableReference.cpp | 108 | ||||
-rw-r--r-- | src/sksl/ir/SkSLVariableReference.h | 104 |
2 files changed, 120 insertions, 92 deletions
diff --git a/src/sksl/ir/SkSLVariableReference.cpp b/src/sksl/ir/SkSLVariableReference.cpp new file mode 100644 index 0000000000..37e0ca2e7d --- /dev/null +++ b/src/sksl/ir/SkSLVariableReference.cpp @@ -0,0 +1,108 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLVariableReference.h" + +#include "SkSLConstructor.h" +#include "SkSLFloatLiteral.h" +#include "SkSLIRGenerator.h" +#include "SkSLSetting.h" + +namespace SkSL { + +VariableReference::VariableReference(int offset, const Variable& variable, RefKind refKind) +: INHERITED(offset, kVariableReference_Kind, variable.fType) +, fVariable(variable) +, fRefKind(refKind) { + if (refKind != kRead_RefKind) { + fVariable.fWriteCount++; + } + if (refKind != kWrite_RefKind) { + fVariable.fReadCount++; + } +} + +VariableReference::~VariableReference() { + if (fRefKind != kRead_RefKind) { + fVariable.fWriteCount--; + } + if (fRefKind != kWrite_RefKind) { + fVariable.fReadCount--; + } +} + +void VariableReference::setRefKind(RefKind refKind) { + if (fRefKind != kRead_RefKind) { + fVariable.fWriteCount--; + } + if (fRefKind != kWrite_RefKind) { + fVariable.fReadCount--; + } + if (refKind != kRead_RefKind) { + fVariable.fWriteCount++; + } + if (refKind != kWrite_RefKind) { + fVariable.fReadCount++; + } + fRefKind = refKind; +} + +std::unique_ptr<Expression> VariableReference::copy_constant(const IRGenerator& irGenerator, + const Expression* expr) { + ASSERT(expr->isConstant()); + switch (expr->fKind) { + case Expression::kIntLiteral_Kind: + return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, + -1, + ((IntLiteral*) expr)->fValue)); + case Expression::kFloatLiteral_Kind: + return std::unique_ptr<Expression>(new FloatLiteral( + irGenerator.fContext, + -1, + ((FloatLiteral*) expr)->fValue)); + case Expression::kBoolLiteral_Kind: + return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext, + -1, + ((BoolLiteral*) expr)->fValue)); + case Expression::kConstructor_Kind: { + const Constructor* c = (const Constructor*) expr; + std::vector<std::unique_ptr<Expression>> args; + for (const auto& arg : c->fArguments) { + args.push_back(copy_constant(irGenerator, arg.get())); + } + return std::unique_ptr<Expression>(new Constructor(-1, c->fType, + std::move(args))); + } + case Expression::kSetting_Kind: { + const Setting* s = (const Setting*) expr; + return std::unique_ptr<Expression>(new Setting(-1, s->fName, + copy_constant(irGenerator, + s->fValue.get()))); + } + default: + ABORT("unsupported constant\n"); + } +} + +std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerator& irGenerator, + const DefinitionMap& definitions) { + if (fRefKind != kRead_RefKind) { + return nullptr; + } + if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue && + fVariable.fInitialValue->isConstant()) { + return copy_constant(irGenerator, fVariable.fInitialValue); + } + auto exprIter = definitions.find(&fVariable); + if (exprIter != definitions.end() && exprIter->second && + (*exprIter->second)->isConstant()) { + return copy_constant(irGenerator, exprIter->second->get()); + } + return nullptr; +} + +} // namespace diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h index e1f19ac742..14ddf796ff 100644 --- a/src/sksl/ir/SkSLVariableReference.h +++ b/src/sksl/ir/SkSLVariableReference.h @@ -8,16 +8,12 @@ #ifndef SKSL_VARIABLEREFERENCE #define SKSL_VARIABLEREFERENCE -#include "SkSLBoolLiteral.h" -#include "SkSLConstructor.h" #include "SkSLExpression.h" -#include "SkSLFloatLiteral.h" -#include "SkSLIRGenerator.h" -#include "SkSLIntLiteral.h" -#include "SkSLSetting.h" namespace SkSL { +class IRGenerator; + /** * A reference to a variable, through which it can be read or written. In the statement: * @@ -29,49 +25,21 @@ struct VariableReference : public Expression { enum RefKind { kRead_RefKind, kWrite_RefKind, - kReadWrite_RefKind + kReadWrite_RefKind, + // taking the address of a variable - we consider this a read & write but don't complain if + // the variable was not previously assigned + kPointer_RefKind }; - VariableReference(int offset, const Variable& variable, RefKind refKind = kRead_RefKind) - : INHERITED(offset, kVariableReference_Kind, variable.fType) - , fVariable(variable) - , fRefKind(refKind) { - if (refKind != kRead_RefKind) { - fVariable.fWriteCount++; - } - if (refKind != kWrite_RefKind) { - fVariable.fReadCount++; - } - } + VariableReference(int offset, const Variable& variable, RefKind refKind = kRead_RefKind); - ~VariableReference() override { - if (fRefKind != kRead_RefKind) { - fVariable.fWriteCount--; - } - if (fRefKind != kWrite_RefKind) { - fVariable.fReadCount--; - } - } + ~VariableReference() override; - RefKind refKind() { + RefKind refKind() const { return fRefKind; } - void setRefKind(RefKind refKind) { - if (fRefKind != kRead_RefKind) { - fVariable.fWriteCount--; - } - if (fRefKind != kWrite_RefKind) { - fVariable.fReadCount--; - } - if (refKind != kRead_RefKind) { - fVariable.fWriteCount++; - } - if (refKind != kWrite_RefKind) { - fVariable.fReadCount++; - } - fRefKind = refKind; - } + void setRefKind(RefKind refKind); bool hasSideEffects() const override { return false; @@ -86,58 +54,10 @@ struct VariableReference : public Expression { } static std::unique_ptr<Expression> copy_constant(const IRGenerator& irGenerator, - const Expression* expr) { - ASSERT(expr->isConstant()); - switch (expr->fKind) { - case Expression::kIntLiteral_Kind: - return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, - -1, - ((IntLiteral*) expr)->fValue)); - case Expression::kFloatLiteral_Kind: - return std::unique_ptr<Expression>(new FloatLiteral( - irGenerator.fContext, - -1, - ((FloatLiteral*) expr)->fValue)); - case Expression::kBoolLiteral_Kind: - return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext, - -1, - ((BoolLiteral*) expr)->fValue)); - case Expression::kConstructor_Kind: { - const Constructor* c = (const Constructor*) expr; - std::vector<std::unique_ptr<Expression>> args; - for (const auto& arg : c->fArguments) { - args.push_back(copy_constant(irGenerator, arg.get())); - } - return std::unique_ptr<Expression>(new Constructor(-1, c->fType, - std::move(args))); - } - case Expression::kSetting_Kind: { - const Setting* s = (const Setting*) expr; - return std::unique_ptr<Expression>(new Setting(-1, s->fName, - copy_constant(irGenerator, - s->fValue.get()))); - } - default: - ABORT("unsupported constant\n"); - } - } + const Expression* expr); std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, - const DefinitionMap& definitions) override { - if (fRefKind != kRead_RefKind) { - return nullptr; - } - if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue && - fVariable.fInitialValue->isConstant()) { - return copy_constant(irGenerator, fVariable.fInitialValue); - } - auto exprIter = definitions.find(&fVariable); - if (exprIter != definitions.end() && exprIter->second && - (*exprIter->second)->isConstant()) { - return copy_constant(irGenerator, exprIter->second->get()); - } - return nullptr; - } + const DefinitionMap& definitions) override; const Variable& fVariable; RefKind fRefKind; |