PPC/s390: [builtins] Introduce proper Float64Exp operator.

Port d5f2ac5e33

Original commit message:

    Import base::ieee754::exp() from FreeBSD msun and introduce a Float64Exp
    TurboFan operator based on that, similar to what we do for Float64Log.
    Rewrite Math.exp() as TurboFan builtin and use that operator to also
    inline Math.exp() into optimized TurboFan functions.

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

BUG=v8:3266,v8:3468,v8:3493,v8:5086,v8:5108,chromium:620786
LOG=N

Review-Url: https://codereview.chromium.org/2075263002
Cr-Commit-Position: refs/heads/master@{#37073}
This commit is contained in:
bjaideep 2016-06-18 02:35:44 -07:00 committed by Commit bot
parent c781e83194
commit a54e289e68
12 changed files with 26 additions and 371 deletions

View File

@ -1263,6 +1263,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atan2:
ASSEMBLE_IEEE754_BINOP(atan2);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
case kIeee754Float64Log:
ASSEMBLE_IEEE754_UNOP(log);
break;

View File

@ -1252,6 +1252,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atan2:
ASSEMBLE_IEEE754_BINOP(atan2);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
case kIeee754Float64Log:
ASSEMBLE_IEEE754_UNOP(log);
break;

View File

@ -3774,20 +3774,13 @@ void LCodeGen::DoPower(LPower* instr) {
}
}
void LCodeGen::DoMathExp(LMathExp* instr) {
DoubleRegister input = ToDoubleRegister(instr->value());
DoubleRegister result = ToDoubleRegister(instr->result());
DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
DoubleRegister double_scratch2 = double_scratch0();
Register temp1 = ToRegister(instr->temp1());
Register temp2 = ToRegister(instr->temp2());
MathExpGenerator::EmitMathExp(masm(), input, result, double_scratch1,
double_scratch2, temp1, temp2, scratch0());
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
@ -3795,7 +3788,6 @@ void LCodeGen::DoMathLog(LMathLog* instr) {
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathClz32(LMathClz32* instr) {
Register input = ToRegister(instr->value());
Register result = ToRegister(instr->result());

View File

@ -1146,8 +1146,8 @@ LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), d1);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr);
LOperand* input = UseFixedDouble(instr->value(), d0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d0), instr);
}
@ -1161,12 +1161,8 @@ LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseRegister(instr->value());
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LOperand* double_temp = TempDoubleRegister();
LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2);
return DefineAsRegister(result);
LOperand* input = UseFixedDouble(instr->value(), d0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), d0), instr);
}

View File

