Commit 2eaee5fd authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[x64] Refactor and fix uint to float conversions

The Cvtqui2ss and Cvtqui2sd methods did overwrite the {src} register and
the given {tmp} register.
This CL fixes this to avoid the overwrite of the {src} register, and to
use the kScratchRegister instead of an explicitly passed tmp register.
It also adds u32 -> f32/f64 conversions.
All these methods can take either a register or an operand as src. This
sometimes saves a mov operation.

R=neis@chromium.org, ahaas@chromium.org

Change-Id: I912a2a3b9d9c356f04ce51869a01c6fd11c76dd3
Reviewed-on: https://chromium-review.googlesource.com/1017121Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52676}
parent cbcecc2f
...@@ -1598,37 +1598,31 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1598,37 +1598,31 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break; break;
case kSSEUint64ToFloat32: case kSSEUint64ToFloat32:
if (instr->InputAt(0)->IsRegister()) { if (instr->InputAt(0)->IsRegister()) {
__ movq(kScratchRegister, i.InputRegister(0)); __ Cvtqui2ss(i.OutputDoubleRegister(), i.InputRegister(0));
} else { } else {
__ movq(kScratchRegister, i.InputOperand(0)); __ Cvtqui2ss(i.OutputDoubleRegister(), i.InputOperand(0));
} }
__ Cvtqui2ss(i.OutputDoubleRegister(), kScratchRegister,
i.TempRegister(0));
break; break;
case kSSEUint64ToFloat64: case kSSEUint64ToFloat64:
if (instr->InputAt(0)->IsRegister()) { if (instr->InputAt(0)->IsRegister()) {
__ movq(kScratchRegister, i.InputRegister(0)); __ Cvtqui2sd(i.OutputDoubleRegister(), i.InputRegister(0));
} else { } else {
__ movq(kScratchRegister, i.InputOperand(0)); __ Cvtqui2sd(i.OutputDoubleRegister(), i.InputOperand(0));
} }
__ Cvtqui2sd(i.OutputDoubleRegister(), kScratchRegister,
i.TempRegister(0));
break; break;
case kSSEUint32ToFloat64: case kSSEUint32ToFloat64:
if (instr->InputAt(0)->IsRegister()) { if (instr->InputAt(0)->IsRegister()) {
__ movl(kScratchRegister, i.InputRegister(0)); __ Cvtlui2sd(i.OutputDoubleRegister(), i.InputRegister(0));
} else { } else {
__ movl(kScratchRegister, i.InputOperand(0)); __ Cvtlui2sd(i.OutputDoubleRegister(), i.InputOperand(0));
} }
__ Cvtqsi2sd(i.OutputDoubleRegister(), kScratchRegister);
break; break;
case kSSEUint32ToFloat32: case kSSEUint32ToFloat32:
if (instr->InputAt(0)->IsRegister()) { if (instr->InputAt(0)->IsRegister()) {
__ movl(kScratchRegister, i.InputRegister(0)); __ Cvtlui2ss(i.OutputDoubleRegister(), i.InputRegister(0));
} else { } else {
__ movl(kScratchRegister, i.InputOperand(0)); __ Cvtlui2ss(i.OutputDoubleRegister(), i.InputOperand(0));
} }
__ Cvtqsi2ss(i.OutputDoubleRegister(), kScratchRegister);
break; break;
case kSSEFloat64ExtractLowWord32: case kSSEFloat64ExtractLowWord32:
if (instr->InputAt(0)->IsFPStackSlot()) { if (instr->InputAt(0)->IsFPStackSlot()) {
......
...@@ -1248,7 +1248,9 @@ void VisitFloatUnop(InstructionSelector* selector, Node* node, Node* input, ...@@ -1248,7 +1248,9 @@ void VisitFloatUnop(InstructionSelector* selector, Node* node, Node* input,
V(RoundFloat64ToInt32, kSSEFloat64ToInt32) \ V(RoundFloat64ToInt32, kSSEFloat64ToInt32) \
V(RoundInt32ToFloat32, kSSEInt32ToFloat32) \ V(RoundInt32ToFloat32, kSSEInt32ToFloat32) \
V(RoundInt64ToFloat32, kSSEInt64ToFloat32) \ V(RoundInt64ToFloat32, kSSEInt64ToFloat32) \
V(RoundUint64ToFloat32, kSSEUint64ToFloat32) \
V(RoundInt64ToFloat64, kSSEInt64ToFloat64) \ V(RoundInt64ToFloat64, kSSEInt64ToFloat64) \
V(RoundUint64ToFloat64, kSSEUint64ToFloat64) \
V(RoundUint32ToFloat32, kSSEUint32ToFloat32) \ V(RoundUint32ToFloat32, kSSEUint32ToFloat32) \
V(BitcastFloat32ToInt32, kX64BitcastFI) \ V(BitcastFloat32ToInt32, kX64BitcastFI) \
V(BitcastFloat64ToInt64, kX64BitcastDL) \ V(BitcastFloat64ToInt64, kX64BitcastDL) \
...@@ -1318,21 +1320,6 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { ...@@ -1318,21 +1320,6 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value)); Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
} }
void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
X64OperandGenerator g(this);
InstructionOperand temps[] = {g.TempRegister()};
Emit(kSSEUint64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0)),
arraysize(temps), temps);
}
void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
X64OperandGenerator g(this);
InstructionOperand temps[] = {g.TempRegister()};
Emit(kSSEUint64ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)),
arraysize(temps), temps);
}
void InstructionSelector::VisitFloat32Add(Node* node) { void InstructionSelector::VisitFloat32Add(Node* node) {
VisitFloatBinop(this, node, kAVXFloat32Add, kSSEFloat32Add); VisitFloatBinop(this, node, kAVXFloat32Add, kSSEFloat32Add);
} }
......
...@@ -902,7 +902,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -902,7 +902,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
Cvtqsi2ss(dst.fp(), src.gp()); Cvtqsi2ss(dst.fp(), src.gp());
return true; return true;
case kExprF32UConvertI64: case kExprF32UConvertI64:
Cvtqui2ss(dst.fp(), src.gp(), kScratchRegister); Cvtqui2ss(dst.fp(), src.gp());
return true; return true;
case kExprF32ConvertF64: case kExprF32ConvertF64:
Cvtsd2ss(dst.fp(), src.fp()); Cvtsd2ss(dst.fp(), src.fp());
...@@ -921,7 +921,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -921,7 +921,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
Cvtqsi2sd(dst.fp(), src.gp()); Cvtqsi2sd(dst.fp(), src.gp());
return true; return true;
case kExprF64UConvertI64: case kExprF64UConvertI64:
Cvtqui2sd(dst.fp(), src.gp(), kScratchRegister); Cvtqui2sd(dst.fp(), src.gp());
return true; return true;
case kExprF64ConvertF32: case kExprF64ConvertF32:
Cvtss2sd(dst.fp(), src.fp()); Cvtss2sd(dst.fp(), src.fp());
......
...@@ -723,39 +723,76 @@ void TurboAssembler::Cvtqsi2sd(XMMRegister dst, Operand src) { ...@@ -723,39 +723,76 @@ void TurboAssembler::Cvtqsi2sd(XMMRegister dst, Operand src) {
} }
} }
void TurboAssembler::Cvtqui2ss(XMMRegister dst, Register src, Register tmp) { void TurboAssembler::Cvtlui2ss(XMMRegister dst, Register src) {
Label msb_set_src; // Zero-extend the 32 bit value to 64 bit.
Label jmp_return; movl(kScratchRegister, src);
testq(src, src); Cvtqsi2ss(dst, kScratchRegister);
j(sign, &msb_set_src, Label::kNear); }
Cvtqsi2ss(dst, src);
jmp(&jmp_return, Label::kNear); void TurboAssembler::Cvtlui2ss(XMMRegister dst, Operand src) {
bind(&msb_set_src); // Zero-extend the 32 bit value to 64 bit.
movq(tmp, src); movl(kScratchRegister, src);
shrq(src, Immediate(1)); Cvtqsi2ss(dst, kScratchRegister);
// Recover the least significant bit to avoid rounding errors. }
andq(tmp, Immediate(1));
orq(src, tmp); void TurboAssembler::Cvtlui2sd(XMMRegister dst, Register src) {
// Zero-extend the 32 bit value to 64 bit.
movl(kScratchRegister, src);
Cvtqsi2sd(dst, kScratchRegister);
}
void TurboAssembler::Cvtlui2sd(XMMRegister dst, Operand src) {
// Zero-extend the 32 bit value to 64 bit.
movl(kScratchRegister, src);
Cvtqsi2sd(dst, kScratchRegister);
}
void TurboAssembler::Cvtqui2ss(XMMRegister dst, Register src) {
Label done;
Cvtqsi2ss(dst, src); Cvtqsi2ss(dst, src);
testq(src, src);
j(positive, &done, Label::kNear);
// Compute {src/2 | (src&1)} (retain the LSB to avoid rounding errors).
if (src != kScratchRegister) movq(kScratchRegister, src);
shrq(kScratchRegister, Immediate(1));
// The LSB is shifted into CF. If it is set, set the LSB in {tmp}.
Label msb_not_set;
j(not_carry, &msb_not_set, Label::kNear);
orq(kScratchRegister, Immediate(1));
bind(&msb_not_set);
Cvtqsi2ss(dst, kScratchRegister);
addss(dst, dst); addss(dst, dst);
bind(&jmp_return); bind(&done);
} }
void TurboAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) { void TurboAssembler::Cvtqui2ss(XMMRegister dst, Operand src) {
Label msb_set_src; movq(kScratchRegister, src);
Label jmp_return; Cvtqui2ss(dst, kScratchRegister);
testq(src, src); }
j(sign, &msb_set_src, Label::kNear);
Cvtqsi2sd(dst, src); void TurboAssembler::Cvtqui2sd(XMMRegister dst, Register src) {
jmp(&jmp_return, Label::kNear); Label done;
bind(&msb_set_src);
movq(tmp, src);
shrq(src, Immediate(1));
andq(tmp, Immediate(1));
orq(src, tmp);
Cvtqsi2sd(dst, src); Cvtqsi2sd(dst, src);
testq(src, src);
j(positive, &done, Label::kNear);
// Compute {src/2 | (src&1)} (retain the LSB to avoid rounding errors).
if (src != kScratchRegister) movq(kScratchRegister, src);
shrq(kScratchRegister, Immediate(1));
// The LSB is shifted into CF. If it is set, set the LSB in {tmp}.
Label msb_not_set;
j(not_carry, &msb_not_set, Label::kNear);
orq(kScratchRegister, Immediate(1));
bind(&msb_not_set);
Cvtqsi2sd(dst, kScratchRegister);
addsd(dst, dst); addsd(dst, dst);
bind(&jmp_return); bind(&done);
}
void TurboAssembler::Cvtqui2sd(XMMRegister dst, Operand src) {
movq(kScratchRegister, src);
Cvtqui2sd(dst, kScratchRegister);
} }
void TurboAssembler::Cvttss2si(Register dst, XMMRegister src) { void TurboAssembler::Cvttss2si(Register dst, XMMRegister src) {
......
...@@ -287,8 +287,14 @@ class TurboAssembler : public Assembler { ...@@ -287,8 +287,14 @@ class TurboAssembler : public Assembler {
void Cvtqsi2sd(XMMRegister dst, Operand src); void Cvtqsi2sd(XMMRegister dst, Operand src);
void Cvtlsi2ss(XMMRegister dst, Register src); void Cvtlsi2ss(XMMRegister dst, Register src);
void Cvtlsi2ss(XMMRegister dst, Operand src); void Cvtlsi2ss(XMMRegister dst, Operand src);
void Cvtqui2ss(XMMRegister dst, Register src, Register tmp); void Cvtlui2ss(XMMRegister dst, Register src);
void Cvtqui2sd(XMMRegister dst, Register src, Register tmp); void Cvtlui2ss(XMMRegister dst, Operand src);
void Cvtlui2sd(XMMRegister dst, Register src);
void Cvtlui2sd(XMMRegister dst, Operand src);
void Cvtqui2ss(XMMRegister dst, Register src);
void Cvtqui2ss(XMMRegister dst, Operand src);
void Cvtqui2sd(XMMRegister dst, Register src);
void Cvtqui2sd(XMMRegister dst, Operand src);
void Cvttsd2uiq(Register dst, Operand src, Label* fail = nullptr); void Cvttsd2uiq(Register dst, Operand src, Label* fail = nullptr);
void Cvttsd2uiq(Register dst, XMMRegister src, Label* fail = nullptr); void Cvttsd2uiq(Register dst, XMMRegister src, Label* fail = nullptr);
void Cvttss2uiq(Register dst, Operand src, Label* fail = nullptr); void Cvttss2uiq(Register dst, Operand src, Label* fail = nullptr);
......
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