[tint] Materialize compound assignment RHS

The RHS of a compound assignment statement may need to be
materialized. This was showing up when converting things like `i += 1`
to IR, as abstract types were creeping into the IR.

Change-Id: Idf9b1523d1751e26c28a795af07769ca85a65f14
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133221
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
James Price 2023-05-17 14:49:26 +00:00 committed by Dawn LUCI CQ
parent 11ee6b6cc6
commit db5ad9f357
2 changed files with 30 additions and 8 deletions

View File

@ -211,6 +211,10 @@ enum class Method {
// abstract_expr[runtime-index] // abstract_expr[runtime-index]
kRuntimeIndex, kRuntimeIndex,
// var a : target_type;
// a += abstract_expr;
kCompoundAssign,
}; };
static std::ostream& operator<<(std::ostream& o, Method m) { static std::ostream& operator<<(std::ostream& o, Method m) {
@ -247,6 +251,8 @@ static std::ostream& operator<<(std::ostream& o, Method m) {
return o << "workgroup-size"; return o << "workgroup-size";
case Method::kRuntimeIndex: case Method::kRuntimeIndex:
return o << "runtime-index"; return o << "runtime-index";
case Method::kCompoundAssign:
return o << "compound-assign";
} }
return o << "<unknown>"; return o << "<unknown>";
} }
@ -387,10 +393,15 @@ TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
utils::Vector{WorkgroupSize(target_expr(), abstract_expr, Expr(123_a)), utils::Vector{WorkgroupSize(target_expr(), abstract_expr, Expr(123_a)),
Stage(ast::PipelineStage::kCompute)}); Stage(ast::PipelineStage::kCompute)});
break; break;
case Method::kRuntimeIndex: case Method::kRuntimeIndex: {
auto* runtime_index = Var("runtime_index", Expr(1_i)); auto* runtime_index = Var("runtime_index", Expr(1_i));
WrapInFunction(runtime_index, IndexAccessor(abstract_expr, runtime_index)); WrapInFunction(runtime_index, IndexAccessor(abstract_expr, runtime_index));
break; break;
}
case Method::kCompoundAssign:
WrapInFunction(Decl(Var("a", target_ty())),
CompoundAssign("a", abstract_expr, ast::BinaryOp::kAdd));
break;
} }
switch (expectation) { switch (expectation) {
@ -421,6 +432,10 @@ TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
expect = "error: no matching overload for operator + (" + expect = "error: no matching overload for operator + (" +
data.target_type_name + ", " + data.abstract_type_name + ")"; data.target_type_name + ", " + data.abstract_type_name + ")";
break; break;
case Method::kCompoundAssign:
expect = "error: no matching overload for operator += (" +
data.target_type_name + ", " + data.abstract_type_name + ")";
break;
default: default:
expect = "error: cannot convert value of type '" + data.abstract_type_name + expect = "error: cannot convert value of type '" + data.abstract_type_name +
"' to type '" + data.target_type_name + "'"; "' to type '" + data.target_type_name + "'";
@ -440,13 +455,13 @@ TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
/// Methods that support scalar materialization /// Methods that support scalar materialization
constexpr Method kScalarMethods[] = { constexpr Method kScalarMethods[] = {
Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg, Method::kBuiltinArg, Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg, Method::kBuiltinArg,
Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp, Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp, Method::kCompoundAssign,
}; };
/// Methods that support vector materialization /// Methods that support vector materialization
constexpr Method kVectorMethods[] = { constexpr Method kVectorMethods[] = {
Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg, Method::kBuiltinArg, Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg, Method::kBuiltinArg,
Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp, Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp, Method::kCompoundAssign,
}; };
/// Methods that support matrix materialization /// Methods that support matrix materialization

View File

@ -4479,7 +4479,7 @@ sem::Statement* Resolver::CompoundAssignmentStatement(
return false; return false;
} }
auto* rhs = Load(ValueExpression(stmt->rhs)); const auto* rhs = ValueExpression(stmt->rhs);
if (!rhs) { if (!rhs) {
return false; return false;
} }
@ -4491,12 +4491,19 @@ sem::Statement* Resolver::CompoundAssignmentStatement(
auto* lhs_ty = lhs->Type()->UnwrapRef(); auto* lhs_ty = lhs->Type()->UnwrapRef();
auto* rhs_ty = rhs->Type()->UnwrapRef(); auto* rhs_ty = rhs->Type()->UnwrapRef();
auto stage = sem::EarliestStage(lhs->Stage(), rhs->Stage()); auto stage = sem::EarliestStage(lhs->Stage(), rhs->Stage());
auto* ty =
intrinsic_table_->Lookup(stmt->op, lhs_ty, rhs_ty, stage, stmt->source, true).result; auto op = intrinsic_table_->Lookup(stmt->op, lhs_ty, rhs_ty, stage, stmt->source, true);
if (!ty) { if (!op.result) {
return false; return false;
} }
return validator_.Assignment(stmt, ty);
// Load or materialize the RHS if necessary.
rhs = Load(Materialize(rhs, op.rhs));
if (!rhs) {
return false;
}
return validator_.Assignment(stmt, op.result);
}); });
} }