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) {
// kExprI64Clz:
// 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:
default: { DefaultLowering(node); }
......
......@@ -471,6 +471,12 @@ const Operator* MachineOperatorBuilder::CheckedStore(
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 internal
} // namespace v8
......@@ -164,6 +164,7 @@ class MachineOperatorBuilder final : public ZoneObject {
const OptionalOperator Word32Ctz();
const OptionalOperator Word32Popcnt();
const OptionalOperator Word64Popcnt();
const Operator* Word64PopcntPlaceholder();
const OptionalOperator Word32ReverseBits();
const OptionalOperator Word64ReverseBits();
bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; }
......
......@@ -834,6 +834,16 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
// kExprI64Clz:
// kExprI64Ctz:
// 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:
case wasm::kExprI64Eqz:
op = m->Word64Equal();
......@@ -905,14 +915,6 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
return BuildI64Ctz(input);
}
}
case wasm::kExprI64Popcnt: {
if (m->Word64Popcnt().IsSupported()) {
op = m->Word64Popcnt().op();
break;
} else {
return BuildI64Popcnt(input);
}
}
#endif
default:
op = UnsupportedOpcode(opcode);
......
......@@ -70,7 +70,7 @@
V(I64GeU, true) \
V(I64Clz, false) \
V(I64Ctz, false) \
V(I64Popcnt, false) \
V(I64Popcnt, !MIPS_OR_X87) \
V(I32ConvertI64, true) \
V(I64SConvertF32, false) \
V(I64SConvertF64, false) \
......@@ -519,6 +519,22 @@ TEST(Run_Wasm_I64UConvertI32) {
// kExprI64Clz:
// kExprI64Ctz:
// 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:
TEST(Run_WasmF32SConvertI64) {
......
......@@ -324,7 +324,6 @@ TEST(Run_WasmI32Eqz) {
TestInt32Unop(kExprI32Eqz, 1, 0);
}
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)));
......
......@@ -29,7 +29,9 @@ namespace compiler {
class Int64LoweringTest : public GraphTest {
public:
Int64LoweringTest()
: GraphTest(), machine_(zone(), MachineRepresentation::kWord32) {
: GraphTest(),
machine_(zone(), MachineRepresentation::kWord32,
MachineOperatorBuilder::Flag::kAllOptionalOps) {
value_[0] = 0x1234567890abcdef;
value_[1] = 0x1edcba098765432f;
value_[2] = 0x1133557799886644;
......@@ -512,6 +514,18 @@ TEST_F(Int64LoweringTest, Dfs) {
IsInt32Constant(high_word_value(1)))),
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 internal
} // namespace v8
......@@ -2247,6 +2247,7 @@ IS_UNOP_MATCHER(NumberToUint32)
IS_UNOP_MATCHER(ObjectIsReceiver)
IS_UNOP_MATCHER(ObjectIsSmi)
IS_UNOP_MATCHER(Word32Clz)
IS_UNOP_MATCHER(Word32Popcnt)
#undef IS_UNOP_MATCHER
} // namespace compiler
......
......@@ -278,6 +278,7 @@ Matcher<Node*> IsWord32Ror(const Matcher<Node*>& lhs_matcher,
Matcher<Node*> IsWord32Equal(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_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,
const Matcher<Node*>& rhs_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