ARM: Optimisations for call, jump and untag.

Improves some V8 benchmarks by a few % on A9.

Patch by ARM Ltd.

BUG=none
TEST=Added to test-assembler-arm.cc.

Review URL: http://codereview.chromium.org/6874010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7647 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent dc99761f
......@@ -3614,10 +3614,13 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
LOperand* input = instr->InputAt(0);
ASSERT(input->IsRegister() && input->Equals(instr->result()));
if (instr->needs_check()) {
__ tst(ToRegister(input), Operand(kSmiTagMask));
DeoptimizeIf(ne, instr->environment());
ASSERT(kHeapObjectTag == 1);
// If the input is a HeapObject, SmiUntag will set the carry flag.
__ SmiUntag(ToRegister(input), SetCC);
DeoptimizeIf(cs, instr->environment());
} else {
__ SmiUntag(ToRegister(input));
}
__ SmiUntag(ToRegister(input));
}
......@@ -3688,6 +3691,12 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
Label done;
// The input was optimistically untagged; revert it.
// The carry flag is set when we reach this deferred code as we just executed
// SmiUntag(heap_object, SetCC)
ASSERT(kHeapObjectTag == 1);
__ adc(input_reg, input_reg, Operand(input_reg));
// Heap number map check.
__ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
......@@ -3760,13 +3769,12 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr);
// Smi check.
__ tst(input_reg, Operand(kSmiTagMask));
__ b(ne, deferred->entry());
// Smi to int32 conversion
__ SmiUntag(input_reg); // Untag smi.
// Optimistically untag the input.
// If the input is a HeapObject, SmiUntag will set the carry flag.
__ SmiUntag(input_reg, SetCC);
// Branch to deferred code if the input was tagged.
// The deferred code will take care of restoring the tag.
__ b(cs, deferred->entry());
__ bind(deferred->exit());
}
......
......@@ -83,7 +83,7 @@ void MacroAssembler::Jump(Register target, Condition cond) {
void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
Condition cond) {
#if USE_BX
mov(ip, Operand(target, rmode), LeaveCC, cond);
mov(ip, Operand(target, rmode));
bx(ip, cond);
#else
mov(pc, Operand(target, rmode), LeaveCC, cond);
......@@ -168,7 +168,7 @@ void MacroAssembler::Call(intptr_t target,
// we have to do it explicitly.
positions_recorder()->WriteRecordedPositions();
mov(ip, Operand(target, rmode), LeaveCC, cond);
mov(ip, Operand(target, rmode));
blx(ip, cond);
ASSERT(kCallTargetAddressOffset == 2 * kInstrSize);
......@@ -2887,7 +2887,7 @@ void MacroAssembler::CallCFunctionHelper(Register function,
Call(function);
int stack_passed_arguments = (num_arguments <= kRegisterPassedArguments) ?
0 : num_arguments - kRegisterPassedArguments;
if (OS::ActivationFrameAlignment() > kPointerSize) {
if (ActivationFrameAlignment() > kPointerSize) {
ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
} else {
add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
......
......@@ -1282,12 +1282,13 @@ void Simulator::SetVFlag(bool val) {
// Calculate C flag value for additions.
bool Simulator::CarryFrom(int32_t left, int32_t right) {
bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
uint32_t uleft = static_cast<uint32_t>(left);
uint32_t uright = static_cast<uint32_t>(right);
uint32_t urest = 0xffffffffU - uleft;
return (uright > urest);
return (uright > urest) ||
(carry && (((uright + 1) > urest) || (uright > (urest - 1))));
}
......@@ -2209,8 +2210,15 @@ void Simulator::DecodeType01(Instruction* instr) {
}
case ADC: {
Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
Format(instr, "adc'cond's 'rd, 'rn, 'imm");
// Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
// Format(instr, "adc'cond's 'rd, 'rn, 'imm");
alu_out = rn_val + shifter_operand + GetCarry();
set_register(rd, alu_out);
if (instr->HasS()) {
SetNZFlags(alu_out);
SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
}
break;
}
......
......@@ -223,13 +223,17 @@ class Simulator {
void SetNZFlags(int32_t val);
void SetCFlag(bool val);
void SetVFlag(bool val);
bool CarryFrom(int32_t left, int32_t right);
bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
bool BorrowFrom(int32_t left, int32_t right);
bool OverflowFrom(int32_t alu_out,
int32_t left,
int32_t right,
bool addition);
inline int GetCarry() {
return c_flag_ ? 1 : 0;
};
// Support for VFP.
void Compute_FPSCR_Flags(double val1, double val2);
void Copy_FPSCR_to_APSR();
......
......@@ -945,4 +945,69 @@ TEST(10) {
}
}
TEST(11) {
// Test instructions using the carry flag.
InitializeVM();
v8::HandleScope scope;
typedef struct {
int32_t a;
int32_t b;
int32_t c;
int32_t d;
} I;
I i;
i.a = 0xabcd0001;
i.b = 0xabcd0000;
Assembler assm(Isolate::Current(), NULL, 0);
// Test HeapObject untagging.
__ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
__ mov(r1, Operand(r1, ASR, 1), SetCC);
__ adc(r1, r1, Operand(r1), LeaveCC, cs);
__ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
__ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
__ mov(r2, Operand(r2, ASR, 1), SetCC);
__ adc(r2, r2, Operand(r2), LeaveCC, cs);
__ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
// Test corner cases.
__ mov(r1, Operand(0xffffffff));
__ mov(r2, Operand(0));
__ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
__ adc(r3, r1, Operand(r2));
__ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
__ mov(r1, Operand(0xffffffff));
__ mov(r2, Operand(0));
__ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
__ adc(r3, r1, Operand(r2));
__ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
__ mov(pc, Operand(lr));
CodeDesc desc;
assm.GetCode(&desc);
Object* code = HEAP->CreateCode(
desc,
Code::ComputeFlags(Code::STUB),
Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
CHECK(code->IsCode());
#ifdef DEBUG
Code::cast(code)->Print();
#endif
F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
USE(dummy);
CHECK_EQ(0xabcd0001, i.a);
CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
CHECK_EQ(0x00000000, i.c);
CHECK_EQ(0xffffffff, i.d);
}
#undef __
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