[turbofan] Add RoundUint32ToFloat32 operator to Turbofan.
BUG= Review URL: https://codereview.chromium.org/1628133002 Cr-Commit-Position: refs/heads/master@{#33796}
This commit is contained in:
parent
057f129b72
commit
187b3f2845
@ -2923,6 +2923,12 @@ void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
|
||||
}
|
||||
|
||||
|
||||
void Assembler::vcvt_f32_u32(const SwVfpRegister dst, const SwVfpRegister src,
|
||||
VFPConversionMode mode, const Condition cond) {
|
||||
emit(EncodeVCVT(F32, dst.code(), U32, src.code(), mode, cond));
|
||||
}
|
||||
|
||||
|
||||
void Assembler::vcvt_s32_f32(const SwVfpRegister dst, const SwVfpRegister src,
|
||||
VFPConversionMode mode, const Condition cond) {
|
||||
emit(EncodeVCVT(S32, dst.code(), F32, src.code(), mode, cond));
|
||||
|
@ -1125,6 +1125,10 @@ class Assembler : public AssemblerBase {
|
||||
const SwVfpRegister src,
|
||||
VFPConversionMode mode = kDefaultRoundToZero,
|
||||
const Condition cond = al);
|
||||
void vcvt_f32_u32(const SwVfpRegister dst,
|
||||
const SwVfpRegister src,
|
||||
VFPConversionMode mode = kDefaultRoundToZero,
|
||||
const Condition cond = al);
|
||||
void vcvt_s32_f32(const SwVfpRegister dst,
|
||||
const SwVfpRegister src,
|
||||
VFPConversionMode mode = kDefaultRoundToZero,
|
||||
|
@ -850,6 +850,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
}
|
||||
case kArmVcvtF32U32: {
|
||||
SwVfpRegister scratch = kScratchDoubleReg.low();
|
||||
__ vmov(scratch, i.InputRegister(0));
|
||||
__ vcvt_f32_u32(i.OutputFloat32Register(), scratch);
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
}
|
||||
case kArmVcvtF64S32: {
|
||||
SwVfpRegister scratch = kScratchDoubleReg.low();
|
||||
__ vmov(scratch, i.InputRegister(0));
|
||||
|
@ -77,6 +77,7 @@ namespace compiler {
|
||||
V(ArmVcvtF32F64) \
|
||||
V(ArmVcvtF64F32) \
|
||||
V(ArmVcvtF32S32) \
|
||||
V(ArmVcvtF32U32) \
|
||||
V(ArmVcvtF64S32) \
|
||||
V(ArmVcvtF64U32) \
|
||||
V(ArmVcvtS32F32) \
|
||||
|
@ -79,6 +79,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kArmVcvtF32F64:
|
||||
case kArmVcvtF64F32:
|
||||
case kArmVcvtF32S32:
|
||||
case kArmVcvtF32U32:
|
||||
case kArmVcvtF64S32:
|
||||
case kArmVcvtF64U32:
|
||||
case kArmVcvtS32F32:
|
||||
|
@ -926,6 +926,11 @@ void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
VisitRR(this, kArmVcvtF32U32, node);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
|
||||
VisitRR(this, kArmVcvtF64S32, node);
|
||||
}
|
||||
|
@ -1160,6 +1160,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kArm64Int64ToFloat64:
|
||||
__ Scvtf(i.OutputDoubleRegister(), i.InputRegister64(0));
|
||||
break;
|
||||
case kArm64Uint32ToFloat32:
|
||||
__ Ucvtf(i.OutputFloat32Register(), i.InputRegister32(0));
|
||||
break;
|
||||
case kArm64Uint32ToFloat64:
|
||||
__ Ucvtf(i.OutputDoubleRegister(), i.InputRegister32(0));
|
||||
break;
|
||||
|
@ -123,6 +123,7 @@ namespace compiler {
|
||||
V(Arm64Int32ToFloat64) \
|
||||
V(Arm64Int64ToFloat32) \
|
||||
V(Arm64Int64ToFloat64) \
|
||||
V(Arm64Uint32ToFloat32) \
|
||||
V(Arm64Uint32ToFloat64) \
|
||||
V(Arm64Uint64ToFloat32) \
|
||||
V(Arm64Uint64ToFloat64) \
|
||||
|
@ -117,6 +117,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kArm64Int32ToFloat64:
|
||||
case kArm64Int64ToFloat32:
|
||||
case kArm64Int64ToFloat64:
|
||||
case kArm64Uint32ToFloat32:
|
||||
case kArm64Uint32ToFloat64:
|
||||
case kArm64Uint64ToFloat32:
|
||||
case kArm64Uint64ToFloat64:
|
||||
|
@ -1224,6 +1224,11 @@ void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
VisitRR(this, kArm64Uint32ToFloat32, node);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
|
||||
VisitRR(this, kArm64Int32ToFloat64, node);
|
||||
}
|
||||
|
@ -767,6 +767,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
case kSSEInt32ToFloat32:
|
||||
__ cvtsi2ss(i.OutputDoubleRegister(), i.InputOperand(0));
|
||||
break;
|
||||
case kSSEUint32ToFloat32: {
|
||||
Register scratch0 = i.TempRegister(0);
|
||||
Register scratch1 = i.TempRegister(1);
|
||||
__ mov(scratch0, i.InputOperand(0));
|
||||
__ Cvtui2ss(i.OutputDoubleRegister(), scratch0, scratch1);
|
||||
break;
|
||||
}
|
||||
case kSSEInt32ToFloat64:
|
||||
__ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
|
||||
break;
|
||||
|
@ -62,6 +62,7 @@ namespace compiler {
|
||||
V(SSEFloat64ToInt32) \
|
||||
V(SSEFloat64ToUint32) \
|
||||
V(SSEInt32ToFloat32) \
|
||||
V(SSEUint32ToFloat32) \
|
||||
V(SSEInt32ToFloat64) \
|
||||
V(SSEUint32ToFloat64) \
|
||||
V(SSEFloat64ExtractLowWord32) \
|
||||
|
@ -65,6 +65,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kSSEFloat64ToInt32:
|
||||
case kSSEFloat64ToUint32:
|
||||
case kSSEInt32ToFloat32:
|
||||
case kSSEUint32ToFloat32:
|
||||
case kSSEInt32ToFloat64:
|
||||
case kSSEUint32ToFloat64:
|
||||
case kSSEFloat64ExtractLowWord32:
|
||||
|
@ -701,6 +701,14 @@ void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
IA32OperandGenerator g(this);
|
||||
InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
|
||||
Emit(kSSEUint32ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0)),
|
||||
arraysize(temps), temps);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
|
||||
VisitRO(this, node, kSSEInt32ToFloat64);
|
||||
}
|
||||
|
@ -985,6 +985,8 @@ void InstructionSelector::VisitNode(Node* node) {
|
||||
return MarkAsFloat64(node), VisitRoundInt64ToFloat64(node);
|
||||
case IrOpcode::kBitcastFloat32ToInt32:
|
||||
return MarkAsWord32(node), VisitBitcastFloat32ToInt32(node);
|
||||
case IrOpcode::kRoundUint32ToFloat32:
|
||||
return MarkAsFloat32(node), VisitRoundUint32ToFloat32(node);
|
||||
case IrOpcode::kRoundUint64ToFloat32:
|
||||
return MarkAsFloat64(node), VisitRoundUint64ToFloat32(node);
|
||||
case IrOpcode::kRoundUint64ToFloat64:
|
||||
|
@ -157,6 +157,7 @@ MachineRepresentation StackSlotRepresentationOf(Operator const* op) {
|
||||
V(RoundInt32ToFloat32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundInt64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundInt64ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundUint32ToFloat32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundUint64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(RoundUint64ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1) \
|
||||
|
@ -232,6 +232,7 @@ class MachineOperatorBuilder final : public ZoneObject {
|
||||
const Operator* RoundInt32ToFloat32();
|
||||
const Operator* RoundInt64ToFloat32();
|
||||
const Operator* RoundInt64ToFloat64();
|
||||
const Operator* RoundUint32ToFloat32();
|
||||
const Operator* RoundUint64ToFloat32();
|
||||
const Operator* RoundUint64ToFloat64();
|
||||
|
||||
|
@ -514,6 +514,11 @@ void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
|
||||
VisitRR(this, kMipsCvtDW, node);
|
||||
}
|
||||
|
@ -821,6 +821,11 @@ void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
|
||||
VisitRR(this, kMips64CvtDW, node);
|
||||
}
|
||||
|
@ -287,6 +287,7 @@
|
||||
V(RoundInt32ToFloat32) \
|
||||
V(RoundInt64ToFloat32) \
|
||||
V(RoundInt64ToFloat64) \
|
||||
V(RoundUint32ToFloat32) \
|
||||
V(RoundUint64ToFloat32) \
|
||||
V(RoundUint64ToFloat64) \
|
||||
V(BitcastFloat32ToInt32) \
|
||||
|
@ -945,6 +945,11 @@ void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
|
||||
VisitRR(this, kPPC_Int32ToDouble, node);
|
||||
}
|
||||
|
@ -505,6 +505,9 @@ class RawMachineAssembler {
|
||||
Node* RoundInt64ToFloat64(Node* a) {
|
||||
return AddNode(machine()->RoundInt64ToFloat64(), a);
|
||||
}
|
||||
Node* RoundUint32ToFloat32(Node* a) {
|
||||
return AddNode(machine()->RoundUint32ToFloat32(), a);
|
||||
}
|
||||
Node* RoundUint64ToFloat32(Node* a) {
|
||||
return AddNode(machine()->RoundUint64ToFloat32(), a);
|
||||
}
|
||||
|
@ -2195,6 +2195,11 @@ Type* Typer::Visitor::TypeRoundInt64ToFloat64(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
Type* Typer::Visitor::TypeRoundUint32ToFloat32(Node* node) {
|
||||
return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat32(), zone());
|
||||
}
|
||||
|
||||
|
||||
Type* Typer::Visitor::TypeRoundUint64ToFloat32(Node* node) {
|
||||
return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat32(), zone());
|
||||
}
|
||||
|
@ -918,6 +918,7 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
case IrOpcode::kRoundInt32ToFloat32:
|
||||
case IrOpcode::kRoundInt64ToFloat32:
|
||||
case IrOpcode::kRoundInt64ToFloat64:
|
||||
case IrOpcode::kRoundUint32ToFloat32:
|
||||
case IrOpcode::kRoundUint64ToFloat64:
|
||||
case IrOpcode::kRoundUint64ToFloat32:
|
||||
case IrOpcode::kTruncateFloat64ToFloat32:
|
||||
|
@ -706,9 +706,7 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
|
||||
op = m->RoundInt32ToFloat32();
|
||||
break;
|
||||
case wasm::kExprF32UConvertI32:
|
||||
op = m->ChangeUint32ToFloat64();
|
||||
input = graph()->NewNode(op, input);
|
||||
op = m->TruncateFloat64ToFloat32();
|
||||
op = m->RoundUint32ToFloat32();
|
||||
break;
|
||||
case wasm::kExprI32SConvertF32:
|
||||
return BuildI32SConvertF32(input);
|
||||
|
@ -1263,6 +1263,14 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
}
|
||||
__ Cvtqsi2sd(i.OutputDoubleRegister(), kScratchRegister);
|
||||
break;
|
||||
case kSSEUint32ToFloat32:
|
||||
if (instr->InputAt(0)->IsRegister()) {
|
||||
__ movl(kScratchRegister, i.InputRegister(0));
|
||||
} else {
|
||||
__ movl(kScratchRegister, i.InputOperand(0));
|
||||
}
|
||||
__ Cvtqsi2ss(i.OutputDoubleRegister(), kScratchRegister);
|
||||
break;
|
||||
case kSSEFloat64ExtractLowWord32:
|
||||
if (instr->InputAt(0)->IsDoubleStackSlot()) {
|
||||
__ movl(i.OutputRegister(), i.InputOperand(0));
|
||||
|
@ -91,6 +91,7 @@ namespace compiler {
|
||||
V(SSEUint64ToFloat32) \
|
||||
V(SSEUint64ToFloat64) \
|
||||
V(SSEUint32ToFloat64) \
|
||||
V(SSEUint32ToFloat32) \
|
||||
V(SSEFloat64ExtractLowWord32) \
|
||||
V(SSEFloat64ExtractHighWord32) \
|
||||
V(SSEFloat64InsertLowWord32) \
|
||||
|
@ -93,6 +93,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kSSEUint64ToFloat32:
|
||||
case kSSEUint64ToFloat64:
|
||||
case kSSEUint32ToFloat64:
|
||||
case kSSEUint32ToFloat32:
|
||||
case kSSEFloat64ExtractLowWord32:
|
||||
case kSSEFloat64ExtractHighWord32:
|
||||
case kSSEFloat64InsertLowWord32:
|
||||
|
@ -1071,6 +1071,12 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
X64OperandGenerator g(this);
|
||||
Emit(kSSEUint32ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
|
||||
X64OperandGenerator g(this);
|
||||
InstructionOperand temps[] = {g.TempRegister()};
|
||||
|
@ -663,6 +663,11 @@ void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
|
||||
X87OperandGenerator g(this);
|
||||
Emit(kX87Int32ToFloat64, g.DefineAsFixed(node, stX_0),
|
||||
|
@ -705,6 +705,25 @@ void MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
|
||||
Label msb_set_src;
|
||||
Label jmp_return;
|
||||
test(src, src);
|
||||
j(sign, &msb_set_src, Label::kNear);
|
||||
cvtsi2ss(dst, src);
|
||||
jmp(&jmp_return, Label::kNear);
|
||||
bind(&msb_set_src);
|
||||
mov(tmp, src);
|
||||
shr(src, 1);
|
||||
// Recover the least significant bit to avoid rounding errors.
|
||||
and_(tmp, Immediate(1));
|
||||
or_(src, tmp);
|
||||
cvtsi2ss(dst, src);
|
||||
addss(dst, dst);
|
||||
bind(&jmp_return);
|
||||
}
|
||||
|
||||
|
||||
bool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
|
||||
static const int kMaxImmediateBits = 17;
|
||||
if (!RelocInfo::IsNone(x.rmode_)) return false;
|
||||
|
@ -356,6 +356,8 @@ class MacroAssembler: public Assembler {
|
||||
void Cvtsi2sd(XMMRegister dst, Register src) { Cvtsi2sd(dst, Operand(src)); }
|
||||
void Cvtsi2sd(XMMRegister dst, const Operand& src);
|
||||
|
||||
void Cvtui2ss(XMMRegister dst, Register src, Register tmp);
|
||||
|
||||
// Support for constant splitting.
|
||||
bool IsUnsafeImmediate(const Immediate& x);
|
||||
void SafeMove(Register dst, const Immediate& x);
|
||||
|
@ -6095,6 +6095,13 @@ TEST(RunRoundInt32ToFloat32) {
|
||||
}
|
||||
|
||||
|
||||
TEST(RunRoundUint32ToFloat32) {
|
||||
BufferedRawMachineAssemblerTester<float> m(MachineType::Uint32());
|
||||
m.Return(m.RoundUint32ToFloat32(m.Parameter(0)));
|
||||
FOR_UINT32_INPUTS(i) { CHECK_EQ(static_cast<float>(*i), m.Call(*i)); }
|
||||
}
|
||||
|
||||
|
||||
TEST(RunBitcastInt32ToFloat32) {
|
||||
int32_t input = 1;
|
||||
float output = 0.0;
|
||||
|
Loading…
Reference in New Issue
Block a user