Commit 053e280c authored by ahaas's avatar ahaas Committed by Commit bot

Added Popcnt as an optional operator and implement it on x64 and ia32.

R=titzer@google.com

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

Cr-Commit-Position: refs/heads/master@{#31319}
parent 13d783d7
......@@ -700,6 +700,9 @@ void InstructionSelector::VisitWord32Clz(Node* node) {
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
ArmOperandGenerator g(this);
Int32BinopMatcher m(node);
......
......@@ -930,6 +930,9 @@ void InstructionSelector::VisitWord32Clz(Node* node) {
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
Arm64OperandGenerator g(this);
Int32BinopMatcher m(node);
......
......@@ -512,6 +512,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kIA32Tzcnt:
__ Tzcnt(i.OutputRegister(), i.InputOperand(0));
break;
case kIA32Popcnt:
__ Popcnt(i.OutputRegister(), i.InputOperand(0));
break;
case kSSEFloat32Cmp:
__ ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
break;
......
......@@ -32,6 +32,7 @@ namespace compiler {
V(IA32Ror) \
V(IA32Lzcnt) \
V(IA32Tzcnt) \
V(IA32Popcnt) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \
V(SSEFloat32Sub) \
......
......@@ -559,6 +559,12 @@ void InstructionSelector::VisitWord32Ctz(Node* node) {
}
void InstructionSelector::VisitWord32Popcnt(Node* node) {
IA32OperandGenerator g(this);
Emit(kIA32Popcnt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitInt32Add(Node* node) {
IA32OperandGenerator g(this);
......@@ -1365,6 +1371,9 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kFloat64Min |
MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kWord32Ctz;
if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt;
}
if (CpuFeatures::IsSupported(SSE4_1)) {
flags |= MachineOperatorBuilder::kFloat64RoundDown |
MachineOperatorBuilder::kFloat64RoundTruncate;
......
......@@ -614,6 +614,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord32(node), VisitWord32Clz(node);
case IrOpcode::kWord32Ctz:
return MarkAsWord32(node), VisitWord32Ctz(node);
case IrOpcode::kWord32Popcnt:
return MarkAsWord32(node), VisitWord32Popcnt(node);
case IrOpcode::kWord64And:
return MarkAsWord64(node), VisitWord64And(node);
case IrOpcode::kWord64Or:
......
......@@ -168,6 +168,7 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
#define PURE_OPTIONAL_OP_LIST(V) \
V(Word32Ctz, Operator::kNoProperties, 1, 0, 1) \
V(Word32Popcnt, 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) \
......
......@@ -118,9 +118,10 @@ class MachineOperatorBuilder final : public ZoneObject {
kUint32DivIsSafe = 1u << 8,
kWord32ShiftIsSafe = 1u << 9,
kWord32Ctz = 1u << 10,
kWord32Popcnt = 1u << 11,
kAllOptionalOps = kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
kFloat64RoundDown | kFloat64RoundTruncate |
kFloat64RoundTiesAway | kWord32Ctz
kFloat64RoundTiesAway | kWord32Ctz | kWord32Popcnt
};
typedef base::Flags<Flag, unsigned> Flags;
......@@ -137,6 +138,7 @@ class MachineOperatorBuilder final : public ZoneObject {
const Operator* Word32Equal();
const Operator* Word32Clz();
const OptionalOperator Word32Ctz();
const OptionalOperator Word32Popcnt();
bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; }
const Operator* Word64And();
......
......@@ -272,6 +272,9 @@ void InstructionSelector::VisitWord32Clz(Node* node) {
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
MipsOperandGenerator g(this);
......
......@@ -324,6 +324,9 @@ void InstructionSelector::VisitWord32Clz(Node* node) {
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord64Ror(Node* node) {
VisitRRO(this, kMips64Dror, node);
}
......
......@@ -227,6 +227,7 @@
V(Word32Ror) \
V(Word32Clz) \
V(Word32Ctz) \
V(Word32Popcnt) \
V(Word64And) \
V(Word64Or) \
V(Word64Xor) \
......
......@@ -740,6 +740,9 @@ void InstructionSelector::VisitWord32Clz(Node* node) {
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
VisitBinop<Int32BinopMatcher>(this, node, kPPC_Add, kInt16Imm);
}
......
......@@ -1701,6 +1701,11 @@ Type* Typer::Visitor::TypeWord32Clz(Node* node) { return Type::Integral32(); }
Type* Typer::Visitor::TypeWord32Ctz(Node* node) { return Type::Integral32(); }
Type* Typer::Visitor::TypeWord32Popcnt(Node* node) {
return Type::Integral32();
}
Type* Typer::Visitor::TypeWord64And(Node* node) { return Type::Internal(); }
......
......@@ -804,6 +804,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kWord32Equal:
case IrOpcode::kWord32Clz:
case IrOpcode::kWord32Ctz:
case IrOpcode::kWord32Popcnt:
case IrOpcode::kWord64And:
case IrOpcode::kWord64Or:
case IrOpcode::kWord64Xor:
......
......@@ -777,6 +777,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Tzcntl(i.OutputRegister(), i.InputOperand(0));
}
break;
case kX64Popcnt32:
if (instr->InputAt(0)->IsRegister()) {
__ Popcntl(i.OutputRegister(), i.InputRegister(0));
} else {
__ Popcntl(i.OutputRegister(), i.InputOperand(0));
}
break;
case kSSEFloat32Cmp:
ASSEMBLE_SSE_BINOP(ucomiss);
break;
......
......@@ -48,6 +48,7 @@ namespace compiler {
V(X64Ror32) \
V(X64Lzcnt32) \
V(X64Tzcnt32) \
V(X64Popcnt32) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \
V(SSEFloat32Sub) \
......
......@@ -584,6 +584,12 @@ void InstructionSelector::VisitWord32Ctz(Node* node) {
}
void InstructionSelector::VisitWord32Popcnt(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Popcnt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitInt32Add(Node* node) {
X64OperandGenerator g(this);
......@@ -1712,6 +1718,9 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kFloat64Min |
MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kWord32Ctz;
if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt;
}
if (CpuFeatures::IsSupported(SSE4_1)) {
flags |= MachineOperatorBuilder::kFloat64RoundDown |
MachineOperatorBuilder::kFloat64RoundTruncate;
......
......@@ -517,6 +517,9 @@ void InstructionSelector::VisitWord32Clz(Node* node) {
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
X87OperandGenerator g(this);
......
......@@ -2444,6 +2444,16 @@ void MacroAssembler::Tzcnt(Register dst, const Operand& src) {
}
void MacroAssembler::Popcnt(Register dst, const Operand& src) {
if (CpuFeatures::IsSupported(POPCNT)) {
CpuFeatureScope scope(this, POPCNT);
popcnt(dst, src);
return;
}
UNREACHABLE();
}
void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
if (FLAG_native_code_counters && counter->Enabled()) {
mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
......
......@@ -856,6 +856,9 @@ class MacroAssembler: public Assembler {
void Tzcnt(Register dst, Register src) { Tzcnt(dst, Operand(src)); }
void Tzcnt(Register dst, const Operand& src);
void Popcnt(Register dst, Register src) { Popcnt(dst, Operand(src)); }
void Popcnt(Register dst, const Operand& src);
// Emit call to the code we are currently generating.
void CallSelf() {
Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
......
......@@ -2906,6 +2906,26 @@ void MacroAssembler::Tzcntl(Register dst, const Operand& src) {
}
void MacroAssembler::Popcntl(Register dst, Register src) {
if (CpuFeatures::IsSupported(POPCNT)) {
CpuFeatureScope scope(this, POPCNT);
popcntl(dst, src);
return;
}
UNREACHABLE();
}
void MacroAssembler::Popcntl(Register dst, const Operand& src) {
if (CpuFeatures::IsSupported(POPCNT)) {
CpuFeatureScope scope(this, POPCNT);
popcntl(dst, src);
return;
}
UNREACHABLE();
}
void MacroAssembler::Pushad() {
Push(rax);
Push(rcx);
......
......@@ -947,6 +947,9 @@ class MacroAssembler: public Assembler {
void Tzcntl(Register dst, Register src);
void Tzcntl(Register dst, const Operand& src);
void Popcntl(Register dst, Register src);
void Popcntl(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
......
......@@ -120,6 +120,29 @@ TEST(RunInt32Clz) {
}
void TestWord32Popcnt(int32_t value, int32_t expected) {
RawMachineAssemblerTester<int32_t> m;
compiler::OptionalOperator op = m.machine()->Word32Popcnt();
if (op.IsSupported()) {
Node* popcnt = m.AddNode(op.op(), m.Int32Constant(value));
m.Return(popcnt);
CHECK_EQ(expected, m.Call());
}
}
TEST(RunWord32Popcnt) {
TestWord32Popcnt(0x00000000, 0);
TestWord32Popcnt(0x00000001, 1);
TestWord32Popcnt(0x80000000, 1);
TestWord32Popcnt(0xffffffff, 32);
TestWord32Popcnt(0x000dc100, 6);
TestWord32Popcnt(0xe00dc100, 9);
TestWord32Popcnt(0xe00dc103, 11);
TestWord32Popcnt(0x000dc107, 9);
}
static Node* Int32Input(RawMachineAssemblerTester<int32_t>* m, int index) {
switch (index) {
case 0:
......
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