[turbofan] Add the TruncateFloat32ToInt32 operator to turbofan.
The new operator converts a float32 input to int32 through truncation. I provide implementations of the new operator for x64, ia32, arm, arm64, mips, mips64, and x87. @v8-ppc-ports, can you please take care of the ppc implementation? R=titzer@chromium.org, v8-arm-ports@googlegroups.com, v8-mips-ports@googlegroups.com, weiliang.lin@intel.com Review URL: https://codereview.chromium.org/1583323004 Cr-Commit-Position: refs/heads/master@{#33346}
This commit is contained in:
parent
dc6a593918
commit
fc53eed14b
@ -2923,6 +2923,12 @@ void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Assembler::vcvt_s32_f32(const SwVfpRegister dst, const SwVfpRegister src,
|
||||||
|
VFPConversionMode mode, const Condition cond) {
|
||||||
|
emit(EncodeVCVT(S32, dst.code(), F32, src.code(), mode, cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
|
void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
|
||||||
const DwVfpRegister src,
|
const DwVfpRegister src,
|
||||||
VFPConversionMode mode,
|
VFPConversionMode mode,
|
||||||
|
@ -1125,6 +1125,10 @@ class Assembler : public AssemblerBase {
|
|||||||
const SwVfpRegister src,
|
const SwVfpRegister src,
|
||||||
VFPConversionMode mode = kDefaultRoundToZero,
|
VFPConversionMode mode = kDefaultRoundToZero,
|
||||||
const Condition cond = al);
|
const Condition cond = al);
|
||||||
|
void vcvt_s32_f32(const SwVfpRegister dst,
|
||||||
|
const SwVfpRegister src,
|
||||||
|
VFPConversionMode mode = kDefaultRoundToZero,
|
||||||
|
const Condition cond = al);
|
||||||
void vcvt_s32_f64(const SwVfpRegister dst,
|
void vcvt_s32_f64(const SwVfpRegister dst,
|
||||||
const DwVfpRegister src,
|
const DwVfpRegister src,
|
||||||
VFPConversionMode mode = kDefaultRoundToZero,
|
VFPConversionMode mode = kDefaultRoundToZero,
|
||||||
|
@ -845,6 +845,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kArmVcvtS32F32: {
|
||||||
|
SwVfpRegister scratch = kScratchDoubleReg.low();
|
||||||
|
__ vcvt_s32_f32(scratch, i.InputFloat32Register(0));
|
||||||
|
__ vmov(i.OutputRegister(), scratch);
|
||||||
|
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kArmVcvtS32F64: {
|
case kArmVcvtS32F64: {
|
||||||
SwVfpRegister scratch = kScratchDoubleReg.low();
|
SwVfpRegister scratch = kScratchDoubleReg.low();
|
||||||
__ vcvt_s32_f64(scratch, i.InputFloat64Register(0));
|
__ vcvt_s32_f64(scratch, i.InputFloat64Register(0));
|
||||||
|
@ -78,6 +78,7 @@ namespace compiler {
|
|||||||
V(ArmVcvtF64F32) \
|
V(ArmVcvtF64F32) \
|
||||||
V(ArmVcvtF64S32) \
|
V(ArmVcvtF64S32) \
|
||||||
V(ArmVcvtF64U32) \
|
V(ArmVcvtF64U32) \
|
||||||
|
V(ArmVcvtS32F32) \
|
||||||
V(ArmVcvtS32F64) \
|
V(ArmVcvtS32F64) \
|
||||||
V(ArmVcvtU32F64) \
|
V(ArmVcvtU32F64) \
|
||||||
V(ArmVmovLowU32F64) \
|
V(ArmVmovLowU32F64) \
|
||||||
|
@ -80,6 +80,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
|||||||
case kArmVcvtF64F32:
|
case kArmVcvtF64F32:
|
||||||
case kArmVcvtF64S32:
|
case kArmVcvtF64S32:
|
||||||
case kArmVcvtF64U32:
|
case kArmVcvtF64U32:
|
||||||
|
case kArmVcvtS32F32:
|
||||||
case kArmVcvtS32F64:
|
case kArmVcvtS32F64:
|
||||||
case kArmVcvtU32F64:
|
case kArmVcvtU32F64:
|
||||||
case kArmVmovLowU32F64:
|
case kArmVmovLowU32F64:
|
||||||
|
@ -931,6 +931,11 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
||||||
|
VisitRR(this, kArmVcvtS32F32, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
||||||
VisitRR(this, kArmVcvtS32F64, node);
|
VisitRR(this, kArmVcvtS32F64, node);
|
||||||
}
|
}
|
||||||
|
@ -1042,6 +1042,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
case kArm64Float64ToFloat32:
|
case kArm64Float64ToFloat32:
|
||||||
__ Fcvt(i.OutputDoubleRegister().S(), i.InputDoubleRegister(0));
|
__ Fcvt(i.OutputDoubleRegister().S(), i.InputDoubleRegister(0));
|
||||||
break;
|
break;
|
||||||
|
case kArm64Float32ToInt32:
|
||||||
|
__ Fcvtzs(i.OutputRegister32(), i.InputFloat32Register(0));
|
||||||
|
break;
|
||||||
case kArm64Float64ToInt32:
|
case kArm64Float64ToInt32:
|
||||||
__ Fcvtzs(i.OutputRegister32(), i.InputDoubleRegister(0));
|
__ Fcvtzs(i.OutputRegister32(), i.InputDoubleRegister(0));
|
||||||
break;
|
break;
|
||||||
|
@ -110,6 +110,7 @@ namespace compiler {
|
|||||||
V(Arm64Float64RoundTiesEven) \
|
V(Arm64Float64RoundTiesEven) \
|
||||||
V(Arm64Float32ToFloat64) \
|
V(Arm64Float32ToFloat64) \
|
||||||
V(Arm64Float64ToFloat32) \
|
V(Arm64Float64ToFloat32) \
|
||||||
|
V(Arm64Float32ToInt32) \
|
||||||
V(Arm64Float64ToInt32) \
|
V(Arm64Float64ToInt32) \
|
||||||
V(Arm64Float64ToUint32) \
|
V(Arm64Float64ToUint32) \
|
||||||
V(Arm64Float32ToInt64) \
|
V(Arm64Float32ToInt64) \
|
||||||
|
@ -106,6 +106,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
|||||||
case kArm64Float32RoundUp:
|
case kArm64Float32RoundUp:
|
||||||
case kArm64Float32ToFloat64:
|
case kArm64Float32ToFloat64:
|
||||||
case kArm64Float64ToFloat32:
|
case kArm64Float64ToFloat32:
|
||||||
|
case kArm64Float32ToInt32:
|
||||||
case kArm64Float64ToInt32:
|
case kArm64Float64ToInt32:
|
||||||
case kArm64Float64ToUint32:
|
case kArm64Float64ToUint32:
|
||||||
case kArm64Float32ToInt64:
|
case kArm64Float32ToInt64:
|
||||||
|
@ -1229,6 +1229,11 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
||||||
|
VisitRR(this, kArm64Float32ToInt32, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
||||||
VisitRR(this, kArm64Float64ToInt32, node);
|
VisitRR(this, kArm64Float64ToInt32, node);
|
||||||
}
|
}
|
||||||
|
@ -739,6 +739,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
case kSSEFloat64ToFloat32:
|
case kSSEFloat64ToFloat32:
|
||||||
__ cvtsd2ss(i.OutputDoubleRegister(), i.InputOperand(0));
|
__ cvtsd2ss(i.OutputDoubleRegister(), i.InputOperand(0));
|
||||||
break;
|
break;
|
||||||
|
case kSSEFloat32ToInt32:
|
||||||
|
__ cvttss2si(i.OutputRegister(), i.InputOperand(0));
|
||||||
|
break;
|
||||||
case kSSEFloat64ToInt32:
|
case kSSEFloat64ToInt32:
|
||||||
__ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
|
__ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
|
||||||
break;
|
break;
|
||||||
|
@ -58,6 +58,7 @@ namespace compiler {
|
|||||||
V(SSEFloat64Round) \
|
V(SSEFloat64Round) \
|
||||||
V(SSEFloat32ToFloat64) \
|
V(SSEFloat32ToFloat64) \
|
||||||
V(SSEFloat64ToFloat32) \
|
V(SSEFloat64ToFloat32) \
|
||||||
|
V(SSEFloat32ToInt32) \
|
||||||
V(SSEFloat64ToInt32) \
|
V(SSEFloat64ToInt32) \
|
||||||
V(SSEFloat64ToUint32) \
|
V(SSEFloat64ToUint32) \
|
||||||
V(SSEInt32ToFloat64) \
|
V(SSEInt32ToFloat64) \
|
||||||
|
@ -61,6 +61,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
|||||||
case kSSEFloat64Round:
|
case kSSEFloat64Round:
|
||||||
case kSSEFloat32ToFloat64:
|
case kSSEFloat32ToFloat64:
|
||||||
case kSSEFloat64ToFloat32:
|
case kSSEFloat64ToFloat32:
|
||||||
|
case kSSEFloat32ToInt32:
|
||||||
case kSSEFloat64ToInt32:
|
case kSSEFloat64ToInt32:
|
||||||
case kSSEFloat64ToUint32:
|
case kSSEFloat64ToUint32:
|
||||||
case kSSEInt32ToFloat64:
|
case kSSEInt32ToFloat64:
|
||||||
|
@ -705,6 +705,11 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
||||||
|
VisitRO(this, node, kSSEFloat32ToInt32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
||||||
VisitRO(this, node, kSSEFloat64ToInt32);
|
VisitRO(this, node, kSSEFloat64ToInt32);
|
||||||
}
|
}
|
||||||
|
@ -956,6 +956,8 @@ void InstructionSelector::VisitNode(Node* node) {
|
|||||||
return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
|
return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
|
||||||
case IrOpcode::kChangeFloat64ToUint32:
|
case IrOpcode::kChangeFloat64ToUint32:
|
||||||
return MarkAsWord32(node), VisitChangeFloat64ToUint32(node);
|
return MarkAsWord32(node), VisitChangeFloat64ToUint32(node);
|
||||||
|
case IrOpcode::kTruncateFloat32ToInt32:
|
||||||
|
return MarkAsWord32(node), VisitTruncateFloat32ToInt32(node);
|
||||||
case IrOpcode::kTryTruncateFloat32ToInt64:
|
case IrOpcode::kTryTruncateFloat32ToInt64:
|
||||||
return MarkAsWord64(node), VisitTryTruncateFloat32ToInt64(node);
|
return MarkAsWord64(node), VisitTryTruncateFloat32ToInt64(node);
|
||||||
case IrOpcode::kTryTruncateFloat64ToInt64:
|
case IrOpcode::kTryTruncateFloat64ToInt64:
|
||||||
|
@ -144,6 +144,7 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
|
|||||||
V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
||||||
V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \
|
V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \
|
||||||
V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 0, 1) \
|
V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 0, 1) \
|
||||||
|
V(TruncateFloat32ToInt32, Operator::kNoProperties, 1, 0, 1) \
|
||||||
V(TryTruncateFloat32ToInt64, Operator::kNoProperties, 1, 0, 2) \
|
V(TryTruncateFloat32ToInt64, Operator::kNoProperties, 1, 0, 2) \
|
||||||
V(TryTruncateFloat64ToInt64, Operator::kNoProperties, 1, 0, 2) \
|
V(TryTruncateFloat64ToInt64, Operator::kNoProperties, 1, 0, 2) \
|
||||||
V(TryTruncateFloat32ToUint64, Operator::kNoProperties, 1, 0, 2) \
|
V(TryTruncateFloat32ToUint64, Operator::kNoProperties, 1, 0, 2) \
|
||||||
|
@ -213,6 +213,7 @@ class MachineOperatorBuilder final : public ZoneObject {
|
|||||||
const Operator* ChangeFloat32ToFloat64();
|
const Operator* ChangeFloat32ToFloat64();
|
||||||
const Operator* ChangeFloat64ToInt32(); // narrowing
|
const Operator* ChangeFloat64ToInt32(); // narrowing
|
||||||
const Operator* ChangeFloat64ToUint32(); // narrowing
|
const Operator* ChangeFloat64ToUint32(); // narrowing
|
||||||
|
const Operator* TruncateFloat32ToInt32();
|
||||||
const Operator* TryTruncateFloat32ToInt64();
|
const Operator* TryTruncateFloat32ToInt64();
|
||||||
const Operator* TryTruncateFloat64ToInt64();
|
const Operator* TryTruncateFloat64ToInt64();
|
||||||
const Operator* TryTruncateFloat32ToUint64();
|
const Operator* TryTruncateFloat32ToUint64();
|
||||||
|
@ -513,6 +513,11 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
||||||
|
VisitRR(this, kMipsTruncWS, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
||||||
MipsOperandGenerator g(this);
|
MipsOperandGenerator g(this);
|
||||||
Node* value = node->InputAt(0);
|
Node* value = node->InputAt(0);
|
||||||
|
@ -812,6 +812,11 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
||||||
|
VisitRR(this, kMips64TruncWS, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
||||||
Mips64OperandGenerator g(this);
|
Mips64OperandGenerator g(this);
|
||||||
Node* value = node->InputAt(0);
|
Node* value = node->InputAt(0);
|
||||||
|
@ -270,6 +270,7 @@
|
|||||||
V(ChangeFloat32ToFloat64) \
|
V(ChangeFloat32ToFloat64) \
|
||||||
V(ChangeFloat64ToInt32) \
|
V(ChangeFloat64ToInt32) \
|
||||||
V(ChangeFloat64ToUint32) \
|
V(ChangeFloat64ToUint32) \
|
||||||
|
V(TruncateFloat32ToInt32) \
|
||||||
V(TryTruncateFloat32ToInt64) \
|
V(TryTruncateFloat32ToInt64) \
|
||||||
V(TryTruncateFloat64ToInt64) \
|
V(TryTruncateFloat64ToInt64) \
|
||||||
V(TryTruncateFloat32ToUint64) \
|
V(TryTruncateFloat32ToUint64) \
|
||||||
|
@ -432,10 +432,8 @@ class RawMachineAssembler {
|
|||||||
Node* ChangeFloat64ToUint32(Node* a) {
|
Node* ChangeFloat64ToUint32(Node* a) {
|
||||||
return AddNode(machine()->ChangeFloat64ToUint32(), a);
|
return AddNode(machine()->ChangeFloat64ToUint32(), a);
|
||||||
}
|
}
|
||||||
Node* TruncateFloat32ToInt64(Node* a) {
|
Node* TruncateFloat32ToInt32(Node* a) {
|
||||||
// TODO(ahaas): Remove this function as soon as it is not used anymore in
|
return AddNode(machine()->TruncateFloat32ToInt32(), a);
|
||||||
// WebAssembly.
|
|
||||||
return AddNode(machine()->TryTruncateFloat32ToInt64(), a);
|
|
||||||
}
|
}
|
||||||
Node* TryTruncateFloat32ToInt64(Node* a) {
|
Node* TryTruncateFloat32ToInt64(Node* a) {
|
||||||
return AddNode(machine()->TryTruncateFloat32ToInt64(), a);
|
return AddNode(machine()->TryTruncateFloat32ToInt64(), a);
|
||||||
@ -448,11 +446,6 @@ class RawMachineAssembler {
|
|||||||
Node* TryTruncateFloat64ToInt64(Node* a) {
|
Node* TryTruncateFloat64ToInt64(Node* a) {
|
||||||
return AddNode(machine()->TryTruncateFloat64ToInt64(), a);
|
return AddNode(machine()->TryTruncateFloat64ToInt64(), a);
|
||||||
}
|
}
|
||||||
Node* TruncateFloat32ToUint64(Node* a) {
|
|
||||||
// TODO(ahaas): Remove this function as soon as it is not used anymore in
|
|
||||||
// WebAssembly.
|
|
||||||
return AddNode(machine()->TryTruncateFloat32ToUint64(), a);
|
|
||||||
}
|
|
||||||
Node* TryTruncateFloat32ToUint64(Node* a) {
|
Node* TryTruncateFloat32ToUint64(Node* a) {
|
||||||
return AddNode(machine()->TryTruncateFloat32ToUint64(), a);
|
return AddNode(machine()->TryTruncateFloat32ToUint64(), a);
|
||||||
}
|
}
|
||||||
|
@ -2145,6 +2145,11 @@ Type* Typer::Visitor::TypeChangeFloat64ToUint32(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Type* Typer::Visitor::TypeTruncateFloat32ToInt32(Node* node) {
|
||||||
|
return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Type* Typer::Visitor::TypeTryTruncateFloat32ToInt64(Node* node) {
|
Type* Typer::Visitor::TypeTryTruncateFloat32ToInt64(Node* node) {
|
||||||
return Type::Internal();
|
return Type::Internal();
|
||||||
}
|
}
|
||||||
|
@ -924,6 +924,7 @@ void Verifier::Visitor::Check(Node* node) {
|
|||||||
case IrOpcode::kChangeFloat32ToFloat64:
|
case IrOpcode::kChangeFloat32ToFloat64:
|
||||||
case IrOpcode::kChangeFloat64ToInt32:
|
case IrOpcode::kChangeFloat64ToInt32:
|
||||||
case IrOpcode::kChangeFloat64ToUint32:
|
case IrOpcode::kChangeFloat64ToUint32:
|
||||||
|
case IrOpcode::kTruncateFloat32ToInt32:
|
||||||
case IrOpcode::kTryTruncateFloat32ToInt64:
|
case IrOpcode::kTryTruncateFloat32ToInt64:
|
||||||
case IrOpcode::kTryTruncateFloat64ToInt64:
|
case IrOpcode::kTryTruncateFloat64ToInt64:
|
||||||
case IrOpcode::kTryTruncateFloat32ToUint64:
|
case IrOpcode::kTryTruncateFloat32ToUint64:
|
||||||
|
@ -1121,14 +1121,12 @@ Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input) {
|
|||||||
MachineOperatorBuilder* m = jsgraph()->machine();
|
MachineOperatorBuilder* m = jsgraph()->machine();
|
||||||
// Truncation of the input value is needed for the overflow check later.
|
// Truncation of the input value is needed for the overflow check later.
|
||||||
Node* trunc = Unop(wasm::kExprF32Trunc, input);
|
Node* trunc = Unop(wasm::kExprF32Trunc, input);
|
||||||
// TODO(titzer): two conversions
|
Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc);
|
||||||
Node* f64_trunc = graph()->NewNode(m->ChangeFloat32ToFloat64(), trunc);
|
|
||||||
Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), f64_trunc);
|
|
||||||
|
|
||||||
// Convert the result back to f64. If we end up at a different value than the
|
// Convert the result back to f64. If we end up at a different value than the
|
||||||
// truncated input value, then there has been an overflow and we trap.
|
// truncated input value, then there has been an overflow and we trap.
|
||||||
Node* check = Unop(wasm::kExprF64SConvertI32, result);
|
Node* check = Unop(wasm::kExprF32SConvertI32, result);
|
||||||
Node* overflow = Binop(wasm::kExprF64Ne, f64_trunc, check);
|
Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
|
||||||
trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow);
|
trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -947,6 +947,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
__ Roundss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
|
__ Roundss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kSSEFloat32ToInt32:
|
||||||
|
if (instr->InputAt(0)->IsDoubleRegister()) {
|
||||||
|
__ Cvttss2si(i.OutputRegister(), i.InputDoubleRegister(0));
|
||||||
|
} else {
|
||||||
|
__ Cvttss2si(i.OutputRegister(), i.InputOperand(0));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case kSSEFloat64Cmp:
|
case kSSEFloat64Cmp:
|
||||||
ASSEMBLE_SSE_BINOP(Ucomisd);
|
ASSEMBLE_SSE_BINOP(Ucomisd);
|
||||||
break;
|
break;
|
||||||
|
@ -63,6 +63,7 @@ namespace compiler {
|
|||||||
V(SSEFloat32Max) \
|
V(SSEFloat32Max) \
|
||||||
V(SSEFloat32Min) \
|
V(SSEFloat32Min) \
|
||||||
V(SSEFloat32ToFloat64) \
|
V(SSEFloat32ToFloat64) \
|
||||||
|
V(SSEFloat32ToInt32) \
|
||||||
V(SSEFloat32Round) \
|
V(SSEFloat32Round) \
|
||||||
V(SSEFloat64Cmp) \
|
V(SSEFloat64Cmp) \
|
||||||
V(SSEFloat64Add) \
|
V(SSEFloat64Add) \
|
||||||
|
@ -79,6 +79,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
|||||||
case kSSEFloat64Max:
|
case kSSEFloat64Max:
|
||||||
case kSSEFloat64Min:
|
case kSSEFloat64Min:
|
||||||
case kSSEFloat64ToFloat32:
|
case kSSEFloat64ToFloat32:
|
||||||
|
case kSSEFloat32ToInt32:
|
||||||
case kSSEFloat64ToInt32:
|
case kSSEFloat64ToInt32:
|
||||||
case kSSEFloat64ToUint32:
|
case kSSEFloat64ToUint32:
|
||||||
case kSSEFloat64ToInt64:
|
case kSSEFloat64ToInt64:
|
||||||
|
@ -857,6 +857,12 @@ void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
||||||
|
X64OperandGenerator g(this);
|
||||||
|
Emit(kSSEFloat32ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
|
void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
|
||||||
X64OperandGenerator g(this);
|
X64OperandGenerator g(this);
|
||||||
InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))};
|
InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))};
|
||||||
|
@ -1005,6 +1005,16 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
__ LoadUint32NoSSE2(i.InputRegister(0));
|
__ LoadUint32NoSSE2(i.InputRegister(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kX87Float32ToInt32: {
|
||||||
|
if (!instr->InputAt(0)->IsDoubleRegister()) {
|
||||||
|
__ fld_s(i.InputOperand(0));
|
||||||
|
}
|
||||||
|
__ TruncateX87TOSToI(i.OutputRegister(0));
|
||||||
|
if (!instr->InputAt(0)->IsDoubleRegister()) {
|
||||||
|
__ fstp(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kX87Float64ToInt32: {
|
case kX87Float64ToInt32: {
|
||||||
if (!instr->InputAt(0)->IsDoubleRegister()) {
|
if (!instr->InputAt(0)->IsDoubleRegister()) {
|
||||||
__ fld_d(i.InputOperand(0));
|
__ fld_d(i.InputOperand(0));
|
||||||
|
@ -57,6 +57,7 @@ namespace compiler {
|
|||||||
V(X87Float32ToFloat64) \
|
V(X87Float32ToFloat64) \
|
||||||
V(X87Uint32ToFloat64) \
|
V(X87Uint32ToFloat64) \
|
||||||
V(X87Float64ToInt32) \
|
V(X87Float64ToInt32) \
|
||||||
|
V(X87Float32ToInt32) \
|
||||||
V(X87Float64ToFloat32) \
|
V(X87Float64ToFloat32) \
|
||||||
V(X87Float64ToUint32) \
|
V(X87Float64ToUint32) \
|
||||||
V(X87Float64ExtractHighWord32) \
|
V(X87Float64ExtractHighWord32) \
|
||||||
|
@ -669,6 +669,12 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
||||||
|
X87OperandGenerator g(this);
|
||||||
|
Emit(kX87Float32ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
||||||
X87OperandGenerator g(this);
|
X87OperandGenerator g(this);
|
||||||
Emit(kX87Float64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
|
Emit(kX87Float64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
|
||||||
|
@ -1384,6 +1384,14 @@ class Assembler : public AssemblerBase {
|
|||||||
void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
|
void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
|
||||||
vsd(0x2a, dst, src1, src2, kF2, k0F, kW1);
|
vsd(0x2a, dst, src1, src2, kF2, k0F, kW1);
|
||||||
}
|
}
|
||||||
|
void vcvttss2si(Register dst, XMMRegister src) {
|
||||||
|
XMMRegister idst = {dst.code()};
|
||||||
|
vsd(0x2c, idst, xmm0, src, kF3, k0F, kW0);
|
||||||
|
}
|
||||||
|
void vcvttss2si(Register dst, const Operand& src) {
|
||||||
|
XMMRegister idst = {dst.code()};
|
||||||
|
vsd(0x2c, idst, xmm0, src, kF3, k0F, kW0);
|
||||||
|
}
|
||||||
void vcvttsd2si(Register dst, XMMRegister src) {
|
void vcvttsd2si(Register dst, XMMRegister src) {
|
||||||
XMMRegister idst = {dst.code()};
|
XMMRegister idst = {dst.code()};
|
||||||
vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
|
vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
|
||||||
|
@ -918,6 +918,26 @@ void MacroAssembler::Cvtsd2si(Register dst, XMMRegister src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::Cvttss2si(Register dst, XMMRegister src) {
|
||||||
|
if (CpuFeatures::IsSupported(AVX)) {
|
||||||
|
CpuFeatureScope scope(this, AVX);
|
||||||
|
vcvttss2si(dst, src);
|
||||||
|
} else {
|
||||||
|
cvttss2si(dst, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::Cvttss2si(Register dst, const Operand& src) {
|
||||||
|
if (CpuFeatures::IsSupported(AVX)) {
|
||||||
|
CpuFeatureScope scope(this, AVX);
|
||||||
|
vcvttss2si(dst, src);
|
||||||
|
} else {
|
||||||
|
cvttss2si(dst, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::Cvttsd2si(Register dst, XMMRegister src) {
|
void MacroAssembler::Cvttsd2si(Register dst, XMMRegister src) {
|
||||||
if (CpuFeatures::IsSupported(AVX)) {
|
if (CpuFeatures::IsSupported(AVX)) {
|
||||||
CpuFeatureScope scope(this, AVX);
|
CpuFeatureScope scope(this, AVX);
|
||||||
|
@ -823,6 +823,8 @@ class MacroAssembler: public Assembler {
|
|||||||
|
|
||||||
void Cvtsd2si(Register dst, XMMRegister src);
|
void Cvtsd2si(Register dst, XMMRegister src);
|
||||||
|
|
||||||
|
void Cvttss2si(Register dst, XMMRegister src);
|
||||||
|
void Cvttss2si(Register dst, const Operand& src);
|
||||||
void Cvttsd2si(Register dst, XMMRegister src);
|
void Cvttsd2si(Register dst, XMMRegister src);
|
||||||
void Cvttsd2si(Register dst, const Operand& src);
|
void Cvttsd2si(Register dst, const Operand& src);
|
||||||
void Cvttss2siq(Register dst, XMMRegister src);
|
void Cvttss2siq(Register dst, XMMRegister src);
|
||||||
|
@ -92,7 +92,7 @@ class BufferedRawMachineAssemblerTester
|
|||||||
// parameters from memory. Thereby it is possible to pass 64 bit parameters
|
// parameters from memory. Thereby it is possible to pass 64 bit parameters
|
||||||
// to the IR graph.
|
// to the IR graph.
|
||||||
Node* Parameter(size_t index) {
|
Node* Parameter(size_t index) {
|
||||||
CHECK(index >= 0 && index < 4);
|
CHECK(index < 4);
|
||||||
return parameter_nodes_[index];
|
return parameter_nodes_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4124,6 +4124,18 @@ TEST(RunChangeUint32ToFloat64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(RunTruncateFloat32ToInt32) {
|
||||||
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Float32());
|
||||||
|
m.Return(m.TruncateFloat32ToInt32(m.Parameter(0)));
|
||||||
|
FOR_FLOAT32_INPUTS(i) {
|
||||||
|
if (*i <= static_cast<float>(std::numeric_limits<int32_t>::max()) &&
|
||||||
|
*i >= static_cast<float>(std::numeric_limits<int32_t>::min())) {
|
||||||
|
CheckFloatEq(static_cast<int32_t>(*i), m.Call(*i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(RunChangeFloat64ToInt32_A) {
|
TEST(RunChangeFloat64ToInt32_A) {
|
||||||
BufferedRawMachineAssemblerTester<int32_t> m;
|
BufferedRawMachineAssemblerTester<int32_t> m;
|
||||||
double magic = 11.1;
|
double magic = 11.1;
|
||||||
|
Loading…
Reference in New Issue
Block a user