Commit d167c374 authored by titzer's avatar titzer Committed by Commit bot

[wasm] Mask shift counts on architectures that don't implicitly mask.

R=ahaas@chromium.org,bradnelson@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1845443003

Cr-Commit-Position: refs/heads/master@{#35136}
parent 8d20f2fe
......@@ -412,17 +412,22 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
break;
case wasm::kExprI32Shl:
op = m->Word32Shl();
right = MaskShiftCount32(right);
break;
case wasm::kExprI32ShrU:
op = m->Word32Shr();
right = MaskShiftCount32(right);
break;
case wasm::kExprI32ShrS:
op = m->Word32Sar();
right = MaskShiftCount32(right);
break;
case wasm::kExprI32Ror:
op = m->Word32Ror();
right = MaskShiftCount32(right);
break;
case wasm::kExprI32Rol:
right = MaskShiftCount32(right);
return BuildI32Rol(left, right);
case wasm::kExprI32Eq:
op = m->Word32Equal();
......@@ -496,14 +501,17 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
// kExprI64Shl:
case wasm::kExprI64Shl:
op = m->Word64Shl();
right = MaskShiftCount64(right);
break;
// kExprI64ShrU:
case wasm::kExprI64ShrU:
op = m->Word64Shr();
right = MaskShiftCount64(right);
break;
// kExprI64ShrS:
case wasm::kExprI64ShrS:
op = m->Word64Sar();
right = MaskShiftCount64(right);
break;
// kExprI64Eq:
case wasm::kExprI64Eq:
......@@ -547,8 +555,10 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
// TODO(titzer): query the machine operator builder here instead of #ifdef.
case wasm::kExprI64Ror:
op = m->Word64Ror();
right = MaskShiftCount64(right);
break;
case wasm::kExprI64Rol:
right = MaskShiftCount64(right);
return BuildI64Rol(left, right);
#endif
......@@ -963,6 +973,37 @@ Node* WasmGraphBuilder::Unreachable() {
return nullptr;
}
Node* WasmGraphBuilder::MaskShiftCount32(Node* node) {
static const int32_t kMask32 = 0x1f;
if (!jsgraph()->machine()->Word32ShiftIsSafe()) {
// Shifts by constants are so common we pattern-match them here.
Int32Matcher match(node);
if (match.HasValue()) {
int32_t masked = (match.Value() & kMask32);
if (match.Value() != masked) node = jsgraph()->Int32Constant(masked);
} else {
node = graph()->NewNode(jsgraph()->machine()->Word32And(), node,
jsgraph()->Int32Constant(kMask32));
}
}
return node;
}
Node* WasmGraphBuilder::MaskShiftCount64(Node* node) {
static const int64_t kMask64 = 0x3f;
if (!jsgraph()->machine()->Word32ShiftIsSafe()) {
// Shifts by constants are so common we pattern-match them here.
Int64Matcher match(node);
if (match.HasValue()) {
int64_t masked = (match.Value() & kMask64);
if (match.Value() != masked) node = jsgraph()->Int64Constant(masked);
} else {
node = graph()->NewNode(jsgraph()->machine()->Word64And(), node,
jsgraph()->Int64Constant(kMask64));
}
}
return node;
}
Node* WasmGraphBuilder::BuildF32Neg(Node* input) {
Node* result =
......
......@@ -164,6 +164,9 @@ class WasmGraphBuilder {
Node* MemBuffer(uint32_t offset);
void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset);
Node* MaskShiftCount32(Node* node);
Node* MaskShiftCount64(Node* node);
Node* BuildCCall(MachineSignature* sig, Node** args);
Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
......
......@@ -1317,3 +1317,42 @@ TEST(Run_WasmI64Eqz) {
CHECK_EQ(result, r.Call(*i));
}
}
TEST(Run_WasmI64Shl) {
REQUIRE(I64Shl);
WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT64_INPUTS(i) {
FOR_UINT64_INPUTS(j) {
uint64_t expected = (*i) << (*j & 0x3f);
CHECK_EQ(expected, r.Call(*i, *j));
}
}
}
TEST(Run_WasmI64Shr) {
REQUIRE(I64ShrU);
WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT64_INPUTS(i) {
FOR_UINT64_INPUTS(j) {
uint64_t expected = (*i) >> (*j & 0x3f);
CHECK_EQ(expected, r.Call(*i, *j));
}
}
}
TEST(Run_WasmI64Sar) {
REQUIRE(I64ShrS);
WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT64_INPUTS(i) {
FOR_INT64_INPUTS(j) {
int64_t expected = (*i) >> (*j & 0x3f);
CHECK_EQ(expected, r.Call(*i, *j));
}
}
}
......@@ -324,6 +324,42 @@ TEST(Run_WasmI32Eqz) {
TestInt32Unop(kExprI32Eqz, 1, 0);
}
TEST(Run_WasmI32Shl) {
WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
BUILD(r, WASM_I32_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i) << (*j & 0x1f);
CHECK_EQ(expected, r.Call(*i, *j));
}
}
}
TEST(Run_WasmI32Shr) {
WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
BUILD(r, WASM_I32_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i) >> (*j & 0x1f);
CHECK_EQ(expected, r.Call(*i, *j));
}
}
}
TEST(Run_WasmI32Sar) {
WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
BUILD(r, WASM_I32_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
int32_t expected = (*i) >> (*j & 0x1f);
CHECK_EQ(expected, r.Call(*i, *j));
}
}
}
TEST(Run_WASM_Int32DivS_trap) {
WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
......
......@@ -218,9 +218,9 @@ var funcs = [
i32_and,
i32_or,
i32_xor,
// TODO(titzer): i32_shl on arm
// TODO(titzer): i32_shr on arm
// TODO(titzer): i32_sar on arm
i32_shl,
i32_shr,
i32_sar,
i32_eq,
i32_ne,
i32_lt,
......
......@@ -196,9 +196,9 @@ var funcs = [
u32_and,
u32_or,
u32_xor,
// TODO(titzer): u32_shl on arm
// TODO(titzer): u32_shr on arm
// TODO(titzer): u32_sar on arm
u32_shl,
u32_shr,
u32_sar,
u32_eq,
u32_ne,
u32_lt,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment