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:
parent
425983190a
commit
0d4f8a913d
@ -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.
|
||||
|
@ -68,6 +68,9 @@ namespace compiler {
|
||||
V(MipsCvtSD) \
|
||||
V(MipsCvtDS) \
|
||||
V(MipsTruncWD) \
|
||||
V(MipsRoundWD) \
|
||||
V(MipsFloorWD) \
|
||||
V(MipsCeilWD) \
|
||||
V(MipsTruncUwD) \
|
||||
V(MipsCvtDW) \
|
||||
V(MipsCvtDUw) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -81,6 +81,9 @@ namespace compiler {
|
||||
V(Mips64CvtSD) \
|
||||
V(Mips64CvtDS) \
|
||||
V(Mips64TruncWD) \
|
||||
V(Mips64RoundWD) \
|
||||
V(Mips64FloorWD) \
|
||||
V(Mips64CeilWD) \
|
||||
V(Mips64TruncLS) \
|
||||
V(Mips64TruncLD) \
|
||||
V(Mips64TruncUwD) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user