Commit cf512308 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[turbofan] Add proper conversion operators for int32<->int64.

This affects arm64 and x64. Note that we do not yet optimize
these conversions. Later we will add support for merging these
conversion operators into other operations during instruction
selection.

TEST=cctest,compiler-unittests
R=jarin@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23184 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 91599ffc
...@@ -274,6 +274,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -274,6 +274,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArm64Ror32: case kArm64Ror32:
ASSEMBLE_SHIFT(Ror, 32); ASSEMBLE_SHIFT(Ror, 32);
break; break;
case kArm64Mov32:
__ Mov(i.OutputRegister32(), i.InputRegister32(0));
break;
case kArm64Sxtw:
__ Sxtw(i.OutputRegister(), i.InputRegister32(0));
break;
case kArm64CallCodeObject: { case kArm64CallCodeObject: {
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
...@@ -383,14 +389,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -383,14 +389,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
0, 2); 0, 2);
break; break;
} }
case kArm64Int32ToInt64:
__ Sxtw(i.OutputRegister(), i.InputRegister(0));
break;
case kArm64Int64ToInt32:
if (!i.OutputRegister().is(i.InputRegister(0))) {
__ Mov(i.OutputRegister(), i.InputRegister(0));
}
break;
case kArm64Float64ToInt32: case kArm64Float64ToInt32:
__ Fcvtzs(i.OutputRegister32(), i.InputDoubleRegister(0)); __ Fcvtzs(i.OutputRegister32(), i.InputDoubleRegister(0));
break; break;
......
...@@ -48,6 +48,8 @@ namespace compiler { ...@@ -48,6 +48,8 @@ namespace compiler {
V(Arm64Sar32) \ V(Arm64Sar32) \
V(Arm64Ror) \ V(Arm64Ror) \
V(Arm64Ror32) \ V(Arm64Ror32) \
V(Arm64Mov32) \
V(Arm64Sxtw) \
V(Arm64CallCodeObject) \ V(Arm64CallCodeObject) \
V(Arm64CallJSFunction) \ V(Arm64CallJSFunction) \
V(Arm64CallAddress) \ V(Arm64CallAddress) \
...@@ -62,8 +64,6 @@ namespace compiler { ...@@ -62,8 +64,6 @@ namespace compiler {
V(Arm64Float64Mul) \ V(Arm64Float64Mul) \
V(Arm64Float64Div) \ V(Arm64Float64Div) \
V(Arm64Float64Mod) \ V(Arm64Float64Mod) \
V(Arm64Int32ToInt64) \
V(Arm64Int64ToInt32) \
V(Arm64Float64ToInt32) \ V(Arm64Float64ToInt32) \
V(Arm64Float64ToUint32) \ V(Arm64Float64ToUint32) \
V(Arm64Int32ToFloat64) \ V(Arm64Int32ToFloat64) \
......
...@@ -71,14 +71,6 @@ class Arm64OperandGenerator V8_FINAL : public OperandGenerator { ...@@ -71,14 +71,6 @@ class Arm64OperandGenerator V8_FINAL : public OperandGenerator {
}; };
static void VisitRR(InstructionSelector* selector, ArchOpcode opcode,
Node* node) {
Arm64OperandGenerator g(selector);
selector->Emit(opcode, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}
static void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, static void VisitRRR(InstructionSelector* selector, ArchOpcode opcode,
Node* node) { Node* node) {
Arm64OperandGenerator g(selector); Arm64OperandGenerator g(selector);
...@@ -426,16 +418,6 @@ void InstructionSelector::VisitInt64UMod(Node* node) { ...@@ -426,16 +418,6 @@ void InstructionSelector::VisitInt64UMod(Node* node) {
} }
void InstructionSelector::VisitConvertInt32ToInt64(Node* node) {
VisitRR(this, kArm64Int32ToInt64, node);
}
void InstructionSelector::VisitConvertInt64ToInt32(Node* node) {
VisitRR(this, kArm64Int64ToInt32, node);
}
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
Arm64OperandGenerator g(this); Arm64OperandGenerator g(this);
Emit(kArm64Int32ToFloat64, g.DefineAsDoubleRegister(node), Emit(kArm64Int32ToFloat64, g.DefineAsDoubleRegister(node),
...@@ -464,6 +446,24 @@ void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { ...@@ -464,6 +446,24 @@ void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
} }
void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
Arm64OperandGenerator g(this);
Emit(kArm64Sxtw, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
}
void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
Arm64OperandGenerator g(this);
Emit(kArm64Mov32, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
}
void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
Arm64OperandGenerator g(this);
Emit(kArm64Mov32, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
}
void InstructionSelector::VisitFloat64Add(Node* node) { void InstructionSelector::VisitFloat64Add(Node* node) {
VisitRRRFloat64(this, kArm64Float64Add, node); VisitRRRFloat64(this, kArm64Float64Add, node);
} }
......
...@@ -88,7 +88,9 @@ Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) { ...@@ -88,7 +88,9 @@ Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) {
Reduction ChangeLowering::ChangeInt32ToTagged(Node* val, Node* control) { Reduction ChangeLowering::ChangeInt32ToTagged(Node* val, Node* control) {
if (machine()->is64()) { if (machine()->is64()) {
return Replace( return Replace(
graph()->NewNode(machine()->WordShl(), val, SmiShiftBitsConstant())); graph()->NewNode(machine()->Word64Shl(),
graph()->NewNode(machine()->ChangeInt32ToInt64(), val),
SmiShiftBitsConstant()));
} }
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val, val); Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val, val);
...@@ -129,7 +131,7 @@ Reduction ChangeLowering::ChangeTaggedToInt32(Node* val, Node* control) { ...@@ -129,7 +131,7 @@ Reduction ChangeLowering::ChangeTaggedToInt32(Node* val, Node* control) {
graph()->NewNode(machine()->WordSar(), val, SmiShiftBitsConstant()); graph()->NewNode(machine()->WordSar(), val, SmiShiftBitsConstant());
Node* number = Node* number =
machine()->is64() machine()->is64()
? graph()->NewNode(machine()->ConvertInt64ToInt32(), integer) ? graph()->NewNode(machine()->TruncateInt64ToInt32(), integer)
: integer; : integer;
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
...@@ -158,7 +160,7 @@ Reduction ChangeLowering::ChangeTaggedToFloat64(Node* val, Node* control) { ...@@ -158,7 +160,7 @@ Reduction ChangeLowering::ChangeTaggedToFloat64(Node* val, Node* control) {
Node* number = graph()->NewNode( Node* number = graph()->NewNode(
machine()->ChangeInt32ToFloat64(), machine()->ChangeInt32ToFloat64(),
machine()->is64() machine()->is64()
? graph()->NewNode(machine()->ConvertInt64ToInt32(), integer) ? graph()->NewNode(machine()->TruncateInt64ToInt32(), integer)
: integer); : integer);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
......
...@@ -575,10 +575,6 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -575,10 +575,6 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitInt64LessThan(node); return VisitInt64LessThan(node);
case IrOpcode::kInt64LessThanOrEqual: case IrOpcode::kInt64LessThanOrEqual:
return VisitInt64LessThanOrEqual(node); return VisitInt64LessThanOrEqual(node);
case IrOpcode::kConvertInt32ToInt64:
return VisitConvertInt32ToInt64(node);
case IrOpcode::kConvertInt64ToInt32:
return VisitConvertInt64ToInt32(node);
case IrOpcode::kChangeInt32ToFloat64: case IrOpcode::kChangeInt32ToFloat64:
return MarkAsDouble(node), VisitChangeInt32ToFloat64(node); return MarkAsDouble(node), VisitChangeInt32ToFloat64(node);
case IrOpcode::kChangeUint32ToFloat64: case IrOpcode::kChangeUint32ToFloat64:
...@@ -587,6 +583,12 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -587,6 +583,12 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitChangeFloat64ToInt32(node); return VisitChangeFloat64ToInt32(node);
case IrOpcode::kChangeFloat64ToUint32: case IrOpcode::kChangeFloat64ToUint32:
return VisitChangeFloat64ToUint32(node); return VisitChangeFloat64ToUint32(node);
case IrOpcode::kChangeInt32ToInt64:
return VisitChangeInt32ToInt64(node);
case IrOpcode::kChangeUint32ToUint64:
return VisitChangeUint32ToUint64(node);
case IrOpcode::kTruncateInt64ToInt32:
return VisitTruncateInt64ToInt32(node);
case IrOpcode::kFloat64Add: case IrOpcode::kFloat64Add:
return MarkAsDouble(node), VisitFloat64Add(node); return MarkAsDouble(node), VisitFloat64Add(node);
case IrOpcode::kFloat64Sub: case IrOpcode::kFloat64Sub:
...@@ -752,12 +754,17 @@ void InstructionSelector::VisitInt64Mod(Node* node) { UNIMPLEMENTED(); } ...@@ -752,12 +754,17 @@ void InstructionSelector::VisitInt64Mod(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt64UMod(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitInt64UMod(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitConvertInt64ToInt32(Node* node) { void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void InstructionSelector::VisitConvertInt32ToInt64(Node* node) { void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -280,12 +280,13 @@ class MachineNodeFactory { ...@@ -280,12 +280,13 @@ class MachineNodeFactory {
return Int64LessThanOrEqual(b, a); return Int64LessThanOrEqual(b, a);
} }
// TODO(turbofan): What is this used for?
Node* ConvertIntPtrToInt32(Node* a) { Node* ConvertIntPtrToInt32(Node* a) {
return kPointerSize == 8 ? NEW_NODE_1(MACHINE()->ConvertInt64ToInt32(), a) return kPointerSize == 8 ? NEW_NODE_1(MACHINE()->TruncateInt64ToInt32(), a)
: a; : a;
} }
Node* ConvertInt32ToIntPtr(Node* a) { Node* ConvertInt32ToIntPtr(Node* a) {
return kPointerSize == 8 ? NEW_NODE_1(MACHINE()->ConvertInt32ToInt64(), a) return kPointerSize == 8 ? NEW_NODE_1(MACHINE()->ChangeInt32ToInt64(), a)
: a; : a;
} }
...@@ -339,12 +340,6 @@ class MachineNodeFactory { ...@@ -339,12 +340,6 @@ class MachineNodeFactory {
} }
// Conversions. // Conversions.
Node* ConvertInt32ToInt64(Node* a) {
return NEW_NODE_1(MACHINE()->ConvertInt32ToInt64(), a);
}
Node* ConvertInt64ToInt32(Node* a) {
return NEW_NODE_1(MACHINE()->ConvertInt64ToInt32(), a);
}
Node* ChangeInt32ToFloat64(Node* a) { Node* ChangeInt32ToFloat64(Node* a) {
return NEW_NODE_1(MACHINE()->ChangeInt32ToFloat64(), a); return NEW_NODE_1(MACHINE()->ChangeInt32ToFloat64(), a);
} }
...@@ -357,6 +352,15 @@ class MachineNodeFactory { ...@@ -357,6 +352,15 @@ class MachineNodeFactory {
Node* ChangeFloat64ToUint32(Node* a) { Node* ChangeFloat64ToUint32(Node* a) {
return NEW_NODE_1(MACHINE()->ChangeFloat64ToUint32(), a); return NEW_NODE_1(MACHINE()->ChangeFloat64ToUint32(), a);
} }
Node* ChangeInt32ToInt64(Node* a) {
return NEW_NODE_1(MACHINE()->ChangeInt32ToInt64(), a);
}
Node* ChangeUint32ToUint64(Node* a) {
return NEW_NODE_1(MACHINE()->ChangeUint32ToUint64(), a);
}
Node* TruncateInt64ToInt32(Node* a) {
return NEW_NODE_1(MACHINE()->TruncateInt64ToInt32(), a);
}
#ifdef MACHINE_ASSEMBLER_SUPPORTS_CALL_C #ifdef MACHINE_ASSEMBLER_SUPPORTS_CALL_C
// Call to C. // Call to C.
......
...@@ -121,19 +121,22 @@ class MachineOperatorBuilder { ...@@ -121,19 +121,22 @@ class MachineOperatorBuilder {
Operator* Int64LessThan() { BINOP(Int64LessThan); } Operator* Int64LessThan() { BINOP(Int64LessThan); }
Operator* Int64LessThanOrEqual() { BINOP(Int64LessThanOrEqual); } Operator* Int64LessThanOrEqual() { BINOP(Int64LessThanOrEqual); }
Operator* ConvertInt32ToInt64() { UNOP(ConvertInt32ToInt64); }
Operator* ConvertInt64ToInt32() { UNOP(ConvertInt64ToInt32); }
// Convert representation of integers between float64 and int32/uint32. // Convert representation of integers between float64 and int32/uint32.
// The precise rounding mode and handling of out of range inputs are *not* // The precise rounding mode and handling of out of range inputs are *not*
// defined for these operators, since they are intended only for use with // defined for these operators, since they are intended only for use with
// integers. // integers.
// TODO(titzer): rename ConvertXXX to ChangeXXX in machine operators.
Operator* ChangeInt32ToFloat64() { UNOP(ChangeInt32ToFloat64); } Operator* ChangeInt32ToFloat64() { UNOP(ChangeInt32ToFloat64); }
Operator* ChangeUint32ToFloat64() { UNOP(ChangeUint32ToFloat64); } Operator* ChangeUint32ToFloat64() { UNOP(ChangeUint32ToFloat64); }
Operator* ChangeFloat64ToInt32() { UNOP(ChangeFloat64ToInt32); } Operator* ChangeFloat64ToInt32() { UNOP(ChangeFloat64ToInt32); }
Operator* ChangeFloat64ToUint32() { UNOP(ChangeFloat64ToUint32); } Operator* ChangeFloat64ToUint32() { UNOP(ChangeFloat64ToUint32); }
// Sign/zero extend int32/uint32 to int64/uint64.
Operator* ChangeInt32ToInt64() { UNOP(ChangeInt32ToInt64); }
Operator* ChangeUint32ToUint64() { UNOP(ChangeUint32ToUint64); }
// Truncate the high order bits and convert the remaining bits to int32.
Operator* TruncateInt64ToInt32() { UNOP(TruncateInt64ToInt32); }
// Floating point operators always operate with IEEE 754 round-to-nearest. // Floating point operators always operate with IEEE 754 round-to-nearest.
Operator* Float64Add() { BINOP_C(Float64Add); } Operator* Float64Add() { BINOP_C(Float64Add); }
Operator* Float64Sub() { BINOP(Float64Sub); } Operator* Float64Sub() { BINOP(Float64Sub); }
......
...@@ -200,12 +200,13 @@ ...@@ -200,12 +200,13 @@
V(Int64UMod) \ V(Int64UMod) \
V(Int64LessThan) \ V(Int64LessThan) \
V(Int64LessThanOrEqual) \ V(Int64LessThanOrEqual) \
V(ConvertInt64ToInt32) \
V(ConvertInt32ToInt64) \
V(ChangeInt32ToFloat64) \ V(ChangeInt32ToFloat64) \
V(ChangeUint32ToFloat64) \ V(ChangeUint32ToFloat64) \
V(ChangeFloat64ToInt32) \ V(ChangeFloat64ToInt32) \
V(ChangeFloat64ToUint32) \ V(ChangeFloat64ToUint32) \
V(ChangeInt32ToInt64) \
V(ChangeUint32ToUint64) \
V(TruncateInt64ToInt32) \
V(Float64Add) \ V(Float64Add) \
V(Float64Sub) \ V(Float64Sub) \
V(Float64Mul) \ V(Float64Mul) \
......
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
#ifndef V8_COMPILER_OPERATOR_PROPERTIES_INL_H_ #ifndef V8_COMPILER_OPERATOR_PROPERTIES_INL_H_
#define V8_COMPILER_OPERATOR_PROPERTIES_INL_H_ #define V8_COMPILER_OPERATOR_PROPERTIES_INL_H_
#include "src/v8.h" #include "src/compiler/common-operator.h"
#include "src/compiler/js-operator.h" #include "src/compiler/js-operator.h"
#include "src/compiler/opcodes.h" #include "src/compiler/opcodes.h"
#include "src/compiler/operator-properties.h" #include "src/compiler/operator-properties.h"
......
...@@ -627,10 +627,13 @@ class RepresentationSelector { ...@@ -627,10 +627,13 @@ class RepresentationSelector {
case IrOpcode::kWord64Equal: case IrOpcode::kWord64Equal:
return VisitBinop(node, kRepWord64, kRepBit); return VisitBinop(node, kRepWord64, kRepBit);
case IrOpcode::kConvertInt32ToInt64: case IrOpcode::kChangeInt32ToInt64:
return VisitUnop(node, kTypeInt32 | kRepWord32, return VisitUnop(node, kTypeInt32 | kRepWord32,
kTypeInt32 | kRepWord64); kTypeInt64 | kRepWord64);
case IrOpcode::kConvertInt64ToInt32: case IrOpcode::kChangeUint32ToUint64:
return VisitUnop(node, kTypeUint32 | kRepWord32,
kTypeUint64 | kRepWord64);
case IrOpcode::kTruncateInt64ToInt32:
return VisitUnop(node, kTypeInt64 | kRepWord64, return VisitUnop(node, kTypeInt64 | kRepWord64,
kTypeInt32 | kRepWord32); kTypeInt32 | kRepWord32);
......
...@@ -388,6 +388,24 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -388,6 +388,24 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kX64PushI: case kX64PushI:
__ pushq(i.InputImmediate(0)); __ pushq(i.InputImmediate(0));
break; break;
case kX64Movl: {
RegisterOrOperand input = i.InputRegisterOrOperand(0);
if (input.type == kRegister) {
__ movl(i.OutputRegister(), input.reg);
} else {
__ movl(i.OutputRegister(), input.operand);
}
break;
}
case kX64Movsxlq: {
RegisterOrOperand input = i.InputRegisterOrOperand(0);
if (input.type == kRegister) {
__ movsxlq(i.OutputRegister(), input.reg);
} else {
__ movsxlq(i.OutputRegister(), input.operand);
}
break;
}
case kX64CallCodeObject: { case kX64CallCodeObject: {
if (HasImmediateInput(instr, 0)) { if (HasImmediateInput(instr, 0)) {
Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
...@@ -484,12 +502,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -484,12 +502,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ addq(rsp, Immediate(kDoubleSize)); __ addq(rsp, Immediate(kDoubleSize));
break; break;
} }
case kX64Int32ToInt64:
__ movzxwq(i.OutputRegister(), i.InputRegister(0));
break;
case kX64Int64ToInt32:
__ Move(i.OutputRegister(), i.InputRegister(0));
break;
case kSSEFloat64ToInt32: { case kSSEFloat64ToInt32: {
RegisterOrOperand input = i.InputRegisterOrOperand(0); RegisterOrOperand input = i.InputRegisterOrOperand(0);
if (input.type == kDoubleRegister) { if (input.type == kDoubleRegister) {
......
...@@ -46,6 +46,8 @@ namespace compiler { ...@@ -46,6 +46,8 @@ namespace compiler {
V(X64Ror32) \ V(X64Ror32) \
V(X64Push) \ V(X64Push) \
V(X64PushI) \ V(X64PushI) \
V(X64Movsxlq) \
V(X64Movl) \
V(X64CallCodeObject) \ V(X64CallCodeObject) \
V(X64CallAddress) \ V(X64CallAddress) \
V(PopStack) \ V(PopStack) \
...@@ -56,8 +58,6 @@ namespace compiler { ...@@ -56,8 +58,6 @@ namespace compiler {
V(SSEFloat64Mul) \ V(SSEFloat64Mul) \
V(SSEFloat64Div) \ V(SSEFloat64Div) \
V(SSEFloat64Mod) \ V(SSEFloat64Mod) \
V(X64Int32ToInt64) \
V(X64Int64ToInt32) \
V(SSEFloat64ToInt32) \ V(SSEFloat64ToInt32) \
V(SSEFloat64ToUint32) \ V(SSEFloat64ToUint32) \
V(SSEInt32ToFloat64) \ V(SSEInt32ToFloat64) \
......
...@@ -513,6 +513,24 @@ void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { ...@@ -513,6 +513,24 @@ void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
} }
void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Movsxlq, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitFloat64Add(Node* node) { void InstructionSelector::VisitFloat64Add(Node* node) {
X64OperandGenerator g(this); X64OperandGenerator g(this);
Emit(kSSEFloat64Add, g.DefineSameAsFirst(node), Emit(kSSEFloat64Add, g.DefineSameAsFirst(node),
...@@ -554,22 +572,6 @@ void InstructionSelector::VisitFloat64Mod(Node* node) { ...@@ -554,22 +572,6 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
} }
void InstructionSelector::VisitConvertInt64ToInt32(Node* node) {
X64OperandGenerator g(this);
// TODO(dcarney): other modes
Emit(kX64Int64ToInt32, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}
void InstructionSelector::VisitConvertInt32ToInt64(Node* node) {
X64OperandGenerator g(this);
// TODO(dcarney): other modes
Emit(kX64Int32ToInt64, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}
void InstructionSelector::VisitInt32AddWithOverflow(Node* node, void InstructionSelector::VisitInt32AddWithOverflow(Node* node,
FlagsContinuation* cont) { FlagsContinuation* cont) {
VisitBinop(this, node, kX64Add32, cont); VisitBinop(this, node, kX64Add32, cont);
......
...@@ -4202,4 +4202,47 @@ TEST(RunInt32SubWithOverflowInBranchP) { ...@@ -4202,4 +4202,47 @@ TEST(RunInt32SubWithOverflowInBranchP) {
} }
} }
TEST(RunChangeInt32ToInt64P) {
if (kPointerSize < 8) return;
int64_t actual = -1;
RawMachineAssemblerTester<int32_t> m(kMachInt32);
m.StoreToPointer(&actual, kMachInt64, m.ChangeInt32ToInt64(m.Parameter(0)));
m.Return(m.Int32Constant(0));
FOR_INT32_INPUTS(i) {
int64_t expected = *i;
CHECK_EQ(0, m.Call(*i));
CHECK_EQ(expected, actual);
}
}
TEST(RunChangeUint32ToUint64P) {
if (kPointerSize < 8) return;
int64_t actual = -1;
RawMachineAssemblerTester<int32_t> m(kMachUint32);
m.StoreToPointer(&actual, kMachUint64,
m.ChangeUint32ToUint64(m.Parameter(0)));
m.Return(m.Int32Constant(0));
FOR_UINT32_INPUTS(i) {
int64_t expected = static_cast<uint64_t>(*i);
CHECK_EQ(0, m.Call(*i));
CHECK_EQ(expected, actual);
}
}
TEST(RunTruncateInt64ToInt32P) {
if (kPointerSize < 8) return;
int64_t expected = -1;
RawMachineAssemblerTester<int32_t> m;
m.Return(m.TruncateInt64ToInt32(m.LoadFromPointer(&expected, kMachInt64)));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
expected = (static_cast<uint64_t>(*j) << 32) | *i;
CHECK_UINT32_EQ(expected, m.Call());
}
}
}
#endif // V8_TURBOFAN_TARGET #endif // V8_TURBOFAN_TARGET
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include "test/compiler-unittests/instruction-selector-unittest.h" #include "test/compiler-unittests/instruction-selector-unittest.h"
#include "test/cctest/compiler/instruction-selector-tester.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
...@@ -128,6 +126,37 @@ TEST_F(InstructionSelectorTest, MulDivWithParameter) { ...@@ -128,6 +126,37 @@ TEST_F(InstructionSelectorTest, MulDivWithParameter) {
} }
} }
// -----------------------------------------------------------------------------
// Conversions.
TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) {
StreamBuilder m(this, kMachInt64, kMachInt32);
m.Return(m.ChangeInt32ToInt64(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Sxtw, s[0]->arch_opcode());
}
TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) {
StreamBuilder m(this, kMachUint64, kMachUint32);
m.Return(m.ChangeUint32ToUint64(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Mov32, s[0]->arch_opcode());
}
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
StreamBuilder m(this, kMachInt32, kMachInt64);
m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Mov32, s[0]->arch_opcode());
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -295,7 +295,8 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) { ...@@ -295,7 +295,8 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
ASSERT_TRUE(reduction.Changed()); ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), EXPECT_THAT(reduction.replacement(),
IsWord64Shl(val, IsInt32Constant(SmiShiftAmount()))); IsWord64Shl(IsChangeInt32ToInt64(val),
IsInt32Constant(SmiShiftAmount())));
} }
...@@ -315,7 +316,7 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) { ...@@ -315,7 +316,7 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
IsPhi( IsPhi(
IsLoad(kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()), IsLoad(kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
IsControlEffect(CaptureEq(&if_true))), IsControlEffect(CaptureEq(&if_true))),
IsChangeInt32ToFloat64(IsConvertInt64ToInt32( IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(
IsWord64Sar(val, IsInt32Constant(SmiShiftAmount())))), IsWord64Sar(val, IsInt32Constant(SmiShiftAmount())))),
IsMerge( IsMerge(
AllOf(CaptureEq(&if_true), AllOf(CaptureEq(&if_true),
...@@ -343,7 +344,7 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) { ...@@ -343,7 +344,7 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
IsPhi(IsChangeFloat64ToInt32(IsLoad( IsPhi(IsChangeFloat64ToInt32(IsLoad(
kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()), kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
IsControlEffect(CaptureEq(&if_true)))), IsControlEffect(CaptureEq(&if_true)))),
IsConvertInt64ToInt32( IsTruncateInt64ToInt32(
IsWord64Sar(val, IsInt32Constant(SmiShiftAmount()))), IsWord64Sar(val, IsInt32Constant(SmiShiftAmount()))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf( IsIfFalse(AllOf(
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
'graph-unittest.h', 'graph-unittest.h',
'instruction-selector-unittest.cc', 'instruction-selector-unittest.cc',
'machine-operator-reducer-unittest.cc', 'machine-operator-reducer-unittest.cc',
'machine-operator-unittest.cc',
], ],
'conditions': [ 'conditions': [
['v8_target_arch=="arm"', { ['v8_target_arch=="arm"', {
...@@ -45,6 +46,11 @@ ...@@ -45,6 +46,11 @@
'ia32/instruction-selector-ia32-unittest.cc', 'ia32/instruction-selector-ia32-unittest.cc',
], ],
}], }],
['v8_target_arch=="x64"', {
'sources': [ ### gcmole(arch:x64) ###
'x64/instruction-selector-x64-unittest.cc',
],
}],
['component=="shared_library"', { ['component=="shared_library"', {
# compiler-unittests can't be built against a shared library, so we # compiler-unittests can't be built against a shared library, so we
# need to depend on the underlying static target in that case. # need to depend on the underlying static target in that case.
......
...@@ -73,6 +73,11 @@ class CompilerTest : public ::testing::Test { ...@@ -73,6 +73,11 @@ class CompilerTest : public ::testing::Test {
Zone zone_; Zone zone_;
}; };
template <typename T>
class CompilerTestWithParam : public CompilerTest,
public ::testing::WithParamInterface<T> {};
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -676,9 +676,11 @@ IS_BINOP_MATCHER(Int32AddWithOverflow) ...@@ -676,9 +676,11 @@ IS_BINOP_MATCHER(Int32AddWithOverflow)
Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher) { \ Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher) { \
return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \ return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \
} }
IS_UNOP_MATCHER(ConvertInt64ToInt32)
IS_UNOP_MATCHER(ChangeFloat64ToInt32) IS_UNOP_MATCHER(ChangeFloat64ToInt32)
IS_UNOP_MATCHER(ChangeInt32ToFloat64) IS_UNOP_MATCHER(ChangeInt32ToFloat64)
IS_UNOP_MATCHER(ChangeInt32ToInt64)
IS_UNOP_MATCHER(ChangeUint32ToUint64)
IS_UNOP_MATCHER(TruncateInt64ToInt32)
#undef IS_UNOP_MATCHER #undef IS_UNOP_MATCHER
} // namespace compiler } // namespace compiler
......
...@@ -94,9 +94,11 @@ Matcher<Node*> IsWord64Equal(const Matcher<Node*>& lhs_matcher, ...@@ -94,9 +94,11 @@ Matcher<Node*> IsWord64Equal(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher); const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32AddWithOverflow(const Matcher<Node*>& lhs_matcher, Matcher<Node*> IsInt32AddWithOverflow(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher); const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsConvertInt64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeFloat64ToInt32(const Matcher<Node*>& input_matcher); Matcher<Node*> IsChangeFloat64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher); Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeInt32ToInt64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeUint32ToUint64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/machine-operator.h"
#include "src/compiler/operator-properties-inl.h"
#include "test/compiler-unittests/compiler-unittests.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::IsNull;
namespace v8 {
namespace internal {
namespace compiler {
class MachineOperatorCommonTest : public CompilerTestWithParam<MachineType> {
public:
MachineOperatorCommonTest() : machine_(NULL) {}
virtual ~MachineOperatorCommonTest() { EXPECT_THAT(machine_, IsNull()); }
virtual void SetUp() V8_OVERRIDE {
CompilerTestWithParam::SetUp();
machine_ = new MachineOperatorBuilder(zone(), GetParam());
}
virtual void TearDown() V8_OVERRIDE {
delete machine_;
machine_ = NULL;
CompilerTestWithParam::TearDown();
}
protected:
MachineOperatorBuilder* machine() const { return machine_; }
private:
MachineOperatorBuilder* machine_;
};
TEST_P(MachineOperatorCommonTest, ChangeInt32ToInt64) {
Operator* op = machine()->ChangeInt32ToInt64();
EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
}
TEST_P(MachineOperatorCommonTest, ChangeUint32ToUint64) {
Operator* op = machine()->ChangeUint32ToUint64();
EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
}
TEST_P(MachineOperatorCommonTest, TruncateInt64ToInt32) {
Operator* op = machine()->TruncateInt64ToInt32();
EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
}
INSTANTIATE_TEST_CASE_P(MachineOperatorTest, MachineOperatorCommonTest,
::testing::Values(kRepWord32, kRepWord64));
} // namespace compiler
} // namespace internal
} // namespace v8
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/compiler-unittests/instruction-selector-unittest.h"
namespace v8 {
namespace internal {
namespace compiler {
// -----------------------------------------------------------------------------
// Conversions.
TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) {
StreamBuilder m(this, kMachInt64, kMachInt32);
m.Return(m.ChangeInt32ToInt64(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
}
TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) {
StreamBuilder m(this, kMachUint64, kMachUint32);
m.Return(m.ChangeUint32ToUint64(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
}
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
StreamBuilder m(this, kMachInt32, kMachInt64);
m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
}
} // namespace compiler
} // namespace internal
} // namespace v8
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