MIPS: Enable Math rounding operations call reduction optimization in TF.
TEST= BUG= R=paul.lind@imgtec.com Review URL: https://codereview.chromium.org/791473003 Cr-Commit-Position: refs/heads/master@{#25931}
This commit is contained in:
parent
1903447927
commit
8c4b7d272a
@ -20,6 +20,7 @@ namespace compiler {
|
||||
// TODO(plind): Possibly avoid using these lithium names.
|
||||
#define kScratchReg kLithiumScratchReg
|
||||
#define kCompareReg kLithiumScratchReg2
|
||||
#define kScratchReg2 kLithiumScratchReg2
|
||||
#define kScratchDoubleReg kLithiumScratchDouble
|
||||
|
||||
|
||||
@ -162,6 +163,45 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode {
|
||||
Register const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineRound : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRound(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineCode(gen), result_(result) {}
|
||||
|
||||
void Generate() FINAL {
|
||||
// Handle rounding to zero case where sign has to be preserved.
|
||||
// High bits of double input already in kScratchReg.
|
||||
__ srl(at, kScratchReg, 31);
|
||||
__ sll(at, at, 31);
|
||||
__ Mthc1(at, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
DoubleRegister const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineTruncate FINAL : public OutOfLineRound {
|
||||
public:
|
||||
OutOfLineTruncate(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineRound(gen, result) {}
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineFloor FINAL : public OutOfLineRound {
|
||||
public:
|
||||
OutOfLineFloor(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineRound(gen, result) {}
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineCeil FINAL : public OutOfLineRound {
|
||||
public:
|
||||
OutOfLineCeil(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineRound(gen, result) {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -239,6 +279,27 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode {
|
||||
} while (0)
|
||||
|
||||
|
||||
#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(asm_instr, operation) \
|
||||
do { \
|
||||
auto ool = \
|
||||
new (zone()) OutOfLine##operation(this, i.OutputDoubleRegister()); \
|
||||
Label done; \
|
||||
__ Mfhc1(kScratchReg, i.InputDoubleRegister(0)); \
|
||||
__ Ext(at, kScratchReg, HeapNumber::kExponentShift, \
|
||||
HeapNumber::kExponentBits); \
|
||||
__ Branch(USE_DELAY_SLOT, &done, hs, at, \
|
||||
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \
|
||||
__ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ Move(at, kScratchReg2, i.OutputDoubleRegister()); \
|
||||
__ or_(at, at, kScratchReg2); \
|
||||
__ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \
|
||||
__ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
|
||||
__ bind(ool->exit()); \
|
||||
__ bind(&done); \
|
||||
} while (0)
|
||||
|
||||
|
||||
// Assembles an instruction after register allocation, producing machine code.
|
||||
void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
MipsOperandConverter i(this, instr);
|
||||
@ -407,6 +468,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister());
|
||||
break;
|
||||
}
|
||||
case kMipsFloat64Floor: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor_l_d, Floor);
|
||||
break;
|
||||
}
|
||||
case kMipsFloat64Ceil: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil_l_d, Ceil);
|
||||
break;
|
||||
}
|
||||
case kMipsFloat64RoundTruncate: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc_l_d, Truncate);
|
||||
break;
|
||||
}
|
||||
case kMipsSqrtD: {
|
||||
__ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
|
@ -40,6 +40,9 @@ namespace compiler {
|
||||
V(MipsDivD) \
|
||||
V(MipsModD) \
|
||||
V(MipsSqrtD) \
|
||||
V(MipsFloat64Floor) \
|
||||
V(MipsFloat64Ceil) \
|
||||
V(MipsFloat64RoundTruncate) \
|
||||
V(MipsCvtSD) \
|
||||
V(MipsCvtDS) \
|
||||
V(MipsTruncWD) \
|
||||
|
@ -69,6 +69,14 @@ static void VisitRRR(InstructionSelector* selector, ArchOpcode opcode,
|
||||
}
|
||||
|
||||
|
||||
static void VisitRR(InstructionSelector* selector, ArchOpcode opcode,
|
||||
Node* node) {
|
||||
MipsOperandGenerator g(selector);
|
||||
selector->Emit(opcode, g.DefineAsRegister(node),
|
||||
g.UseRegister(node->InputAt(0)));
|
||||
}
|
||||
|
||||
|
||||
static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode,
|
||||
Node* node) {
|
||||
MipsOperandGenerator g(selector);
|
||||
@ -420,14 +428,18 @@ void InstructionSelector::VisitFloat64Sqrt(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64Floor(Node* node) { UNREACHABLE(); }
|
||||
void InstructionSelector::VisitFloat64Floor(Node* node) {
|
||||
VisitRR(this, kMipsFloat64Floor, node);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64Ceil(Node* node) { UNREACHABLE(); }
|
||||
void InstructionSelector::VisitFloat64Ceil(Node* node) {
|
||||
VisitRR(this, kMipsFloat64Ceil, node);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
|
||||
UNREACHABLE();
|
||||
VisitRR(this, kMipsFloat64RoundTruncate, node);
|
||||
}
|
||||
|
||||
|
||||
@ -806,6 +818,11 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
|
||||
// static
|
||||
MachineOperatorBuilder::Flags
|
||||
InstructionSelector::SupportedMachineOperatorFlags() {
|
||||
if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
|
||||
return MachineOperatorBuilder::kFloat64Floor |
|
||||
MachineOperatorBuilder::kFloat64Ceil |
|
||||
MachineOperatorBuilder::kFloat64RoundTruncate;
|
||||
}
|
||||
return MachineOperatorBuilder::kNoFlags;
|
||||
}
|
||||
|
||||
|
@ -163,6 +163,46 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode {
|
||||
Register const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineRound : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRound(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineCode(gen), result_(result) {}
|
||||
|
||||
void Generate() FINAL {
|
||||
// Handle rounding to zero case where sign has to be preserved.
|
||||
// High bits of double input already in kScratchReg.
|
||||
__ dsrl(at, kScratchReg, 31);
|
||||
__ dsll(at, at, 31);
|
||||
__ mthc1(at, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
DoubleRegister const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineTruncate FINAL : public OutOfLineRound {
|
||||
public:
|
||||
OutOfLineTruncate(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineRound(gen, result) {}
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineFloor FINAL : public OutOfLineRound {
|
||||
public:
|
||||
OutOfLineFloor(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineRound(gen, result) {}
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineCeil FINAL : public OutOfLineRound {
|
||||
public:
|
||||
OutOfLineCeil(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineRound(gen, result) {}
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -240,6 +280,26 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode {
|
||||
} while (0)
|
||||
|
||||
|
||||
#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(asm_instr, operation) \
|
||||
do { \
|
||||
auto ool = \
|
||||
new (zone()) OutOfLine##operation(this, i.OutputDoubleRegister()); \
|
||||
Label done; \
|
||||
__ mfhc1(kScratchReg, i.InputDoubleRegister(0)); \
|
||||
__ Ext(at, kScratchReg, HeapNumber::kExponentShift, \
|
||||
HeapNumber::kExponentBits); \
|
||||
__ Branch(USE_DELAY_SLOT, &done, hs, at, \
|
||||
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \
|
||||
__ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ dmfc1(at, i.OutputDoubleRegister()); \
|
||||
__ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \
|
||||
__ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
|
||||
__ bind(ool->exit()); \
|
||||
__ bind(&done); \
|
||||
} while (0)
|
||||
|
||||
|
||||
// Assembles an instruction after register allocation, producing machine code.
|
||||
void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
MipsOperandConverter i(this, instr);
|
||||
@ -472,19 +532,16 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister());
|
||||
break;
|
||||
}
|
||||
case kMips64FloorD: {
|
||||
__ floor_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
__ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister());
|
||||
case kMips64Float64Floor: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor_l_d, Floor);
|
||||
break;
|
||||
}
|
||||
case kMips64CeilD: {
|
||||
__ ceil_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
__ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister());
|
||||
case kMips64Float64Ceil: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil_l_d, Ceil);
|
||||
break;
|
||||
}
|
||||
case kMips64RoundTruncateD: {
|
||||
__ trunc_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
__ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister());
|
||||
case kMips64Float64RoundTruncate: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc_l_d, Truncate);
|
||||
break;
|
||||
}
|
||||
case kMips64SqrtD: {
|
||||
|
@ -53,9 +53,9 @@ namespace compiler {
|
||||
V(Mips64DivD) \
|
||||
V(Mips64ModD) \
|
||||
V(Mips64SqrtD) \
|
||||
V(Mips64FloorD) \
|
||||
V(Mips64CeilD) \
|
||||
V(Mips64RoundTruncateD) \
|
||||
V(Mips64Float64Floor) \
|
||||
V(Mips64Float64Ceil) \
|
||||
V(Mips64Float64RoundTruncate) \
|
||||
V(Mips64CvtSD) \
|
||||
V(Mips64CvtDS) \
|
||||
V(Mips64TruncWD) \
|
||||
|
@ -609,17 +609,17 @@ void InstructionSelector::VisitFloat64Sqrt(Node* node) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64Floor(Node* node) {
|
||||
VisitRR(this, kMips64FloorD, node);
|
||||
VisitRR(this, kMips64Float64Floor, node);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64Ceil(Node* node) {
|
||||
VisitRR(this, kMips64CeilD, node);
|
||||
VisitRR(this, kMips64Float64Ceil, node);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
|
||||
VisitRR(this, kMips64RoundTruncateD, node);
|
||||
VisitRR(this, kMips64Float64RoundTruncate, node);
|
||||
}
|
||||
|
||||
|
||||
@ -1069,7 +1069,9 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
|
||||
// static
|
||||
MachineOperatorBuilder::Flags
|
||||
InstructionSelector::SupportedMachineOperatorFlags() {
|
||||
return MachineOperatorBuilder::kNoFlags;
|
||||
return MachineOperatorBuilder::kFloat64Floor |
|
||||
MachineOperatorBuilder::kFloat64Ceil |
|
||||
MachineOperatorBuilder::kFloat64RoundTruncate;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
|
Loading…
Reference in New Issue
Block a user