Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Unified Diff: src/compiler/ia32/code-generator-ia32.cc

Issue 1584663007: [turbofan] Implement rounding of floats on x64 and ia32 without sse4.1. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/compiler/ia32/instruction-selector-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/ia32/code-generator-ia32.cc
diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc
index 9bb5a22cd19b45707165323321d109aaeca32cc9..3e9b6cb37b4f47a9bcfa4bc66f0f6d6adccd7b43 100644
--- a/src/compiler/ia32/code-generator-ia32.cc
+++ b/src/compiler/ia32/code-generator-ia32.cc
@@ -654,10 +654,53 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kSSEFloat32Round: {
- CpuFeatureScope sse_scope(masm(), SSE4_1);
RoundingMode const mode =
static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
__ roundss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
+ } else {
+ Register kScratchRegister = i.TempRegister(0);
titzer 2016/01/18 10:44:28 Don't call this kScratchRegister, it's not a const
ahaas 2016/01/18 15:30:30 Done.
+
+ // We have to store the original rounding mode to restore it later.
titzer 2016/01/18 10:44:28 This code sucks so much I think it should go to ma
ahaas 2016/01/18 15:30:30 Done.
+ __ sub(esp, Immediate(kPointerSize * 2));
+ __ stmxcsr(Operand(esp, 0));
+ __ mov(kScratchRegister, Operand(esp, 0));
+ __ and_(kScratchRegister, Immediate(0xffff9fff));
+ __ or_(kScratchRegister, Immediate(mode << 13));
+ __ mov(Operand(esp, kPointerSize), kScratchRegister);
+ __ ldmxcsr(Operand(esp, kPointerSize));
+
+ // Convert the input to int32.
+ if (instr->InputAt(0)->IsDoubleRegister()) {
+ __ cvtss2si(kScratchRegister, i.InputDoubleRegister(0));
titzer 2016/01/18 10:44:28 If you require the input to be in a register, you
ahaas 2016/01/18 15:30:30 Done.
+ } else {
+ __ cvtss2si(kScratchRegister, i.InputOperand(0));
+ }
+
+ Label out_of_range;
+ Label done;
+ // Check whether the input is within int32 range.
+ __ cmp(kScratchRegister, Immediate(1));
+ __ j(overflow, &out_of_range);
+ // The input is within int32 range. We achieve rounding by converting
+ // back to float.
+ __ cvtsi2ss(i.OutputDoubleRegister(), kScratchRegister);
+ __ jmp(&done);
+ __ bind(&out_of_range);
+
+ // The input value is already an integer number, no rounding necessary.
titzer 2016/01/18 10:44:28 If you do a DefineSameAsFirst, you can get rid of
ahaas 2016/01/18 15:30:30 Done.
+ if (instr->InputAt(0)->IsDoubleRegister()) {
+ __ movss(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+ } else {
+ __ movss(i.OutputDoubleRegister(), i.InputOperand(0));
+ }
+
+ __ bind(&done);
+ // Restore the original rounding mode.
+ __ ldmxcsr(Operand(esp, 0));
+ __ add(esp, Immediate(kPointerSize * 2));
+ }
break;
}
case kSSEFloat64Cmp:
@@ -727,10 +770,95 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
break;
case kSSEFloat64Round: {
- CpuFeatureScope sse_scope(masm(), SSE4_1);
RoundingMode const mode =
static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
- __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
+ } else {
+ Register kScratchRegister = i.TempRegister(0);
+
+ // We have to store the original rounding mode to restore it later.
+ __ sub(esp, Immediate(kPointerSize * 2));
+ __ stmxcsr(Operand(esp, 0));
+ __ mov(kScratchRegister, Operand(esp, 0));
+ __ and_(kScratchRegister, Immediate(0xffff9fff));
+ __ or_(kScratchRegister, Immediate(mode << 13));
+ __ mov(Operand(esp, kPointerSize), kScratchRegister);
+ __ ldmxcsr(Operand(esp, kPointerSize));
+
+ // Convert the input to int32.
+ if (instr->InputAt(0)->IsDoubleRegister()) {
titzer 2016/01/18 10:44:28 Same for this one. Require the input in a register
ahaas 2016/01/18 15:30:30 Done.
+ __ cvtsd2si(kScratchRegister, i.InputDoubleRegister(0));
+ } else {
+ __ cvtsd2si(kScratchRegister, i.InputOperand(0));
+ }
+
+ Label out_of_range;
+ Label done;
+ // Check whether the input is within int32 range.
+ __ cmp(kScratchRegister, Immediate(1));
+ __ j(overflow, &out_of_range);
+ // The input is within int32 range. We achieve rounding by converting
+ // back to float.
+ __ Cvtsi2sd(i.OutputDoubleRegister(), kScratchRegister);
+ __ jmp(&done);
+ __ bind(&out_of_range);
+
+ if (instr->InputAt(0)->IsDoubleRegister()) {
+ __ movsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+ } else {
+ __ movsd(i.OutputDoubleRegister(), i.InputOperand(0));
+ }
+
+ // If the input is outside [-2^52, 2^52], then the result = input.
+ int64_t offset = 1;
+ offset <<= 52;
+ __ Move(kScratchDoubleReg, static_cast<double>(offset));
+
+ if (instr->InputAt(0)->IsDoubleRegister()) {
+ __ ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0));
+ } else {
+ __ ucomisd(kScratchDoubleReg, i.InputOperand(0));
+ }
+
+ __ j(below_equal, &done);
+
+ __ Move(kScratchDoubleReg, static_cast<double>(-offset));
+
+ if (instr->InputAt(0)->IsDoubleRegister()) {
+ __ ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0));
+ } else {
+ __ ucomisd(kScratchDoubleReg, i.InputOperand(0));
+ }
+ __ j(above_equal, &done);
+
+ // Positive number have to be handled differently than negative numbers.
+ __ xorpd(kScratchDoubleReg, kScratchDoubleReg);
+ if (instr->InputAt(0)->IsDoubleRegister()) {
+ __ ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0));
+ } else {
+ __ ucomisd(kScratchDoubleReg, i.InputOperand(0));
+ }
+
+ __ Move(kScratchDoubleReg, static_cast<double>(offset));
+
+ Label below_zero;
+ __ j(above, &below_zero);
+
+ __ addsd(i.OutputDoubleRegister(), kScratchDoubleReg);
+ __ subsd(i.OutputDoubleRegister(), kScratchDoubleReg);
+ __ jmp(&done);
+
+ __ bind(&below_zero);
+ __ subsd(i.OutputDoubleRegister(), kScratchDoubleReg);
+ __ addsd(i.OutputDoubleRegister(), kScratchDoubleReg);
+
+ __ bind(&done);
+ // Restore the original rounding mode.
+ __ ldmxcsr(Operand(esp, 0));
+ __ add(esp, Immediate(kPointerSize * 2));
+ }
break;
}
case kSSEFloat32ToFloat64:
« no previous file with comments | « no previous file | src/compiler/ia32/instruction-selector-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698