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(
break;
case kSSEUint64ToFloat32:
if (instr->InputAt(0)->IsRegister()) {
__ movq(kScratchRegister, i.InputRegister(0));
__ Cvtqui2ss(i.OutputDoubleRegister(), i.InputRegister(0));
} else {
__ movq(kScratchRegister, i.InputOperand(0));
__ Cvtqui2ss(i.OutputDoubleRegister(), i.InputOperand(0));
}
__ Cvtqui2ss(i.OutputDoubleRegister(), kScratchRegister,
i.TempRegister(0));
break;
case kSSEUint64ToFloat64:
if (instr->InputAt(0)->IsRegister()) {
__ movq(kScratchRegister, i.InputRegister(0));
__ Cvtqui2sd(i.OutputDoubleRegister(), i.InputRegister(0));
} else {
__ movq(kScratchRegister, i.InputOperand(0));
__ Cvtqui2sd(i.OutputDoubleRegister(), i.InputOperand(0));
}
__ Cvtqui2sd(i.OutputDoubleRegister(), kScratchRegister,
i.TempRegister(0));
break;
case kSSEUint32ToFloat64:
if (instr->InputAt(0)->IsRegister()) {
__ movl(kScratchRegister, i.InputRegister(0));
__ Cvtlui2sd(i.OutputDoubleRegister(), i.InputRegister(0));
} else {
__ movl(kScratchRegister, i.InputOperand(0));
__ Cvtlui2sd(i.OutputDoubleRegister(), i.InputOperand(0));
}
__ Cvtqsi2sd(i.OutputDoubleRegister(), kScratchRegister);
break;
case kSSEUint32ToFloat32:
if (instr->InputAt(0)->IsRegister()) {
__ movl(kScratchRegister, i.InputRegister(0));
__ Cvtlui2ss(i.OutputDoubleRegister(), i.InputRegister(0));
} else {
__ movl(kScratchRegister, i.InputOperand(0));
__ Cvtlui2ss(i.OutputDoubleRegister(), i.InputOperand(0));
}
__ Cvtqsi2ss(i.OutputDoubleRegister(), kScratchRegister);
break;
case kSSEFloat64ExtractLowWord32:
if (instr->InputAt(0)->IsFPStackSlot()) {
......
......@@ -1248,7 +1248,9 @@ void VisitFloatUnop(InstructionSelector* selector, Node* node, Node* input,
V(RoundFloat64ToInt32, kSSEFloat64ToInt32) \
V(RoundInt32ToFloat32, kSSEInt32ToFloat32) \
V(RoundInt64ToFloat32, kSSEInt64ToFloat32) \
V(RoundUint64ToFloat32, kSSEUint64ToFloat32) \
V(RoundInt64ToFloat64, kSSEInt64ToFloat64) \
V(RoundUint64ToFloat64, kSSEUint64ToFloat64) \
V(RoundUint32ToFloat32, kSSEUint32ToFloat32) \
V(BitcastFloat32ToInt32, kX64BitcastFI) \
V(BitcastFloat64ToInt64, kX64BitcastDL) \
......@@ -1318,21 +1320,6 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
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) {
VisitFloatBinop(this, node, kAVXFloat32Add, kSSEFloat32Add);
}
......
......@@ -902,7 +902,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
Cvtqsi2ss(dst.fp(), src.gp());
return true;
case kExprF32UConvertI64:
Cvtqui2ss(dst.fp(), src.gp(), kScratchRegister);
Cvtqui2ss(dst.fp(), src.gp());
return true;
case kExprF32ConvertF64:
Cvtsd2ss(dst.fp(), src.fp());
......@@ -921,7 +921,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
Cvtqsi2sd(dst.fp(), src.gp());
return true;
case kExprF64UConvertI64:
Cvtqui2sd(dst.fp(), src.gp(), kScratchRegister);
Cvtqui2sd(dst.fp(), src.gp());
return true;
case kExprF64ConvertF32:
Cvtss2sd(dst.fp(), src.fp());
......
......@@ -723,39 +723,76 @@ void TurboAssembler::Cvtqsi2sd(XMMRegister dst, Operand src) {
}
}
void TurboAssembler::Cvtqui2ss(XMMRegister dst, Register src, Register tmp) {
Label msb_set_src;
Label jmp_return;
testq(src, src);
j(sign, &msb_set_src, Label::kNear);
Cvtqsi2ss(dst, src);
jmp(&jmp_return, Label::kNear);
bind(&msb_set_src);
movq(tmp, src);
shrq(src, Immediate(1));
// Recover the least significant bit to avoid rounding errors.
andq(tmp, Immediate(1));
orq(src, tmp);
void TurboAssembler::Cvtlui2ss(XMMRegister dst, Register src) {
// Zero-extend the 32 bit value to 64 bit.
movl(kScratchRegister, src);
Cvtqsi2ss(dst, kScratchRegister);
}
void TurboAssembler::Cvtlui2ss(XMMRegister dst, Operand src) {
// Zero-extend the 32 bit value to 64 bit.
movl(kScratchRegister, src);
Cvtqsi2ss(dst, kScratchRegister);
}
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);
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);
bind(&jmp_return);
bind(&done);
}
void TurboAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) {
Label msb_set_src;
Label jmp_return;
testq(src, src);
j(sign, &msb_set_src, Label::kNear);
Cvtqsi2sd(dst, src);
jmp(&jmp_return, Label::kNear);
bind(&msb_set_src);
movq(tmp, src);
shrq(src, Immediate(1));
andq(tmp, Immediate(1));
orq(src, tmp);
void TurboAssembler::Cvtqui2ss(XMMRegister dst, Operand src) {
movq(kScratchRegister, src);
Cvtqui2ss(dst, kScratchRegister);
}
void TurboAssembler::Cvtqui2sd(XMMRegister dst, Register src) {
Label done;
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);
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) {
......
......@@ -287,8 +287,14 @@ class TurboAssembler : public Assembler {
void Cvtqsi2sd(XMMRegister dst, Operand src);
void Cvtlsi2ss(XMMRegister dst, Register src);
void Cvtlsi2ss(XMMRegister dst, Operand src);
void Cvtqui2ss(XMMRegister dst, Register src, Register tmp);
void Cvtqui2sd(XMMRegister dst, Register src, Register tmp);
void Cvtlui2ss(XMMRegister dst, Register src);
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, XMMRegister 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