< prev index next >

src/hotspot/share/opto/lcm.cpp

Print this page
@@ -282,13 +282,13 @@
          } else {
            // only regular oops are expected here
            tptr = base->bottom_type()->is_ptr();
          }
          // Give up if offset is not a compile-time constant.
-         if (offset == Type::OffsetBot || tptr->_offset == Type::OffsetBot)
+         if (offset == Type::OffsetBot || tptr->offset() == Type::OffsetBot)
            continue;
-         offset += tptr->_offset; // correct if base is offsetted
+         offset += tptr->offset(); // correct if base is offsetted
          // Give up if reference is beyond page size.
          if (MacroAssembler::needs_explicit_null_check(offset))
            continue;
          // Give up if base is a decode node and the heap base is not protected.
          if (base->is_Mach() && base->as_Mach()->ideal_Opcode() == Op_DecodeN &&

@@ -321,11 +321,15 @@
          vidx = j;
          // Ignore DecodeN val which could be hoisted to where needed.
          if( is_decoden ) continue;
        }
        // Block of memory-op input
-       Block *inb = get_block_for_node(mach->in(j));
+       Block* inb = get_block_for_node(mach->in(j));
+       if (mach->in(j)->is_Con() && mach->in(j)->req() == 1 && inb == get_block_for_node(mach)) {
+         // Ignore constant loads scheduled in the same block (we can simply hoist them as well)
+         continue;
+       }
        Block *b = block;          // Start from nul check
        while( b != inb && b->_dom_depth > inb->_dom_depth )
          b = b->_idom;           // search upwards for input
        // See if input dominates null check
        if( b != inb )

@@ -414,10 +418,31 @@
            map_node_to_block(n, block);
          }
        }
      }
    }
+ 
+   // Hoist constant load inputs as well.
+   for (uint i = 1; i < best->req(); ++i) {
+     Node* n = best->in(i);
+     if (n->is_Con() && get_block_for_node(n) == get_block_for_node(best)) {
+       get_block_for_node(n)->find_remove(n);
+       block->add_inst(n);
+       map_node_to_block(n, block);
+       // Constant loads may kill flags (for example, when XORing a register).
+       // Check for flag-killing projections that also need to be hoisted.
+       for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
+         Node* proj = n->fast_out(j);
+         if (proj->is_MachProj()) {
+           get_block_for_node(proj)->find_remove(proj);
+           block->add_inst(proj);
+           map_node_to_block(proj, block);
+         }
+       }
+     }
+   }
+ 
    // Hoist the memory candidate up to the end of the test block.
    Block *old_block = get_block_for_node(best);
    old_block->find_remove(best);
    block->add_inst(best);
    map_node_to_block(best, block);

@@ -884,11 +909,11 @@
    // Act as if the call defines the Frame Pointer.
    // Certainly the FP is alive and well after the call.
    regs.Insert(_matcher.c_frame_pointer());
  
    // Set all registers killed and not already defined by the call.
-   uint r_cnt = mcall->tf()->range()->cnt();
+   uint r_cnt = mcall->tf()->range_cc()->cnt();
    int op = mcall->ideal_Opcode();
    MachProjNode *proj = new MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj );
    map_node_to_block(proj, block);
    block->insert_node(proj, node_cnt++);
  
< prev index next >