Commit 01fd8e05 authored by ahaas's avatar ahaas Committed by Commit bot

Implemented the Word64Popcnt TurboFan operator for x64.

Popcnt is implemented as an optional operator, which is only implementd by x64
at the moment.

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

Cr-Commit-Position: refs/heads/master@{#31928}
parent e2f4f04f
...@@ -964,6 +964,9 @@ void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); } ...@@ -964,6 +964,9 @@ void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); } void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord64Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) { void InstructionSelector::VisitInt32Add(Node* node) {
Arm64OperandGenerator g(this); Arm64OperandGenerator g(this);
Int32BinopMatcher m(node); Int32BinopMatcher m(node);
......
...@@ -722,6 +722,8 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -722,6 +722,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord32(node), VisitWord32Ctz(node); return MarkAsWord32(node), VisitWord32Ctz(node);
case IrOpcode::kWord32Popcnt: case IrOpcode::kWord32Popcnt:
return MarkAsWord32(node), VisitWord32Popcnt(node); return MarkAsWord32(node), VisitWord32Popcnt(node);
case IrOpcode::kWord64Popcnt:
return MarkAsWord32(node), VisitWord64Popcnt(node);
case IrOpcode::kWord64And: case IrOpcode::kWord64And:
return MarkAsWord64(node), VisitWord64And(node); return MarkAsWord64(node), VisitWord64And(node);
case IrOpcode::kWord64Or: case IrOpcode::kWord64Or:
...@@ -981,6 +983,9 @@ void InstructionSelector::VisitWord64Clz(Node* node) { UNIMPLEMENTED(); } ...@@ -981,6 +983,9 @@ void InstructionSelector::VisitWord64Clz(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Ctz(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitWord64Ctz(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Popcnt(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Equal(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitWord64Equal(Node* node) { UNIMPLEMENTED(); }
......
...@@ -176,6 +176,7 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) { ...@@ -176,6 +176,7 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
V(Word32Ctz, Operator::kNoProperties, 1, 0, 1) \ V(Word32Ctz, Operator::kNoProperties, 1, 0, 1) \
V(Word64Ctz, Operator::kNoProperties, 1, 0, 1) \ V(Word64Ctz, Operator::kNoProperties, 1, 0, 1) \
V(Word32Popcnt, Operator::kNoProperties, 1, 0, 1) \ V(Word32Popcnt, Operator::kNoProperties, 1, 0, 1) \
V(Word64Popcnt, Operator::kNoProperties, 1, 0, 1) \
V(Float32Max, Operator::kNoProperties, 2, 0, 1) \ V(Float32Max, Operator::kNoProperties, 2, 0, 1) \
V(Float32Min, Operator::kNoProperties, 2, 0, 1) \ V(Float32Min, Operator::kNoProperties, 2, 0, 1) \
V(Float64Max, Operator::kNoProperties, 2, 0, 1) \ V(Float64Max, Operator::kNoProperties, 2, 0, 1) \
......
...@@ -125,10 +125,11 @@ class MachineOperatorBuilder final : public ZoneObject { ...@@ -125,10 +125,11 @@ class MachineOperatorBuilder final : public ZoneObject {
kWord32Ctz = 1u << 10, kWord32Ctz = 1u << 10,
kWord32Popcnt = 1u << 11, kWord32Popcnt = 1u << 11,
kWord64Ctz = 1u << 12, kWord64Ctz = 1u << 12,
kWord64Popcnt = 1u << 13,
kAllOptionalOps = kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min | kAllOptionalOps = kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
kFloat64RoundDown | kFloat64RoundTruncate | kFloat64RoundDown | kFloat64RoundTruncate |
kFloat64RoundTiesAway | kWord32Ctz | kWord32Popcnt | kFloat64RoundTiesAway | kWord32Ctz | kWord32Popcnt |
kWord64Ctz kWord64Ctz | kWord64Popcnt
}; };
typedef base::Flags<Flag, unsigned> Flags; typedef base::Flags<Flag, unsigned> Flags;
...@@ -146,6 +147,7 @@ class MachineOperatorBuilder final : public ZoneObject { ...@@ -146,6 +147,7 @@ class MachineOperatorBuilder final : public ZoneObject {
const Operator* Word32Clz(); const Operator* Word32Clz();
const OptionalOperator Word32Ctz(); const OptionalOperator Word32Ctz();
const OptionalOperator Word32Popcnt(); const OptionalOperator Word32Popcnt();
const OptionalOperator Word64Popcnt();
bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; } bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; }
const Operator* Word64And(); const Operator* Word64And();
......
...@@ -352,6 +352,9 @@ void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); } ...@@ -352,6 +352,9 @@ void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); } void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord64Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord64Ror(Node* node) { void InstructionSelector::VisitWord64Ror(Node* node) {
VisitRRO(this, kMips64Dror, node); VisitRRO(this, kMips64Dror, node);
} }
......
...@@ -235,6 +235,7 @@ ...@@ -235,6 +235,7 @@
V(Word32Clz) \ V(Word32Clz) \
V(Word32Ctz) \ V(Word32Ctz) \
V(Word32Popcnt) \ V(Word32Popcnt) \
V(Word64Popcnt) \
V(Word64And) \ V(Word64And) \
V(Word64Or) \ V(Word64Or) \
V(Word64Xor) \ V(Word64Xor) \
......
...@@ -1961,6 +1961,9 @@ Type* Typer::Visitor::TypeWord64Clz(Node* node) { return Type::Internal(); } ...@@ -1961,6 +1961,9 @@ Type* Typer::Visitor::TypeWord64Clz(Node* node) { return Type::Internal(); }
Type* Typer::Visitor::TypeWord64Ctz(Node* node) { return Type::Internal(); } Type* Typer::Visitor::TypeWord64Ctz(Node* node) { return Type::Internal(); }
Type* Typer::Visitor::TypeWord64Popcnt(Node* node) { return Type::Internal(); }
Type* Typer::Visitor::TypeWord64Equal(Node* node) { return Type::Boolean(); } Type* Typer::Visitor::TypeWord64Equal(Node* node) { return Type::Boolean(); }
......
...@@ -829,6 +829,7 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -829,6 +829,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kWord64Sar: case IrOpcode::kWord64Sar:
case IrOpcode::kWord64Ror: case IrOpcode::kWord64Ror:
case IrOpcode::kWord64Clz: case IrOpcode::kWord64Clz:
case IrOpcode::kWord64Popcnt:
case IrOpcode::kWord64Ctz: case IrOpcode::kWord64Ctz:
case IrOpcode::kWord64Equal: case IrOpcode::kWord64Equal:
case IrOpcode::kInt32Add: case IrOpcode::kInt32Add:
......
...@@ -854,6 +854,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -854,6 +854,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Tzcntl(i.OutputRegister(), i.InputOperand(0)); __ Tzcntl(i.OutputRegister(), i.InputOperand(0));
} }
break; break;
case kX64Popcnt:
if (instr->InputAt(0)->IsRegister()) {
__ Popcntq(i.OutputRegister(), i.InputRegister(0));
} else {
__ Popcntq(i.OutputRegister(), i.InputOperand(0));
}
break;
case kX64Popcnt32: case kX64Popcnt32:
if (instr->InputAt(0)->IsRegister()) { if (instr->InputAt(0)->IsRegister()) {
__ Popcntl(i.OutputRegister(), i.InputRegister(0)); __ Popcntl(i.OutputRegister(), i.InputRegister(0));
......
...@@ -50,6 +50,7 @@ namespace compiler { ...@@ -50,6 +50,7 @@ namespace compiler {
V(X64Lzcnt32) \ V(X64Lzcnt32) \
V(X64Tzcnt) \ V(X64Tzcnt) \
V(X64Tzcnt32) \ V(X64Tzcnt32) \
V(X64Popcnt) \
V(X64Popcnt32) \ V(X64Popcnt32) \
V(SSEFloat32Cmp) \ V(SSEFloat32Cmp) \
V(SSEFloat32Add) \ V(SSEFloat32Add) \
......
...@@ -625,6 +625,12 @@ void InstructionSelector::VisitWord32Popcnt(Node* node) { ...@@ -625,6 +625,12 @@ void InstructionSelector::VisitWord32Popcnt(Node* node) {
} }
void InstructionSelector::VisitWord64Popcnt(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Popcnt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitInt32Add(Node* node) { void InstructionSelector::VisitInt32Add(Node* node) {
X64OperandGenerator g(this); X64OperandGenerator g(this);
...@@ -1637,7 +1643,8 @@ InstructionSelector::SupportedMachineOperatorFlags() { ...@@ -1637,7 +1643,8 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kWord32ShiftIsSafe | MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kWord32Ctz | MachineOperatorBuilder::kWord64Ctz; MachineOperatorBuilder::kWord32Ctz | MachineOperatorBuilder::kWord64Ctz;
if (CpuFeatures::IsSupported(POPCNT)) { if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt; flags |= MachineOperatorBuilder::kWord32Popcnt |
MachineOperatorBuilder::kWord64Popcnt;
} }
if (CpuFeatures::IsSupported(SSE4_1)) { if (CpuFeatures::IsSupported(SSE4_1)) {
flags |= MachineOperatorBuilder::kFloat64RoundDown | flags |= MachineOperatorBuilder::kFloat64RoundDown |
......
...@@ -1852,13 +1852,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { ...@@ -1852,13 +1852,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
} else { } else {
AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
} }
} else if (opcode == 0xBC) { } else if (opcode == 0xB8 || opcode == 0xBC || opcode == 0xBD) {
AppendToBuffer("%s%c ", mnemonic, operand_size_code()); // POPCNT, CTZ, CLZ.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%s,", NameOfCPURegister(regop));
current += PrintRightOperand(current);
} else if (opcode == 0xBD) {
AppendToBuffer("%s%c ", mnemonic, operand_size_code()); AppendToBuffer("%s%c ", mnemonic, operand_size_code());
int mod, regop, rm; int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm); get_modrm(*current, &mod, &regop, &rm);
......
...@@ -3267,6 +3267,26 @@ void MacroAssembler::Popcntl(Register dst, const Operand& src) { ...@@ -3267,6 +3267,26 @@ void MacroAssembler::Popcntl(Register dst, const Operand& src) {
} }
void MacroAssembler::Popcntq(Register dst, Register src) {
if (CpuFeatures::IsSupported(POPCNT)) {
CpuFeatureScope scope(this, POPCNT);
popcntq(dst, src);
return;
}
UNREACHABLE();
}
void MacroAssembler::Popcntq(Register dst, const Operand& src) {
if (CpuFeatures::IsSupported(POPCNT)) {
CpuFeatureScope scope(this, POPCNT);
popcntq(dst, src);
return;
}
UNREACHABLE();
}
void MacroAssembler::Pushad() { void MacroAssembler::Pushad() {
Push(rax); Push(rax);
Push(rcx); Push(rcx);
......
...@@ -1025,6 +1025,9 @@ class MacroAssembler: public Assembler { ...@@ -1025,6 +1025,9 @@ class MacroAssembler: public Assembler {
void Popcntl(Register dst, Register src); void Popcntl(Register dst, Register src);
void Popcntl(Register dst, const Operand& src); void Popcntl(Register dst, const Operand& src);
void Popcntq(Register dst, Register src);
void Popcntq(Register dst, const Operand& src);
// Non-x64 instructions. // Non-x64 instructions.
// Push/pop all general purpose registers. // Push/pop all general purpose registers.
// Does not push rsp/rbp nor any of the assembler's special purpose registers // Does not push rsp/rbp nor any of the assembler's special purpose registers
......
...@@ -284,6 +284,25 @@ TEST(RunWord64Ctz) { ...@@ -284,6 +284,25 @@ TEST(RunWord64Ctz) {
CHECK_EQ(1, m.Call(uint64_t(0x000000009afdbc82))); CHECK_EQ(1, m.Call(uint64_t(0x000000009afdbc82)));
CHECK_EQ(0, m.Call(uint64_t(0x000000009afdbc81))); CHECK_EQ(0, m.Call(uint64_t(0x000000009afdbc81)));
} }
TEST(RunWord64Popcnt) {
BufferedRawMachineAssemblerTester<int32_t> m(kMachUint64);
if (!m.machine()->Word64Popcnt().IsSupported()) {
return;
}
m.Return(m.AddNode(m.machine()->Word64Popcnt().op(), m.Parameter(0)));
CHECK_EQ(0, m.Call(uint64_t(0x0000000000000000)));
CHECK_EQ(1, m.Call(uint64_t(0x0000000000000001)));
CHECK_EQ(1, m.Call(uint64_t(0x8000000000000000)));
CHECK_EQ(64, m.Call(uint64_t(0xffffffffffffffff)));
CHECK_EQ(12, m.Call(uint64_t(0x000dc100000dc100)));
CHECK_EQ(18, m.Call(uint64_t(0xe00dc100e00dc100)));
CHECK_EQ(22, m.Call(uint64_t(0xe00dc103e00dc103)));
CHECK_EQ(18, m.Call(uint64_t(0x000dc107000dc107)));
}
#endif // V8_TARGET_ARCH_64_BIT #endif // V8_TARGET_ARCH_64_BIT
......
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