Commit 7bc8fac4 authored by dusan.m.milosavljevic's avatar dusan.m.milosavljevic Committed by Commit bot

MIPS: [turbofan] Optimize Float32 to Int32 rep. changes with Float32 round ops.

TEST=unittests/InstructionSelectorTest.CombineChangeFloat32ToInt32WithRoundFloat32,
     ChangeFloat64ToInt32OfChangeFloat32ToFloat64, TruncateFloat64ToFloat32OfChangeInt32ToFloat64
BUG=

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

Cr-Commit-Position: refs/heads/master@{#32969}
parent 53a0cc84
......@@ -944,6 +944,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ cvt_d_w(i.OutputDoubleRegister(), scratch);
break;
}
case kMipsCvtSW: {
FPURegister scratch = kScratchDoubleReg;
__ mtc1(i.InputRegister(0), scratch);
__ cvt_s_w(i.OutputDoubleRegister(), scratch);
break;
}
case kMipsCvtDUw: {
FPURegister scratch = kScratchDoubleReg;
__ Cvt_d_uw(i.OutputDoubleRegister(), i.InputRegister(0), scratch);
......@@ -974,6 +980,30 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsFloorWS: {
FPURegister scratch = kScratchDoubleReg;
__ floor_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsCeilWS: {
FPURegister scratch = kScratchDoubleReg;
__ ceil_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsRoundWS: {
FPURegister scratch = kScratchDoubleReg;
__ round_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsTruncWS: {
FPURegister scratch = kScratchDoubleReg;
__ trunc_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsTruncUwD: {
FPURegister scratch = kScratchDoubleReg;
// TODO(plind): Fix wrong param order of Trunc_uw_d() macro-asm function.
......
......@@ -71,9 +71,14 @@ namespace compiler {
V(MipsRoundWD) \
V(MipsFloorWD) \
V(MipsCeilWD) \
V(MipsTruncWS) \
V(MipsRoundWS) \
V(MipsFloorWS) \
V(MipsCeilWS) \
V(MipsTruncUwD) \
V(MipsCvtDW) \
V(MipsCvtDUw) \
V(MipsCvtSW) \
V(MipsLb) \
V(MipsLbu) \
V(MipsSb) \
......
......@@ -535,10 +535,42 @@ void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
g.UseRegister(value->InputAt(0)));
return;
default:
VisitRR(this, kMipsTruncWD, node);
break;
}
if (value->opcode() == IrOpcode::kChangeFloat32ToFloat64) {
Node* next = value->InputAt(0);
if (CanCover(value, next)) {
// Match ChangeFloat64ToInt32(ChangeFloat32ToFloat64(Float64Round##OP))
switch (next->opcode()) {
case IrOpcode::kFloat32RoundDown:
Emit(kMipsFloorWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
case IrOpcode::kFloat32RoundUp:
Emit(kMipsCeilWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
case IrOpcode::kFloat32RoundTiesEven:
Emit(kMipsRoundWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
case IrOpcode::kFloat32RoundTruncate:
Emit(kMipsTruncWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
default:
Emit(kMipsTruncWS, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
}
} else {
// Match float32 -> float64 -> int32 representation change path.
Emit(kMipsTruncWS, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
}
}
}
VisitRR(this, kMipsTruncWD, node);
}
......@@ -549,6 +581,16 @@ void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
MipsOperandGenerator g(this);
Node* value = node->InputAt(0);
// Match TruncateFloat64ToFloat32(ChangeInt32ToFloat64) to corresponding
// instruction.
if (CanCover(node, value) &&
value->opcode() == IrOpcode::kChangeInt32ToFloat64) {
Emit(kMipsCvtSW, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
}
VisitRR(this, kMipsCvtSD, node);
}
......
......@@ -1041,6 +1041,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ cvt_d_w(i.OutputDoubleRegister(), scratch);
break;
}
case kMips64CvtSW: {
FPURegister scratch = kScratchDoubleReg;
__ mtc1(i.InputRegister(0), scratch);
__ cvt_s_w(i.OutputDoubleRegister(), scratch);
break;
}
case kMips64CvtSL: {
FPURegister scratch = kScratchDoubleReg;
__ dmtc1(i.InputRegister(0), scratch);
......@@ -1090,6 +1096,30 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64FloorWS: {
FPURegister scratch = kScratchDoubleReg;
__ floor_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64CeilWS: {
FPURegister scratch = kScratchDoubleReg;
__ ceil_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64RoundWS: {
FPURegister scratch = kScratchDoubleReg;
__ round_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64TruncWS: {
FPURegister scratch = kScratchDoubleReg;
__ trunc_w_s(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64TruncLS: {
FPURegister scratch = kScratchDoubleReg;
Register tmp_fcsr = kScratchReg;
......
......@@ -84,6 +84,10 @@ namespace compiler {
V(Mips64RoundWD) \
V(Mips64FloorWD) \
V(Mips64CeilWD) \
V(Mips64TruncWS) \
V(Mips64RoundWS) \
V(Mips64FloorWS) \
V(Mips64CeilWS) \
V(Mips64TruncLS) \
V(Mips64TruncLD) \
V(Mips64TruncUwD) \
......@@ -91,6 +95,7 @@ namespace compiler {
V(Mips64TruncUlD) \
V(Mips64CvtDW) \
V(Mips64CvtSL) \
V(Mips64CvtSW) \
V(Mips64CvtSUl) \
V(Mips64CvtDL) \
V(Mips64CvtDUw) \
......
......@@ -836,10 +836,42 @@ void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
g.UseRegister(value->InputAt(0)));
return;
default:
VisitRR(this, kMips64TruncWD, node);
break;
}
if (value->opcode() == IrOpcode::kChangeFloat32ToFloat64) {
Node* next = value->InputAt(0);
if (CanCover(value, next)) {
// Match ChangeFloat64ToInt32(ChangeFloat32ToFloat64(Float64Round##OP))
switch (next->opcode()) {
case IrOpcode::kFloat32RoundDown:
Emit(kMips64FloorWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
case IrOpcode::kFloat32RoundUp:
Emit(kMips64CeilWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
case IrOpcode::kFloat32RoundTiesEven:
Emit(kMips64RoundWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
case IrOpcode::kFloat32RoundTruncate:
Emit(kMips64TruncWS, g.DefineAsRegister(node),
g.UseRegister(next->InputAt(0)));
return;
default:
Emit(kMips64TruncWS, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
}
} else {
// Match float32 -> float64 -> int32 representation change path.
Emit(kMips64TruncWS, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
}
}
}
VisitRR(this, kMips64TruncWD, node);
}
......@@ -954,6 +986,16 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
Mips64OperandGenerator g(this);
Node* value = node->InputAt(0);
// Match TruncateFloat64ToFloat32(ChangeInt32ToFloat64) to corresponding
// instruction.
if (CanCover(node, value) &&
value->opcode() == IrOpcode::kChangeInt32ToFloat64) {
Emit(kMips64CvtSW, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
}
VisitRR(this, kMips64CvtSD, node);
}
......
......@@ -244,17 +244,31 @@ const Conversion kConversionInstructions[] = {
const Conversion kFloat64RoundInstructions[] = {
{{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMipsCeilWD,
MachineType::Float64()},
MachineType::Int32()},
{{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown", kMipsFloorWD,
MachineType::Float64()},
{{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown", kMipsFloorWD,
MachineType::Int32()},
MachineType::Float64()},
{{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
kMipsRoundWD, MachineType::Float64()},
MachineType::Int32()},
kMipsRoundWD, MachineType::Int32()},
MachineType::Float64()},
{{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
kMipsTruncWD, MachineType::Float64()},
MachineType::Int32()}};
kMipsTruncWD, MachineType::Int32()},
MachineType::Float64()}};
const Conversion kFloat32RoundInstructions[] = {
{{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMipsCeilWS,
MachineType::Int32()},
MachineType::Float32()},
{{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown", kMipsFloorWS,
MachineType::Int32()},
MachineType::Float32()},
{{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven",
kMipsRoundWS, MachineType::Int32()},
MachineType::Float32()},
{{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate",
kMipsTruncWS, MachineType::Int32()},
MachineType::Float32()}};
} // namespace
......@@ -710,6 +724,59 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
::testing::ValuesIn(kFloat64RoundInstructions));
typedef InstructionSelectorTestWithParam<Conversion>
CombineChangeFloat32ToInt32WithRoundFloat32;
TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) {
{
const Conversion conv = GetParam();
StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
m.Return(m.ChangeFloat64ToInt32(
m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0)))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
CombineChangeFloat32ToInt32WithRoundFloat32,
::testing::ValuesIn(kFloat32RoundInstructions));
TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) {
{
StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMipsTruncWS, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
TEST_F(InstructionSelectorTest,
TruncateFloat64ToFloat32OfChangeInt32ToFloat64) {
{
StreamBuilder m(this, MachineType::Float32(), MachineType::Int32());
m.Return(
m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMipsCvtSW, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
// ----------------------------------------------------------------------------
// Loads and stores.
// ----------------------------------------------------------------------------
......
......@@ -262,17 +262,31 @@ const Conversion kConversionInstructions[] = {
const Conversion kFloat64RoundInstructions[] = {
{{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMips64CeilWD,
MachineType::Float64()},
MachineType::Int32()},
MachineType::Float64()},
{{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown",
kMips64FloorWD, MachineType::Float64()},
MachineType::Int32()},
kMips64FloorWD, MachineType::Int32()},
MachineType::Float64()},
{{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
kMips64RoundWD, MachineType::Float64()},
MachineType::Int32()},
kMips64RoundWD, MachineType::Int32()},
MachineType::Float64()},
{{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
kMips64TruncWD, MachineType::Float64()},
MachineType::Int32()}};
kMips64TruncWD, MachineType::Int32()},
MachineType::Float64()}};
const Conversion kFloat32RoundInstructions[] = {
{{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMips64CeilWS,
MachineType::Int32()},
MachineType::Float32()},
{{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown",
kMips64FloorWS, MachineType::Int32()},
MachineType::Float32()},
{{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven",
kMips64RoundWS, MachineType::Int32()},
MachineType::Float32()},
{{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate",
kMips64TruncWS, MachineType::Int32()},
MachineType::Float32()}};
} // namespace
......@@ -881,6 +895,58 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
CombineChangeFloat64ToInt32WithRoundFloat64,
::testing::ValuesIn(kFloat64RoundInstructions));
typedef InstructionSelectorTestWithParam<Conversion>
CombineChangeFloat32ToInt32WithRoundFloat32;
TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) {
{
const Conversion conv = GetParam();
StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
m.Return(m.ChangeFloat64ToInt32(
m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0)))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
CombineChangeFloat32ToInt32WithRoundFloat32,
::testing::ValuesIn(kFloat32RoundInstructions));
TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) {
{
StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64TruncWS, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
TEST_F(InstructionSelectorTest,
TruncateFloat64ToFloat32OfChangeInt32ToFloat64) {
{
StreamBuilder m(this, MachineType::Float32(), MachineType::Int32());
m.Return(
m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kMips64CvtSW, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
TEST_F(InstructionSelectorTest, CombineShiftsWithMul) {
{
......
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