Commit 2f7d6b46 authored by ahaas's avatar ahaas Committed by Commit bot

Implemented the RoundUint64ToFloat32 TurboFan operator for x64, arm64,

and ppc64.

R=titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32031}
parent 7c449a62
......@@ -992,6 +992,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArm64Uint32ToFloat64:
__ Ucvtf(i.OutputDoubleRegister(), i.InputRegister32(0));
break;
case kArm64Uint64ToFloat32:
__ Ucvtf(i.OutputDoubleRegister().S(), i.InputRegister64(0));
break;
case kArm64Uint64ToFloat64:
__ Ucvtf(i.OutputDoubleRegister(), i.InputRegister64(0));
break;
......
......@@ -112,6 +112,7 @@ namespace compiler {
V(Arm64Int64ToFloat32) \
V(Arm64Int64ToFloat64) \
V(Arm64Uint32ToFloat64) \
V(Arm64Uint64ToFloat32) \
V(Arm64Uint64ToFloat64) \
V(Arm64Float64ExtractLowWord32) \
V(Arm64Float64ExtractHighWord32) \
......
......@@ -1326,6 +1326,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
}
void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
VisitRR(this, kArm64Uint64ToFloat32, node);
}
void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
VisitRR(this, kArm64Uint64ToFloat64, node);
}
......
......@@ -830,6 +830,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitRoundInt64ToFloat64(node);
case IrOpcode::kBitcastFloat32ToInt32:
return MarkAsWord32(node), VisitBitcastFloat32ToInt32(node);
case IrOpcode::kRoundUint64ToFloat32:
return MarkAsFloat64(node), VisitRoundUint64ToFloat32(node);
case IrOpcode::kRoundUint64ToFloat64:
return MarkAsFloat64(node), VisitRoundUint64ToFloat64(node);
case IrOpcode::kBitcastFloat64ToInt64:
......@@ -1067,6 +1069,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
}
void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
UNIMPLEMENTED();
}
......
......@@ -138,6 +138,7 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(RoundInt64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
V(RoundInt64ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(RoundUint64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
V(RoundUint64ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
......
......@@ -214,6 +214,7 @@ class MachineOperatorBuilder final : public ZoneObject {
const Operator* TruncateInt64ToInt32();
const Operator* RoundInt64ToFloat32();
const Operator* RoundInt64ToFloat64();
const Operator* RoundUint64ToFloat32();
const Operator* RoundUint64ToFloat64();
// These operators reinterpret the bits of a floating point number as an
......
......@@ -960,6 +960,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Cvt_d_ul(i.OutputDoubleRegister(), i.InputRegister(0));
break;
}
case kMips64CvtSUl: {
__ Cvt_s_ul(i.OutputDoubleRegister(), i.InputRegister(0));
break;
}
case kMips64TruncWD: {
FPURegister scratch = kScratchDoubleReg;
// Other arches use round to zero here, so we follow.
......
......@@ -76,6 +76,7 @@ namespace compiler {
V(Mips64TruncUwD) \
V(Mips64CvtDW) \
V(Mips64CvtSL) \
V(Mips64CvtSUl) \
V(Mips64CvtDL) \
V(Mips64CvtDUw) \
V(Mips64CvtDUl) \
......
......@@ -627,6 +627,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
}
void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
VisitRR(this, kMips64CvtSUl, node);
}
void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
VisitRR(this, kMips64CvtDUl, node);
}
......
......@@ -275,6 +275,7 @@
V(TruncateInt64ToInt32) \
V(RoundInt64ToFloat32) \
V(RoundInt64ToFloat64) \
V(RoundUint64ToFloat32) \
V(RoundUint64ToFloat64) \
V(BitcastFloat32ToInt32) \
V(BitcastFloat64ToInt64) \
......
......@@ -1107,6 +1107,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister());
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
case kPPC_Uint64ToFloat32:
__ ConvertUnsignedInt64ToFloat(i.InputRegister(0),
i.OutputDoubleRegister());
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
case kPPC_Uint64ToDouble:
__ ConvertUnsignedInt64ToDouble(i.InputRegister(0),
i.OutputDoubleRegister());
......
......@@ -80,6 +80,7 @@ namespace compiler {
V(PPC_Int64ToInt32) \
V(PPC_Int64ToFloat32) \
V(PPC_Int64ToDouble) \
V(PPC_Uint64ToFloat32) \
V(PPC_Uint64ToDouble) \
V(PPC_Int32ToDouble) \
V(PPC_Uint32ToDouble) \
......
......@@ -973,6 +973,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
}
void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
VisitRR(this, kPPC_Uint64ToFloat32, node);
}
void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
VisitRR(this, kPPC_Uint64ToDouble, node);
}
......
......@@ -464,6 +464,9 @@ class RawMachineAssembler {
Node* RoundInt64ToFloat64(Node* a) {
return AddNode(machine()->RoundInt64ToFloat64(), a);
}
Node* RoundUint64ToFloat32(Node* a) {
return AddNode(machine()->RoundUint64ToFloat32(), a);
}
Node* RoundUint64ToFloat64(Node* a) {
return AddNode(machine()->RoundUint64ToFloat64(), a);
}
......
......@@ -2120,6 +2120,11 @@ Type* Typer::Visitor::TypeRoundInt64ToFloat64(Node* node) {
}
Type* Typer::Visitor::TypeRoundUint64ToFloat32(Node* node) {
return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat32(), zone());
}
Type* Typer::Visitor::TypeRoundUint64ToFloat64(Node* node) {
return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat64(), zone());
}
......
......@@ -890,6 +890,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kRoundInt64ToFloat32:
case IrOpcode::kRoundInt64ToFloat64:
case IrOpcode::kRoundUint64ToFloat64:
case IrOpcode::kRoundUint64ToFloat32:
case IrOpcode::kTruncateFloat64ToFloat32:
case IrOpcode::kTruncateFloat64ToInt32:
case IrOpcode::kBitcastFloat32ToInt32:
......
......@@ -1041,6 +1041,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Cvtqsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
}
break;
case kSSEUint64ToFloat32:
if (instr->InputAt(0)->IsRegister()) {
__ movq(kScratchRegister, i.InputRegister(0));
} else {
__ movq(kScratchRegister, i.InputOperand(0));
}
__ Cvtqui2ss(i.OutputDoubleRegister(), kScratchRegister,
i.TempRegister(0));
break;
case kSSEUint64ToFloat64:
if (instr->InputAt(0)->IsRegister()) {
__ movq(kScratchRegister, i.InputRegister(0));
......
......@@ -81,6 +81,7 @@ namespace compiler {
V(SSEInt32ToFloat64) \
V(SSEInt64ToFloat32) \
V(SSEInt64ToFloat64) \
V(SSEUint64ToFloat32) \
V(SSEUint64ToFloat64) \
V(SSEUint32ToFloat64) \
V(SSEFloat64ExtractLowWord32) \
......
......@@ -971,6 +971,14 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
}
void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
X64OperandGenerator g(this);
InstructionOperand temps[] = {g.TempRegister()};
Emit(kSSEUint64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0)),
arraysize(temps), temps);
}
void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
X64OperandGenerator g(this);
InstructionOperand temps[] = {g.TempRegister()};
......
......@@ -1548,6 +1548,41 @@ void MacroAssembler::Cvt_d_ul(FPURegister fd, Register rs) {
}
void MacroAssembler::Cvt_s_ul(FPURegister fd, FPURegister fs) {
// Move the data from fs to t8.
dmfc1(t8, fs);
Cvt_s_ul(fd, t8);
}
void MacroAssembler::Cvt_s_ul(FPURegister fd, Register rs) {
// Convert rs to a FP value in fd.
DCHECK(!rs.is(t9));
DCHECK(!rs.is(at));
Label positive, conversion_done;
Branch(&positive, ge, rs, Operand(zero_reg));
// Rs >= 2^31.
andi(t9, rs, 1);
dsrl(rs, rs, 1);
or_(t9, t9, rs);
dmtc1(t9, fd);
cvt_s_l(fd, fd);
Branch(USE_DELAY_SLOT, &conversion_done);
add_s(fd, fd, fd); // In delay slot.
bind(&positive);
// Rs < 2^31, we can do simple conversion.
dmtc1(rs, fd);
cvt_s_l(fd, fd);
bind(&conversion_done);
}
void MacroAssembler::Round_l_d(FPURegister fd, FPURegister fs) {
round_l_d(fd, fs);
}
......
......@@ -825,6 +825,10 @@ class MacroAssembler: public Assembler {
void Cvt_d_ul(FPURegister fd, FPURegister fs);
void Cvt_d_ul(FPURegister fd, Register rs);
// Convert unsigned long to float.
void Cvt_s_ul(FPURegister fd, FPURegister fs);
void Cvt_s_ul(FPURegister fd, Register rs);
// Convert double to unsigned long.
void Trunc_l_ud(FPURegister fd, FPURegister fs, FPURegister scratch);
......
......@@ -2169,6 +2169,12 @@ void Assembler::fcfidu(const DoubleRegister frt, const DoubleRegister frb,
}
void Assembler::fcfidus(const DoubleRegister frt, const DoubleRegister frb,
RCBit rc) {
emit(EXT3 | FCFIDU | frt.code() * B21 | frb.code() * B11 | rc);
}
void Assembler::fcfids(const DoubleRegister frt, const DoubleRegister frb,
RCBit rc) {
emit(EXT3 | FCFID | frt.code() * B21 | frb.code() * B11 | rc);
......
......@@ -1052,6 +1052,8 @@ class Assembler : public AssemblerBase {
RCBit rc = LeaveRC);
void fcfidu(const DoubleRegister frt, const DoubleRegister frb,
RCBit rc = LeaveRC);
void fcfidus(const DoubleRegister frt, const DoubleRegister frb,
RCBit rc = LeaveRC);
void fcfids(const DoubleRegister frt, const DoubleRegister frb,
RCBit rc = LeaveRC);
void fctid(const DoubleRegister frt, const DoubleRegister frb,
......
......@@ -889,6 +889,10 @@ void Decoder::DecodeExt3(Instruction* instr) {
Format(instr, "fcfids'. 'Dt, 'Db");
break;
}
case FCFIDU: {
Format(instr, "fcfidus'.'Dt, 'Db");
break;
}
default: {
Unknown(instr); // not used by V8
}
......
......@@ -671,6 +671,13 @@ void MacroAssembler::ConvertInt64ToDouble(Register src,
}
void MacroAssembler::ConvertUnsignedInt64ToFloat(Register src,
DoubleRegister double_dst) {
MovInt64ToDouble(double_dst, src);
fcfidus(double_dst, double_dst);
}
void MacroAssembler::ConvertUnsignedInt64ToDouble(Register src,
DoubleRegister double_dst) {
MovInt64ToDouble(double_dst, src);
......
......@@ -387,9 +387,10 @@ class MacroAssembler : public Assembler {
const Register int_scratch);
#if V8_TARGET_ARCH_PPC64
void ConvertInt64ToFloat(Register src, DoubleRegister double_dst);
void ConvertInt64ToDouble(Register src, DoubleRegister double_dst);
void ConvertUnsignedInt64ToFloat(Register src, DoubleRegister double_dst);
void ConvertUnsignedInt64ToDouble(Register src, DoubleRegister double_dst);
void ConvertInt64ToFloat(Register src, DoubleRegister double_dst);
#endif
// Converts the double_input to an integer. Note that, upon return,
......
......@@ -2707,6 +2707,15 @@ void Simulator::ExecuteExt3(Instruction* instr) {
set_d_register_from_double(frt, frt_val);
return;
}
case FCFIDU: {
// fcfidus
int frt = instr->RTValue();
int frb = instr->RBValue();
uint64_t frb_val = get_d_register(frb);
double frt_val = static_cast<float>(frb_val);
set_d_register_from_double(frt, frt_val);
return;
}
}
UNIMPLEMENTED(); // Not used by V8.
}
......
......@@ -899,6 +899,25 @@ void MacroAssembler::Cvtqsi2sd(XMMRegister dst, const Operand& src) {
}
void MacroAssembler::Cvtqui2ss(XMMRegister dst, Register src, Register tmp) {
Label msb_set_src;
Label jmp_return;
testq(src, src);
j(sign, &msb_set_src, Label::kNear);
Cvtqsi2ss(dst, src);
jmp(&jmp_return, Label::kNear);
bind(&msb_set_src);
movq(tmp, src);
shrq(src, Immediate(1));
// Recover the least significant bit to avoid rounding errors.
andq(tmp, Immediate(1));
orq(src, tmp);
Cvtqsi2ss(dst, src);
addss(dst, dst);
bind(&jmp_return);
}
void MacroAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) {
Label msb_set_src;
Label jmp_return;
......@@ -909,7 +928,6 @@ void MacroAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) {
bind(&msb_set_src);
movq(tmp, src);
shrq(src, Immediate(1));
// Recover the least significant bit to avoid rounding errors.
andq(tmp, Immediate(1));
orq(src, tmp);
Cvtqsi2sd(dst, src);
......
......@@ -823,6 +823,8 @@ class MacroAssembler: public Assembler {
void Cvtqsi2sd(XMMRegister dst, Register src);
void Cvtqsi2sd(XMMRegister dst, const Operand& src);
void Cvtqui2ss(XMMRegister dst, Register src, Register tmp);
void Cvtqui2sd(XMMRegister dst, Register src, Register tmp);
void Cvtsd2si(Register dst, XMMRegister src);
......
......@@ -5535,6 +5535,96 @@ TEST(RunRoundUint64ToFloat64) {
}
TEST(RunRoundUint64ToFloat32) {
struct {
uint64_t input;
uint32_t expected;
} values[] = {{0x0, 0x0},
{0x1, 0x3f800000},
{0xffffffff, 0x4f800000},
{0x1b09788b, 0x4dd84bc4},
{0x4c5fce8, 0x4c98bf9d},
{0xcc0de5bf, 0x4f4c0de6},
{0x2, 0x40000000},
{0x3, 0x40400000},
{0x4, 0x40800000},
{0x5, 0x40a00000},
{0x8, 0x41000000},
{0x9, 0x41100000},
{0xffffffffffffffff, 0x5f800000},
{0xfffffffffffffffe, 0x5f800000},
{0xfffffffffffffffd, 0x5f800000},
{0x0, 0x0},
{0x100000000, 0x4f800000},
{0xffffffff00000000, 0x5f800000},
{0x1b09788b00000000, 0x5dd84bc4},
{0x4c5fce800000000, 0x5c98bf9d},
{0xcc0de5bf00000000, 0x5f4c0de6},
{0x200000000, 0x50000000},
{0x300000000, 0x50400000},
{0x400000000, 0x50800000},
{0x500000000, 0x50a00000},
{0x800000000, 0x51000000},
{0x900000000, 0x51100000},
{0x273a798e187937a3, 0x5e1ce9e6},
{0xece3af835495a16b, 0x5f6ce3b0},
{0xb668ecc11223344, 0x5d3668ed},
{0x9e, 0x431e0000},
{0x43, 0x42860000},
{0xaf73, 0x472f7300},
{0x116b, 0x458b5800},
{0x658ecc, 0x4acb1d98},
{0x2b3b4c, 0x4a2ced30},
{0x88776655, 0x4f087766},
{0x70000000, 0x4ee00000},
{0x7200000, 0x4ce40000},
{0x7fffffff, 0x4f000000},
{0x56123761, 0x4eac246f},
{0x7fffff00, 0x4efffffe},
{0x761c4761eeeeeeee, 0x5eec388f},
{0x80000000eeeeeeee, 0x5f000000},
{0x88888888dddddddd, 0x5f088889},
{0xa0000000dddddddd, 0x5f200000},
{0xddddddddaaaaaaaa, 0x5f5dddde},
{0xe0000000aaaaaaaa, 0x5f600000},
{0xeeeeeeeeeeeeeeee, 0x5f6eeeef},
{0xfffffffdeeeeeeee, 0x5f800000},
{0xf0000000dddddddd, 0x5f700000},
{0x7fffffdddddddd, 0x5b000000},
{0x3fffffaaaaaaaa, 0x5a7fffff},
{0x1fffffaaaaaaaa, 0x59fffffd},
{0xfffff, 0x497ffff0},
{0x7ffff, 0x48ffffe0},
{0x3ffff, 0x487fffc0},
{0x1ffff, 0x47ffff80},
{0xffff, 0x477fff00},
{0x7fff, 0x46fffe00},
{0x3fff, 0x467ffc00},
{0x1fff, 0x45fff800},
{0xfff, 0x457ff000},
{0x7ff, 0x44ffe000},
{0x3ff, 0x447fc000},
{0x1ff, 0x43ff8000},
{0x3fffffffffff, 0x56800000},
{0x1fffffffffff, 0x56000000},
{0xfffffffffff, 0x55800000},
{0x7ffffffffff, 0x55000000},
{0x3ffffffffff, 0x54800000},
{0x1ffffffffff, 0x54000000},
{0x8000008000000000, 0x5f000000},
{0x8000008000000001, 0x5f000001},
{0x8000000000000400, 0x5f000000},
{0x8000000000000401, 0x5f000000}};
BufferedRawMachineAssemblerTester<float> m(kMachUint64);
m.Return(m.RoundUint64ToFloat32(m.Parameter(0)));
for (int i = 0; i < arraysize(values); i++) {
CHECK_EQ(bit_cast<float>(values[i].expected), m.Call(values[i].input));
}
}
#endif
......
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