Commit 4e93ce4f authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [crankshaft] Address the deoptimization loops of Math.floor, Math.round and Math.ceil.

Port 978ad03b

Original commit message:
    Fix and re-enable the flexible representation for Math.floor (which is used to
    implement Math.ceil) and Math.round, which allows Math.floor and Math.round to
    return double results instead of int32, and therefore allows values outside
    the int32 range, especially -0 is now a valid result, which doesn't deopt.

    Also port this feature to x64 and ia32 when the CPU supports the SSE4.1
    extension.

    This addresses all the known deoptimization loops related to Math.round
    in the Kraken benchmark suite, and seems to also address most of the
    deoptimization loops related to Math.floor in the Oort Online benchmark.

    Drive-by-fix: Import the regression tests for the broken HMathFloorOfDiv
    optimization that caused the initial revert of the feature (for arm64 only
    back then).

R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=chromium:476477,v8:2890,v8:4059
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#35659}
parent aef33eda
......@@ -2498,7 +2498,7 @@ class HUnaryMathOperation final : public HTemplateInstruction<2> {
// Indicates if we support a double (and int32) output for Math.floor and
// Math.round.
bool SupportsFlexibleFloorAndRound() const {
#if V8_TARGET_ARCH_ARM64
#if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
return true;
#elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
return CpuFeatures::IsSupported(SSE4_1);
......
......@@ -3613,8 +3613,13 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
}
}
void LCodeGen::DoMathFloorD(LMathFloorD* instr) {
DoubleRegister input_reg = ToDoubleRegister(instr->value());
DoubleRegister output_reg = ToDoubleRegister(instr->result());
__ frim(output_reg, input_reg);
}
void LCodeGen::DoMathFloor(LMathFloor* instr) {
void LCodeGen::DoMathFloorI(LMathFloorI* instr) {
DoubleRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
Register input_high = scratch0();
......@@ -3636,8 +3641,30 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ bind(&done);
}
void LCodeGen::DoMathRoundD(LMathRoundD* instr) {
DoubleRegister input_reg = ToDoubleRegister(instr->value());
DoubleRegister output_reg = ToDoubleRegister(instr->result());
DoubleRegister dot_five = double_scratch0();
Label done;
__ frin(output_reg, input_reg);
__ fcmpu(input_reg, kDoubleRegZero);
__ bge(&done);
__ fcmpu(output_reg, input_reg);
__ beq(&done);
// Negative, non-integer case
__ LoadDoubleLiteral(dot_five, 0.5, r0);
__ fadd(output_reg, input_reg, dot_five);
__ frim(output_reg, output_reg);
// The range [-0.5, -0.0[ yielded +0.0. Force the sign to negative.
__ fabs(output_reg, output_reg);
__ fneg(output_reg, output_reg);
__ bind(&done);
}
void LCodeGen::DoMathRound(LMathRound* instr) {
void LCodeGen::DoMathRoundI(LMathRoundI* instr) {
DoubleRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
......
......@@ -1142,20 +1142,32 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseRegister(instr->value());
LMathFloor* result = new (zone()) LMathFloor(input);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
if (instr->representation().IsInteger32()) {
LMathFloorI* result = new (zone()) LMathFloorI(input);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
} else {
DCHECK(instr->representation().IsDouble());
LMathFloorD* result = new (zone()) LMathFloorD(input);
return DefineAsRegister(result);
}
}
LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseRegister(instr->value());
LOperand* temp = TempDoubleRegister();
LMathRound* result = new (zone()) LMathRound(input, temp);
return AssignEnvironment(DefineAsRegister(result));
if (instr->representation().IsInteger32()) {
LOperand* temp = TempDoubleRegister();
LMathRoundI* result = new (zone()) LMathRoundI(input, temp);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
} else {
DCHECK(instr->representation().IsDouble());
LMathRoundD* result = new (zone()) LMathRoundD(input);
return DefineAsRegister(result);
}
}
LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
LOperand* input = UseRegister(instr->value());
LMathFround* result = new (zone()) LMathFround(input);
......
......@@ -99,12 +99,14 @@ class LCodeGen;
V(MathAbs) \
V(MathClz32) \
V(MathExp) \
V(MathFloor) \
V(MathFloorD) \
V(MathFloorI) \
V(MathFround) \
V(MathLog) \
V(MathMinMax) \
V(MathPowHalf) \
V(MathRound) \
V(MathRoundD) \
V(MathRoundI) \
V(MathSqrt) \
V(MaybeGrowElements) \
V(ModByConstI) \
......@@ -151,7 +153,6 @@ class LCodeGen;
V(UnknownOSRValue) \
V(WrapReceiver)
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
Opcode opcode() const final { return LInstruction::k##type; } \
void CompileToNative(LCodeGen* generator) final; \
......@@ -807,21 +808,43 @@ class LCompareNumericAndBranch final : public LControlInstruction<2, 0> {
void PrintDataTo(StringStream* stream) override;
};
// Math.floor with a double result.
class LMathFloorD final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathFloorD(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};
class LMathFloor final : public LTemplateInstruction<1, 1, 0> {
// Math.floor with an integer result.
class LMathFloorI final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathFloor(LOperand* value) { inputs_[0] = value; }
explicit LMathFloorI(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathFloor, "math-floor")
DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};
// Math.round with a double result.
class LMathRoundD final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathRoundD(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};
class LMathRound final : public LTemplateInstruction<1, 1, 1> {
// Math.round with an integer result.
class LMathRoundI final : public LTemplateInstruction<1, 1, 1> {
public:
LMathRound(LOperand* value, LOperand* temp) {
LMathRoundI(LOperand* value, LOperand* temp) {
inputs_[0] = value;
temps_[0] = temp;
}
......@@ -829,7 +852,7 @@ class LMathRound final : public LTemplateInstruction<1, 1, 1> {
LOperand* value() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round")
DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};
......
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