MIPS: [turbofan] Combine ChangeFloat64ToInt32 with Float64Round ops.

TEST=unittests/InstructionSlectorTest.CombineChangeFloat64ToInt32WithRoundFloat64
BUG=

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

Cr-Commit-Position: refs/heads/master@{#32668}
This commit is contained in:
dusan.m.milosavljevic 2015-12-07 15:35:49 -08:00 committed by Commit bot
parent 425983190a
commit 0d4f8a913d
8 changed files with 168 additions and 0 deletions

View File

@ -924,6 +924,24 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Cvt_d_uw(i.OutputDoubleRegister(), i.InputRegister(0), scratch);
break;
}
case kMipsFloorWD: {
FPURegister scratch = kScratchDoubleReg;
__ floor_w_d(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsCeilWD: {
FPURegister scratch = kScratchDoubleReg;
__ ceil_w_d(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsRoundWD: {
FPURegister scratch = kScratchDoubleReg;
__ round_w_d(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMipsTruncWD: {
FPURegister scratch = kScratchDoubleReg;
// Other arches use round to zero here, so we follow.

View File

@ -68,6 +68,9 @@ namespace compiler {
V(MipsCvtSD) \
V(MipsCvtDS) \
V(MipsTruncWD) \
V(MipsRoundWD) \
V(MipsFloorWD) \
V(MipsCeilWD) \
V(MipsTruncUwD) \
V(MipsCvtDW) \
V(MipsCvtDUw) \

View File

@ -513,6 +513,33 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
MipsOperandGenerator g(this);
Node* value = node->InputAt(0);
// Match ChangeFloat64ToInt32(Float64Round##OP) to corresponding instruction
// which does rounding and conversion to integer format.
if (CanCover(node, value)) {
switch (value->opcode()) {
case IrOpcode::kFloat64RoundDown:
Emit(kMipsFloorWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
case IrOpcode::kFloat64RoundUp:
Emit(kMipsCeilWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
case IrOpcode::kFloat64RoundTiesEven:
Emit(kMipsRoundWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
case IrOpcode::kFloat64RoundTruncate:
Emit(kMipsTruncWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
default:
VisitRR(this, kMipsTruncWD, node);
return;
}
}
VisitRR(this, kMipsTruncWD, node);
}

View File

@ -1030,6 +1030,24 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Cvt_s_ul(i.OutputDoubleRegister(), i.InputRegister(0));
break;
}
case kMips64FloorWD: {
FPURegister scratch = kScratchDoubleReg;
__ floor_w_d(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64CeilWD: {
FPURegister scratch = kScratchDoubleReg;
__ ceil_w_d(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64RoundWD: {
FPURegister scratch = kScratchDoubleReg;
__ round_w_d(scratch, i.InputDoubleRegister(0));
__ mfc1(i.OutputRegister(), scratch);
break;
}
case kMips64TruncWD: {
FPURegister scratch = kScratchDoubleReg;
// Other arches use round to zero here, so we follow.

View File

@ -81,6 +81,9 @@ namespace compiler {
V(Mips64CvtSD) \
V(Mips64CvtDS) \
V(Mips64TruncWD) \
V(Mips64RoundWD) \
V(Mips64FloorWD) \
V(Mips64CeilWD) \
V(Mips64TruncLS) \
V(Mips64TruncLD) \
V(Mips64TruncUwD) \

View File

@ -814,6 +814,33 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
Mips64OperandGenerator g(this);
Node* value = node->InputAt(0);
// Match ChangeFloat64ToInt32(Float64Round##OP) to corresponding instruction
// which does rounding and conversion to integer format.
if (CanCover(node, value)) {
switch (value->opcode()) {
case IrOpcode::kFloat64RoundDown:
Emit(kMips64FloorWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
case IrOpcode::kFloat64RoundUp:
Emit(kMips64CeilWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
case IrOpcode::kFloat64RoundTiesEven:
Emit(kMips64RoundWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
case IrOpcode::kFloat64RoundTruncate:
Emit(kMips64TruncWD, g.DefineAsRegister(node),
g.UseRegister(value->InputAt(0)));
return;
default:
VisitRR(this, kMips64TruncWD, node);
return;
}
}
VisitRR(this, kMips64TruncWD, node);
}

View File

@ -218,6 +218,20 @@ const Conversion kConversionInstructions[] = {
kMipsTruncUwD, kMachFloat64},
kMachInt32}};
const Conversion kFloat64RoundInstructions[] = {
{{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMipsCeilWD,
kMachFloat64},
kMachInt32},
{{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown", kMipsFloorWD,
kMachFloat64},
kMachInt32},
{{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
kMipsRoundWD, kMachFloat64},
kMachInt32},
{{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
kMipsTruncWD, kMachFloat64},
kMachInt32}};
} // namespace
@ -648,6 +662,28 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
::testing::ValuesIn(kConversionInstructions));
typedef InstructionSelectorTestWithParam<Conversion>
CombineChangeFloat64ToInt32WithRoundFloat64;
TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) {
{
const Conversion conv = GetParam();
StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
m.Return(m.ChangeFloat64ToInt32((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,
CombineChangeFloat64ToInt32WithRoundFloat64,
::testing::ValuesIn(kFloat64RoundInstructions));
// ----------------------------------------------------------------------------
// Loads and stores.
// ----------------------------------------------------------------------------

View File

@ -228,6 +228,20 @@ const Conversion kConversionInstructions[] = {
kMips64TruncUwD, kMachFloat64},
kMachInt32}};
const Conversion kFloat64RoundInstructions[] = {
{{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMips64CeilWD,
kMachFloat64},
kMachInt32},
{{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown",
kMips64FloorWD, kMachFloat64},
kMachInt32},
{{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
kMips64RoundWD, kMachFloat64},
kMachInt32},
{{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
kMips64TruncWD, kMachFloat64},
kMachInt32}};
} // namespace
@ -812,6 +826,28 @@ TEST_F(InstructionSelectorTest, ChangesFromToSmi) {
}
typedef InstructionSelectorTestWithParam<Conversion>
CombineChangeFloat64ToInt32WithRoundFloat64;
TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) {
{
const Conversion conv = GetParam();
StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
m.Return(m.ChangeFloat64ToInt32((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,
CombineChangeFloat64ToInt32WithRoundFloat64,
::testing::ValuesIn(kFloat64RoundInstructions));
TEST_F(InstructionSelectorTest, CombineShiftsWithMul) {
{
StreamBuilder m(this, kMachInt32, kMachInt32);