Improve constant folding for int vectors.
This implements constant folding optimizations on int vectors (== != + - * /) that were previously only supported on float vectors. Bug: skia:10908 Change-Id: Ibf61ab43eb7ae2ce8e99cce21cc55777359817e5 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/332424 Commit-Queue: John Stiles <johnstiles@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com> Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
56277e5a6e
commit
cf27b4f744
@ -1721,6 +1721,57 @@ static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::unique_ptr<Expression> IRGenerator::constantFoldVector(const Expression& left,
|
||||
Token::Kind op,
|
||||
const Expression& right) const {
|
||||
SkASSERT(left.type() == right.type());
|
||||
const Type& type = left.type();
|
||||
|
||||
// Handle boolean operations: == !=
|
||||
if (op == Token::Kind::TK_EQEQ || op == Token::Kind::TK_NEQ) {
|
||||
if (left.kind() == right.kind()) {
|
||||
bool result = left.compareConstant(fContext, right) ^ (op == Token::Kind::TK_NEQ);
|
||||
return std::make_unique<BoolLiteral>(fContext, left.fOffset, result);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Handle floating-point arithmetic: + - * /
|
||||
const auto vectorComponentwiseFold = [&](auto foldFn) -> std::unique_ptr<Constructor> {
|
||||
ExpressionArray args;
|
||||
for (int i = 0; i < type.columns(); i++) {
|
||||
T value = foldFn(left.getVecComponent<T>(i), right.getVecComponent<T>(i));
|
||||
args.push_back(std::make_unique<Literal<T>>(fContext, left.fOffset, value));
|
||||
}
|
||||
return std::make_unique<Constructor>(left.fOffset, &type, std::move(args));
|
||||
};
|
||||
|
||||
const auto isVectorDivisionByZero = [&]() -> bool {
|
||||
for (int i = 0; i < type.columns(); i++) {
|
||||
if (right.getVecComponent<T>(i) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
switch (op) {
|
||||
case Token::Kind::TK_PLUS: return vectorComponentwiseFold([](T a, T b) { return a + b; });
|
||||
case Token::Kind::TK_MINUS: return vectorComponentwiseFold([](T a, T b) { return a - b; });
|
||||
case Token::Kind::TK_STAR: return vectorComponentwiseFold([](T a, T b) { return a * b; });
|
||||
case Token::Kind::TK_SLASH: {
|
||||
if (isVectorDivisionByZero()) {
|
||||
fErrors.error(right.fOffset, "division by zero");
|
||||
return nullptr;
|
||||
}
|
||||
return vectorComponentwiseFold([](T a, T b) { return a / b; });
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
|
||||
Token::Kind op,
|
||||
const Expression& right) const {
|
||||
@ -1836,46 +1887,12 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
|
||||
}
|
||||
const Type& leftType = left.type();
|
||||
const Type& rightType = right.type();
|
||||
if (leftType.typeKind() == Type::TypeKind::kVector && leftType.componentType().isFloat() &&
|
||||
leftType == rightType) {
|
||||
ExpressionArray args;
|
||||
#define RETURN_VEC_COMPONENTWISE_RESULT(op) \
|
||||
for (int i = 0; i < leftType.columns(); i++) { \
|
||||
SKSL_FLOAT value = left.getFVecComponent(i) op right.getFVecComponent(i); \
|
||||
args.push_back(std::make_unique<FloatLiteral>(fContext, left.fOffset, value)); \
|
||||
} \
|
||||
return std::make_unique<Constructor>(left.fOffset, &leftType, std::move(args))
|
||||
switch (op) {
|
||||
case Token::Kind::TK_EQEQ:
|
||||
if (left.kind() == right.kind()) {
|
||||
return std::make_unique<BoolLiteral>(fContext, left.fOffset,
|
||||
left.compareConstant(fContext, right));
|
||||
}
|
||||
return nullptr;
|
||||
case Token::Kind::TK_NEQ:
|
||||
if (left.kind() == right.kind()) {
|
||||
return std::make_unique<BoolLiteral>(fContext, left.fOffset,
|
||||
!left.compareConstant(fContext, right));
|
||||
}
|
||||
return nullptr;
|
||||
case Token::Kind::TK_PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
|
||||
case Token::Kind::TK_MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
|
||||
case Token::Kind::TK_STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
|
||||
case Token::Kind::TK_SLASH:
|
||||
for (int i = 0; i < leftType.columns(); i++) {
|
||||
SKSL_FLOAT rvalue = right.getFVecComponent(i);
|
||||
if (rvalue == 0.0) {
|
||||
fErrors.error(right.fOffset, "division by zero");
|
||||
return nullptr;
|
||||
}
|
||||
SKSL_FLOAT value = left.getFVecComponent(i) / rvalue;
|
||||
args.push_back(std::make_unique<FloatLiteral>(fContext, /*offset=*/-1, value));
|
||||
}
|
||||
return std::make_unique<Constructor>(/*offset=*/-1, &leftType, std::move(args));
|
||||
default:
|
||||
return nullptr;
|
||||
if (leftType.typeKind() == Type::TypeKind::kVector && leftType == rightType) {
|
||||
if (leftType.componentType().isFloat()) {
|
||||
return constantFoldVector<SKSL_FLOAT>(left, op, right);
|
||||
} else if (leftType.componentType().isInteger()) {
|
||||
return constantFoldVector<SKSL_INT>(left, op, right);
|
||||
}
|
||||
#undef RETURN_VEC_COMPONENTWISE_RESULT
|
||||
}
|
||||
if (leftType.typeKind() == Type::TypeKind::kMatrix &&
|
||||
rightType.typeKind() == Type::TypeKind::kMatrix &&
|
||||
|
@ -171,6 +171,10 @@ private:
|
||||
ExpressionArray arguments);
|
||||
CoercionCost coercionCost(const Expression& expr, const Type& type);
|
||||
std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
|
||||
template <typename T>
|
||||
std::unique_ptr<Expression> constantFoldVector(const Expression& left,
|
||||
Token::Kind op,
|
||||
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,
|
||||
|
@ -9,10 +9,10 @@ void main() {
|
||||
}
|
||||
|
||||
{
|
||||
sk_FragColor.x = float(ivec4(-1) == ivec4(ivec2(-1), ivec2(-1)) ? 1 : 0);
|
||||
sk_FragColor.y = float(ivec4(1) != ivec4(-1) ? 1 : 0);
|
||||
sk_FragColor.z = float(ivec4(-2) == ivec4(-2, ivec3(-2)) ? 1 : 0);
|
||||
sk_FragColor.w = float(ivec2(1, -2) == ivec2(1, -2) ? 1 : 0);
|
||||
sk_FragColor.x = 1.0;
|
||||
sk_FragColor.y = 1.0;
|
||||
sk_FragColor.z = 1.0;
|
||||
sk_FragColor.w = 1.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
|
||||
}
|
||||
|
||||
{
|
||||
_out->sk_FragColor.x = float(all(int4(-1) == int4(int2(-1), int2(-1))) ? 1 : 0);
|
||||
_out->sk_FragColor.y = float(any(int4(1) != int4(-1)) ? 1 : 0);
|
||||
_out->sk_FragColor.z = float(all(int4(-2) == int4(-2, int3(-2))) ? 1 : 0);
|
||||
_out->sk_FragColor.w = float(all(int2(1, -2) == int2(1, -2)) ? 1 : 0);
|
||||
_out->sk_FragColor.x = 1.0;
|
||||
_out->sk_FragColor.y = 1.0;
|
||||
_out->sk_FragColor.z = 1.0;
|
||||
_out->sk_FragColor.w = 1.0;
|
||||
}
|
||||
|
||||
return *_out;
|
||||
|
@ -52,21 +52,21 @@ void main() {
|
||||
{
|
||||
ivec4 _0_result;
|
||||
_0_result.x = 2;
|
||||
_0_result = ivec4(ivec2(1), ivec2(2, 3)) + ivec4(5, 6, 7, 8);
|
||||
_0_result = ivec4(8, ivec3(10)) - ivec4(1);
|
||||
_0_result = ivec4(2) * ivec4(1, 2, 3, 4);
|
||||
_0_result = ivec4(12) / ivec4(1, 2, 3, 4);
|
||||
sk_FragColor.x = float((ivec4(12) / ivec4(1, 2, 3, 4)).y);
|
||||
sk_FragColor.x = ivec4(1) == ivec4(1) ? 1.0 : -1.0;
|
||||
sk_FragColor.x = ivec4(1) == ivec4(2) ? 2.0 : -2.0;
|
||||
sk_FragColor.x = ivec2(1) == ivec2(1, 1) ? 3.0 : -3.0;
|
||||
sk_FragColor.x = ivec2(1, 1) == ivec2(1, 1) ? 4.0 : -4.0;
|
||||
sk_FragColor.x = ivec2(1) == ivec2(1, 0) ? 5.0 : -5.0;
|
||||
sk_FragColor.x = ivec4(1) == ivec4(ivec2(1), ivec2(1)) ? 6.0 : -6.0;
|
||||
sk_FragColor.x = ivec4(ivec3(1), 1) == ivec4(ivec2(1), ivec2(1)) ? 7.0 : -7.0;
|
||||
sk_FragColor.x = ivec4(ivec3(1), 1) == ivec4(ivec2(1), 1, 0) ? 8.0 : -8.0;
|
||||
sk_FragColor.x = ivec2(1) != ivec2(1, 0) ? 9.0 : -9.0;
|
||||
sk_FragColor.x = ivec4(1) != ivec4(ivec2(1), ivec2(1)) ? 10.0 : -10.0;
|
||||
_0_result = ivec4(6, 7, 9, 11);
|
||||
_0_result = ivec4(7, 9, 9, 9);
|
||||
_0_result = ivec4(2, 4, 6, 8);
|
||||
_0_result = ivec4(12, 6, 4, 3);
|
||||
sk_FragColor.x = 6.0;
|
||||
sk_FragColor.x = 1.0;
|
||||
sk_FragColor.x = -2.0;
|
||||
sk_FragColor.x = 3.0;
|
||||
sk_FragColor.x = 4.0;
|
||||
sk_FragColor.x = -5.0;
|
||||
sk_FragColor.x = 6.0;
|
||||
sk_FragColor.x = 7.0;
|
||||
sk_FragColor.x = -8.0;
|
||||
sk_FragColor.x = 9.0;
|
||||
sk_FragColor.x = -10.0;
|
||||
_0_result = ivec4(int(sqrt(1.0)));
|
||||
_0_result = ivec4(int(sqrt(2.0)));
|
||||
_0_result = ivec4(0);
|
||||
|
@ -60,21 +60,21 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
|
||||
{
|
||||
int4 _0_result;
|
||||
_0_result.x = 2;
|
||||
_0_result = int4(int2(1), int2(2, 3)) + int4(5, 6, 7, 8);
|
||||
_0_result = int4(8, int3(10)) - int4(1);
|
||||
_0_result = int4(2) * int4(1, 2, 3, 4);
|
||||
_0_result = int4(12) / int4(1, 2, 3, 4);
|
||||
_out->sk_FragColor.x = float((int4(12) / int4(1, 2, 3, 4)).y);
|
||||
_out->sk_FragColor.x = all(int4(1) == int4(1)) ? 1.0 : -1.0;
|
||||
_out->sk_FragColor.x = all(int4(1) == int4(2)) ? 2.0 : -2.0;
|
||||
_out->sk_FragColor.x = all(int2(1) == int2(1, 1)) ? 3.0 : -3.0;
|
||||
_out->sk_FragColor.x = all(int2(1, 1) == int2(1, 1)) ? 4.0 : -4.0;
|
||||
_out->sk_FragColor.x = all(int2(1) == int2(1, 0)) ? 5.0 : -5.0;
|
||||
_out->sk_FragColor.x = all(int4(1) == int4(int2(1), int2(1))) ? 6.0 : -6.0;
|
||||
_out->sk_FragColor.x = all(int4(int3(1), 1) == int4(int2(1), int2(1))) ? 7.0 : -7.0;
|
||||
_out->sk_FragColor.x = all(int4(int3(1), 1) == int4(int2(1), 1, 0)) ? 8.0 : -8.0;
|
||||
_out->sk_FragColor.x = any(int2(1) != int2(1, 0)) ? 9.0 : -9.0;
|
||||
_out->sk_FragColor.x = any(int4(1) != int4(int2(1), int2(1))) ? 10.0 : -10.0;
|
||||
_0_result = int4(6, 7, 9, 11);
|
||||
_0_result = int4(7, 9, 9, 9);
|
||||
_0_result = int4(2, 4, 6, 8);
|
||||
_0_result = int4(12, 6, 4, 3);
|
||||
_out->sk_FragColor.x = 6.0;
|
||||
_out->sk_FragColor.x = 1.0;
|
||||
_out->sk_FragColor.x = -2.0;
|
||||
_out->sk_FragColor.x = 3.0;
|
||||
_out->sk_FragColor.x = 4.0;
|
||||
_out->sk_FragColor.x = -5.0;
|
||||
_out->sk_FragColor.x = 6.0;
|
||||
_out->sk_FragColor.x = 7.0;
|
||||
_out->sk_FragColor.x = -8.0;
|
||||
_out->sk_FragColor.x = 9.0;
|
||||
_out->sk_FragColor.x = -10.0;
|
||||
_0_result = int4(int(sqrt(1.0)));
|
||||
_0_result = int4(int(sqrt(2.0)));
|
||||
_0_result = int4(0);
|
||||
|
Loading…
Reference in New Issue
Block a user