@ -902,21 +902,11 @@ class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
};
class LMathExp final : public LTemplateInstruction<1, 1, 3> {
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
public:
LMathExp(LOperand* value, LOperand* double_temp, LOperand* temp1,
LOperand* temp2) {
inputs_[0] = value;
temps_[0] = temp1;
temps_[1] = temp2;
temps_[2] = double_temp;
ExternalReference::InitializeMathExpData();
}
explicit LMathExp(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
LOperand* temp1() { return temps_[0]; }
LOperand* temp2() { return temps_[1]; }
LOperand* double_temp() { return temps_[2]; }
DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
};

View File

@ -3670,15 +3670,10 @@ void LCodeGen::DoPower(LPower* instr) {
}
void LCodeGen::DoMathExp(LMathExp* instr) {
DoubleRegister input = ToDoubleRegister(instr->value());
DoubleRegister result = ToDoubleRegister(instr->result());
DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
DoubleRegister double_scratch2 = double_scratch0();
Register temp1 = ToRegister(instr->temp1());
Register temp2 = ToRegister(instr->temp2());
MathExpGenerator::EmitMathExp(masm(), input, result, double_scratch1,
double_scratch2, temp1, temp2, scratch0());
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathLog(LMathLog* instr) {

View File

@ -1034,8 +1034,8 @@ LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), d1);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr);
LOperand* input = UseFixedDouble(instr->value(), d0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d0), instr);
}
LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
@ -1047,12 +1047,8 @@ LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseRegister(instr->value());
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LOperand* double_temp = TempDoubleRegister();
LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2);
return DefineAsRegister(result);
LOperand* input = UseFixedDouble(instr->value(), d0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), d0), instr);
}
LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {

View File

@ -836,21 +836,11 @@ class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
};
class LMathExp final : public LTemplateInstruction<1, 1, 3> {
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
public:
LMathExp(LOperand* value, LOperand* double_temp, LOperand* temp1,
LOperand* temp2) {
inputs_[0] = value;
temps_[0] = temp1;
temps_[1] = temp2;
temps_[2] = double_temp;
ExternalReference::InitializeMathExpData();
}
explicit LMathExp(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
LOperand* temp1() { return temps_[0]; }
LOperand* temp2() { return temps_[1]; }
LOperand* double_temp() { return temps_[2]; }
DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
};

View File

@ -16,62 +16,6 @@ namespace internal {
#define __ masm.
#if defined(USE_SIMULATOR)
byte* fast_exp_ppc_machine_code = nullptr;
double fast_exp_simulator(double x, Isolate* isolate) {
return Simulator::current(isolate)
->CallFPReturnsDouble(fast_exp_ppc_machine_code, x, 0);
}
#endif
UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
size_t actual_size;
byte* buffer =
static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
if (buffer == nullptr) return nullptr;
ExternalReference::InitializeMathExpData();
MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
CodeObjectRequired::kNo);
{
DoubleRegister input = d1;
DoubleRegister result = d2;
DoubleRegister double_scratch1 = d3;
DoubleRegister double_scratch2 = d4;
Register temp1 = r7;
Register temp2 = r8;
Register temp3 = r9;
// Called from C
__ function_descriptor();
__ Push(temp3, temp2, temp1);
MathExpGenerator::EmitMathExp(&masm, input, result, double_scratch1,
double_scratch2, temp1, temp2, temp3);
__ Pop(temp3, temp2, temp1);
__ fmr(d1, result);
__ Ret();
}
CodeDesc desc;
masm.GetCode(&desc);
DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
Assembler::FlushICache(isolate, buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
#if !defined(USE_SIMULATOR)
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#else
fast_exp_ppc_machine_code = buffer;
return &fast_exp_simulator;
#endif
}
UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
#if defined(USE_SIMULATOR)
return nullptr;
@ -513,96 +457,6 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm, Register string,
__ bind(&done);
}
static MemOperand ExpConstant(int index, Register base) {
return MemOperand(base, index * kDoubleSize);
}
void MathExpGenerator::EmitMathExp(MacroAssembler* masm, DoubleRegister input,
DoubleRegister result,
DoubleRegister double_scratch1,
DoubleRegister double_scratch2,
Register temp1, Register temp2,
Register temp3) {
DCHECK(!input.is(result));
DCHECK(!input.is(double_scratch1));
DCHECK(!input.is(double_scratch2));
DCHECK(!result.is(double_scratch1));
DCHECK(!result.is(double_scratch2));
DCHECK(!double_scratch1.is(double_scratch2));
DCHECK(!temp1.is(temp2));
DCHECK(!temp1.is(temp3));
DCHECK(!temp2.is(temp3));
DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
DCHECK(!masm->serializer_enabled()); // External references not serializable.
Label zero, infinity, done;
__ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
__ lfd(double_scratch1, ExpConstant(0, temp3));
__ fcmpu(double_scratch1, input);
__ fmr(result, input);
__ bunordered(&done);
__ bge(&zero);
__ lfd(double_scratch2, ExpConstant(1, temp3));
__ fcmpu(input, double_scratch2);
__ bge(&infinity);
__ lfd(double_scratch1, ExpConstant(3, temp3));
__ lfd(result, ExpConstant(4, temp3));
__ fmul(double_scratch1, double_scratch1, input);
__ fadd(double_scratch1, double_scratch1, result);
__ MovDoubleLowToInt(temp2, double_scratch1);
__ fsub(double_scratch1, double_scratch1, result);
__ lfd(result, ExpConstant(6, temp3));
__ lfd(double_scratch2, ExpConstant(5, temp3));
__ fmul(double_scratch1, double_scratch1, double_scratch2);
__ fsub(double_scratch1, double_scratch1, input);
__ fsub(result, result, double_scratch1);
__ fmul(double_scratch2, double_scratch1, double_scratch1);
__ fmul(result, result, double_scratch2);
__ lfd(double_scratch2, ExpConstant(7, temp3));
__ fmul(result, result, double_scratch2);
__ fsub(result, result, double_scratch1);
__ lfd(double_scratch2, ExpConstant(8, temp3));
__ fadd(result, result, double_scratch2);
__ srwi(temp1, temp2, Operand(11));
__ andi(temp2, temp2, Operand(0x7ff));
__ addi(temp1, temp1, Operand(0x3ff));
// Must not call ExpConstant() after overwriting temp3!
__ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
__ slwi(temp2, temp2, Operand(3));
#if V8_TARGET_ARCH_PPC64
__ ldx(temp2, MemOperand(temp3, temp2));
__ sldi(temp1, temp1, Operand(52));
__ orx(temp2, temp1, temp2);
__ MovInt64ToDouble(double_scratch1, temp2);
#else
__ add(ip, temp3, temp2);
__ lwz(temp3, MemOperand(ip, Register::kExponentOffset));
__ lwz(temp2, MemOperand(ip, Register::kMantissaOffset));
__ slwi(temp1, temp1, Operand(20));
__ orx(temp3, temp1, temp3);
__ MovInt64ToDouble(double_scratch1, temp3, temp2);
#endif
__ fmul(result, result, double_scratch1);
__ b(&done);
__ bind(&zero);
__ fmr(result, kDoubleRegZero);
__ b(&done);
__ bind(&infinity);
__ lfd(result, ExpConstant(2, temp3));
__ bind(&done);
}
#undef __
CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {

View File

@ -23,18 +23,6 @@ class StringCharLoadGenerator : public AllStatic {
private:
DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
};
class MathExpGenerator : public AllStatic {
public:
// Register input isn't modified. All other registers are clobbered.
static void EmitMathExp(MacroAssembler* masm, DoubleRegister input,
DoubleRegister result, DoubleRegister double_scratch1,
DoubleRegister double_scratch2, Register temp1,
Register temp2, Register temp3);
private:
DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
};
} // namespace internal
} // namespace v8

