Push/pop is just one peephole optimization. Puth them all
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 May 2010 11:19:10 +0000 (11:19 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 May 2010 11:19:10 +0000 (11:19 +0000)
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
src/arm/assembler-arm.h
src/flag-definitions.h
src/ia32/assembler-ia32.cc

index 94652bb..474a74e 100644 (file)
@@ -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());
     }
   }
index 3199e7e..eb63b28 100644 (file)
@@ -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<Instr*>(pc); }
   static void instr_at_put(byte* pc, Instr instr) {
index 3e9a709..4d120ce 100644 (file)
@@ -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,
index 26e40b1..19895d0 100644 (file)
@@ -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;