Commit 691e6d39 authored by zhengxing.li's avatar zhengxing.li Committed by Commit bot

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

  port ba092fb0 (r37971)

  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).

BUG=

  Drive-by-fix: Also nuke the unused Float32Max/Float32Min operators.
Review-Url: https://codereview.chromium.org/2187463005

Cr-Commit-Position: refs/heads/master@{#38119}
parent f8ded112
......@@ -191,18 +191,14 @@ class OutOfLineLoadInteger final : public OutOfLineCode {
Register const result_;
};
class OutOfLineLoadFloat final : public OutOfLineCode {
class OutOfLineLoadNaN final : public OutOfLineCode {
public:
OutOfLineLoadFloat(CodeGenerator* gen, X87Register result)
OutOfLineLoadNaN(CodeGenerator* gen, X87Register result)
: OutOfLineCode(gen), result_(result) {}
void Generate() final {
DCHECK(result_.code() == 0);
USE(result_);
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
__ VerifyX87StackDepth(1);
}
__ fstp(0);
__ push(Immediate(0xffffffff));
__ push(Immediate(0x7fffffff));
......@@ -275,25 +271,23 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
} // namespace
#define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \
do { \
auto result = i.OutputDoubleRegister(); \
auto offset = i.InputRegister(0); \
DCHECK(result.code() == 0); \
if (instr->InputAt(1)->IsRegister()) { \
__ cmp(offset, i.InputRegister(1)); \
} else { \
__ cmp(offset, i.InputImmediate(1)); \
} \
OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \
__ j(above_equal, ool->entry()); \
__ fstp(0); \
__ asm_instr(i.MemoryOperand(2)); \
__ bind(ool->exit()); \
#define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \
do { \
auto result = i.OutputDoubleRegister(); \
auto offset = i.InputRegister(0); \
DCHECK(result.code() == 0); \
if (instr->InputAt(1)->IsRegister()) { \
__ cmp(offset, i.InputRegister(1)); \
} else { \
__ cmp(offset, i.InputImmediate(1)); \
} \
OutOfLineCode* ool = new (zone()) OutOfLineLoadNaN(this, result); \
__ j(above_equal, ool->entry()); \
__ fstp(0); \
__ asm_instr(i.MemoryOperand(2)); \
__ bind(ool->exit()); \
} while (false)
#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \
do { \
auto result = i.OutputRegister(); \
......@@ -1164,93 +1158,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ X87SetFPUCW(0x037F);
break;
}
case kX87Float32Max: {
Label check_nan_left, check_zero, return_left, return_right;
Condition condition = below;
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
__ VerifyX87StackDepth(1);
}
__ fstp(0);
__ fld_s(MemOperand(esp, kFloatSize));
__ fld_s(MemOperand(esp, 0));
__ fld(1);
__ fld(1);
__ FCmp();
// At least one NaN.
// Return the second operands if one of the two operands is NaN
__ j(parity_even, &return_right, Label::kNear);
__ j(equal, &check_zero, Label::kNear); // left == right.
__ j(condition, &return_left, Label::kNear);
__ jmp(&return_right, Label::kNear);
__ bind(&check_zero);
__ fld(0);
__ fldz();
__ FCmp();
__ j(not_equal, &return_left, Label::kNear); // left == right != 0.
__ fadd(1);
__ jmp(&return_left, Label::kNear);
__ bind(&return_right);
__ fxch();
__ bind(&return_left);
__ fstp(0);
__ lea(esp, Operand(esp, 2 * kFloatSize));
break;
}
case kX87Float32Min: {
Label check_nan_left, check_zero, return_left, return_right;
Condition condition = above;
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
__ VerifyX87StackDepth(1);
}
__ fstp(0);
__ fld_s(MemOperand(esp, kFloatSize));
__ fld_s(MemOperand(esp, 0));
__ fld(1);
__ fld(1);
__ FCmp();
// At least one NaN.
// Return the second operands if one of the two operands is NaN
__ j(parity_even, &return_right, Label::kNear);
__ j(equal, &check_zero, Label::kNear); // left == right.
__ j(condition, &return_left, Label::kNear);
__ jmp(&return_right, Label::kNear);
__ bind(&check_zero);
__ fld(0);
__ fldz();
__ FCmp();
__ j(not_equal, &return_left, Label::kNear); // left == right != 0.
// At this point, both left and right are either 0 or -0.
// Push st0 and st1 to stack, then pop them to temp registers and OR them,
// load it to left.
__ push(eax);
__ fld(1);
__ fld(1);
__ sub(esp, Immediate(2 * kPointerSize));
__ fstp_s(MemOperand(esp, 0));
__ fstp_s(MemOperand(esp, kPointerSize));
__ pop(eax);
__ xor_(MemOperand(esp, 0), eax);
__ fstp(0);
__ fld_s(MemOperand(esp, 0));
__ pop(eax); // restore esp
__ pop(eax); // restore esp
__ jmp(&return_left, Label::kNear);
__ bind(&return_right);
__ fxch();
__ bind(&return_left);
__ fstp(0);
__ lea(esp, Operand(esp, 2 * kFloatSize));
break;
}
case kX87Float32Sqrt: {
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
__ VerifyX87StackDepth(1);
......@@ -1366,8 +1274,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
}
case kX87Float64Max: {
Label check_zero, return_left, return_right;
Condition condition = below;
Label compare_swap, done_compare;
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
__ VerifyX87StackDepth(1);
}
......@@ -1377,29 +1284,32 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ fld(1);
__ fld(1);
__ FCmp();
__ j(parity_even, &return_right,
Label::kNear); // At least one NaN, Return right.
__ j(equal, &check_zero, Label::kNear); // left == right.
__ j(condition, &return_left, Label::kNear);
__ jmp(&return_right, Label::kNear);
__ bind(&check_zero);
__ fld(0);
__ fldz();
__ FCmp();
__ j(not_equal, &return_left, Label::kNear); // left == right != 0.
auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister());
__ j(parity_even, ool->entry());
__ j(below, &done_compare, Label::kNear);
__ j(above, &compare_swap, Label::kNear);
__ push(eax);
__ lea(esp, Operand(esp, -kDoubleSize));
__ fld(1);
__ fstp_d(Operand(esp, 0));
__ mov(eax, MemOperand(esp, 4));
__ and_(eax, Immediate(0x80000000));
__ lea(esp, Operand(esp, kDoubleSize));
__ pop(eax);
__ j(zero, &done_compare, Label::kNear);
__ bind(&return_right);
__ fxch();
__ bind(&compare_swap);
__ bind(ool->exit());
__ fxch(1);
__ bind(&return_left);
__ bind(&done_compare);
__ fstp(0);
__ lea(esp, Operand(esp, 2 * kDoubleSize));
break;
}
case kX87Float64Min: {
Label check_zero, return_left, return_right;
Condition condition = above;
Label compare_swap, done_compare;
if (FLAG_debug_code && FLAG_enable_slow_asserts) {
__ VerifyX87StackDepth(1);
}
......@@ -1409,22 +1319,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ fld(1);
__ fld(1);
__ FCmp();
__ j(parity_even, &return_right,
Label::kNear); // At least one NaN, return right value.
__ j(equal, &check_zero, Label::kNear); // left == right.
__ j(condition, &return_left, Label::kNear);
__ jmp(&return_right, Label::kNear);
__ bind(&check_zero);
auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister());
__ j(parity_even, ool->entry());
__ j(above, &done_compare, Label::kNear);
__ j(below, &compare_swap, Label::kNear);
__ push(eax);
__ lea(esp, Operand(esp, -kDoubleSize));
__ fld(0);
__ fldz();
__ FCmp();
__ j(not_equal, &return_left, Label::kNear); // left == right != 0.
__ fstp_d(Operand(esp, 0));
__ mov(eax, MemOperand(esp, 4));
__ and_(eax, Immediate(0x80000000));
__ lea(esp, Operand(esp, kDoubleSize));
__ pop(eax);
__ j(zero, &done_compare, Label::kNear);
__ bind(&return_right);
__ fxch();
__ bind(&compare_swap);
__ bind(ool->exit());
__ fxch(1);
__ bind(&return_left);
__ bind(&done_compare);
__ fstp(0);
__ lea(esp, Operand(esp, 2 * kDoubleSize));
break;
......
......@@ -49,8 +49,6 @@ namespace compiler {
V(X87Float32Sub) \
V(X87Float32Mul) \
V(X87Float32Div) \
V(X87Float32Max) \
V(X87Float32Min) \
V(X87Float32Abs) \
V(X87Float32Sqrt) \
V(X87Float32Round) \
......
......@@ -977,14 +977,6 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
}
void InstructionSelector::VisitFloat32Max(Node* node) {
X87OperandGenerator g(this);
Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1)));
Emit(kX87Float32Max, g.DefineAsFixed(node, stX_0), 0, nullptr);
}
void InstructionSelector::VisitFloat64Max(Node* node) {
X87OperandGenerator g(this);
Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
......@@ -993,14 +985,6 @@ void InstructionSelector::VisitFloat64Max(Node* node) {
}
void InstructionSelector::VisitFloat32Min(Node* node) {
X87OperandGenerator g(this);
Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1)));
Emit(kX87Float32Min, g.DefineAsFixed(node, stX_0), 0, nullptr);
}
void InstructionSelector::VisitFloat64Min(Node* node) {
X87OperandGenerator g(this);
Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
......@@ -1710,10 +1694,6 @@ void InstructionSelector::VisitAtomicStore(Node* node) {
MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::kFloat32Max |
MachineOperatorBuilder::kFloat32Min |
MachineOperatorBuilder::kFloat64Max |
MachineOperatorBuilder::kFloat64Min |
MachineOperatorBuilder::kWord32ShiftIsSafe;
if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt;
......
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