Commit 322d246e authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

ARM: Improve register allocation and constraints.

Gives ~20% boost for Crypto benchmark on A9.

BUG=none
TEST=none

Review URL: http://codereview.chromium.org//7148018
Patch from Martyn Capewell <m.m.capewell@googlemail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8381 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8677fd37
...@@ -167,13 +167,14 @@ struct SwVfpRegister { ...@@ -167,13 +167,14 @@ struct SwVfpRegister {
// Double word VFP register. // Double word VFP register.
struct DwVfpRegister { struct DwVfpRegister {
// d0 has been excluded from allocation. This is following ia32
// where xmm0 is excluded. This should be revisited.
// Currently d0 is used as a scratch register.
// d1 has also been excluded from allocation to be used as a scratch
// register as well.
static const int kNumRegisters = 16; static const int kNumRegisters = 16;
static const int kNumAllocatableRegisters = 15; // A few double registers are reserved: one as a scratch register and one to
// hold 0.0, that does not fit in the immediate field of vmov instructions.
// d14: 0.0
// d15: scratch register.
static const int kNumReservedRegisters = 2;
static const int kNumAllocatableRegisters = kNumRegisters -
kNumReservedRegisters;
static int ToAllocationIndex(DwVfpRegister reg) { static int ToAllocationIndex(DwVfpRegister reg) {
ASSERT(reg.code() != 0); ASSERT(reg.code() != 0);
...@@ -188,6 +189,7 @@ struct DwVfpRegister { ...@@ -188,6 +189,7 @@ struct DwVfpRegister {
static const char* AllocationIndexToString(int index) { static const char* AllocationIndexToString(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters); ASSERT(index >= 0 && index < kNumAllocatableRegisters);
const char* const names[] = { const char* const names[] = {
"d0",
"d1", "d1",
"d2", "d2",
"d3", "d3",
...@@ -200,9 +202,7 @@ struct DwVfpRegister { ...@@ -200,9 +202,7 @@ struct DwVfpRegister {
"d10", "d10",
"d11", "d11",
"d12", "d12",
"d13", "d13"
"d14",
"d15"
}; };
return names[index]; return names[index];
} }
...@@ -306,6 +306,7 @@ const DwVfpRegister d15 = { 15 }; ...@@ -306,6 +306,7 @@ const DwVfpRegister d15 = { 15 };
// Aliases for double registers. // Aliases for double registers.
const DwVfpRegister kFirstCalleeSavedDoubleReg = d8; const DwVfpRegister kFirstCalleeSavedDoubleReg = d8;
const DwVfpRegister kLastCalleeSavedDoubleReg = d15; const DwVfpRegister kLastCalleeSavedDoubleReg = d15;
const DwVfpRegister kDoubleRegZero = d14;
// Coprocessor register // Coprocessor register
......
...@@ -3541,6 +3541,8 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { ...@@ -3541,6 +3541,8 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
CpuFeatures::Scope scope(VFP3); CpuFeatures::Scope scope(VFP3);
// Save callee-saved vfp registers. // Save callee-saved vfp registers.
__ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
// Set up the reserved register for 0.0.
__ vmov(kDoubleRegZero, 0.0);
} }
// Get address of argv, see stm above. // Get address of argv, see stm above.
......
...@@ -823,7 +823,7 @@ LInstruction* LChunkBuilder::DoBit(Token::Value op, ...@@ -823,7 +823,7 @@ LInstruction* LChunkBuilder::DoBit(Token::Value op,
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
return DefineSameAsFirst(new LBitI(op, left, right)); return DefineAsRegister(new LBitI(op, left, right));
} else { } else {
ASSERT(instr->representation().IsTagged()); ASSERT(instr->representation().IsTagged());
ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->left()->representation().IsTagged());
...@@ -862,7 +862,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, ...@@ -862,7 +862,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op,
right = chunk_->DefineConstantOperand(constant); right = chunk_->DefineConstantOperand(constant);
constant_value = constant->Integer32Value() & 0x1f; constant_value = constant->Integer32Value() & 0x1f;
} else { } else {
right = UseRegister(right_value); right = UseRegisterAtStart(right_value);
} }
// Shift operations can only deoptimize if we do a logical shift // Shift operations can only deoptimize if we do a logical shift
...@@ -879,7 +879,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, ...@@ -879,7 +879,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op,
} }
LInstruction* result = LInstruction* result =
DefineSameAsFirst(new LShiftI(op, left, right, does_deopt)); DefineAsRegister(new LShiftI(op, left, right, does_deopt));
return does_deopt ? AssignEnvironment(result) : result; return does_deopt ? AssignEnvironment(result) : result;
} }
...@@ -893,7 +893,7 @@ LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, ...@@ -893,7 +893,7 @@ LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
LOperand* left = UseRegisterAtStart(instr->left()); LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right()); LOperand* right = UseRegisterAtStart(instr->right());
LArithmeticD* result = new LArithmeticD(op, left, right); LArithmeticD* result = new LArithmeticD(op, left, right);
return DefineSameAsFirst(result); return DefineAsRegister(result);
} }
...@@ -1237,15 +1237,15 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { ...@@ -1237,15 +1237,15 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
switch (op) { switch (op) {
case kMathAbs: case kMathAbs:
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
case kMathFloor: case kMathFloor:
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
case kMathSqrt: case kMathSqrt:
return DefineSameAsFirst(result); return DefineAsRegister(result);
case kMathRound: case kMathRound:
return AssignEnvironment(DefineAsRegister(result)); return AssignEnvironment(DefineAsRegister(result));
case kMathPowHalf: case kMathPowHalf:
return DefineSameAsFirst(result); return DefineAsRegister(result);
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;
...@@ -1323,7 +1323,7 @@ LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { ...@@ -1323,7 +1323,7 @@ LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
ASSERT(instr->value()->representation().IsInteger32()); ASSERT(instr->value()->representation().IsInteger32());
ASSERT(instr->representation().IsInteger32()); ASSERT(instr->representation().IsInteger32());
return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value()))); return DefineAsRegister(new LBitNotI(UseRegisterAtStart(instr->value())));
} }
...@@ -1372,11 +1372,14 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) { ...@@ -1372,11 +1372,14 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
mod = new LModI(dividend, mod = new LModI(dividend,
divisor, divisor,
TempRegister(), TempRegister(),
FixedTemp(d1), FixedTemp(d10),
FixedTemp(d2)); FixedTemp(d11));
} }
return AssignEnvironment(DefineSameAsFirst(mod)); bool needs_env = (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
instr->CheckFlag(HValue::kCanBeDivByZero));
return needs_env ? AssignEnvironment(DefineAsRegister(mod))
: DefineAsRegister(mod);
} else if (instr->representation().IsTagged()) { } else if (instr->representation().IsTagged()) {
return DoArithmeticT(Token::MOD, instr); return DoArithmeticT(Token::MOD, instr);
} else { } else {
...@@ -1396,15 +1399,18 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { ...@@ -1396,15 +1399,18 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
if (instr->representation().IsInteger32()) { if (instr->representation().IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); LOperand* left;
LOperand* right = UseOrConstant(instr->MostConstantOperand()); LOperand* right = UseOrConstant(instr->MostConstantOperand());
LOperand* temp = NULL; LOperand* temp = NULL;
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
(instr->CheckFlag(HValue::kCanOverflow) || (instr->CheckFlag(HValue::kCanOverflow) ||
!right->IsConstantOperand())) { !right->IsConstantOperand())) {
left = UseRegister(instr->LeastConstantOperand());
temp = TempRegister(); temp = TempRegister();
} else {
left = UseRegisterAtStart(instr->LeastConstantOperand());
} }
return AssignEnvironment(DefineSameAsFirst(new LMulI(left, right, temp))); return AssignEnvironment(DefineAsRegister(new LMulI(left, right, temp)));
} else if (instr->representation().IsDouble()) { } else if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::MUL, instr); return DoArithmeticD(Token::MUL, instr);
...@@ -1422,7 +1428,7 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) { ...@@ -1422,7 +1428,7 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
LOperand* left = UseRegisterAtStart(instr->left()); LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right()); LOperand* right = UseOrConstantAtStart(instr->right());
LSubI* sub = new LSubI(left, right); LSubI* sub = new LSubI(left, right);
LInstruction* result = DefineSameAsFirst(sub); LInstruction* result = DefineAsRegister(sub);
if (instr->CheckFlag(HValue::kCanOverflow)) { if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result); result = AssignEnvironment(result);
} }
...@@ -1442,7 +1448,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { ...@@ -1442,7 +1448,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
LAddI* add = new LAddI(left, right); LAddI* add = new LAddI(left, right);
LInstruction* result = DefineSameAsFirst(add); LInstruction* result = DefineAsRegister(add);
if (instr->CheckFlag(HValue::kCanOverflow)) { if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result); result = AssignEnvironment(result);
} }
...@@ -1608,7 +1614,7 @@ LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { ...@@ -1608,7 +1614,7 @@ LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
LOperand* object = UseRegister(instr->value()); LOperand* object = UseRegister(instr->value());
LValueOf* result = new LValueOf(object, TempRegister()); LValueOf* result = new LValueOf(object, TempRegister());
return AssignEnvironment(DefineSameAsFirst(result)); return AssignEnvironment(DefineAsRegister(result));
} }
...@@ -1663,7 +1669,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1663,7 +1669,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* temp1 = TempRegister(); LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL; : NULL;
LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3) LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
: NULL; : NULL;
res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3)); res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
res = AssignEnvironment(res); res = AssignEnvironment(res);
...@@ -1757,14 +1763,14 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { ...@@ -1757,14 +1763,14 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
Representation input_rep = value->representation(); Representation input_rep = value->representation();
LOperand* reg = UseRegister(value); LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) { if (input_rep.IsDouble()) {
return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d1))); return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11)));
} else if (input_rep.IsInteger32()) { } else if (input_rep.IsInteger32()) {
return DefineAsRegister(new LClampIToUint8(reg)); return DefineAsRegister(new LClampIToUint8(reg));
} else { } else {
ASSERT(input_rep.IsTagged()); ASSERT(input_rep.IsTagged());
// Register allocator doesn't (yet) support allocation of double // Register allocator doesn't (yet) support allocation of double
// temps. Reserve d1 explicitly. // temps. Reserve d1 explicitly.
LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d1)); LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11));
return AssignEnvironment(DefineAsRegister(result)); return AssignEnvironment(DefineAsRegister(result));
} }
} }
...@@ -1788,7 +1794,7 @@ LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) { ...@@ -1788,7 +1794,7 @@ LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) {
ASSERT(input_rep.IsTagged()); ASSERT(input_rep.IsTagged());
LOperand* temp1 = TempRegister(); LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister(); LOperand* temp2 = TempRegister();
LOperand* temp3 = FixedTemp(d3); LOperand* temp3 = FixedTemp(d11);
LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3); LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3);
return AssignEnvironment(DefineSameAsFirst(res)); return AssignEnvironment(DefineSameAsFirst(res));
} }
...@@ -1926,7 +1932,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( ...@@ -1926,7 +1932,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterAtStart(instr->key()); LOperand* key = UseRegisterAtStart(instr->key());
LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
return AssignEnvironment(DefineSameAsFirst(result)); return AssignEnvironment(DefineAsRegister(result));
} }
......
This diff is collapsed.
...@@ -148,7 +148,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -148,7 +148,7 @@ class LCodeGen BASE_EMBEDDED {
HGraph* graph() const { return chunk_->graph(); } HGraph* graph() const { return chunk_->graph(); }
Register scratch0() { return r9; } Register scratch0() { return r9; }
DwVfpRegister double_scratch0() { return d0; } DwVfpRegister double_scratch0() { return d15; }
int GetNextEmittedBlock(int block); int GetNextEmittedBlock(int block);
LInstruction* GetNextInstruction(); LInstruction* GetNextInstruction();
......
...@@ -309,9 +309,9 @@ void MacroAssembler::Move(Register dst, Handle<Object> value) { ...@@ -309,9 +309,9 @@ void MacroAssembler::Move(Register dst, Handle<Object> value) {
} }
void MacroAssembler::Move(Register dst, Register src) { void MacroAssembler::Move(Register dst, Register src, Condition cond) {
if (!dst.is(src)) { if (!dst.is(src)) {
mov(dst, src); mov(dst, src, LeaveCC, cond);
} }
} }
...@@ -755,6 +755,23 @@ void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1, ...@@ -755,6 +755,23 @@ void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
vmrs(fpscr_flags, cond); vmrs(fpscr_flags, cond);
} }
void MacroAssembler::Vmov(const DwVfpRegister dst,
const double imm,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
static const DoubleRepresentation minus_zero(-0.0);
static const DoubleRepresentation zero(0.0);
DoubleRepresentation value(imm);
// Handle special values first.
if (value.bits == zero.bits) {
vmov(dst, kDoubleRegZero, cond);
} else if (value.bits == minus_zero.bits) {
vneg(dst, kDoubleRegZero, cond);
} else {
vmov(dst, imm, cond);
}
}
void MacroAssembler::EnterFrame(StackFrame::Type type) { void MacroAssembler::EnterFrame(StackFrame::Type type) {
// r0-r3: preserved // r0-r3: preserved
...@@ -3112,7 +3129,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg, ...@@ -3112,7 +3129,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
Label done; Label done;
Label in_bounds; Label in_bounds;
vmov(temp_double_reg, 0.0); Vmov(temp_double_reg, 0.0);
VFPCompareAndSetFlags(input_reg, temp_double_reg); VFPCompareAndSetFlags(input_reg, temp_double_reg);
b(gt, &above_zero); b(gt, &above_zero);
...@@ -3122,7 +3139,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg, ...@@ -3122,7 +3139,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
// Double value is >= 255, return 255. // Double value is >= 255, return 255.
bind(&above_zero); bind(&above_zero);
vmov(temp_double_reg, 255.0); Vmov(temp_double_reg, 255.0);
VFPCompareAndSetFlags(input_reg, temp_double_reg); VFPCompareAndSetFlags(input_reg, temp_double_reg);
b(le, &in_bounds); b(le, &in_bounds);
mov(result_reg, Operand(255)); mov(result_reg, Operand(255));
...@@ -3130,7 +3147,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg, ...@@ -3130,7 +3147,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
// In 0-255 range, round and truncate. // In 0-255 range, round and truncate.
bind(&in_bounds); bind(&in_bounds);
vmov(temp_double_reg, 0.5); Vmov(temp_double_reg, 0.5);
vadd(temp_double_reg, input_reg, temp_double_reg); vadd(temp_double_reg, input_reg, temp_double_reg);
vcvt_u32_f64(s0, temp_double_reg); vcvt_u32_f64(s0, temp_double_reg);
vmov(result_reg, s0); vmov(result_reg, s0);
......
...@@ -143,7 +143,7 @@ class MacroAssembler: public Assembler { ...@@ -143,7 +143,7 @@ class MacroAssembler: public Assembler {
// Register move. May do nothing if the registers are identical. // Register move. May do nothing if the registers are identical.
void Move(Register dst, Handle<Object> value); void Move(Register dst, Handle<Object> value);
void Move(Register dst, Register src); void Move(Register dst, Register src, Condition cond = al);
void Move(DoubleRegister dst, DoubleRegister src); void Move(DoubleRegister dst, DoubleRegister src);
// Load an object from the root table. // Load an object from the root table.
...@@ -312,6 +312,10 @@ class MacroAssembler: public Assembler { ...@@ -312,6 +312,10 @@ class MacroAssembler: public Assembler {
const Register fpscr_flags, const Register fpscr_flags,
const Condition cond = al); const Condition cond = al);
void Vmov(const DwVfpRegister dst,
const double imm,
const Condition cond = al);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Activation frames // Activation frames
......
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