Unrevert "tint: rhs of left shift is always u32 or vector of u32"
Was failing e2e tests. Bug fixed in a parent commit. Bug: tint:1713 Change-Id: I5cf20e6fd21e6358bb418f2ede7f4a7e0a61f138 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/107141 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
e0f78f924c
commit
25fdff1ff8
|
@ -972,8 +972,8 @@ op || (bool, bool) -> bool
|
|||
|
||||
@const op << <T: iu32>(T, u32) -> T
|
||||
@const op << <T: iu32, N: num> (vec<N, T>, vec<N, u32>) -> vec<N, T>
|
||||
@const op << <T: ia>(T, ia) -> T
|
||||
@const op << <T: ia, N: num> (vec<N, T>, vec<N, ia>) -> vec<N, T>
|
||||
@const op << <T: ia>(T, u32) -> T
|
||||
@const op << <T: ia, N: num> (vec<N, T>, vec<N, u32>) -> vec<N, T>
|
||||
|
||||
op >> <T: iu32>(T, u32) -> T
|
||||
op >> <T: iu32, N: num> (vec<N, T>, vec<N, u32>) -> vec<N, T>
|
||||
|
|
|
@ -54,7 +54,7 @@ T First(T&& first, ...) {
|
|||
}
|
||||
|
||||
/// Helper that calls `f` passing in the value of all `cs`.
|
||||
/// Assumes all `cs` are of the same type.
|
||||
/// Calls `f` with all constants cast to the type of the first `cs` argument.
|
||||
template <typename F, typename... CONSTANTS>
|
||||
auto Dispatch_ia_iu32(F&& f, CONSTANTS&&... cs) {
|
||||
return Switch(
|
||||
|
@ -65,7 +65,7 @@ auto Dispatch_ia_iu32(F&& f, CONSTANTS&&... cs) {
|
|||
}
|
||||
|
||||
/// Helper that calls `f` passing in the value of all `cs`.
|
||||
/// Assumes all `cs` are of the same type.
|
||||
/// Calls `f` with all constants cast to the type of the first `cs` argument.
|
||||
template <typename F, typename... CONSTANTS>
|
||||
auto Dispatch_ia_iu32_bool(F&& f, CONSTANTS&&... cs) {
|
||||
return Switch(
|
||||
|
@ -77,7 +77,7 @@ auto Dispatch_ia_iu32_bool(F&& f, CONSTANTS&&... cs) {
|
|||
}
|
||||
|
||||
/// Helper that calls `f` passing in the value of all `cs`.
|
||||
/// Assumes all `cs` are of the same type.
|
||||
/// Calls `f` with all constants cast to the type of the first `cs` argument.
|
||||
template <typename F, typename... CONSTANTS>
|
||||
auto Dispatch_fia_fi32_f16(F&& f, CONSTANTS&&... cs) {
|
||||
return Switch(
|
||||
|
@ -90,7 +90,7 @@ auto Dispatch_fia_fi32_f16(F&& f, CONSTANTS&&... cs) {
|
|||
}
|
||||
|
||||
/// Helper that calls `f` passing in the value of all `cs`.
|
||||
/// Assumes all `cs` are of the same type.
|
||||
/// Calls `f` with all constants cast to the type of the first `cs` argument.
|
||||
template <typename F, typename... CONSTANTS>
|
||||
auto Dispatch_fia_fiu32_f16(F&& f, CONSTANTS&&... cs) {
|
||||
return Switch(
|
||||
|
@ -104,7 +104,7 @@ auto Dispatch_fia_fiu32_f16(F&& f, CONSTANTS&&... cs) {
|
|||
}
|
||||
|
||||
/// Helper that calls `f` passing in the value of all `cs`.
|
||||
/// Assumes all `cs` are of the same type.
|
||||
/// Calls `f` with all constants cast to the type of the first `cs` argument.
|
||||
template <typename F, typename... CONSTANTS>
|
||||
auto Dispatch_fia_fiu32_f16_bool(F&& f, CONSTANTS&&... cs) {
|
||||
return Switch(
|
||||
|
@ -119,7 +119,7 @@ auto Dispatch_fia_fiu32_f16_bool(F&& f, CONSTANTS&&... cs) {
|
|||
}
|
||||
|
||||
/// Helper that calls `f` passing in the value of all `cs`.
|
||||
/// Assumes all `cs` are of the same type.
|
||||
/// Calls `f` with all constants cast to the type of the first `cs` argument.
|
||||
template <typename F, typename... CONSTANTS>
|
||||
auto Dispatch_fa_f32_f16(F&& f, CONSTANTS&&... cs) {
|
||||
return Switch(
|
||||
|
@ -130,7 +130,7 @@ auto Dispatch_fa_f32_f16(F&& f, CONSTANTS&&... cs) {
|
|||
}
|
||||
|
||||
/// Helper that calls `f` passing in the value of all `cs`.
|
||||
/// Assumes all `cs` are of the same type.
|
||||
/// Calls `f` with all constants cast to the type of the first `cs` argument.
|
||||
template <typename F, typename... CONSTANTS>
|
||||
auto Dispatch_bool(F&& f, CONSTANTS&&... cs) {
|
||||
return f(cs->template As<bool>()...);
|
||||
|
@ -1450,13 +1450,6 @@ ConstEval::Result ConstEval::OpShiftLeft(const sem::Type* ty,
|
|||
UT e2u = static_cast<UT>(e2);
|
||||
|
||||
if constexpr (IsAbstract<NumberT>) {
|
||||
// NOTE: Concrete shift left requires an unsigned rhs, so this check only applies
|
||||
// for abstracts.
|
||||
if (e2 < 0) {
|
||||
AddError("cannot shift left by a negative value", source);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The e2 + 1 most significant bits of e1 must have the same bit value, otherwise
|
||||
// sign change (overflow) would occur.
|
||||
// Check sign change only if e2 is less than bit width of e1. If e1 is larger
|
||||
|
@ -1520,6 +1513,12 @@ ConstEval::Result ConstEval::OpShiftLeft(const sem::Type* ty,
|
|||
return Dispatch_ia_iu32(create, c0, c1);
|
||||
};
|
||||
|
||||
if (!sem::Type::DeepestElementOf(args[1]->Type())->Is<sem::U32>()) {
|
||||
TINT_ICE(Resolver, builder.Diagnostics())
|
||||
<< "Element type of rhs of ShiftLeft must be a u32";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto r = TransformElements(builder, ty, transform, args[0], args[1]);
|
||||
if (builder.Diagnostics().contains_errors()) {
|
||||
return utils::Failure;
|
||||
|
|
|
@ -636,21 +636,21 @@ std::vector<Case> ShiftLeftCases() {
|
|||
Vec(T{0b0010'1000'0000}, T{0b0101'0000'0000}, T{0b1010'0000'0000})), //
|
||||
};
|
||||
|
||||
// Only abstract 0 can be shifted left as much as we like. For concrete 0 (and any number), it
|
||||
// cannot be shifted equal or more than the number of bits of the lhs (see
|
||||
// ResolverConstEvalShiftLeftConcreteGeqBitWidthError for negative tests)
|
||||
// Abstract 0 can be shifted by any u32 value (0 to 2^32), whereas concrete 0 (or any number)
|
||||
// can only by shifted by a value less than the number of bits of the lhs.
|
||||
// (see ResolverConstEvalShiftLeftConcreteGeqBitWidthError for negative tests)
|
||||
ConcatIntoIf<IsAbstract<T>>( //
|
||||
r, std::vector<Case>{
|
||||
C(T{0}, ST{64}, T{0}),
|
||||
C(T{0}, ST{65}, T{0}),
|
||||
C(T{0}, ST{65}, T{0}),
|
||||
C(T{0}, ST{10000}, T{0}),
|
||||
C(T{0}, T::Highest(), T{0}),
|
||||
C(Negate(T{0}), ST{64}, Negate(T{0})),
|
||||
C(Negate(T{0}), ST{65}, Negate(T{0})),
|
||||
C(Negate(T{0}), ST{65}, Negate(T{0})),
|
||||
C(Negate(T{0}), ST{10000}, Negate(T{0})),
|
||||
C(Negate(T{0}), T::Highest(), Negate(T{0})),
|
||||
C(T{0}, ST{64}, T{0}), //
|
||||
C(T{0}, ST{65}, T{0}), //
|
||||
C(T{0}, ST{65}, T{0}), //
|
||||
C(T{0}, ST{10000}, T{0}), //
|
||||
C(T{0}, ST{u32::Highest()}, T{0}), //
|
||||
C(Negate(T{0}), ST{64}, Negate(T{0})), //
|
||||
C(Negate(T{0}), ST{65}, Negate(T{0})), //
|
||||
C(Negate(T{0}), ST{65}, Negate(T{0})), //
|
||||
C(Negate(T{0}), ST{10000}, Negate(T{0})), //
|
||||
C(Negate(T{0}), ST{u32::Highest()}, Negate(T{0})), //
|
||||
});
|
||||
|
||||
// Cases that are fine for signed values (no sign change), but would overflow unsigned values.
|
||||
|
@ -898,9 +898,29 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
|
||||
// AInt left shift negative value -> error
|
||||
TEST_F(ResolverConstEvalTest, BinaryAbstractShiftLeftByNegativeValue_Error) {
|
||||
GlobalConst("c", Shl(Source{{1, 1}}, Expr(1_a), Expr(-1_a)));
|
||||
GlobalConst("c", Shl(Expr(1_a), Expr(Source{{1, 1}}, -1_a)));
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(), "1:1 error: cannot shift left by a negative value");
|
||||
EXPECT_EQ(r()->error(), "1:1 error: value -1 cannot be represented as 'u32'");
|
||||
}
|
||||
|
||||
// AInt left shift by AInt or u32 always results in an AInt
|
||||
TEST_F(ResolverConstEvalTest, BinaryAbstractShiftLeftRemainsAbstract) {
|
||||
auto* expr1 = Shl(Expr(1_a), Expr(1_u));
|
||||
GlobalConst("c1", expr1);
|
||||
|
||||
auto* expr2 = Shl(Expr(1_a), Expr(1_a));
|
||||
GlobalConst("c2", expr2);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
auto* sem1 = Sem().Get(expr1);
|
||||
ASSERT_NE(sem1, nullptr);
|
||||
auto* sem2 = Sem().Get(expr2);
|
||||
ASSERT_NE(sem2, nullptr);
|
||||
|
||||
auto aint_ty = create<sem::AbstractInt>();
|
||||
EXPECT_EQ(sem1->Type(), aint_ty);
|
||||
EXPECT_EQ(sem2->Type(), aint_ty);
|
||||
}
|
||||
|
||||
// i32/u32 left shift by >= 32 -> error
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
const a = 1 << 30u; // First shift, result should be abstract
|
||||
const b = a << 10u; // Valid only if 'a' is abstract
|
||||
|
||||
const c = 5000000000 << 3u; // Valid only if result is abtract
|
|
@ -0,0 +1,5 @@
|
|||
[numthreads(1, 1, 1)]
|
||||
void unused_entry_point() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
[numthreads(1, 1, 1)]
|
||||
void unused_entry_point() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#version 310 es
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
void unused_entry_point() {
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
|
@ -0,0 +1,16 @@
|
|||
; SPIR-V
|
||||
; Version: 1.3
|
||||
; Generator: Google Tint Compiler; 0
|
||||
; Bound: 5
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
|
||||
OpExecutionMode %unused_entry_point LocalSize 1 1 1
|
||||
OpName %unused_entry_point "unused_entry_point"
|
||||
%void = OpTypeVoid
|
||||
%1 = OpTypeFunction %void
|
||||
%unused_entry_point = OpFunction %void None %1
|
||||
%4 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
|
@ -0,0 +1,5 @@
|
|||
const a = (1 << 30u);
|
||||
|
||||
const b = (a << 10u);
|
||||
|
||||
const c = (5000000000 << 3u);
|
Loading…
Reference in New Issue