PPC/s390: [turbofan] Add Float32(Max|Min) machine operators.

Port 2027b0bed1

Original commit message:

    The new operators are implemented similar to the Float64(Max|Min) which
    already exist. The purpose of the new operators is the implementation
    of the F32Max and F32Min instructions in WebAssembly.

R=ahaas@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/2263383002
Cr-Commit-Position: refs/heads/master@{#38803}
This commit is contained in:
bjaideep 2016-08-22 13:32:46 -07:00 committed by Commit bot
parent 232a33602b
commit ad82a40509
5 changed files with 203 additions and 90 deletions

View File

@ -1310,6 +1310,9 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
g.UseFixed(node->InputAt(1), d2))->MarkAsCall();
}
void InstructionSelector::VisitFloat32Max(Node* node) {
VisitRRR(this, kPPC_MaxDouble | MiscField::encode(1), node);
}
void InstructionSelector::VisitFloat64Max(Node* node) {
VisitRRR(this, kPPC_MaxDouble, node);
@ -1320,6 +1323,9 @@ void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
VisitRR(this, kPPC_Float64SilenceNaN, node);
}
void InstructionSelector::VisitFloat32Min(Node* node) {
VisitRRR(this, kPPC_MinDouble | MiscField::encode(1), node);
}
void InstructionSelector::VisitFloat64Min(Node* node) {
VisitRRR(this, kPPC_MinDouble, node);

View File

@ -390,96 +390,185 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
__ MovFromFloatResult(i.OutputDoubleRegister()); \
} while (0)
#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); \
#define ASSEMBLE_DOUBLE_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_DOUBLE_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)
#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; \
__ cebr(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); \
__ cebr(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); \
__ aebr(result_reg, right_reg); \
__ b(&done, Label::kNear); \
\
__ bind(&check_nan_left); \
__ cebr(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; \
__ cebr(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); \
__ cebr(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) */ \
__ lcebr(left_reg, left_reg); \
__ ldr(result_reg, left_reg); \
if (left_reg.is(right_reg)) { \
__ aebr(result_reg, right_reg); \
} else { \
__ sebr(result_reg, right_reg); \
} \
__ lcebr(result_reg, result_reg); \
__ b(&done, Label::kNear); \
\
__ bind(&check_nan_left); \
__ cebr(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
#define ASSEMBLE_LOAD_FLOAT(asm_instr) \
do { \
@ -1512,12 +1601,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kS390_Neg64:
__ lcgr(i.OutputRegister(), i.InputRegister(0));
break;
case kS390_MaxDouble:
case kS390_MaxFloat:
ASSEMBLE_FLOAT_MAX();
break;
case kS390_MinDouble:
case kS390_MaxDouble:
ASSEMBLE_DOUBLE_MAX();
break;
case kS390_MinFloat:
ASSEMBLE_FLOAT_MIN();
break;
case kS390_MinDouble:
ASSEMBLE_DOUBLE_MIN();
break;
case kS390_AbsDouble:
__ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;

View File

@ -78,7 +78,9 @@ namespace compiler {
V(S390_CeilDouble) \
V(S390_TruncateDouble) \
V(S390_RoundDouble) \
V(S390_MaxFloat) \
V(S390_MaxDouble) \
V(S390_MinFloat) \
V(S390_MinDouble) \
V(S390_AbsDouble) \
V(S390_Cntlz32) \

View File

@ -79,7 +79,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kS390_CeilDouble:
case kS390_TruncateDouble:
case kS390_RoundDouble:
case kS390_MaxFloat:
case kS390_MaxDouble:
case kS390_MinFloat:
case kS390_MinDouble:
case kS390_AbsDouble:
case kS390_Cntlz32:

View File

@ -1337,6 +1337,10 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
->MarkAsCall();
}
void InstructionSelector::VisitFloat32Max(Node* node) {
VisitRRR(this, kS390_MaxFloat, node);
}
void InstructionSelector::VisitFloat64Max(Node* node) {
VisitRRR(this, kS390_MaxDouble, node);
}
@ -1345,6 +1349,10 @@ void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
VisitRR(this, kS390_Float64SilenceNaN, node);
}
void InstructionSelector::VisitFloat32Min(Node* node) {
VisitRRR(this, kS390_MinFloat, node);
}
void InstructionSelector::VisitFloat64Min(Node* node) {
VisitRRR(this, kS390_MinDouble, node);
}