mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-13 15:16:16 +00:00
tint: const eval of insertBits
Bug: tint:1581 Change-Id: Id89530eb90d3c75bd1f99dd67a78cad1c923c6f0 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/107924 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
e372511e1b
commit
336f3536e5
@@ -485,8 +485,8 @@ fn frexp<N: num, T: f32_f16>(vec<N, T>) -> __frexp_result_vec<N, T>
|
||||
@stage("fragment") fn fwidthCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
|
||||
@stage("fragment") fn fwidthFine(f32) -> f32
|
||||
@stage("fragment") fn fwidthFine<N: num>(vec<N, f32>) -> vec<N, f32>
|
||||
fn insertBits<T: iu32>(T, T, u32, u32) -> T
|
||||
fn insertBits<N: num, T: iu32>(vec<N, T>, vec<N, T>, u32, u32) -> vec<N, T>
|
||||
@const fn insertBits<T: iu32>(T, T, u32, u32) -> T
|
||||
@const fn insertBits<N: num, T: iu32>(vec<N, T>, vec<N, T>, u32, u32) -> vec<N, T>
|
||||
fn inverseSqrt<T: f32_f16>(T) -> T
|
||||
fn inverseSqrt<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
|
||||
fn ldexp<T: f32_f16>(T, i32) -> T
|
||||
|
||||
@@ -1790,6 +1790,58 @@ ConstEval::Result ConstEval::firstTrailingBit(const sem::Type* ty,
|
||||
return TransformElements(builder, ty, transform, args[0]);
|
||||
}
|
||||
|
||||
ConstEval::Result ConstEval::insertBits(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source& source) {
|
||||
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1) {
|
||||
auto create = [&](auto in_e, auto in_newbits) -> ImplResult {
|
||||
using NumberT = decltype(in_e);
|
||||
using T = UnwrapNumber<NumberT>;
|
||||
using UT = std::make_unsigned_t<T>;
|
||||
using NumberUT = Number<UT>;
|
||||
|
||||
// Read args that are always scalar
|
||||
NumberUT in_offset = args[2]->As<NumberUT>();
|
||||
NumberUT in_count = args[3]->As<NumberUT>();
|
||||
|
||||
constexpr UT w = sizeof(UT) * 8;
|
||||
if ((in_offset + in_count) > w) {
|
||||
AddError("'offset + 'count' must be less than or equal to the bit width of 'e'",
|
||||
source);
|
||||
return utils::Failure;
|
||||
}
|
||||
|
||||
// Cast all to unsigned
|
||||
UT e = static_cast<UT>(in_e);
|
||||
UT newbits = static_cast<UT>(in_newbits);
|
||||
UT o = static_cast<UT>(in_offset);
|
||||
UT c = static_cast<UT>(in_count);
|
||||
|
||||
NumberT result;
|
||||
if (c == UT{0}) {
|
||||
// The result is e if c is 0
|
||||
result = NumberT{e};
|
||||
} else if (c == w) {
|
||||
// The result is newbits if c is w
|
||||
result = NumberT{newbits};
|
||||
} else {
|
||||
// Otherwise, bits o..o + c - 1 of the result are copied from bits 0..c - 1 of
|
||||
// newbits. Other bits of the result are copied from e.
|
||||
UT from = newbits << o;
|
||||
UT mask = ((UT{1} << c) - UT{1}) << UT{o};
|
||||
auto r = e; // Start with 'e' as the result
|
||||
r = r & ~mask; // Zero the bits in 'e' we're overwriting
|
||||
r = r | (from & mask); // Overwrite from 'newbits' (shifted into position)
|
||||
result = NumberT{r};
|
||||
}
|
||||
|
||||
return CreateElement(builder, c0->Type(), result);
|
||||
};
|
||||
return Dispatch_iu32(create, c0, c1);
|
||||
};
|
||||
return TransformElements(builder, ty, transform, args[0], args[1]);
|
||||
}
|
||||
|
||||
ConstEval::Result ConstEval::saturate(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source&) {
|
||||
|
||||
@@ -485,6 +485,15 @@ class ConstEval {
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source& source);
|
||||
|
||||
/// insertBits builtin
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
/// @param source the source location of the conversion
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
Result insertBits(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source& source);
|
||||
|
||||
/// saturate builtin
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
|
||||
@@ -713,6 +713,94 @@ INSTANTIATE_TEST_SUITE_P( //
|
||||
testing::ValuesIn(Concat(FirstTrailingBitCases<i32>(), //
|
||||
FirstTrailingBitCases<u32>()))));
|
||||
|
||||
template <typename T>
|
||||
std::vector<Case> InsertBitsCases() {
|
||||
using UT = Number<std::make_unsigned_t<UnwrapNumber<T>>>;
|
||||
|
||||
auto e = /* */ T(0b0101'1100'0011'1010'0101'1100'0011'1010);
|
||||
auto newbits = T{0b1010'0011'1100'0101'1010'0011'1100'0101};
|
||||
|
||||
auto r = std::vector<Case>{
|
||||
// args: e, newbits, offset, count
|
||||
|
||||
// If count is 0, result is e
|
||||
C({e, newbits, UT(0), UT(0)}, e), //
|
||||
C({e, newbits, UT(1), UT(0)}, e), //
|
||||
C({e, newbits, UT(2), UT(0)}, e), //
|
||||
C({e, newbits, UT(3), UT(0)}, e), //
|
||||
// ...
|
||||
C({e, newbits, UT(29), UT(0)}, e), //
|
||||
C({e, newbits, UT(30), UT(0)}, e), //
|
||||
C({e, newbits, UT(31), UT(0)}, e),
|
||||
|
||||
// Copy 1 to 32 bits of newbits to e at offset 0
|
||||
C({e, newbits, UT(0), UT(1)}, T(0b0101'1100'0011'1010'0101'1100'0011'1011)),
|
||||
C({e, newbits, UT(0), UT(2)}, T(0b0101'1100'0011'1010'0101'1100'0011'1001)),
|
||||
C({e, newbits, UT(0), UT(3)}, T(0b0101'1100'0011'1010'0101'1100'0011'1101)),
|
||||
C({e, newbits, UT(0), UT(4)}, T(0b0101'1100'0011'1010'0101'1100'0011'0101)),
|
||||
C({e, newbits, UT(0), UT(5)}, T(0b0101'1100'0011'1010'0101'1100'0010'0101)),
|
||||
C({e, newbits, UT(0), UT(6)}, T(0b0101'1100'0011'1010'0101'1100'0000'0101)),
|
||||
// ...
|
||||
C({e, newbits, UT(0), UT(29)}, T(0b0100'0011'1100'0101'1010'0011'1100'0101)),
|
||||
C({e, newbits, UT(0), UT(30)}, T(0b0110'0011'1100'0101'1010'0011'1100'0101)),
|
||||
C({e, newbits, UT(0), UT(31)}, T(0b0010'0011'1100'0101'1010'0011'1100'0101)),
|
||||
C({e, newbits, UT(0), UT(32)}, T(0b1010'0011'1100'0101'1010'0011'1100'0101)),
|
||||
|
||||
// Copy at varying offsets and counts
|
||||
C({e, newbits, UT(3), UT(8)}, T(0b0101'1100'0011'1010'0101'1110'0010'1010)),
|
||||
C({e, newbits, UT(8), UT(8)}, T(0b0101'1100'0011'1010'1100'0101'0011'1010)),
|
||||
C({e, newbits, UT(15), UT(1)}, T(0b0101'1100'0011'1010'1101'1100'0011'1010)),
|
||||
C({e, newbits, UT(16), UT(16)}, T(0b1010'0011'1100'0101'0101'1100'0011'1010)),
|
||||
|
||||
// Vector tests
|
||||
C({Vec(T(0b1111'0000'1111'0000'1111'0000'1111'0000), //
|
||||
T(0b0000'1111'0000'1111'0000'1111'0000'1111), //
|
||||
T(0b1010'0101'1010'0101'1010'0101'1010'0101)),
|
||||
Vec(T(0b1111'1111'1111'1111'1111'1111'1111'1111), //
|
||||
T(0b1111'1111'1111'1111'1111'1111'1111'1111), //
|
||||
T(0b1111'1111'1111'1111'1111'1111'1111'1111)),
|
||||
Val(UT(3)), Val(UT(8))},
|
||||
Vec(T(0b1111'0000'1111'0000'1111'0111'1111'1000), //
|
||||
T(0b0000'1111'0000'1111'0000'1111'1111'1111), //
|
||||
T(0b1010'0101'1010'0101'1010'0111'1111'1101))),
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P( //
|
||||
InsertBits,
|
||||
ResolverConstEvalBuiltinTest,
|
||||
testing::Combine(testing::Values(sem::BuiltinType::kInsertBits),
|
||||
testing::ValuesIn(Concat(InsertBitsCases<i32>(), //
|
||||
InsertBitsCases<u32>()))));
|
||||
|
||||
using ResolverConstEvalBuiltinTest_InsertBits_InvalidOffsetAndCount =
|
||||
ResolverTestWithParam<std::tuple<size_t, size_t>>;
|
||||
TEST_P(ResolverConstEvalBuiltinTest_InsertBits_InvalidOffsetAndCount, Test) {
|
||||
auto& p = GetParam();
|
||||
auto* expr = Call(Source{{12, 24}}, sem::str(sem::BuiltinType::kInsertBits), Expr(1_u),
|
||||
Expr(1_u), Expr(u32(std::get<0>(p))), Expr(u32(std::get<1>(p))));
|
||||
GlobalConst("C", expr);
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:24 error: 'offset + 'count' must be less than or equal to the bit width of 'e'");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(InsertBits,
|
||||
ResolverConstEvalBuiltinTest_InsertBits_InvalidOffsetAndCount,
|
||||
testing::Values( //
|
||||
std::make_tuple(33, 0), //
|
||||
std::make_tuple(34, 0), //
|
||||
std::make_tuple(1000, 0), //
|
||||
std::make_tuple(u32::Highest(), 0), //
|
||||
std::make_tuple(0, 33), //
|
||||
std::make_tuple(0, 34), //
|
||||
std::make_tuple(0, 1000), //
|
||||
std::make_tuple(0, u32::Highest()), //
|
||||
std::make_tuple(33, 33), //
|
||||
std::make_tuple(34, 34), //
|
||||
std::make_tuple(1000, 1000), //
|
||||
std::make_tuple(u32::Highest(), u32::Highest())));
|
||||
|
||||
template <typename T>
|
||||
std::vector<Case> SaturateCases() {
|
||||
return {
|
||||
|
||||
@@ -11894,7 +11894,7 @@ constexpr OverloadInfo kOverloads[] = {
|
||||
/* parameters */ &kParameters[423],
|
||||
/* return matcher indices */ &kMatcherIndices[1],
|
||||
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
|
||||
/* const eval */ nullptr,
|
||||
/* const eval */ &ConstEval::insertBits,
|
||||
},
|
||||
{
|
||||
/* [297] */
|
||||
@@ -11906,7 +11906,7 @@ constexpr OverloadInfo kOverloads[] = {
|
||||
/* parameters */ &kParameters[427],
|
||||
/* return matcher indices */ &kMatcherIndices[30],
|
||||
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
|
||||
/* const eval */ nullptr,
|
||||
/* const eval */ &ConstEval::insertBits,
|
||||
},
|
||||
{
|
||||
/* [298] */
|
||||
|
||||
Reference in New Issue
Block a user