< prev index next >

src/hotspot/cpu/aarch64/aarch64.ad

Print this page
rev 48394 : [RFC] MachSpillCopy peephole
Enable OptoPeephole by default on AArch64.
Add manually defined peephole() method for MachSpillCopy node.

@@ -3280,12 +3280,19 @@
             __ fmovs(as_FloatRegister(Matcher::_regEncode[dst_lo]),
                      as_Register(Matcher::_regEncode[src_lo]));
         }
       } else {                    // gpr --> stack spill
         assert(dst_lo_rc == rc_stack, "spill to bad register class");
+        if (_spill_type == Pair) {
+          __ spill(as_Register(Matcher::_regEncode[src_lo]),
+                   as_Register(Matcher::_regEncode[pair_hi_reg]),
+                   is64,
+                   dst_offset);
+        } else {
         __ spill(as_Register(Matcher::_regEncode[src_lo]), is64, dst_offset);
       }
+      }
       break;
     case rc_float:
       if (dst_lo_rc == rc_int) {  // fpr --> gpr copy
         if (is64) {
             __ fmovd(as_Register(Matcher::_regEncode[dst_lo]),

@@ -3308,11 +3315,19 @@
                  is64 ? __ D : __ S, dst_offset);
       }
       break;
     case rc_stack:
       if (dst_lo_rc == rc_int) {  // stack --> gpr load
+        if (_spill_type == Pair) {
+          assert(pair_hi_reg != OptoReg::Bad, "bad register");
+          __ unspill(as_Register(Matcher::_regEncode[dst_lo]),
+                     as_Register(Matcher::_regEncode[pair_hi_reg]),
+                     is64,
+                     src_offset);
+        } else {
         __ unspill(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset);
+        }
       } else if (dst_lo_rc == rc_float) { // stack --> fpr load
         __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
                    is64 ? __ D : __ S, src_offset);
       } else {                    // stack --> stack copy
         assert(dst_lo_rc == rc_stack, "spill to bad register class");

@@ -3364,10 +3379,89 @@
 
 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
   return MachNode::size(ra_);
 }
 
+MachNode *MachSpillCopyNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) {
+  MachSpillCopyNode *inst0 = this;
+  MachSpillCopyNode *inst1 = NULL;
+  if ( block_index - 1 > 0 ) {
+    Node *n = block->get_node(block_index - 1);
+    inst1 = (n->is_MachSpillCopy()) ? n->as_MachSpillCopy() : NULL;
+  }
+  if (inst1 == NULL) {
+    return NULL;
+  }
+  if (bottom_type()->isa_vect() != NULL ||
+      inst1->bottom_type()->isa_vect() != NULL ||
+      _spill_type == Pair ||
+      inst1->_spill_type == Pair) {
+    return NULL;
+  }
+  //
+  OptoReg::Name src_lo = ra_->get_reg_first(in(1));
+  OptoReg::Name dst_lo = ra_->get_reg_first(this);
+  enum RC src_lo_rc = rc_class(src_lo);
+  enum RC dst_lo_rc = rc_class(dst_lo);
+  OptoReg::Name inst1_src_lo = ra_->get_reg_first(inst1->in(1));
+  OptoReg::Name inst1_dst_lo = ra_->get_reg_first(inst1);
+  enum RC inst1_src_lo_rc = rc_class(inst1_src_lo);
+  enum RC inst1_dst_lo_rc = rc_class(inst1_dst_lo);
+  if (((src_lo_rc == rc_stack && dst_lo_rc == rc_int)
+      || (dst_lo_rc == rc_stack && src_lo_rc == rc_int))
+      && ((inst1_src_lo_rc == rc_stack && inst1_dst_lo_rc == rc_int)
+          || (inst1_dst_lo_rc == rc_stack && inst1_src_lo_rc == rc_int))) {
+    OptoReg::Name src_hi = ra_->get_reg_second(in(1));
+    OptoReg::Name dst_hi = ra_->get_reg_second(this);
+    enum RC dst_hi_rc = rc_class(dst_hi);
+    enum RC src_hi_rc = rc_class(src_hi);
+    OptoReg::Name inst1_src_hi = ra_->get_reg_second(inst1->in(1));
+    OptoReg::Name inst1_dst_hi = ra_->get_reg_second(inst1);
+    bool is64 = (src_lo & 1) == 0 && src_lo + 1 == src_hi &&
+      (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi;
+    bool inst1_is64 = (inst1_src_lo & 1) == 0 && inst1_src_lo + 1 == inst1_src_hi &&
+      (inst1_dst_lo & 1) == 0 && inst1_dst_lo + 1 == inst1_dst_hi;
+    if (is64 ^ inst1_is64) {
+      return NULL;
+    }
+    int offset = 0;
+    OptoReg::Name other_reg = OptoReg::Bad;
+    MachSpillCopyNode* pair = NULL;
+    int src_offset = ra_->reg2offset(src_lo);
+    int dst_offset = ra_->reg2offset(dst_lo);
+    int inst1_src_offset = ra_->reg2offset(inst1_src_lo);
+    int inst1_dst_offset = ra_->reg2offset(inst1_dst_lo);
+    if (dst_lo_rc == rc_stack) {
+      assert(dst_offset >= 0, "invalid offset");
+      offset = dst_offset - inst1_dst_offset;
+    } else if (src_lo_rc == rc_stack) {
+      assert(src_offset >= 0, "invalid offset");
+      offset = src_offset - inst1_src_offset;
+    }
+    // TODO alignment check for some CPU.
+    if ((is64 && abs(offset) == 8) || (!is64 && abs(offset) == 4)) { // TODO: 8/4 magic number
+      if (offset < 0) { // (this, inst1)
+        pair = this;
+        pair->pair_hi_reg = (src_lo_rc == rc_stack) ? inst1_dst_lo : inst1_src_lo;
+        if (Verbose) {
+          tty->print_cr("DEBUG: valid replacement found: %d && %d", pair->_idx, inst1->_idx);
+        }
+      } else { // (inst1, this)
+        pair = inst1;
+        pair->pair_hi_reg = (src_lo_rc == rc_stack) ? dst_lo : src_lo;
+        if (Verbose) {
+          tty->print_cr("DEBUG: valid replacement found: %d && %d", pair->_idx, this->_idx);
+        }
+      }
+      pair->_spill_type = Pair;
+      deleted = 2;
+      return pair;
+    }
+  }
+  return NULL;
+}
+
 //=============================================================================
 
 #ifndef PRODUCT
 void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
   int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
< prev index next >