From ad82a40509c5b5b4680d4299c8f08d6c6d31af3c Mon Sep 17 00:00:00 2001 From: bjaideep Date: Mon, 22 Aug 2016 13:32:46 -0700 Subject: [PATCH] PPC/s390: [turbofan] Add Float32(Max|Min) machine operators. Port 2027b0bed15e89583b31a8ea1a53cb85cccffda2 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} --- src/compiler/ppc/instruction-selector-ppc.cc | 6 + src/compiler/s390/code-generator-s390.cc | 275 ++++++++++++------ src/compiler/s390/instruction-codes-s390.h | 2 + .../s390/instruction-scheduler-s390.cc | 2 + .../s390/instruction-selector-s390.cc | 8 + 5 files changed, 203 insertions(+), 90 deletions(-) diff --git a/src/compiler/ppc/instruction-selector-ppc.cc b/src/compiler/ppc/instruction-selector-ppc.cc index d1bd936609..bad8ded131 100644 --- a/src/compiler/ppc/instruction-selector-ppc.cc +++ b/src/compiler/ppc/instruction-selector-ppc.cc @@ -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); diff --git a/src/compiler/s390/code-generator-s390.cc b/src/compiler/s390/code-generator-s390.cc index 4d50c01f01..c0119cdd6c 100644 --- a/src/compiler/s390/code-generator-s390.cc +++ b/src/compiler/s390/code-generator-s390.cc @@ -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; diff --git a/src/compiler/s390/instruction-codes-s390.h b/src/compiler/s390/instruction-codes-s390.h index 0f6f5fe289..80e1532adb 100644 --- a/src/compiler/s390/instruction-codes-s390.h +++ b/src/compiler/s390/instruction-codes-s390.h @@ -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) \ diff --git a/src/compiler/s390/instruction-scheduler-s390.cc b/src/compiler/s390/instruction-scheduler-s390.cc index 56d92f2ecd..5ebe489e39 100644 --- a/src/compiler/s390/instruction-scheduler-s390.cc +++ b/src/compiler/s390/instruction-scheduler-s390.cc @@ -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: diff --git a/src/compiler/s390/instruction-selector-s390.cc b/src/compiler/s390/instruction-selector-s390.cc index 7d735969ca..6fc8a4d9f0 100644 --- a/src/compiler/s390/instruction-selector-s390.cc +++ b/src/compiler/s390/instruction-selector-s390.cc @@ -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); }