Commit aed69fd9 authored by bjaideep's avatar bjaideep Committed by Commit bot

PPC/s390: [turbofan] Change Float64Max/Float64Min to JavaScript semantics.

Port ba092fb0

Original commit message:

    So far we don't have a useful way to inline Math.max or Math.min in
    TurboFan optimized code. This adds new operators NumberMax and NumberMin
    and changes the Float64Max/Float64Min operators to have JavaScript
    semantics instead of the C++ semantics that it had previously.

    This also removes support for recognizing the tenary case in the
    CommonOperatorReducer, since that doesn't seem to have any positive
    impact (and actually doesn't show up in regular JavaScript, where
    people use Math.max/Math.min instead).

    Drive-by-fix: Also nuke the unused Float32Max/Float32Min operators.

R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com, mbrandy@us.ibm.com

BUG=
LOG=N

Review-Url: https://codereview.chromium.org/2179503003
Cr-Commit-Position: refs/heads/master@{#37991}
parent f77d1bfc
......@@ -470,19 +470,88 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
} while (0)
#define ASSEMBLE_FLOAT_MAX(scratch_reg) \
#define ASSEMBLE_FLOAT_MAX() \
do { \
__ fsub(scratch_reg, i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
__ fsel(i.OutputDoubleRegister(), scratch_reg, i.InputDoubleRegister(0), \
i.InputDoubleRegister(1)); \
} while (0)
#define ASSEMBLE_FLOAT_MIN(scratch_reg) \
do { \
__ fsub(scratch_reg, i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
__ fsel(i.OutputDoubleRegister(), scratch_reg, i.InputDoubleRegister(1), \
i.InputDoubleRegister(0)); \
DoubleRegister left_reg = i.InputDoubleRegister(0); \
DoubleRegister right_reg = i.InputDoubleRegister(1); \
DoubleRegister result_reg = i.OutputDoubleRegister(); \
Label check_nan_left, check_zero, return_left, return_right, done; \
__ fcmpu(left_reg, right_reg); \
__ bunordered(&check_nan_left); \
__ beq(&check_zero); \
__ bge(&return_left); \
__ b(&return_right); \
\
__ bind(&check_zero); \
__ fcmpu(left_reg, kDoubleRegZero); \
/* left == right != 0. */ \
__ bne(&return_left); \
/* At this point, both left and right are either 0 or -0. */ \
__ fadd(result_reg, left_reg, right_reg); \
__ b(&done); \
\
__ bind(&check_nan_left); \
__ fcmpu(left_reg, left_reg); \
/* left == NaN. */ \
__ bunordered(&return_left); \
__ bind(&return_right); \
if (!right_reg.is(result_reg)) { \
__ fmr(result_reg, right_reg); \
} \
__ b(&done); \
\
__ bind(&return_left); \
if (!left_reg.is(result_reg)) { \
__ fmr(result_reg, left_reg); \
} \
__ bind(&done); \
} while (0) \
#define ASSEMBLE_FLOAT_MIN() \
do { \
DoubleRegister left_reg = i.InputDoubleRegister(0); \
DoubleRegister right_reg = i.InputDoubleRegister(1); \
DoubleRegister result_reg = i.OutputDoubleRegister(); \
Label check_nan_left, check_zero, return_left, return_right, done; \
__ fcmpu(left_reg, right_reg); \
__ bunordered(&check_nan_left); \
__ beq(&check_zero); \
__ ble(&return_left); \
__ b(&return_right); \
\
__ bind(&check_zero); \
__ fcmpu(left_reg, kDoubleRegZero); \
/* left == right != 0. */ \
__ bne(&return_left); \
/* At this point, both left and right are either 0 or -0. */ \
/* Min: The algorithm is: -((-L) + (-R)), which in case of L and R being */\
/* different registers is most efficiently expressed as -((-L) - R). */ \
__ fneg(left_reg, left_reg); \
if (left_reg.is(right_reg)) { \
__ fadd(result_reg, left_reg, right_reg); \
} else { \
__ fsub(result_reg, left_reg, right_reg); \
} \
__ fneg(result_reg, result_reg); \
__ b(&done); \
\
__ bind(&check_nan_left); \
__ fcmpu(left_reg, left_reg); \
/* left == NaN. */ \
__ bunordered(&return_left); \
\
__ bind(&return_right); \
if (!right_reg.is(result_reg)) { \
__ fmr(result_reg, right_reg); \
} \
__ b(&done); \
\
__ bind(&return_left); \
if (!left_reg.is(result_reg)) { \
__ fmr(result_reg, left_reg); \
} \
__ bind(&done); \
} while (0)
......@@ -1448,10 +1517,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ neg(i.OutputRegister(), i.InputRegister(0), LeaveOE, i.OutputRCBit());
break;
case kPPC_MaxDouble:
ASSEMBLE_FLOAT_MAX(kScratchDoubleReg);
ASSEMBLE_FLOAT_MAX();
break;
case kPPC_MinDouble:
ASSEMBLE_FLOAT_MIN(kScratchDoubleReg);
ASSEMBLE_FLOAT_MIN();
break;
case kPPC_AbsDouble:
ASSEMBLE_FLOAT_UNOP_RC(fabs, 0);
......
......@@ -1331,20 +1331,19 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
}
void InstructionSelector::VisitFloat32Max(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Max(Node* node) {
VisitRRR(this, kPPC_MaxDouble, node);
}
void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
VisitRR(this, kPPC_Float64SilenceNaN, node);
}
void InstructionSelector::VisitFloat32Min(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Min(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Min(Node* node) {
VisitRRR(this, kPPC_MinDouble, node);
}
void InstructionSelector::VisitFloat32Abs(Node* node) {
......
......@@ -412,28 +412,94 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
__ MovFromFloatResult(i.OutputDoubleRegister()); \
} while (0)
#define ASSEMBLE_FLOAT_MAX(double_scratch_reg, general_scratch_reg) \
do { \
Label ge, done; \
__ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
__ bge(&ge, Label::kNear); \
__ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); \
__ b(&done, Label::kNear); \
__ bind(&ge); \
__ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
__ bind(&done); \
} while (0)
#define ASSEMBLE_FLOAT_MIN(double_scratch_reg, general_scratch_reg) \
do { \
Label ge, done; \
__ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
__ bge(&ge, Label::kNear); \
__ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
__ b(&done, Label::kNear); \
__ bind(&ge); \
__ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); \
__ bind(&done); \
#define ASSEMBLE_FLOAT_MAX() \
do { \
DoubleRegister left_reg = i.InputDoubleRegister(0); \
DoubleRegister right_reg = i.InputDoubleRegister(1); \
DoubleRegister result_reg = i.OutputDoubleRegister(); \
Label check_nan_left, check_zero, return_left, return_right, done; \
__ cdbr(left_reg, right_reg); \
__ bunordered(&check_nan_left, Label::kNear); \
__ beq(&check_zero); \
__ bge(&return_left, Label::kNear); \
__ b(&return_right, Label::kNear); \
\
__ bind(&check_zero); \
__ lzdr(kDoubleRegZero); \
__ cdbr(left_reg, kDoubleRegZero); \
/* left == right != 0. */ \
__ bne(&return_left, Label::kNear); \
/* At this point, both left and right are either 0 or -0. */ \
/* N.B. The following works because +0 + -0 == +0 */ \
/* For max we want logical-and of sign bit: (L + R) */ \
__ ldr(result_reg, left_reg); \
__ adbr(result_reg, right_reg); \
__ b(&done, Label::kNear); \
\
__ bind(&check_nan_left); \
__ cdbr(left_reg, left_reg); \
/* left == NaN. */ \
__ bunordered(&return_left, Label::kNear); \
\
__ bind(&return_right); \
if (!right_reg.is(result_reg)) { \
__ ldr(result_reg, right_reg); \
} \
__ b(&done, Label::kNear); \
\
__ bind(&return_left); \
if (!left_reg.is(result_reg)) { \
__ ldr(result_reg, left_reg); \
} \
__ bind(&done); \
} while (0) \
#define ASSEMBLE_FLOAT_MIN() \
do { \
DoubleRegister left_reg = i.InputDoubleRegister(0); \
DoubleRegister right_reg = i.InputDoubleRegister(1); \
DoubleRegister result_reg = i.OutputDoubleRegister(); \
Label check_nan_left, check_zero, return_left, return_right, done; \
__ cdbr(left_reg, right_reg); \
__ bunordered(&check_nan_left, Label::kNear); \
__ beq(&check_zero); \
__ ble(&return_left, Label::kNear); \
__ b(&return_right, Label::kNear); \
\
__ bind(&check_zero); \
__ lzdr(kDoubleRegZero); \
__ cdbr(left_reg, kDoubleRegZero); \
/* left == right != 0. */ \
__ bne(&return_left, Label::kNear); \
/* At this point, both left and right are either 0 or -0. */ \
/* N.B. The following works because +0 + -0 == +0 */ \
/* For min we want logical-or of sign bit: -(-L + -R) */ \
__ lcdbr(left_reg, left_reg); \
__ ldr(result_reg, left_reg); \
if (left_reg.is(right_reg)) { \
__ adbr(result_reg, right_reg); \
} else { \
__ sdbr(result_reg, right_reg); \
} \
__ lcdbr(result_reg, result_reg); \
__ b(&done, Label::kNear); \
\
__ bind(&check_nan_left); \
__ cdbr(left_reg, left_reg); \
/* left == NaN. */ \
__ bunordered(&return_left, Label::kNear); \
\
__ bind(&return_right); \
if (!right_reg.is(result_reg)) { \
__ ldr(result_reg, right_reg); \
} \
__ b(&done, Label::kNear); \
\
__ bind(&return_left); \
if (!left_reg.is(result_reg)) { \
__ ldr(result_reg, left_reg); \
} \
__ bind(&done); \
} while (0)
// Only MRI mode for these instructions available
......@@ -1419,10 +1485,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ LoadComplementRR(i.OutputRegister(), i.InputRegister(0));
break;
case kS390_MaxDouble:
ASSEMBLE_FLOAT_MAX(kScratchDoubleReg, kScratchReg);
ASSEMBLE_FLOAT_MAX();
break;
case kS390_MinDouble:
ASSEMBLE_FLOAT_MIN(kScratchDoubleReg, kScratchReg);
ASSEMBLE_FLOAT_MIN();
break;
case kS390_AbsDouble:
__ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
......
......@@ -1218,17 +1218,17 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
->MarkAsCall();
}
void InstructionSelector::VisitFloat32Max(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Max(Node* node) {
VisitRRR(this, kS390_MaxDouble, node);
}
void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
VisitRR(this, kS390_Float64SilenceNaN, node);
}
void InstructionSelector::VisitFloat32Min(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Min(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Min(Node* node) {
VisitRRR(this, kS390_MinDouble, node);
}
void InstructionSelector::VisitFloat32Abs(Node* node) {
VisitRR(this, kS390_AbsFloat, node);
......
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