Unify conversion constructor simplification code.
Previously, the IR generator had code which could simplify conversion constructors like `int(1.23)`. Separately, the optimizer's constant propagation pass had its own separate implementation of these simplifications as well. This CL unifies the two implementations. Previously, the constant- propagation pass version of the code only supported integer literals, so this change also improves our code generation slightly. Change-Id: I32c70a5f2aed210d03bef3166b1178a2d40cdabd Reviewed-on: https://skia-review.googlesource.com/c/skia/+/350024 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: John Stiles <johnstiles@google.com> Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
6cab033499
commit
53f0ddfa4e
@ -2297,79 +2297,24 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(int offset,
|
||||
std::unique_ptr<Expression> IRGenerator::convertScalarConstructor(int offset,
|
||||
const Type& type,
|
||||
ExpressionArray args) {
|
||||
SkASSERT(type.isNumber());
|
||||
SkASSERT(type.isNumber() || type.isBoolean());
|
||||
if (args.size() != 1) {
|
||||
fErrors.error(offset, "invalid arguments to '" + type.displayName() +
|
||||
"' constructor, (expected exactly 1 argument, but found " +
|
||||
to_string((uint64_t) args.size()) + ")");
|
||||
return nullptr;
|
||||
}
|
||||
const Type& argType = args[0]->type();
|
||||
if (type.isFloat()) {
|
||||
if (args[0]->is<FloatLiteral>()) {
|
||||
// Convert float(1.23) into a FloatLiteral. (Or half(1.23).)
|
||||
return std::make_unique<FloatLiteral>(offset, args[0]->as<FloatLiteral>().value(),
|
||||
&type);
|
||||
}
|
||||
if (args[0]->is<IntLiteral>()) {
|
||||
// Convert float(123) into a FloatLiteral. (Or half(123).)
|
||||
SKSL_FLOAT value = (SKSL_FLOAT)args[0]->as<IntLiteral>().value();
|
||||
return std::make_unique<FloatLiteral>(offset, value, &type);
|
||||
}
|
||||
if (args[0]->is<BoolLiteral>()) {
|
||||
// Convert float(true) into a FloatLiteral. (Or half(true).)
|
||||
bool value = args[0]->as<BoolLiteral>().value();
|
||||
return std::make_unique<FloatLiteral>(offset, value ? 1.0 : 0.0, &type);
|
||||
}
|
||||
} else if (type.isInteger()) {
|
||||
if (args[0]->is<IntLiteral>()) {
|
||||
// Convert int(123) into an IntLiteral. (Or uint(123), short(), byte(), etc.)
|
||||
return std::make_unique<IntLiteral>(offset, args[0]->as<IntLiteral>().value(), &type);
|
||||
}
|
||||
if (args[0]->is<FloatLiteral>()) {
|
||||
// Convert int(1.23) into an IntLiteral. (Or uint(1.23), short(), byte(), etc.)
|
||||
SKSL_INT value = (SKSL_INT)args[0]->as<FloatLiteral>().value();
|
||||
return std::make_unique<IntLiteral>(offset, value, &type);
|
||||
}
|
||||
if (args[0]->is<BoolLiteral>()) {
|
||||
// Convert int(true) into an IntLiteral. (Or uint(true), short(), byte(), etc.)
|
||||
bool value = args[0]->as<BoolLiteral>().value();
|
||||
return std::make_unique<IntLiteral>(offset, value ? 1 : 0, &type);
|
||||
}
|
||||
}
|
||||
if (!argType.isNumber() && !argType.isBoolean()) {
|
||||
fErrors.error(offset, "invalid argument to '" + type.displayName() +
|
||||
"' constructor (expected a number or bool, but found '" +
|
||||
argType.displayName() + "')");
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<Constructor>(offset, &type, std::move(args));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::convertBooleanConstructor(int offset,
|
||||
const Type& type,
|
||||
ExpressionArray args) {
|
||||
SkASSERT(type.isBoolean());
|
||||
if (args.size() != 1) {
|
||||
fErrors.error(offset, "invalid arguments to '" + type.displayName() +
|
||||
"' constructor, (expected exactly 1 argument, but found " +
|
||||
to_string((uint64_t) args.size()) + ")");
|
||||
return nullptr;
|
||||
std::unique_ptr<Expression> converted = Constructor::SimplifyConversion(fContext, type,
|
||||
*args[0]);
|
||||
if (converted) {
|
||||
return converted;
|
||||
}
|
||||
|
||||
const Type& argType = args[0]->type();
|
||||
if (args[0]->is<FloatLiteral>()) {
|
||||
// Convert bool(1.23) into a BoolLiteral.
|
||||
return std::make_unique<BoolLiteral>(fContext, offset,
|
||||
args[0]->as<FloatLiteral>().value() != 0.0);
|
||||
}
|
||||
if (args[0]->is<IntLiteral>()) {
|
||||
// Convert bool(123) into a BoolLiteral.
|
||||
return std::make_unique<BoolLiteral>(fContext, offset,
|
||||
args[0]->as<IntLiteral>().value() != 0);
|
||||
}
|
||||
if (!argType.isNumber() && !argType.isBoolean()) {
|
||||
fErrors.error(offset, "invalid argument to '" + type.displayName() +
|
||||
"' constructor (expected a number or bool, but found '" +
|
||||
@ -2445,11 +2390,8 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(int offset,
|
||||
// Strip off redundant casts--i.e., convert Type(exprOfType) into exprOfType.
|
||||
return std::move(args[0]);
|
||||
}
|
||||
if (type.isNumber()) {
|
||||
return this->convertNumberConstructor(offset, type, std::move(args));
|
||||
}
|
||||
if (type.isBoolean()) {
|
||||
return this->convertBooleanConstructor(offset, type, std::move(args));
|
||||
if (type.isNumber() || type.isBoolean()) {
|
||||
return this->convertScalarConstructor(offset, type, std::move(args));
|
||||
}
|
||||
if (type.isVector() || type.isMatrix()) {
|
||||
return this->convertCompoundConstructor(offset, type, std::move(args));
|
||||
|
@ -179,12 +179,9 @@ private:
|
||||
const Expression& right) const;
|
||||
std::unique_ptr<Block> convertBlock(const ASTNode& block);
|
||||
std::unique_ptr<Statement> convertBreak(const ASTNode& b);
|
||||
std::unique_ptr<Expression> convertNumberConstructor(int offset,
|
||||
std::unique_ptr<Expression> convertScalarConstructor(int offset,
|
||||
const Type& type,
|
||||
ExpressionArray params);
|
||||
std::unique_ptr<Expression> convertBooleanConstructor(int offset,
|
||||
const Type& type,
|
||||
ExpressionArray params);
|
||||
std::unique_ptr<Expression> convertCompoundConstructor(int offset,
|
||||
const Type& type,
|
||||
ExpressionArray params);
|
||||
|
@ -7,24 +7,62 @@
|
||||
|
||||
#include "src/sksl/ir/SkSLConstructor.h"
|
||||
|
||||
#include "src/sksl/ir/SkSLBoolLiteral.h"
|
||||
#include "src/sksl/ir/SkSLFloatLiteral.h"
|
||||
#include "src/sksl/ir/SkSLIntLiteral.h"
|
||||
#include "src/sksl/ir/SkSLPrefixExpression.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
std::unique_ptr<Expression> Constructor::constantPropagate(const IRGenerator& irGenerator,
|
||||
const DefinitionMap& definitions) {
|
||||
if (this->arguments().size() == 1 && this->arguments()[0]->is<IntLiteral>()) {
|
||||
const Context& context = irGenerator.fContext;
|
||||
const Type& type = this->type();
|
||||
SKSL_INT intValue = this->arguments()[0]->as<IntLiteral>().value();
|
||||
// Handle conversion constructors of literal values.
|
||||
if (this->arguments().size() == 1) {
|
||||
return SimplifyConversion(irGenerator.fContext, this->type(), *this->arguments().front());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (type.isFloat()) {
|
||||
std::unique_ptr<Expression> Constructor::SimplifyConversion(const Context& context,
|
||||
const Type& constructorType,
|
||||
const Expression& expr) {
|
||||
if (expr.is<IntLiteral>()) {
|
||||
SKSL_INT value = expr.as<IntLiteral>().value();
|
||||
if (constructorType.isFloat()) {
|
||||
// promote float(1) to 1.0
|
||||
return std::make_unique<FloatLiteral>(context, fOffset, intValue);
|
||||
} else if (type.isInteger()) {
|
||||
return std::make_unique<FloatLiteral>(expr.fOffset, (SKSL_FLOAT)value,
|
||||
&constructorType);
|
||||
} else if (constructorType.isInteger()) {
|
||||
// promote uint(1) to 1u
|
||||
return std::make_unique<IntLiteral>(fOffset, intValue, &type);
|
||||
} else if (&type == context.fBool_Type.get()) {
|
||||
// promote bool(k) to true/false
|
||||
return std::make_unique<BoolLiteral>(context, fOffset, intValue != 0);
|
||||
return std::make_unique<IntLiteral>(expr.fOffset, value, &constructorType);
|
||||
} else if (constructorType.isBoolean()) {
|
||||
// promote bool(1) to true/false
|
||||
return std::make_unique<BoolLiteral>(context, expr.fOffset, value != 0);
|
||||
}
|
||||
} else if (expr.is<FloatLiteral>()) {
|
||||
float value = expr.as<FloatLiteral>().value();
|
||||
if (constructorType.isFloat()) {
|
||||
// promote float(1.23) to 1.23
|
||||
return std::make_unique<FloatLiteral>(expr.fOffset, value, &constructorType);
|
||||
} else if (constructorType.isInteger()) {
|
||||
// promote uint(1.23) to 1u
|
||||
return std::make_unique<IntLiteral>(expr.fOffset, (SKSL_INT)value, &constructorType);
|
||||
} else if (constructorType.isBoolean()) {
|
||||
// promote bool(1.23) to true/false
|
||||
return std::make_unique<BoolLiteral>(context, expr.fOffset, value != 0.0f);
|
||||
}
|
||||
} else if (expr.is<BoolLiteral>()) {
|
||||
bool value = expr.as<BoolLiteral>().value();
|
||||
if (constructorType.isFloat()) {
|
||||
// promote float(true) to 1.0
|
||||
return std::make_unique<FloatLiteral>(expr.fOffset, value ? 1.0f : 0.0f,
|
||||
&constructorType);
|
||||
} else if (constructorType.isInteger()) {
|
||||
// promote uint(true) to 1u
|
||||
return std::make_unique<IntLiteral>(expr.fOffset, value ? 1 : 0, &constructorType);
|
||||
} else if (constructorType.isBoolean()) {
|
||||
// promote bool(true) to true/false
|
||||
return std::make_unique<BoolLiteral>(context, expr.fOffset, value);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -11,9 +11,6 @@
|
||||
#include "include/private/SkTArray.h"
|
||||
#include "src/sksl/SkSLIRGenerator.h"
|
||||
#include "src/sksl/ir/SkSLExpression.h"
|
||||
#include "src/sksl/ir/SkSLFloatLiteral.h"
|
||||
#include "src/sksl/ir/SkSLIntLiteral.h"
|
||||
#include "src/sksl/ir/SkSLPrefixExpression.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
@ -45,6 +42,15 @@ public:
|
||||
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
|
||||
const DefinitionMap& definitions) override;
|
||||
|
||||
// If the passed-in expression is a literal, performs a constructor-conversion of the literal
|
||||
// value to the constructor's type and returns that converted value as a new literal. e.g., the
|
||||
// constructor expression `short(3.14)` would be represented as `FloatLiteral(3.14)` along with
|
||||
// type `Short`, and this would result in `IntLiteral(3, type=Short)`. Returns nullptr if the
|
||||
// expression is not a literal or the conversion cannot be made.
|
||||
static std::unique_ptr<Expression> SimplifyConversion(const Context& context,
|
||||
const Type& constructorType,
|
||||
const Expression& expr);
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
for (const std::unique_ptr<Expression>& arg: this->arguments()) {
|
||||
if (arg->hasProperty(property)) {
|
||||
|
@ -113,7 +113,7 @@ OpDecorate %156 RelaxedPrecision
|
||||
%float_8_0 = OpConstant %float 8
|
||||
%float_9_0 = OpConstant %float 9
|
||||
%_ptr_Function_v3float = OpTypePointer Function %v3float
|
||||
%146 = OpConstantComposite %v4float %float_0_0 %float_0_0 %float_0_0 %float_0_0
|
||||
%146 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%main = OpFunction %void None %11
|
||||
%12 = OpLabel
|
||||
%x = OpVariable %_ptr_Function_v4float Function
|
||||
|
@ -46,8 +46,8 @@ OpDecorate %72 RelaxedPrecision
|
||||
OpDecorate %75 RelaxedPrecision
|
||||
OpDecorate %78 RelaxedPrecision
|
||||
OpDecorate %161 RelaxedPrecision
|
||||
OpDecorate %167 RelaxedPrecision
|
||||
OpDecorate %170 RelaxedPrecision
|
||||
OpDecorate %166 RelaxedPrecision
|
||||
OpDecorate %169 RelaxedPrecision
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
@ -112,6 +112,7 @@ OpDecorate %170 RelaxedPrecision
|
||||
%v2bool = OpTypeVector %bool 2
|
||||
%158 = OpConstantComposite %v2bool %false %false
|
||||
%_ptr_Function_bool = OpTypePointer Function %bool
|
||||
%float_0_0 = OpConstant %float 0
|
||||
%main = OpFunction %void None %11
|
||||
%12 = OpLabel
|
||||
%h3 = OpVariable %_ptr_Function_v3float Function
|
||||
@ -124,8 +125,8 @@ OpDecorate %170 RelaxedPrecision
|
||||
%f2 = OpVariable %_ptr_Function_v2float Function
|
||||
%f3 = OpVariable %_ptr_Function_v3float Function
|
||||
%f2x2 = OpVariable %_ptr_Function_mat2v2float Function
|
||||
%130 = OpVariable %_ptr_Function_mat3v3float Function
|
||||
%138 = OpVariable %_ptr_Function_mat4v4float Function
|
||||
%129 = OpVariable %_ptr_Function_mat3v3float Function
|
||||
%137 = OpVariable %_ptr_Function_mat4v4float Function
|
||||
%b3 = OpVariable %_ptr_Function_v3bool Function
|
||||
%b4 = OpVariable %_ptr_Function_v4bool Function
|
||||
OpStore %h3 %16
|
||||
@ -204,36 +205,36 @@ OpStore %114 %float_1_0
|
||||
%116 = OpCompositeExtract %float %115 0
|
||||
%117 = OpLoad %v3float %f3
|
||||
%118 = OpCompositeExtract %float %117 0
|
||||
%120 = OpCompositeConstruct %v4float %float_1_0 %116 %118 %float_4_0
|
||||
OpStore %sk_FragColor %120
|
||||
%123 = OpCompositeConstruct %v2float %float_2_0 %float_0
|
||||
%124 = OpCompositeConstruct %v2float %float_0 %float_2_0
|
||||
%122 = OpCompositeConstruct %mat2v2float %123 %124
|
||||
OpStore %f2x2 %122
|
||||
%125 = OpAccessChain %_ptr_Function_v2float %f2x2 %int_0
|
||||
%126 = OpAccessChain %_ptr_Function_float %125 %int_0
|
||||
OpStore %126 %float_1_0
|
||||
%127 = OpAccessChain %_ptr_Function_v2float %f2x2 %int_0
|
||||
%128 = OpLoad %v2float %127
|
||||
%129 = OpCompositeExtract %float %128 0
|
||||
%132 = OpCompositeConstruct %v3float %float_3_0 %float_0 %float_0
|
||||
%133 = OpCompositeConstruct %v3float %float_0 %float_3_0 %float_0
|
||||
%134 = OpCompositeConstruct %v3float %float_0 %float_0 %float_3_0
|
||||
%131 = OpCompositeConstruct %mat3v3float %132 %133 %134
|
||||
OpStore %130 %131
|
||||
%135 = OpAccessChain %_ptr_Function_v3float %130 %int_0
|
||||
%136 = OpLoad %v3float %135
|
||||
%137 = OpCompositeExtract %float %136 0
|
||||
%119 = OpCompositeConstruct %v4float %float_1 %116 %118 %float_4
|
||||
OpStore %sk_FragColor %119
|
||||
%122 = OpCompositeConstruct %v2float %float_2_0 %float_0
|
||||
%123 = OpCompositeConstruct %v2float %float_0 %float_2_0
|
||||
%121 = OpCompositeConstruct %mat2v2float %122 %123
|
||||
OpStore %f2x2 %121
|
||||
%124 = OpAccessChain %_ptr_Function_v2float %f2x2 %int_0
|
||||
%125 = OpAccessChain %_ptr_Function_float %124 %int_0
|
||||
OpStore %125 %float_1_0
|
||||
%126 = OpAccessChain %_ptr_Function_v2float %f2x2 %int_0
|
||||
%127 = OpLoad %v2float %126
|
||||
%128 = OpCompositeExtract %float %127 0
|
||||
%131 = OpCompositeConstruct %v3float %float_3_0 %float_0 %float_0
|
||||
%132 = OpCompositeConstruct %v3float %float_0 %float_3_0 %float_0
|
||||
%133 = OpCompositeConstruct %v3float %float_0 %float_0 %float_3_0
|
||||
%130 = OpCompositeConstruct %mat3v3float %131 %132 %133
|
||||
OpStore %129 %130
|
||||
%134 = OpAccessChain %_ptr_Function_v3float %129 %int_0
|
||||
%135 = OpLoad %v3float %134
|
||||
%136 = OpCompositeExtract %float %135 0
|
||||
%140 = OpCompositeConstruct %v4float %float_4_0 %float_0 %float_0 %float_0
|
||||
%141 = OpCompositeConstruct %v4float %float_0 %float_4_0 %float_0 %float_0
|
||||
%142 = OpCompositeConstruct %v4float %float_0 %float_0 %float_4_0 %float_0
|
||||
%143 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_4_0
|
||||
%139 = OpCompositeConstruct %mat4v4float %140 %141 %142 %143
|
||||
OpStore %138 %139
|
||||
%144 = OpAccessChain %_ptr_Function_v4float %138 %int_0
|
||||
OpStore %137 %139
|
||||
%144 = OpAccessChain %_ptr_Function_v4float %137 %int_0
|
||||
%145 = OpLoad %v4float %144
|
||||
%146 = OpCompositeExtract %float %145 0
|
||||
%147 = OpCompositeConstruct %v4float %129 %137 %146 %float_1
|
||||
%147 = OpCompositeConstruct %v4float %128 %136 %146 %float_1
|
||||
OpStore %sk_FragColor %147
|
||||
OpStore %b3 %151
|
||||
OpStore %b4 %156
|
||||
@ -242,15 +243,13 @@ OpStore %b4 %156
|
||||
OpStore %b4 %161
|
||||
%162 = OpAccessChain %_ptr_Function_bool %b3 %int_2
|
||||
OpStore %162 %true
|
||||
%164 = OpSelect %float %true %float_1_0 %float_0
|
||||
%165 = OpSelect %float %false %float_1_0 %float_0
|
||||
%167 = OpLoad %v3bool %b3
|
||||
%168 = OpCompositeExtract %bool %167 0
|
||||
%166 = OpSelect %float %168 %float_1_0 %float_0
|
||||
%170 = OpLoad %v4bool %b4
|
||||
%171 = OpCompositeExtract %bool %170 0
|
||||
%169 = OpSelect %float %171 %float_1_0 %float_0
|
||||
%172 = OpCompositeConstruct %v4float %164 %165 %166 %169
|
||||
OpStore %sk_FragColor %172
|
||||
%166 = OpLoad %v3bool %b3
|
||||
%167 = OpCompositeExtract %bool %166 0
|
||||
%165 = OpSelect %float %167 %float_1_0 %float_0
|
||||
%169 = OpLoad %v4bool %b4
|
||||
%170 = OpCompositeExtract %bool %169 0
|
||||
%168 = OpSelect %float %170 %float_1_0 %float_0
|
||||
%171 = OpCompositeConstruct %v4float %float_1 %float_0_0 %165 %168
|
||||
OpStore %sk_FragColor %171
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
@ -68,5 +68,5 @@ void main() {
|
||||
|
||||
b3.z = true;
|
||||
|
||||
sk_FragColor = vec4(float(true), float(false), float(b3.x), float(b4.x));
|
||||
sk_FragColor = vec4(1.0, 0.0, float(b3.x), float(b4.x));
|
||||
}
|
||||
|
@ -76,6 +76,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
|
||||
|
||||
b3.z = true;
|
||||
|
||||
_out->sk_FragColor = float4(float(true), float(bool(false)), float(b3.x), float(b4.x));
|
||||
_out->sk_FragColor = float4(1.0, 0.0, float(b3.x), float(b4.x));
|
||||
return *_out;
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ OpDecorate %sk_Clockwise BuiltIn FrontFacing
|
||||
%int_0 = OpConstant %int 0
|
||||
%float_0 = OpConstant %float 0
|
||||
%float_1 = OpConstant %float 1
|
||||
%24 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%float_0_0 = OpConstant %float 0
|
||||
%24 = OpConstantComposite %v4float %float_0_0 %float_0_0 %float_0_0 %float_0_0
|
||||
%main = OpFunction %void None %11
|
||||
%12 = OpLabel
|
||||
OpSelectionMerge %15 None
|
||||
|
@ -22,7 +22,8 @@ OpDecorate %sk_Clockwise BuiltIn FrontFacing
|
||||
%11 = OpTypeFunction %void
|
||||
%float_2 = OpConstant %float 2
|
||||
%int = OpTypeInt 32 1
|
||||
%21 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
|
||||
%float_2_0 = OpConstant %float 2
|
||||
%21 = OpConstantComposite %v4float %float_2_0 %float_2_0 %float_2_0 %float_2_0
|
||||
%main = OpFunction %void None %11
|
||||
%12 = OpLabel
|
||||
%14 = OpExtInst %float %1 Sqrt %float_2
|
||||
|
Loading…
Reference in New Issue
Block a user