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