MIPS: [turbofan] Add checked load/store operators.

Port c516d4f094

Partial port to un-break the build. There are a few failing
tests, and the code is suboptimal for smaller offsets.

Fixes and mips64 port will come in another CL.

BUG=

Review URL: https://codereview.chromium.org/762853004

Cr-Commit-Position: refs/heads/master@{#25626}
This commit is contained in:
paul.lind 2014-12-02 16:28:07 -08:00 committed by Commit bot
parent 34d9be2e58
commit a07045af54
6 changed files with 217 additions and 15 deletions

View File

@ -102,10 +102,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);
@ -124,6 +121,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<float>::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<double>::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))); \
__ addu(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))); \
__ addu(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); \
__ addu(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); \
__ addu(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);
@ -373,7 +462,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kMipsPush:
__ Push(i.InputRegister(0));
break;
case kMipsStoreWriteBarrier:
case kMipsStoreWriteBarrier: {
Register object = i.InputRegister(0);
Register index = i.InputRegister(1);
Register value = i.InputRegister(2);
@ -384,6 +473,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;
}
}
@ -805,14 +931,13 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
}
if (destination->IsStackSlot()) __ sw(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<int32_t>(src.ToFloat32())));
__ mtc1(at, dst);
if (destination->IsDoubleStackSlot()) {
__ swc1(dst, g.ToMemOperand(destination));
MemOperand dst = g.ToMemOperand(destination);
__ li(at, Operand(bit_cast<int32_t>(src.ToFloat32())));
__ sw(at, dst);
} else {
FloatRegister dst = g.ToSingleRegister(destination);
__ Move(dst, src.ToFloat32());
}
} else {
DCHECK_EQ(Constant::kFloat64, src.type());

View File

@ -483,6 +483,75 @@ void InstructionSelector::VisitCall(Node* node) {
}
void InstructionSelector::VisitCheckedLoad(Node* node) {
MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
MachineType typ = TypeOf(OpParameter<MachineType>(node));
MipsOperandGenerator 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<MachineType>(node));
MipsOperandGenerator 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.

View File

@ -882,7 +882,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
// 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);

View File

@ -1145,7 +1145,7 @@ void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
// Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
DCHECK(*reinterpret_cast<double*>
(ExternalReference::math_exp_constants(8).address()) == 1);
__ Move(double_scratch2, 1);
__ Move(double_scratch2, 1.);
__ add_d(result, result, double_scratch2);
__ srl(temp1, temp2, 11);
__ Ext(temp2, temp2, 0, 11);

View File

@ -1549,6 +1549,12 @@ void MacroAssembler::BranchF(Label* target,
}
void MacroAssembler::Move(FPURegister dst, float imm) {
li(at, Operand(bit_cast<int32_t>(imm)));
mtc1(at, dst);
}
void MacroAssembler::Move(FPURegister dst, double imm) {
static const DoubleRepresentation minus_zero(-0.0);
static const DoubleRepresentation zero(0.0);

View File

@ -250,8 +250,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);