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

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

Port 2027b0be

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}
parent 232a3360
...@@ -1310,6 +1310,9 @@ void InstructionSelector::VisitFloat64Mod(Node* node) { ...@@ -1310,6 +1310,9 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
g.UseFixed(node->InputAt(1), d2))->MarkAsCall(); 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) { void InstructionSelector::VisitFloat64Max(Node* node) {
VisitRRR(this, kPPC_MaxDouble, node); VisitRRR(this, kPPC_MaxDouble, node);
...@@ -1320,6 +1323,9 @@ void InstructionSelector::VisitFloat64SilenceNaN(Node* node) { ...@@ -1320,6 +1323,9 @@ void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
VisitRR(this, kPPC_Float64SilenceNaN, node); VisitRR(this, kPPC_Float64SilenceNaN, node);
} }
void InstructionSelector::VisitFloat32Min(Node* node) {
VisitRRR(this, kPPC_MinDouble | MiscField::encode(1), node);
}
void InstructionSelector::VisitFloat64Min(Node* node) { void InstructionSelector::VisitFloat64Min(Node* node) {
VisitRRR(this, kPPC_MinDouble, node); VisitRRR(this, kPPC_MinDouble, node);
......
...@@ -390,96 +390,185 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) { ...@@ -390,96 +390,185 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
__ MovFromFloatResult(i.OutputDoubleRegister()); \ __ MovFromFloatResult(i.OutputDoubleRegister()); \
} while (0) } while (0)
#define ASSEMBLE_FLOAT_MAX() \ #define ASSEMBLE_DOUBLE_MAX() \
do { \ do { \
DoubleRegister left_reg = i.InputDoubleRegister(0); \ DoubleRegister left_reg = i.InputDoubleRegister(0); \
DoubleRegister right_reg = i.InputDoubleRegister(1); \ DoubleRegister right_reg = i.InputDoubleRegister(1); \
DoubleRegister result_reg = i.OutputDoubleRegister(); \ DoubleRegister result_reg = i.OutputDoubleRegister(); \
Label check_nan_left, check_zero, return_left, return_right, done; \ Label check_nan_left, check_zero, return_left, return_right, done; \
__ cdbr(left_reg, right_reg); \ __ cdbr(left_reg, right_reg); \
__ bunordered(&check_nan_left, Label::kNear); \ __ bunordered(&check_nan_left, Label::kNear); \
__ beq(&check_zero); \ __ beq(&check_zero); \
__ bge(&return_left, Label::kNear); \ __ bge(&return_left, Label::kNear); \
__ b(&return_right, Label::kNear); \ __ b(&return_right, Label::kNear); \
\ \
__ bind(&check_zero); \ __ bind(&check_zero); \
__ lzdr(kDoubleRegZero); \ __ lzdr(kDoubleRegZero); \
__ cdbr(left_reg, kDoubleRegZero); \ __ cdbr(left_reg, kDoubleRegZero); \
/* left == right != 0. */ \ /* left == right != 0. */ \
__ bne(&return_left, Label::kNear); \ __ bne(&return_left, Label::kNear); \
/* At this point, both left and right are either 0 or -0. */ \ /* At this point, both left and right are either 0 or -0. */ \
/* N.B. The following works because +0 + -0 == +0 */ \ /* N.B. The following works because +0 + -0 == +0 */ \
/* For max we want logical-and of sign bit: (L + R) */ \ /* For max we want logical-and of sign bit: (L + R) */ \
__ ldr(result_reg, left_reg); \ __ ldr(result_reg, left_reg); \
__ adbr(result_reg, right_reg); \ __ adbr(result_reg, right_reg); \
__ b(&done, Label::kNear); \ __ b(&done, Label::kNear); \
\ \
__ bind(&check_nan_left); \ __ bind(&check_nan_left); \
__ cdbr(left_reg, left_reg); \ __ cdbr(left_reg, left_reg); \
/* left == NaN. */ \ /* left == NaN. */ \
__ bunordered(&return_left, Label::kNear); \ __ bunordered(&return_left, Label::kNear); \
\ \
__ bind(&return_right); \ __ bind(&return_right); \
if (!right_reg.is(result_reg)) { \ if (!right_reg.is(result_reg)) { \
__ ldr(result_reg, right_reg); \ __ ldr(result_reg, right_reg); \
} \ } \
__ b(&done, Label::kNear); \ __ b(&done, Label::kNear); \
\ \
__ bind(&return_left); \ __ bind(&return_left); \
if (!left_reg.is(result_reg)) { \ if (!left_reg.is(result_reg)) { \
__ ldr(result_reg, left_reg); \ __ ldr(result_reg, left_reg); \
} \ } \
__ bind(&done); \ __ bind(&done); \
} while (0) \ } while (0)
#define ASSEMBLE_FLOAT_MIN() \ #define ASSEMBLE_DOUBLE_MIN() \
do { \ do { \
DoubleRegister left_reg = i.InputDoubleRegister(0); \ DoubleRegister left_reg = i.InputDoubleRegister(0); \
DoubleRegister right_reg = i.InputDoubleRegister(1); \ DoubleRegister right_reg = i.InputDoubleRegister(1); \
DoubleRegister result_reg = i.OutputDoubleRegister(); \ DoubleRegister result_reg = i.OutputDoubleRegister(); \
Label check_nan_left, check_zero, return_left, return_right, done; \ Label check_nan_left, check_zero, return_left, return_right, done; \
__ cdbr(left_reg, right_reg); \ __ cdbr(left_reg, right_reg); \
__ bunordered(&check_nan_left, Label::kNear); \ __ bunordered(&check_nan_left, Label::kNear); \
__ beq(&check_zero); \ __ beq(&check_zero); \
__ ble(&return_left, Label::kNear); \ __ ble(&return_left, Label::kNear); \
__ b(&return_right, Label::kNear); \ __ b(&return_right, Label::kNear); \
\ \
__ bind(&check_zero); \ __ bind(&check_zero); \
__ lzdr(kDoubleRegZero); \ __ lzdr(kDoubleRegZero); \
__ cdbr(left_reg, kDoubleRegZero); \ __ cdbr(left_reg, kDoubleRegZero); \
/* left == right != 0. */ \ /* left == right != 0. */ \
__ bne(&return_left, Label::kNear); \ __ bne(&return_left, Label::kNear); \
/* At this point, both left and right are either 0 or -0. */ \ /* At this point, both left and right are either 0 or -0. */ \
/* N.B. The following works because +0 + -0 == +0 */ \ /* N.B. The following works because +0 + -0 == +0 */ \
/* For min we want logical-or of sign bit: -(-L + -R) */ \ /* For min we want logical-or of sign bit: -(-L + -R) */ \
__ lcdbr(left_reg, left_reg); \ __ lcdbr(left_reg, left_reg); \
__ ldr(result_reg, left_reg); \ __ ldr(result_reg, left_reg); \
if (left_reg.is(right_reg)) { \ if (left_reg.is(right_reg)) { \
__ adbr(result_reg, right_reg); \ __ adbr(result_reg, right_reg); \
} else { \ } else { \
__ sdbr(result_reg, right_reg); \ __ sdbr(result_reg, right_reg); \
} \ } \
__ lcdbr(result_reg, result_reg); \ __ lcdbr(result_reg, result_reg); \
__ b(&done, Label::kNear); \ __ b(&done, Label::kNear); \
\ \
__ bind(&check_nan_left); \ __ bind(&check_nan_left); \
__ cdbr(left_reg, left_reg); \ __ cdbr(left_reg, left_reg); \
/* left == NaN. */ \ /* left == NaN. */ \
__ bunordered(&return_left, Label::kNear); \ __ bunordered(&return_left, Label::kNear); \
\ \
__ bind(&return_right); \ __ bind(&return_right); \
if (!right_reg.is(result_reg)) { \ if (!right_reg.is(result_reg)) { \
__ ldr(result_reg, right_reg); \ __ ldr(result_reg, right_reg); \
} \ } \
__ b(&done, Label::kNear); \ __ b(&done, Label::kNear); \
\ \
__ bind(&return_left); \ __ bind(&return_left); \
if (!left_reg.is(result_reg)) { \ if (!left_reg.is(result_reg)) { \
__ ldr(result_reg, left_reg); \ __ ldr(result_reg, left_reg); \
} \ } \
__ bind(&done); \ __ bind(&done); \
} while (0) } 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 // Only MRI mode for these instructions available
#define ASSEMBLE_LOAD_FLOAT(asm_instr) \ #define ASSEMBLE_LOAD_FLOAT(asm_instr) \
do { \ do { \
...@@ -1512,12 +1601,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1512,12 +1601,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kS390_Neg64: case kS390_Neg64:
__ lcgr(i.OutputRegister(), i.InputRegister(0)); __ lcgr(i.OutputRegister(), i.InputRegister(0));
break; break;
case kS390_MaxDouble: case kS390_MaxFloat:
ASSEMBLE_FLOAT_MAX(); ASSEMBLE_FLOAT_MAX();
break; break;
case kS390_MinDouble: case kS390_MaxDouble:
ASSEMBLE_DOUBLE_MAX();
break;
case kS390_MinFloat:
ASSEMBLE_FLOAT_MIN(); ASSEMBLE_FLOAT_MIN();
break; break;
case kS390_MinDouble:
ASSEMBLE_DOUBLE_MIN();
break;
case kS390_AbsDouble: case kS390_AbsDouble:
__ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); __ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break; break;
......
...@@ -78,7 +78,9 @@ namespace compiler { ...@@ -78,7 +78,9 @@ namespace compiler {
V(S390_CeilDouble) \ V(S390_CeilDouble) \
V(S390_TruncateDouble) \ V(S390_TruncateDouble) \
V(S390_RoundDouble) \ V(S390_RoundDouble) \
V(S390_MaxFloat) \
V(S390_MaxDouble) \ V(S390_MaxDouble) \
V(S390_MinFloat) \
V(S390_MinDouble) \ V(S390_MinDouble) \
V(S390_AbsDouble) \ V(S390_AbsDouble) \
V(S390_Cntlz32) \ V(S390_Cntlz32) \
......
...@@ -79,7 +79,9 @@ int InstructionScheduler::GetTargetInstructionFlags( ...@@ -79,7 +79,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kS390_CeilDouble: case kS390_CeilDouble:
case kS390_TruncateDouble: case kS390_TruncateDouble:
case kS390_RoundDouble: case kS390_RoundDouble:
case kS390_MaxFloat:
case kS390_MaxDouble: case kS390_MaxDouble:
case kS390_MinFloat:
case kS390_MinDouble: case kS390_MinDouble:
case kS390_AbsDouble: case kS390_AbsDouble:
case kS390_Cntlz32: case kS390_Cntlz32:
......
...@@ -1337,6 +1337,10 @@ void InstructionSelector::VisitFloat64Mod(Node* node) { ...@@ -1337,6 +1337,10 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
->MarkAsCall(); ->MarkAsCall();
} }
void InstructionSelector::VisitFloat32Max(Node* node) {
VisitRRR(this, kS390_MaxFloat, node);
}
void InstructionSelector::VisitFloat64Max(Node* node) { void InstructionSelector::VisitFloat64Max(Node* node) {
VisitRRR(this, kS390_MaxDouble, node); VisitRRR(this, kS390_MaxDouble, node);
} }
...@@ -1345,6 +1349,10 @@ void InstructionSelector::VisitFloat64SilenceNaN(Node* node) { ...@@ -1345,6 +1349,10 @@ void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
VisitRR(this, kS390_Float64SilenceNaN, node); VisitRR(this, kS390_Float64SilenceNaN, node);
} }
void InstructionSelector::VisitFloat32Min(Node* node) {
VisitRRR(this, kS390_MinFloat, node);
}
void InstructionSelector::VisitFloat64Min(Node* node) { void InstructionSelector::VisitFloat64Min(Node* node) {
VisitRRR(this, kS390_MinDouble, node); VisitRRR(this, kS390_MinDouble, 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