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 {
// Double word VFP register.
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 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) {
ASSERT(reg.code() != 0);
......@@ -188,6 +189,7 @@ struct DwVfpRegister {
static const char* AllocationIndexToString(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters);
const char* const names[] = {
"d0",
"d1",
"d2",
"d3",
......@@ -200,9 +202,7 @@ struct DwVfpRegister {
"d10",
"d11",
"d12",
"d13",
"d14",
"d15"
"d13"
};
return names[index];
}
......@@ -306,6 +306,7 @@ const DwVfpRegister d15 = { 15 };
// Aliases for double registers.
const DwVfpRegister kFirstCalleeSavedDoubleReg = d8;
const DwVfpRegister kLastCalleeSavedDoubleReg = d15;
const DwVfpRegister kDoubleRegZero = d14;
// Coprocessor register
......
......@@ -3541,6 +3541,8 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
CpuFeatures::Scope scope(VFP3);
// Save callee-saved vfp registers.
__ 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.
......
......@@ -823,7 +823,7 @@ LInstruction* LChunkBuilder::DoBit(Token::Value op,
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
return DefineSameAsFirst(new LBitI(op, left, right));
return DefineAsRegister(new LBitI(op, left, right));
} else {
ASSERT(instr->representation().IsTagged());
ASSERT(instr->left()->representation().IsTagged());
......@@ -862,7 +862,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op,
right = chunk_->DefineConstantOperand(constant);
constant_value = constant->Integer32Value() & 0x1f;
} else {
right = UseRegister(right_value);
right = UseRegisterAtStart(right_value);
}
// Shift operations can only deoptimize if we do a logical shift
......@@ -879,7 +879,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op,
}
LInstruction* result =
DefineSameAsFirst(new LShiftI(op, left, right, does_deopt));
DefineAsRegister(new LShiftI(op, left, right, does_deopt));
return does_deopt ? AssignEnvironment(result) : result;
}
......@@ -893,7 +893,7 @@ LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
LArithmeticD* result = new LArithmeticD(op, left, right);
return DefineSameAsFirst(result);
return DefineAsRegister(result);
}
......@@ -1237,15 +1237,15 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
switch (op) {
case kMathAbs:
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
case kMathFloor:
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
case kMathSqrt:
return DefineSameAsFirst(result);
return DefineAsRegister(result);
case kMathRound:
return AssignEnvironment(DefineAsRegister(result));
case kMathPowHalf:
return DefineSameAsFirst(result);
return DefineAsRegister(result);
default:
UNREACHABLE();
return NULL;
......@@ -1323,7 +1323,7 @@ LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
ASSERT(instr->value()->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) {
mod = new LModI(dividend,
divisor,
TempRegister(),
FixedTemp(d1),
FixedTemp(d2));
FixedTemp(d10),
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()) {
return DoArithmeticT(Token::MOD, instr);
} else {
......@@ -1396,15 +1399,18 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
if (instr->representation().IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* left;
LOperand* right = UseOrConstant(instr->MostConstantOperand());
LOperand* temp = NULL;
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
(instr->CheckFlag(HValue::kCanOverflow) ||
!right->IsConstantOperand())) {
left = UseRegister(instr->LeastConstantOperand());
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()) {
return DoArithmeticD(Token::MUL, instr);
......@@ -1422,7 +1428,7 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
LSubI* sub = new LSubI(left, right);
LInstruction* result = DefineSameAsFirst(sub);
LInstruction* result = DefineAsRegister(sub);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
}
......@@ -1442,7 +1448,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
LAddI* add = new LAddI(left, right);
LInstruction* result = DefineSameAsFirst(add);
LInstruction* result = DefineAsRegister(add);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
}
......@@ -1608,7 +1614,7 @@ LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
LOperand* object = UseRegister(instr->value());
LValueOf* result = new LValueOf(object, TempRegister());
return AssignEnvironment(DefineSameAsFirst(result));
return AssignEnvironment(DefineAsRegister(result));
}
......@@ -1663,7 +1669,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL;
LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3)
LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
: NULL;
res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
res = AssignEnvironment(res);
......@@ -1757,14 +1763,14 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
Representation input_rep = value->representation();
LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) {
return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d1)));
return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11)));
} else if (input_rep.IsInteger32()) {
return DefineAsRegister(new LClampIToUint8(reg));
} else {
ASSERT(input_rep.IsTagged());
// Register allocator doesn't (yet) support allocation of double
// temps. Reserve d1 explicitly.
LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d1));
LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11));
return AssignEnvironment(DefineAsRegister(result));
}
}
......@@ -1788,7 +1794,7 @@ LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) {
ASSERT(input_rep.IsTagged());
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LOperand* temp3 = FixedTemp(d3);
LOperand* temp3 = FixedTemp(d11);
LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3);
return AssignEnvironment(DefineSameAsFirst(res));
}
......@@ -1926,7 +1932,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterAtStart(instr->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 {
HGraph* graph() const { return chunk_->graph(); }
Register scratch0() { return r9; }
DwVfpRegister double_scratch0() { return d0; }
DwVfpRegister double_scratch0() { return d15; }
int GetNextEmittedBlock(int block);
LInstruction* GetNextInstruction();
......
......@@ -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)) {
mov(dst, src);
mov(dst, src, LeaveCC, cond);
}
}
......@@ -755,6 +755,23 @@ void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
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) {
// r0-r3: preserved
......@@ -3112,7 +3129,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
Label done;
Label in_bounds;
vmov(temp_double_reg, 0.0);
Vmov(temp_double_reg, 0.0);
VFPCompareAndSetFlags(input_reg, temp_double_reg);
b(gt, &above_zero);
......@@ -3122,7 +3139,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
// Double value is >= 255, return 255.
bind(&above_zero);
vmov(temp_double_reg, 255.0);
Vmov(temp_double_reg, 255.0);
VFPCompareAndSetFlags(input_reg, temp_double_reg);
b(le, &in_bounds);
mov(result_reg, Operand(255));
......@@ -3130,7 +3147,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
// In 0-255 range, round and truncate.
bind(&in_bounds);
vmov(temp_double_reg, 0.5);
Vmov(temp_double_reg, 0.5);
vadd(temp_double_reg, input_reg, temp_double_reg);
vcvt_u32_f64(s0, temp_double_reg);
vmov(result_reg, s0);
......
......@@ -143,7 +143,7 @@ class MacroAssembler: public Assembler {
// Register move. May do nothing if the registers are identical.
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);
// Load an object from the root table.
......@@ -312,6 +312,10 @@ class MacroAssembler: public Assembler {
const Register fpscr_flags,
const Condition cond = al);
void Vmov(const DwVfpRegister dst,
const double imm,
const Condition cond = al);
// ---------------------------------------------------------------------------
// 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