From 68c800ef9dd2603e177f9854cf16388a2922fe30 Mon Sep 17 00:00:00 2001 From: "balazs.kilvady" Date: Wed, 3 Dec 2014 06:18:23 -0800 Subject: [PATCH] MIPS64: [turbofan] Add checked load/store operators. Port c516d4f09408879602520748333754d3866224fb BUG= Review URL: https://codereview.chromium.org/773113005 Cr-Commit-Position: refs/heads/master@{#25641} --- src/compiler/mips64/code-generator-mips64.cc | 149 +++++++++++++++++++-- src/compiler/mips64/instruction-selector-mips64.cc | 69 ++++++++++ src/mips64/code-stubs-mips64.cc | 6 +- src/mips64/codegen-mips64.cc | 2 +- src/mips64/lithium-codegen-mips64.cc | 2 +- src/mips64/macro-assembler-mips64.cc | 6 + src/mips64/macro-assembler-mips64.h | 4 +- 7 files changed, 220 insertions(+), 18 deletions(-) diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc index 9d47f29..34ba79a 100644 --- a/src/compiler/mips64/code-generator-mips64.cc +++ b/src/compiler/mips64/code-generator-mips64.cc @@ -103,10 +103,7 @@ class MipsOperandConverter FINAL : public InstructionOperandConverter { return MemOperand(no_reg); } - MemOperand MemoryOperand() { - int index = 0; - return MemoryOperand(&index); - } + MemOperand MemoryOperand(int index = 0) { return MemoryOperand(&index); } MemOperand ToMemOperand(InstructionOperand* op) const { DCHECK(op != NULL); @@ -125,6 +122,98 @@ static inline bool HasRegisterInput(Instruction* instr, int index) { } +namespace { + +class OutOfLineLoadSingle FINAL : public OutOfLineCode { + public: + OutOfLineLoadSingle(CodeGenerator* gen, FloatRegister result) + : OutOfLineCode(gen), result_(result) {} + + void Generate() FINAL { + __ Move(result_, std::numeric_limits::quiet_NaN()); + } + + private: + FloatRegister const result_; +}; + + +class OutOfLineLoadDouble FINAL : public OutOfLineCode { + public: + OutOfLineLoadDouble(CodeGenerator* gen, DoubleRegister result) + : OutOfLineCode(gen), result_(result) {} + + void Generate() FINAL { + __ Move(result_, std::numeric_limits::quiet_NaN()); + } + + private: + DoubleRegister const result_; +}; + + +class OutOfLineLoadInteger FINAL : public OutOfLineCode { + public: + OutOfLineLoadInteger(CodeGenerator* gen, Register result) + : OutOfLineCode(gen), result_(result) {} + + void Generate() FINAL { __ mov(result_, zero_reg); } + + private: + Register const result_; +}; + +} // namespace + + +#define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ + do { \ + auto result = i.Output##width##Register(); \ + auto offset = i.InputRegister(0); \ + auto ool = new (zone()) OutOfLineLoad##width(this, result); \ + __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ + __ Daddu(at, i.InputRegister(2), offset); \ + __ asm_instr(result, MemOperand(at, 0)); \ + __ bind(ool->exit()); \ + } while (0) + + +#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ + do { \ + auto result = i.OutputRegister(); \ + auto offset = i.InputRegister(0); \ + auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ + __ Branch(ool->entry(), hs, offset, Operand(i.InputRegister(1))); \ + __ Daddu(at, i.InputRegister(2), offset); \ + __ asm_instr(result, MemOperand(at, 0)); \ + __ bind(ool->exit()); \ + } while (0) + + +#define ASSEMBLE_CHECKED_STORE_FLOAT(width, asm_instr) \ + do { \ + auto offset = i.InputRegister(0); \ + Label done; \ + __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ + auto value = i.Input##width##Register(2); \ + __ Daddu(at, i.InputRegister(3), offset); \ + __ asm_instr(value, MemOperand(at, 0)); \ + __ bind(&done); \ + } while (0) + + +#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ + do { \ + auto offset = i.InputRegister(0); \ + Label done; \ + __ Branch(&done, hs, offset, Operand(i.InputRegister(1))); \ + auto value = i.InputRegister(2); \ + __ Daddu(at, i.InputRegister(3), offset); \ + __ asm_instr(value, MemOperand(at, 0)); \ + __ bind(&done); \ + } while (0) + + // Assembles an instruction after register allocation, producing machine code. void CodeGenerator::AssembleArchInstruction(Instruction* instr) { MipsOperandConverter i(this, instr); @@ -469,7 +558,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ sd(i.InputRegister(0), MemOperand(sp, slot << kPointerSizeLog2)); break; } - case kMips64StoreWriteBarrier: + case kMips64StoreWriteBarrier: { Register object = i.InputRegister(0); Register index = i.InputRegister(1); Register value = i.InputRegister(2); @@ -480,6 +569,43 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { RAStatus ra_status = kRAHasNotBeenSaved; __ RecordWrite(object, index, value, ra_status, mode); break; + } + case kCheckedLoadInt8: + ASSEMBLE_CHECKED_LOAD_INTEGER(lb); + break; + case kCheckedLoadUint8: + ASSEMBLE_CHECKED_LOAD_INTEGER(lbu); + break; + case kCheckedLoadInt16: + ASSEMBLE_CHECKED_LOAD_INTEGER(lh); + break; + case kCheckedLoadUint16: + ASSEMBLE_CHECKED_LOAD_INTEGER(lhu); + break; + case kCheckedLoadWord32: + ASSEMBLE_CHECKED_LOAD_INTEGER(lw); + break; + case kCheckedLoadFloat32: + ASSEMBLE_CHECKED_LOAD_FLOAT(Single, lwc1); + break; + case kCheckedLoadFloat64: + ASSEMBLE_CHECKED_LOAD_FLOAT(Double, ldc1); + break; + case kCheckedStoreWord8: + ASSEMBLE_CHECKED_STORE_INTEGER(sb); + break; + case kCheckedStoreWord16: + ASSEMBLE_CHECKED_STORE_INTEGER(sh); + break; + case kCheckedStoreWord32: + ASSEMBLE_CHECKED_STORE_INTEGER(sw); + break; + case kCheckedStoreFloat32: + ASSEMBLE_CHECKED_STORE_FLOAT(Single, swc1); + break; + case kCheckedStoreFloat64: + ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1); + break; } } @@ -1090,14 +1216,13 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, } if (destination->IsStackSlot()) __ sd(dst, g.ToMemOperand(destination)); } else if (src.type() == Constant::kFloat32) { - FPURegister dst = destination->IsDoubleRegister() - ? g.ToDoubleRegister(destination) - : kScratchDoubleReg.low(); - // TODO(turbofan): Can we do better here? - __ li(at, Operand(bit_cast(src.ToFloat32()))); - __ mtc1(at, dst); if (destination->IsDoubleStackSlot()) { - __ swc1(dst, g.ToMemOperand(destination)); + MemOperand dst = g.ToMemOperand(destination); + __ li(at, Operand(bit_cast(src.ToFloat32()))); + __ sw(at, dst); + } else { + FloatRegister dst = g.ToSingleRegister(destination); + __ Move(dst, src.ToFloat32()); } } else { DCHECK_EQ(Constant::kFloat64, src.type()); diff --git a/src/compiler/mips64/instruction-selector-mips64.cc b/src/compiler/mips64/instruction-selector-mips64.cc index 24383f3..7cf12b6 100644 --- a/src/compiler/mips64/instruction-selector-mips64.cc +++ b/src/compiler/mips64/instruction-selector-mips64.cc @@ -680,6 +680,75 @@ void InstructionSelector::VisitCall(Node* node) { } +void InstructionSelector::VisitCheckedLoad(Node* node) { + MachineType rep = RepresentationOf(OpParameter(node)); + MachineType typ = TypeOf(OpParameter(node)); + Mips64OperandGenerator g(this); + Node* const buffer = node->InputAt(0); + Node* const offset = node->InputAt(1); + Node* const length = node->InputAt(2); + ArchOpcode opcode; + switch (rep) { + case kRepWord8: + opcode = typ == kTypeInt32 ? kCheckedLoadInt8 : kCheckedLoadUint8; + break; + case kRepWord16: + opcode = typ == kTypeInt32 ? kCheckedLoadInt16 : kCheckedLoadUint16; + break; + case kRepWord32: + opcode = kCheckedLoadWord32; + break; + case kRepFloat32: + opcode = kCheckedLoadFloat32; + break; + case kRepFloat64: + opcode = kCheckedLoadFloat64; + break; + default: + UNREACHABLE(); + return; + } + InstructionOperand* offset_operand = g.UseRegister(offset); + Emit(opcode | AddressingModeField::encode(kMode_MRI), + g.DefineAsRegister(node), offset_operand, g.UseRegister(length), + g.UseRegister(buffer)); +} + + +void InstructionSelector::VisitCheckedStore(Node* node) { + MachineType rep = RepresentationOf(OpParameter(node)); + Mips64OperandGenerator g(this); + Node* const buffer = node->InputAt(0); + Node* const offset = node->InputAt(1); + Node* const length = node->InputAt(2); + Node* const value = node->InputAt(3); + ArchOpcode opcode; + switch (rep) { + case kRepWord8: + opcode = kCheckedStoreWord8; + break; + case kRepWord16: + opcode = kCheckedStoreWord16; + break; + case kRepWord32: + opcode = kCheckedStoreWord32; + break; + case kRepFloat32: + opcode = kCheckedStoreFloat32; + break; + case kRepFloat64: + opcode = kCheckedStoreFloat64; + break; + default: + UNREACHABLE(); + return; + } + InstructionOperand* offset_operand = g.UseRegister(offset); + Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, offset_operand, + g.UseRegister(length), g.UseRegister(value), g.UseRegister(buffer)); +} + + namespace { // Shared routine for multiple compare operations. diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc index 19ad812..55c073f 100644 --- a/src/mips64/code-stubs-mips64.cc +++ b/src/mips64/code-stubs-mips64.cc @@ -851,7 +851,7 @@ void MathPowStub::Generate(MacroAssembler* masm) { // double_scratch can be overwritten in the delay slot. // Calculates square root of base. Check for the special case of // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). - __ Move(double_scratch, -V8_INFINITY); + __ Move(double_scratch, static_cast(-V8_INFINITY)); __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); __ neg_d(double_result, double_scratch); @@ -871,13 +871,13 @@ void MathPowStub::Generate(MacroAssembler* masm) { // double_scratch can be overwritten in the delay slot. // Calculates square root of base. Check for the special case of // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). - __ Move(double_scratch, -V8_INFINITY); + __ Move(double_scratch, static_cast(-V8_INFINITY)); __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); __ Move(double_result, kDoubleRegZero); // Add +0 to convert -0 to +0. __ add_d(double_scratch, double_base, kDoubleRegZero); - __ Move(double_result, 1); + __ Move(double_result, 1.); __ sqrt_d(double_scratch, double_scratch); __ div_d(double_result, double_result, double_scratch); __ jmp(&done); diff --git a/src/mips64/codegen-mips64.cc b/src/mips64/codegen-mips64.cc index cffac91..b292506 100644 --- a/src/mips64/codegen-mips64.cc +++ b/src/mips64/codegen-mips64.cc @@ -1033,7 +1033,7 @@ void MathExpGenerator::EmitMathExp(MacroAssembler* masm, // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1. DCHECK(*reinterpret_cast (ExternalReference::math_exp_constants(8).address()) == 1); - __ Move(double_scratch2, 1); + __ Move(double_scratch2, 1.); __ add_d(result, result, double_scratch2); __ dsrl(temp1, temp2, 11); __ Ext(temp2, temp2, 0, 11); diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc index 35839e6..ecf08d0 100644 --- a/src/mips64/lithium-codegen-mips64.cc +++ b/src/mips64/lithium-codegen-mips64.cc @@ -3869,7 +3869,7 @@ void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { // Math.pow(-Infinity, 0.5) == Infinity // Math.sqrt(-Infinity) == NaN Label done; - __ Move(temp, -V8_INFINITY); + __ Move(temp, static_cast(-V8_INFINITY)); __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input); // Set up Infinity in the delay slot. // result is overwritten if the branch is not taken. diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc index b621e86..916231b 100644 --- a/src/mips64/macro-assembler-mips64.cc +++ b/src/mips64/macro-assembler-mips64.cc @@ -1717,6 +1717,12 @@ void MacroAssembler::BranchF(Label* target, } +void MacroAssembler::Move(FPURegister dst, float imm) { + li(at, Operand(bit_cast(imm))); + mtc1(at, dst); +} + + void MacroAssembler::Move(FPURegister dst, double imm) { static const DoubleRepresentation minus_zero(-0.0); static const DoubleRepresentation zero(0.0); diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h index f0f009f..8fe546d 100644 --- a/src/mips64/macro-assembler-mips64.h +++ b/src/mips64/macro-assembler-mips64.h @@ -271,8 +271,10 @@ class MacroAssembler: public Assembler { mthc1(src_high, dst); } - // Conditional move. + void Move(FPURegister dst, float imm); void Move(FPURegister dst, double imm); + + // Conditional move. void Movz(Register rd, Register rs, Register rt); void Movn(Register rd, Register rs, Register rt); void Movt(Register rd, Register rs, uint16_t cc = 0); -- 2.7.4