Commit 2e6f3e86 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Int64Lowering of Word64Popcnt.

Word64Popcnt is lowered to Word32Popcnt(low-word) + Word32Popcnt(high_word).
Since the optional Word64Popcnt operator does not exist on 32 bit platforms,
I introduced a new operator "Word64PopcntPlaceholder" which is generated
in the WasmCompiler and then lowered in the Int64Lowering.

R=titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34777}
parent e4230ae9
...@@ -447,6 +447,21 @@ void Int64Lowering::LowerNode(Node* node) { ...@@ -447,6 +447,21 @@ void Int64Lowering::LowerNode(Node* node) {
// kExprI64Clz: // kExprI64Clz:
// kExprI64Ctz: // kExprI64Ctz:
case IrOpcode::kWord64Popcnt: {
DCHECK(node->InputCount() == 1);
Node* input = node->InputAt(0);
// We assume that a Word64Popcnt node only has been created if
// Word32Popcnt is actually supported.
DCHECK(machine()->Word32Popcnt().IsSupported());
ReplaceNode(node, graph()->NewNode(
machine()->Int32Add(),
graph()->NewNode(machine()->Word32Popcnt().op(),
GetReplacementLow(input)),
graph()->NewNode(machine()->Word32Popcnt().op(),
GetReplacementHigh(input))),
graph()->NewNode(common()->Int32Constant(0)));
break;
}
// kExprI64Popcnt: // kExprI64Popcnt:
default: { DefaultLowering(node); } default: { DefaultLowering(node); }
......
...@@ -471,6 +471,12 @@ const Operator* MachineOperatorBuilder::CheckedStore( ...@@ -471,6 +471,12 @@ const Operator* MachineOperatorBuilder::CheckedStore(
return nullptr; return nullptr;
} }
// On 32 bit platforms we need to get a reference to a Word64Popcnt operator for
// later lowering, even though 32 bit platforms don't support Word64Popcnt.
const Operator* MachineOperatorBuilder::Word64PopcntPlaceholder() {
return &cache_.kWord64Popcnt;
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -164,6 +164,7 @@ class MachineOperatorBuilder final : public ZoneObject { ...@@ -164,6 +164,7 @@ class MachineOperatorBuilder final : public ZoneObject {
const OptionalOperator Word32Ctz(); const OptionalOperator Word32Ctz();
const OptionalOperator Word32Popcnt(); const OptionalOperator Word32Popcnt();
const OptionalOperator Word64Popcnt(); const OptionalOperator Word64Popcnt();
const Operator* Word64PopcntPlaceholder();
const OptionalOperator Word32ReverseBits(); const OptionalOperator Word32ReverseBits();
const OptionalOperator Word64ReverseBits(); const OptionalOperator Word64ReverseBits();
bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; } bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; }
......
...@@ -834,6 +834,16 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { ...@@ -834,6 +834,16 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
// kExprI64Clz: // kExprI64Clz:
// kExprI64Ctz: // kExprI64Ctz:
// kExprI64Popcnt: // kExprI64Popcnt:
case wasm::kExprI64Popcnt: {
if (m->Word64Popcnt().IsSupported()) {
op = m->Word64Popcnt().op();
} else if (m->Is32() && m->Word32Popcnt().IsSupported()) {
op = m->Word64PopcntPlaceholder();
} else {
return BuildI64Popcnt(input);
}
break;
}
// kExprF32SConvertI64: // kExprF32SConvertI64:
case wasm::kExprI64Eqz: case wasm::kExprI64Eqz:
op = m->Word64Equal(); op = m->Word64Equal();
...@@ -905,14 +915,6 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { ...@@ -905,14 +915,6 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
return BuildI64Ctz(input); return BuildI64Ctz(input);
} }
} }
case wasm::kExprI64Popcnt: {
if (m->Word64Popcnt().IsSupported()) {
op = m->Word64Popcnt().op();
break;
} else {
return BuildI64Popcnt(input);
}
}
#endif #endif
default: default:
op = UnsupportedOpcode(opcode); op = UnsupportedOpcode(opcode);
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
V(I64GeU, true) \ V(I64GeU, true) \
V(I64Clz, false) \ V(I64Clz, false) \
V(I64Ctz, false) \ V(I64Ctz, false) \
V(I64Popcnt, false) \ V(I64Popcnt, !MIPS_OR_X87) \
V(I32ConvertI64, true) \ V(I32ConvertI64, true) \
V(I64SConvertF32, false) \ V(I64SConvertF32, false) \
V(I64SConvertF64, false) \ V(I64SConvertF64, false) \
...@@ -519,6 +519,22 @@ TEST(Run_Wasm_I64UConvertI32) { ...@@ -519,6 +519,22 @@ TEST(Run_Wasm_I64UConvertI32) {
// kExprI64Clz: // kExprI64Clz:
// kExprI64Ctz: // kExprI64Ctz:
// kExprI64Popcnt: // kExprI64Popcnt:
TEST(Run_WasmI64Popcnt) {
struct {
int64_t expected;
uint64_t input;
} values[] = {{64, 0xffffffffffffffff},
{0, 0x0000000000000000},
{2, 0x0000080000008000},
{26, 0x1123456782345678},
{38, 0xffedcba09edcba09}};
WasmRunner<int64_t> r(MachineType::Uint64());
BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
for (size_t i = 0; i < arraysize(values); i++) {
CHECK_EQ(values[i].expected, r.Call(values[i].input));
}
}
// kExprF32SConvertI64: // kExprF32SConvertI64:
TEST(Run_WasmF32SConvertI64) { TEST(Run_WasmF32SConvertI64) {
......
...@@ -324,7 +324,6 @@ TEST(Run_WasmI32Eqz) { ...@@ -324,7 +324,6 @@ TEST(Run_WasmI32Eqz) {
TestInt32Unop(kExprI32Eqz, 1, 0); TestInt32Unop(kExprI32Eqz, 1, 0);
} }
TEST(Run_WASM_Int32DivS_trap) { TEST(Run_WASM_Int32DivS_trap) {
WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
......
...@@ -29,7 +29,9 @@ namespace compiler { ...@@ -29,7 +29,9 @@ namespace compiler {
class Int64LoweringTest : public GraphTest { class Int64LoweringTest : public GraphTest {
public: public:
Int64LoweringTest() Int64LoweringTest()
: GraphTest(), machine_(zone(), MachineRepresentation::kWord32) { : GraphTest(),
machine_(zone(), MachineRepresentation::kWord32,
MachineOperatorBuilder::Flag::kAllOptionalOps) {
value_[0] = 0x1234567890abcdef; value_[0] = 0x1234567890abcdef;
value_[1] = 0x1edcba098765432f; value_[1] = 0x1edcba098765432f;
value_[2] = 0x1133557799886644; value_[2] = 0x1133557799886644;
...@@ -512,6 +514,18 @@ TEST_F(Int64LoweringTest, Dfs) { ...@@ -512,6 +514,18 @@ TEST_F(Int64LoweringTest, Dfs) {
IsInt32Constant(high_word_value(1)))), IsInt32Constant(high_word_value(1)))),
start(), start())); start(), start()));
} }
TEST_F(Int64LoweringTest, I64Popcnt) {
LowerGraph(graph()->NewNode(machine()->Word64PopcntPlaceholder(),
Int64Constant(value(0))),
MachineRepresentation::kWord64);
EXPECT_THAT(
graph()->end()->InputAt(1),
IsReturn2(IsInt32Add(IsWord32Popcnt(IsInt32Constant(low_word_value(0))),
IsWord32Popcnt(IsInt32Constant(high_word_value(0)))),
IsInt32Constant(0), start(), start()));
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -2247,6 +2247,7 @@ IS_UNOP_MATCHER(NumberToUint32) ...@@ -2247,6 +2247,7 @@ IS_UNOP_MATCHER(NumberToUint32)
IS_UNOP_MATCHER(ObjectIsReceiver) IS_UNOP_MATCHER(ObjectIsReceiver)
IS_UNOP_MATCHER(ObjectIsSmi) IS_UNOP_MATCHER(ObjectIsSmi)
IS_UNOP_MATCHER(Word32Clz) IS_UNOP_MATCHER(Word32Clz)
IS_UNOP_MATCHER(Word32Popcnt)
#undef IS_UNOP_MATCHER #undef IS_UNOP_MATCHER
} // namespace compiler } // namespace compiler
......
...@@ -278,6 +278,7 @@ Matcher<Node*> IsWord32Ror(const Matcher<Node*>& lhs_matcher, ...@@ -278,6 +278,7 @@ Matcher<Node*> IsWord32Ror(const Matcher<Node*>& lhs_matcher,
Matcher<Node*> IsWord32Equal(const Matcher<Node*>& lhs_matcher, Matcher<Node*> IsWord32Equal(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher); const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsWord32Clz(const Matcher<Node*>& value_matcher); Matcher<Node*> IsWord32Clz(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsWord32Popcnt(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsWord64And(const Matcher<Node*>& lhs_matcher, Matcher<Node*> IsWord64And(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher); const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsWord64Or(const Matcher<Node*>& lhs_matcher, Matcher<Node*> IsWord64Or(const Matcher<Node*>& lhs_matcher,
......
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