From a31c578f25fb607cb17651a8b63d6ca536a982db Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Mon, 17 May 2010 11:19:10 +0000 Subject: [PATCH] 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 --- src/arm/assembler-arm.cc | 43 +++++++++++++------------------------- src/arm/assembler-arm.h | 6 ++++++ src/flag-definitions.h | 4 ---- src/ia32/assembler-ia32.cc | 20 +++++++++--------- 4 files changed, 30 insertions(+), 43 deletions(-) diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index 94652bb96e..474a74e7a1 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -270,6 +270,7 @@ 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 = @@ -281,7 +282,6 @@ static const Instr kStrRegFpNegOffsetPattern = static const Instr kLdrStrInstrTypeMask = 0xffff0000; static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; static const Instr kLdrStrOffsetMask = 0x00000fff; -static const int kRdShift = 12; // Spare buffer. 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); // 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()); } } @@ -1143,15 +1140,12 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { // 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. - int pattern_size = 2 * kInstrSize; Instr push_instr = instr_at(pc_ - 2 * kInstrSize); Instr pop_instr = instr_at(pc_ - 1 * kInstrSize); - if (FLAG_push_pop_elimination && - last_bound_pos_ <= (pc_offset() - pattern_size) && - reloc_info_writer.last_pc() <= (pc_ - pattern_size) && - IsPush(push_instr) && - IsPop(pop_instr)) { + 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. @@ -1162,23 +1156,20 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { pc_ -= 2 * kInstrSize; // Insert a mov instruction, which is better than a pair of push & pop 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()); } } 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_push_pop_elimination) { + if (FLAG_print_peephole_optimization) { PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); } } } - pattern_size = 2 * kInstrSize; - if (FLAG_peephole_optimization && - last_bound_pos_ <= (pc_offset() - pattern_size) && - reloc_info_writer.last_pc() <= (pc_ - pattern_size)) { + if (can_peephole_optimize(2)) { Instr str_instr = instr_at(pc_ - 2 * 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 (FLAG_push_pop_elimination && - last_bound_pos_ <= (pc_offset() - pattern_size) && - reloc_info_writer.last_pc() <= (pc_ - pattern_size)) { + 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); @@ -1260,7 +1248,7 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { // Reinsert back the ldr rz. 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()); } } else { @@ -1305,7 +1293,7 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { mov(reg_popped, reg_pushed); 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()); } } @@ -1321,16 +1309,13 @@ void Assembler::str(Register src, const MemOperand& dst, Condition cond) { // 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()); } } diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h index 3199e7e580..eb63b28783 100644 --- a/src/arm/assembler-arm.h +++ b/src/arm/assembler-arm.h @@ -976,6 +976,12 @@ class Assembler : public Malloced { int current_position() const { return current_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 static Instr instr_at(byte* pc) { return *reinterpret_cast(pc); } static void instr_at_put(byte* pc, Instr instr) { diff --git a/src/flag-definitions.h b/src/flag-definitions.h index 3e9a709dd6..4d120ce9ad 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -100,10 +100,6 @@ private: DEFINE_bool(debug_code, false, "generate extra code (comments, assertions) for debugging") 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, "perform peephole optimizations in assembly code") DEFINE_bool(print_peephole_optimization, false, diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index 26e40b15bc..19895d0f6f 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -433,7 +433,7 @@ void Assembler::push(const Operand& src) { void Assembler::pop(Register dst) { 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. // 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 @@ -443,7 +443,7 @@ void Assembler::pop(Register dst) { int push_reg_code = instr & 0x7; if (push_reg_code == dst.code()) { pc_ = last_pc_; - if (FLAG_print_push_pop_elimination) { + if (FLAG_print_peephole_optimization) { PrintF("%d push/pop (same reg) eliminated\n", pc_offset()); } } else { @@ -452,7 +452,7 @@ void Assembler::pop(Register dst) { Register src = { push_reg_code }; EnsureSpace ensure_space(this); 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()); } } @@ -466,7 +466,7 @@ void Assembler::pop(Register dst) { last_pc_[0] = 0x8b; last_pc_[1] = op1; last_pc_ = NULL; - if (FLAG_print_push_pop_elimination) { + if (FLAG_print_peephole_optimization) { PrintF("%d push/pop (op->reg) eliminated\n", pc_offset()); } return; @@ -483,7 +483,7 @@ void Assembler::pop(Register dst) { last_pc_[1] = 0xc4; last_pc_[2] = 0x04; last_pc_ = NULL; - if (FLAG_print_push_pop_elimination) { + if (FLAG_print_peephole_optimization) { PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset()); } return; @@ -498,7 +498,7 @@ void Assembler::pop(Register dst) { // change to // 31c0 xor eax,eax last_pc_ = NULL; - if (FLAG_print_push_pop_elimination) { + if (FLAG_print_peephole_optimization) { PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); } return; @@ -521,7 +521,7 @@ void Assembler::pop(Register dst) { // b8XX000000 mov eax,0x000000XX } last_pc_ = NULL; - if (FLAG_print_push_pop_elimination) { + if (FLAG_print_peephole_optimization) { PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); } return; @@ -533,7 +533,7 @@ void Assembler::pop(Register dst) { last_pc_ = NULL; // change to // 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()); } return; @@ -813,7 +813,7 @@ void Assembler::add(Register dst, const Operand& src) { void Assembler::add(const Operand& dst, const Immediate& x) { 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]; if ((instr & 0xf8) == 0x50) { // 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)) { pc_ = last_pc_; last_pc_ = NULL; - if (FLAG_print_push_pop_elimination) { + if (FLAG_print_peephole_optimization) { PrintF("%d push/pop(noreg) eliminated\n", pc_offset()); } return;