View File

@ -15,56 +15,6 @@ namespace internal {
#define __ masm.
#if defined(USE_SIMULATOR)
byte* fast_exp_s390_machine_code = nullptr;
double fast_exp_simulator(double x, Isolate* isolate) {
return Simulator::current(isolate)->CallFPReturnsDouble(
fast_exp_s390_machine_code, x, 0);
}
#endif
UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
size_t actual_size;
byte* buffer =
static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
if (buffer == nullptr) return nullptr;
ExternalReference::InitializeMathExpData();
MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
CodeObjectRequired::kNo);
{
DoubleRegister input = d0;
DoubleRegister result = d2;
DoubleRegister double_scratch1 = d3;
DoubleRegister double_scratch2 = d4;
Register temp1 = r6;
Register temp2 = r7;
Register temp3 = r8;
__ Push(temp3, temp2, temp1);
MathExpGenerator::EmitMathExp(&masm, input, result, double_scratch1,
double_scratch2, temp1, temp2, temp3);
__ Pop(temp3, temp2, temp1);
__ ldr(d0, result);
__ Ret();
}
CodeDesc desc;
masm.GetCode(&desc);
DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
Assembler::FlushICache(isolate, buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
#if !defined(USE_SIMULATOR)
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#else
fast_exp_s390_machine_code = buffer;
return &fast_exp_simulator;
#endif
}
UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
#if defined(USE_SIMULATOR)
return nullptr;
@ -507,95 +457,6 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm, Register string,
__ bind(&done);
}
static MemOperand ExpConstant(int index, Register base) {
return MemOperand(base, index * kDoubleSize);
}
void MathExpGenerator::EmitMathExp(MacroAssembler* masm, DoubleRegister input,
DoubleRegister result,
DoubleRegister double_scratch1,
DoubleRegister double_scratch2,
Register temp1, Register temp2,
Register temp3) {
DCHECK(!input.is(result));
DCHECK(!input.is(double_scratch1));
DCHECK(!input.is(double_scratch2));
DCHECK(!result.is(double_scratch1));
DCHECK(!result.is(double_scratch2));
DCHECK(!double_scratch1.is(double_scratch2));
DCHECK(!temp1.is(temp2));
DCHECK(!temp1.is(temp3));
DCHECK(!temp2.is(temp3));
DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
DCHECK(!masm->serializer_enabled()); // External references not serializable.
Label zero, infinity, done;
__ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
__ LoadDouble(double_scratch1, ExpConstant(0, temp3));
__ cdbr(double_scratch1, input);
__ ldr(result, input);
__ bunordered(&done, Label::kNear);
__ bge(&zero, Label::kNear);
__ LoadDouble(double_scratch2, ExpConstant(1, temp3));
__ cdbr(input, double_scratch2);
__ bge(&infinity, Label::kNear);
__ LoadDouble(double_scratch1, ExpConstant(3, temp3));
__ LoadDouble(result, ExpConstant(4, temp3));
// Do not generate madbr, as intermediate result are not
// rounded properly
__ mdbr(double_scratch1, input);
__ adbr(double_scratch1, result);
// Move low word of double_scratch1 to temp2
__ lgdr(temp2, double_scratch1);
__ nihf(temp2, Operand::Zero());
__ sdbr(double_scratch1, result);
__ LoadDouble(result, ExpConstant(6, temp3));
__ LoadDouble(double_scratch2, ExpConstant(5, temp3));
__ mdbr(double_scratch1, double_scratch2);
__ sdbr(double_scratch1, input);
__ sdbr(result, double_scratch1);
__ ldr(double_scratch2, double_scratch1);
__ mdbr(double_scratch2, double_scratch2);
__ mdbr(result, double_scratch2);
__ LoadDouble(double_scratch2, ExpConstant(7, temp3));
__ mdbr(result, double_scratch2);
__ sdbr(result, double_scratch1);
__ LoadDouble(double_scratch2, ExpConstant(8, temp3));
__ adbr(result, double_scratch2);
__ ShiftRight(temp1, temp2, Operand(11));
__ AndP(temp2, Operand(0x7ff));
__ AddP(temp1, Operand(0x3ff));
// Must not call ExpConstant() after overwriting temp3!
__ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
__ ShiftLeft(temp2, temp2, Operand(3));
__ lg(temp2, MemOperand(temp2, temp3));
__ sllg(temp1, temp1, Operand(52));
__ ogr(temp2, temp1);
__ ldgr(double_scratch1, temp2);
__ mdbr(result, double_scratch1);
__ b(&done, Label::kNear);
__ bind(&zero);
__ lzdr(kDoubleRegZero);
__ ldr(result, kDoubleRegZero);
__ b(&done, Label::kNear);
__ bind(&infinity);
__ LoadDouble(result, ExpConstant(2, temp3));
__ bind(&done);
}
#undef __
CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {

View File

@ -25,19 +25,6 @@ class StringCharLoadGenerator : public AllStatic {
private:
DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
};
class MathExpGenerator : public AllStatic {
public:
// Register input isn't modified. All other registers are clobbered.
static void EmitMathExp(MacroAssembler* masm, DoubleRegister input,
DoubleRegister result, DoubleRegister double_scratch1,
DoubleRegister double_scratch2, Register temp1,
Register temp2, Register temp3);
private:
DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
};
} // namespace internal
} // namespace v8