Push/pop is just one peephole optimization. Puth them all
under one flag. Also other cosmetic changes to peephole optimization. Review URL: http://codereview.chromium.org/2104006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4663 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
afe8c296a4
commit
a31c578f25
@ -270,6 +270,7 @@ const Instr kBlxRegPattern =
|
|||||||
B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4;
|
B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4;
|
||||||
// A mask for the Rd register for push, pop, ldr, str instructions.
|
// A mask for the Rd register for push, pop, ldr, str instructions.
|
||||||
const Instr kRdMask = 0x0000f000;
|
const Instr kRdMask = 0x0000f000;
|
||||||
|
static const int kRdShift = 12;
|
||||||
static const Instr kLdrRegFpOffsetPattern =
|
static const Instr kLdrRegFpOffsetPattern =
|
||||||
al | B26 | L | Offset | fp.code() * B16;
|
al | B26 | L | Offset | fp.code() * B16;
|
||||||
static const Instr kStrRegFpOffsetPattern =
|
static const Instr kStrRegFpOffsetPattern =
|
||||||
@ -281,7 +282,6 @@ static const Instr kStrRegFpNegOffsetPattern =
|
|||||||
static const Instr kLdrStrInstrTypeMask = 0xffff0000;
|
static const Instr kLdrStrInstrTypeMask = 0xffff0000;
|
||||||
static const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
|
static const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
|
||||||
static const Instr kLdrStrOffsetMask = 0x00000fff;
|
static const Instr kLdrStrOffsetMask = 0x00000fff;
|
||||||
static const int kRdShift = 12;
|
|
||||||
|
|
||||||
// Spare buffer.
|
// Spare buffer.
|
||||||
static const int kMinimalBufferSize = 4*KB;
|
static const int kMinimalBufferSize = 4*KB;
|
||||||
@ -938,15 +938,12 @@ void Assembler::add(Register dst, Register src1, const Operand& src2,
|
|||||||
// str(src, MemOperand(sp, 4, NegPreIndex), al);
|
// str(src, MemOperand(sp, 4, NegPreIndex), al);
|
||||||
// add(sp, sp, Operand(kPointerSize));
|
// add(sp, sp, Operand(kPointerSize));
|
||||||
// Both instructions can be eliminated.
|
// Both instructions can be eliminated.
|
||||||
int pattern_size = 2 * kInstrSize;
|
if (can_peephole_optimize(2) &&
|
||||||
if (FLAG_push_pop_elimination &&
|
|
||||||
last_bound_pos_ <= (pc_offset() - pattern_size) &&
|
|
||||||
reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
|
|
||||||
// Pattern.
|
// Pattern.
|
||||||
instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
|
instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
|
||||||
(instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
|
(instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
|
||||||
pc_ -= 2 * kInstrSize;
|
pc_ -= 2 * kInstrSize;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
|
PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1143,15 +1140,12 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
|
|||||||
// Both instructions can be eliminated if ry = rx.
|
// Both instructions can be eliminated if ry = rx.
|
||||||
// If ry != rx, a register copy from ry to rx is inserted
|
// If ry != rx, a register copy from ry to rx is inserted
|
||||||
// after eliminating the push and the pop instructions.
|
// after eliminating the push and the pop instructions.
|
||||||
int pattern_size = 2 * kInstrSize;
|
|
||||||
Instr push_instr = instr_at(pc_ - 2 * kInstrSize);
|
Instr push_instr = instr_at(pc_ - 2 * kInstrSize);
|
||||||
Instr pop_instr = instr_at(pc_ - 1 * kInstrSize);
|
Instr pop_instr = instr_at(pc_ - 1 * kInstrSize);
|
||||||
|
|
||||||
if (FLAG_push_pop_elimination &&
|
if (can_peephole_optimize(2) &&
|
||||||
last_bound_pos_ <= (pc_offset() - pattern_size) &&
|
IsPush(push_instr) &&
|
||||||
reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
|
IsPop(pop_instr)) {
|
||||||
IsPush(push_instr) &&
|
|
||||||
IsPop(pop_instr)) {
|
|
||||||
if ((pop_instr & kRdMask) != (push_instr & kRdMask)) {
|
if ((pop_instr & kRdMask) != (push_instr & kRdMask)) {
|
||||||
// For consecutive push and pop on different registers,
|
// For consecutive push and pop on different registers,
|
||||||
// we delete both the push & pop and insert a register move.
|
// we delete both the push & pop and insert a register move.
|
||||||
@ -1162,23 +1156,20 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
|
|||||||
pc_ -= 2 * kInstrSize;
|
pc_ -= 2 * kInstrSize;
|
||||||
// Insert a mov instruction, which is better than a pair of push & pop
|
// Insert a mov instruction, which is better than a pair of push & pop
|
||||||
mov(reg_popped, reg_pushed);
|
mov(reg_popped, reg_pushed);
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset());
|
PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For consecutive push and pop on the same register,
|
// For consecutive push and pop on the same register,
|
||||||
// both the push and the pop can be deleted.
|
// both the push and the pop can be deleted.
|
||||||
pc_ -= 2 * kInstrSize;
|
pc_ -= 2 * kInstrSize;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
|
PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern_size = 2 * kInstrSize;
|
if (can_peephole_optimize(2)) {
|
||||||
if (FLAG_peephole_optimization &&
|
|
||||||
last_bound_pos_ <= (pc_offset() - pattern_size) &&
|
|
||||||
reloc_info_writer.last_pc() <= (pc_ - pattern_size)) {
|
|
||||||
Instr str_instr = instr_at(pc_ - 2 * kInstrSize);
|
Instr str_instr = instr_at(pc_ - 2 * kInstrSize);
|
||||||
Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize);
|
Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize);
|
||||||
|
|
||||||
@ -1226,10 +1217,7 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern_size = 3 * kInstrSize;
|
if (can_peephole_optimize(3)) {
|
||||||
if (FLAG_push_pop_elimination &&
|
|
||||||
last_bound_pos_ <= (pc_offset() - pattern_size) &&
|
|
||||||
reloc_info_writer.last_pc() <= (pc_ - pattern_size)) {
|
|
||||||
Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize);
|
Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize);
|
||||||
Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize);
|
Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize);
|
||||||
Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize);
|
Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize);
|
||||||
@ -1260,7 +1248,7 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
|
|||||||
// Reinsert back the ldr rz.
|
// Reinsert back the ldr rz.
|
||||||
emit(ldr_instr);
|
emit(ldr_instr);
|
||||||
}
|
}
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
|
PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1305,7 +1293,7 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
|
|||||||
mov(reg_popped, reg_pushed);
|
mov(reg_popped, reg_pushed);
|
||||||
emit(ldr_instr);
|
emit(ldr_instr);
|
||||||
}
|
}
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
|
PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1321,16 +1309,13 @@ void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
|
|||||||
// Eliminate pattern: pop(), push(r)
|
// Eliminate pattern: pop(), push(r)
|
||||||
// add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
|
// add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
|
||||||
// -> str r, [sp, 0], al
|
// -> str r, [sp, 0], al
|
||||||
int pattern_size = 2 * kInstrSize;
|
if (can_peephole_optimize(2) &&
|
||||||
if (FLAG_push_pop_elimination &&
|
|
||||||
last_bound_pos_ <= (pc_offset() - pattern_size) &&
|
|
||||||
reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
|
|
||||||
// Pattern.
|
// Pattern.
|
||||||
instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
|
instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
|
||||||
instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
|
instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
|
||||||
pc_ -= 2 * kInstrSize;
|
pc_ -= 2 * kInstrSize;
|
||||||
emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
|
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());
|
PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -976,6 +976,12 @@ class Assembler : public Malloced {
|
|||||||
int current_position() const { return current_position_; }
|
int current_position() const { return current_position_; }
|
||||||
int current_statement_position() const { return current_statement_position_; }
|
int current_statement_position() const { return current_statement_position_; }
|
||||||
|
|
||||||
|
bool can_peephole_optimize(int instructions) {
|
||||||
|
if (!FLAG_peephole_optimization) return false;
|
||||||
|
if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false;
|
||||||
|
return reloc_info_writer.last_pc() <= pc_ - instructions * kInstrSize;
|
||||||
|
}
|
||||||
|
|
||||||
// Read/patch instructions
|
// Read/patch instructions
|
||||||
static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
|
static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
|
||||||
static void instr_at_put(byte* pc, Instr instr) {
|
static void instr_at_put(byte* pc, Instr instr) {
|
||||||
|
@ -100,10 +100,6 @@ private:
|
|||||||
DEFINE_bool(debug_code, false,
|
DEFINE_bool(debug_code, false,
|
||||||
"generate extra code (comments, assertions) for debugging")
|
"generate extra code (comments, assertions) for debugging")
|
||||||
DEFINE_bool(emit_branch_hints, false, "emit branch hints")
|
DEFINE_bool(emit_branch_hints, false, "emit branch hints")
|
||||||
DEFINE_bool(push_pop_elimination, true,
|
|
||||||
"eliminate redundant push/pops in assembly code")
|
|
||||||
DEFINE_bool(print_push_pop_elimination, false,
|
|
||||||
"print elimination of redundant push/pops in assembly code")
|
|
||||||
DEFINE_bool(peephole_optimization, true,
|
DEFINE_bool(peephole_optimization, true,
|
||||||
"perform peephole optimizations in assembly code")
|
"perform peephole optimizations in assembly code")
|
||||||
DEFINE_bool(print_peephole_optimization, false,
|
DEFINE_bool(print_peephole_optimization, false,
|
||||||
|
@ -433,7 +433,7 @@ void Assembler::push(const Operand& src) {
|
|||||||
|
|
||||||
void Assembler::pop(Register dst) {
|
void Assembler::pop(Register dst) {
|
||||||
ASSERT(reloc_info_writer.last_pc() != NULL);
|
ASSERT(reloc_info_writer.last_pc() != NULL);
|
||||||
if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
|
if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
|
||||||
// (last_pc_ != NULL) is rolled into the above check.
|
// (last_pc_ != NULL) is rolled into the above check.
|
||||||
// If a last_pc_ is set, we need to make sure that there has not been any
|
// If a last_pc_ is set, we need to make sure that there has not been any
|
||||||
// relocation information generated between the last instruction and this
|
// relocation information generated between the last instruction and this
|
||||||
@ -443,7 +443,7 @@ void Assembler::pop(Register dst) {
|
|||||||
int push_reg_code = instr & 0x7;
|
int push_reg_code = instr & 0x7;
|
||||||
if (push_reg_code == dst.code()) {
|
if (push_reg_code == dst.code()) {
|
||||||
pc_ = last_pc_;
|
pc_ = last_pc_;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
|
PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -452,7 +452,7 @@ void Assembler::pop(Register dst) {
|
|||||||
Register src = { push_reg_code };
|
Register src = { push_reg_code };
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
emit_operand(dst, Operand(src));
|
emit_operand(dst, Operand(src));
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
|
PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -466,7 +466,7 @@ void Assembler::pop(Register dst) {
|
|||||||
last_pc_[0] = 0x8b;
|
last_pc_[0] = 0x8b;
|
||||||
last_pc_[1] = op1;
|
last_pc_[1] = op1;
|
||||||
last_pc_ = NULL;
|
last_pc_ = NULL;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
|
PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -483,7 +483,7 @@ void Assembler::pop(Register dst) {
|
|||||||
last_pc_[1] = 0xc4;
|
last_pc_[1] = 0xc4;
|
||||||
last_pc_[2] = 0x04;
|
last_pc_[2] = 0x04;
|
||||||
last_pc_ = NULL;
|
last_pc_ = NULL;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
|
PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -498,7 +498,7 @@ void Assembler::pop(Register dst) {
|
|||||||
// change to
|
// change to
|
||||||
// 31c0 xor eax,eax
|
// 31c0 xor eax,eax
|
||||||
last_pc_ = NULL;
|
last_pc_ = NULL;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
|
PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -521,7 +521,7 @@ void Assembler::pop(Register dst) {
|
|||||||
// b8XX000000 mov eax,0x000000XX
|
// b8XX000000 mov eax,0x000000XX
|
||||||
}
|
}
|
||||||
last_pc_ = NULL;
|
last_pc_ = NULL;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
|
PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -533,7 +533,7 @@ void Assembler::pop(Register dst) {
|
|||||||
last_pc_ = NULL;
|
last_pc_ = NULL;
|
||||||
// change to
|
// change to
|
||||||
// b8XXXXXXXX mov eax,0xXXXXXXXX
|
// b8XXXXXXXX mov eax,0xXXXXXXXX
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
|
PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -813,7 +813,7 @@ void Assembler::add(Register dst, const Operand& src) {
|
|||||||
|
|
||||||
void Assembler::add(const Operand& dst, const Immediate& x) {
|
void Assembler::add(const Operand& dst, const Immediate& x) {
|
||||||
ASSERT(reloc_info_writer.last_pc() != NULL);
|
ASSERT(reloc_info_writer.last_pc() != NULL);
|
||||||
if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
|
if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
|
||||||
byte instr = last_pc_[0];
|
byte instr = last_pc_[0];
|
||||||
if ((instr & 0xf8) == 0x50) {
|
if ((instr & 0xf8) == 0x50) {
|
||||||
// Last instruction was a push. Check whether this is a pop without a
|
// Last instruction was a push. Check whether this is a pop without a
|
||||||
@ -822,7 +822,7 @@ void Assembler::add(const Operand& dst, const Immediate& x) {
|
|||||||
(x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
|
(x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
|
||||||
pc_ = last_pc_;
|
pc_ = last_pc_;
|
||||||
last_pc_ = NULL;
|
last_pc_ = NULL;
|
||||||
if (FLAG_print_push_pop_elimination) {
|
if (FLAG_print_peephole_optimization) {
|
||||||
PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
|
PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user