Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Unified Diff: src/arm/assembler-arm.cc

Issue 2084017: Version 2.2.11... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/assembler-arm.cc
===================================================================
--- src/arm/assembler-arm.cc (revision 4699)
+++ src/arm/assembler-arm.cc (working copy)
@@ -36,6 +36,8 @@
#include "v8.h"
+#if defined(V8_TARGET_ARCH_ARM)
+
#include "arm/assembler-arm-inl.h"
#include "serialize.h"
@@ -106,6 +108,15 @@
const int RelocInfo::kApplyMask = 0;
+bool RelocInfo::IsCodedSpecially() {
+ // The deserializer needs to know whether a pointer is specially coded. Being
+ // specially coded on ARM means that it is a movw/movt instruction. We don't
+ // generate those yet.
+ return false;
+}
+
+
+
void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
// Patch the code at the current address with the supplied instructions.
Instr* pc = reinterpret_cast<Instr*>(pc_);
@@ -268,6 +279,20 @@
15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
const Instr kBlxRegPattern =
B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4;
+// A mask for the Rd register for push, pop, ldr, str instructions.
+const Instr kRdMask = 0x0000f000;
+static const int kRdShift = 12;
+static const Instr kLdrRegFpOffsetPattern =
+ al | B26 | L | Offset | fp.code() * B16;
+static const Instr kStrRegFpOffsetPattern =
+ al | B26 | Offset | fp.code() * B16;
+static const Instr kLdrRegFpNegOffsetPattern =
+ al | B26 | L | NegOffset | fp.code() * B16;
+static const Instr kStrRegFpNegOffsetPattern =
+ al | B26 | NegOffset | fp.code() * B16;
+static const Instr kLdrStrInstrTypeMask = 0xffff0000;
+static const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
+static const Instr kLdrStrOffsetMask = 0x00000fff;
// Spare buffer.
static const int kMinimalBufferSize = 4*KB;
@@ -395,6 +420,43 @@
}
+Register Assembler::GetRd(Instr instr) {
+ Register reg;
+ reg.code_ = ((instr & kRdMask) >> kRdShift);
+ return reg;
+}
+
+
+bool Assembler::IsPush(Instr instr) {
+ return ((instr & ~kRdMask) == kPushRegPattern);
+}
+
+
+bool Assembler::IsPop(Instr instr) {
+ return ((instr & ~kRdMask) == kPopRegPattern);
+}
+
+
+bool Assembler::IsStrRegFpOffset(Instr instr) {
+ return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
+}
+
+
+bool Assembler::IsLdrRegFpOffset(Instr instr) {
+ return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
+}
+
+
+bool Assembler::IsStrRegFpNegOffset(Instr instr) {
+ return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
+}
+
+
+bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
+ return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
+}
+
+
// Labels refer to positions in the (to be) generated code.
// There are bound, linked, and unused labels.
//
@@ -887,15 +949,12 @@
// str(src, MemOperand(sp, 4, NegPreIndex), al);
// add(sp, sp, Operand(kPointerSize));
// Both instructions can be eliminated.
- int pattern_size = 2 * kInstrSize;
- if (FLAG_push_pop_elimination &&
- last_bound_pos_ <= (pc_offset() - pattern_size) &&
- reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+ if (can_peephole_optimize(2) &&
// Pattern.
instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
(instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
pc_ -= 2 * kInstrSize;
- if (FLAG_print_push_pop_elimination) {
+ if (FLAG_print_peephole_optimization) {
PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
}
}
@@ -1086,22 +1145,172 @@
}
addrmod2(cond | B26 | L, dst, src);
- // Eliminate pattern: push(r), pop(r)
- // str(r, MemOperand(sp, 4, NegPreIndex), al)
- // ldr(r, MemOperand(sp, 4, PostIndex), al)
- // Both instructions can be eliminated.
- int pattern_size = 2 * kInstrSize;
- if (FLAG_push_pop_elimination &&
- last_bound_pos_ <= (pc_offset() - pattern_size) &&
- reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
- // Pattern.
- instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) &&
- instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) {
- pc_ -= 2 * kInstrSize;
- if (FLAG_print_push_pop_elimination) {
- PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
+ // Eliminate pattern: push(ry), pop(rx)
+ // str(ry, MemOperand(sp, 4, NegPreIndex), al)
+ // ldr(rx, MemOperand(sp, 4, PostIndex), al)
+ // Both instructions can be eliminated if ry = rx.
+ // If ry != rx, a register copy from ry to rx is inserted
+ // after eliminating the push and the pop instructions.
+ Instr push_instr = instr_at(pc_ - 2 * kInstrSize);
+ Instr pop_instr = instr_at(pc_ - 1 * kInstrSize);
+
+ if (can_peephole_optimize(2) &&
+ IsPush(push_instr) &&
+ IsPop(pop_instr)) {
+ if ((pop_instr & kRdMask) != (push_instr & kRdMask)) {
+ // For consecutive push and pop on different registers,
+ // we delete both the push & pop and insert a register move.
+ // push ry, pop rx --> mov rx, ry
+ Register reg_pushed, reg_popped;
+ reg_pushed = GetRd(push_instr);
+ reg_popped = GetRd(pop_instr);
+ pc_ -= 2 * kInstrSize;
+ // Insert a mov instruction, which is better than a pair of push & pop
+ mov(reg_popped, reg_pushed);
+ if (FLAG_print_peephole_optimization) {
+ PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset());
+ }
+ } else {
+ // For consecutive push and pop on the same register,
+ // both the push and the pop can be deleted.
+ pc_ -= 2 * kInstrSize;
+ if (FLAG_print_peephole_optimization) {
+ PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
+ }
}
}
+
+ if (can_peephole_optimize(2)) {
+ Instr str_instr = instr_at(pc_ - 2 * kInstrSize);
+ Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize);
+
+ if ((IsStrRegFpOffset(str_instr) &&
+ IsLdrRegFpOffset(ldr_instr)) ||
+ (IsStrRegFpNegOffset(str_instr) &&
+ IsLdrRegFpNegOffset(ldr_instr))) {
+ if ((ldr_instr & kLdrStrInstrArgumentMask) ==
+ (str_instr & kLdrStrInstrArgumentMask)) {
+ // Pattern: Ldr/str same fp+offset, same register.
+ //
+ // The following:
+ // str rx, [fp, #-12]
+ // ldr rx, [fp, #-12]
+ //
+ // Becomes:
+ // str rx, [fp, #-12]
+
+ pc_ -= 1 * kInstrSize;
+ if (FLAG_print_peephole_optimization) {
+ PrintF("%x str/ldr (fp + same offset), same reg\n", pc_offset());
+ }
+ } else if ((ldr_instr & kLdrStrOffsetMask) ==
+ (str_instr & kLdrStrOffsetMask)) {
+ // Pattern: Ldr/str same fp+offset, different register.
+ //
+ // The following:
+ // str rx, [fp, #-12]
+ // ldr ry, [fp, #-12]
+ //
+ // Becomes:
+ // str rx, [fp, #-12]
+ // mov ry, rx
+
+ Register reg_stored, reg_loaded;
+ reg_stored = GetRd(str_instr);
+ reg_loaded = GetRd(ldr_instr);
+ pc_ -= 1 * kInstrSize;
+ // Insert a mov instruction, which is better than ldr.
+ mov(reg_loaded, reg_stored);
+ if (FLAG_print_peephole_optimization) {
+ PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset());
+ }
+ }
+ }
+ }
+
+ if (can_peephole_optimize(3)) {
+ Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize);
+ Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize);
+ Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize);
+ if (IsPush(mem_write_instr) &&
+ IsPop(mem_read_instr)) {
+ if ((IsLdrRegFpOffset(ldr_instr) ||
+ IsLdrRegFpNegOffset(ldr_instr))) {
+ if ((mem_write_instr & kRdMask) ==
+ (mem_read_instr & kRdMask)) {
+ // Pattern: push & pop from/to same register,
+ // with a fp+offset ldr in between
+ //
+ // The following:
+ // str rx, [sp, #-4]!
+ // ldr rz, [fp, #-24]
+ // ldr rx, [sp], #+4
+ //
+ // Becomes:
+ // if(rx == rz)
+ // delete all
+ // else
+ // ldr rz, [fp, #-24]
+
+ if ((mem_write_instr & kRdMask) == (ldr_instr & kRdMask)) {
+ pc_ -= 3 * kInstrSize;
+ } else {
+ pc_ -= 3 * kInstrSize;
+ // Reinsert back the ldr rz.
+ emit(ldr_instr);
+ }
+ if (FLAG_print_peephole_optimization) {
+ PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
+ }
+ } else {
+ // Pattern: push & pop from/to different registers
+ // with a fp+offset ldr in between
+ //
+ // The following:
+ // str rx, [sp, #-4]!
+ // ldr rz, [fp, #-24]
+ // ldr ry, [sp], #+4
+ //
+ // Becomes:
+ // if(ry == rz)
+ // mov ry, rx;
+ // else if(rx != rz)
+ // ldr rz, [fp, #-24]
+ // mov ry, rx
+ // else if((ry != rz) || (rx == rz)) becomes:
+ // mov ry, rx
+ // ldr rz, [fp, #-24]
+
+ Register reg_pushed, reg_popped;
+ if ((mem_read_instr & kRdMask) == (ldr_instr & kRdMask)) {
+ reg_pushed = GetRd(mem_write_instr);
+ reg_popped = GetRd(mem_read_instr);
+ pc_ -= 3 * kInstrSize;
+ mov(reg_popped, reg_pushed);
+ } else if ((mem_write_instr & kRdMask)
+ != (ldr_instr & kRdMask)) {
+ reg_pushed = GetRd(mem_write_instr);
+ reg_popped = GetRd(mem_read_instr);
+ pc_ -= 3 * kInstrSize;
+ emit(ldr_instr);
+ mov(reg_popped, reg_pushed);
+ } else if (((mem_read_instr & kRdMask)
+ != (ldr_instr & kRdMask)) ||
+ ((mem_write_instr & kRdMask)
+ == (ldr_instr & kRdMask)) ) {
+ reg_pushed = GetRd(mem_write_instr);
+ reg_popped = GetRd(mem_read_instr);
+ pc_ -= 3 * kInstrSize;
+ mov(reg_popped, reg_pushed);
+ emit(ldr_instr);
+ }
+ if (FLAG_print_peephole_optimization) {
+ PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
+ }
+ }
+ }
+ }
+ }
}
@@ -1111,16 +1320,13 @@
// Eliminate pattern: pop(), push(r)
// add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
// -> str r, [sp, 0], al
- int pattern_size = 2 * kInstrSize;
- if (FLAG_push_pop_elimination &&
- last_bound_pos_ <= (pc_offset() - pattern_size) &&
- reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+ if (can_peephole_optimize(2) &&
// Pattern.
instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
pc_ -= 2 * kInstrSize;
emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
- if (FLAG_print_push_pop_elimination) {
+ if (FLAG_print_peephole_optimization) {
PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
}
}
@@ -1162,12 +1368,18 @@
#ifdef CAN_USE_ARMV7_INSTRUCTIONS
addrmod3(cond | B7 | B6 | B4, dst, src);
#else
- ldr(dst, src, cond);
+ // Generate two ldr instructions if ldrd is not available.
MemOperand src1(src);
src1.set_offset(src1.offset() + 4);
Register dst1(dst);
- dst1.code_ = dst1.code_ + 1;
- ldr(dst1, src1, cond);
+ dst1.set_code(dst1.code() + 1);
+ if (dst.is(src.rn())) {
+ ldr(dst1, src1, cond);
+ ldr(dst, src, cond);
+ } else {
+ ldr(dst, src, cond);
+ ldr(dst1, src1, cond);
+ }
#endif
}
@@ -1177,11 +1389,12 @@
#ifdef CAN_USE_ARMV7_INSTRUCTIONS
addrmod3(cond | B7 | B6 | B5 | B4, src, dst);
#else
- str(src, dst, cond);
+ // Generate two str instructions if strd is not available.
MemOperand dst1(dst);
dst1.set_offset(dst1.offset() + 4);
Register src1(src);
- src1.code_ = src1.code_ + 1;
+ src1.set_code(src1.code() + 1);
+ str(src, dst, cond);
str(src1, dst1, cond);
#endif
}
@@ -1216,26 +1429,6 @@
}
-// Semaphore instructions.
-void Assembler::swp(Register dst, Register src, Register base, Condition cond) {
- ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
- ASSERT(!dst.is(base) && !src.is(base));
- emit(cond | P | base.code()*B16 | dst.code()*B12 |
- B7 | B4 | src.code());
-}
-
-
-void Assembler::swpb(Register dst,
- Register src,
- Register base,
- Condition cond) {
- ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
- ASSERT(!dst.is(base) && !src.is(base));
- emit(cond | P | B | base.code()*B16 | dst.code()*B12 |
- B7 | B4 | src.code());
-}
-
-
// Exception-generating instructions and debugging support.
void Assembler::stop(const char* msg) {
#ifndef __arm__
@@ -1779,34 +1972,6 @@
}
-void Assembler::lea(Register dst,
- const MemOperand& x,
- SBit s,
- Condition cond) {
- int am = x.am_;
- if (!x.rm_.is_valid()) {
- // Immediate offset.
- if ((am & P) == 0) // post indexing
- mov(dst, Operand(x.rn_), s, cond);
- else if ((am & U) == 0) // negative indexing
- sub(dst, x.rn_, Operand(x.offset_), s, cond);
- else
- add(dst, x.rn_, Operand(x.offset_), s, cond);
- } else {
- // Register offset (shift_imm_ and shift_op_ are 0) or scaled
- // register offset the constructors make sure than both shift_imm_
- // and shift_op_ are initialized.
- ASSERT(!x.rm_.is(pc));
- if ((am & P) == 0) // post indexing
- mov(dst, Operand(x.rn_), s, cond);
- else if ((am & U) == 0) // negative indexing
- sub(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
- else
- add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
- }
-}
-
-
bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
uint32_t dummy1;
uint32_t dummy2;
@@ -2062,3 +2227,5 @@
} } // namespace v8::internal
+
+#endif // V8_TARGET_ARCH_ARM
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698