hotspot/src/share/vm/opto/matcher.cpp

Print this page
rev 611 : Merge

@@ -1,10 +1,10 @@
 #ifdef USE_PRAGMA_IDENT_SRC
 #pragma ident "@(#)matcher.cpp  1.388 07/09/28 10:33:13 JVM"
 #endif
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -31,11 +31,11 @@
 OptoReg::Name OptoReg::c_frame_pointer;
 
 
 
 const int Matcher::base2reg[Type::lastype] = {
-  Node::NotAMachineReg,0,0, Op_RegI, Op_RegL, 0, 
+  Node::NotAMachineReg,0,0, Op_RegI, Op_RegL, 0, Op_RegN,
   Node::NotAMachineReg, Node::NotAMachineReg, /* tuple, array */
   Op_RegP, Op_RegP, Op_RegP, Op_RegP, Op_RegP, Op_RegP, /* the pointers */
   0, 0/*abio*/,
   Op_RegP /* Return address */, 0, /* the memories */
   Op_RegF, Op_RegF, Op_RegF, Op_RegD, Op_RegD, Op_RegD, 

@@ -52,12 +52,13 @@
 //---------------------------Matcher-------------------------------------------
 Matcher::Matcher( Node_List &proj_list ) :
   PhaseTransform( Phase::Ins_Select ),
 #ifdef ASSERT
   _old2new_map(C->comp_arena()),
+  _new2old_map(C->comp_arena()),
 #endif
-  _shared_constants(C->comp_arena()),
+  _shared_nodes(C->comp_arena()),
   _reduceOp(reduceOp), _leftOp(leftOp), _rightOp(rightOp), 
   _swallowed(swallowed), 
   _begin_inst_chain_rule(_BEGIN_INST_CHAIN_RULE), 
   _end_inst_chain_rule(_END_INST_CHAIN_RULE), 
   _must_clone(must_clone), _proj_list(proj_list),

@@ -71,20 +72,23 @@
   _shared(&_states_arena),
   _dontcare(&_states_arena) {
   C->set_matcher(this);
 
   idealreg2spillmask[Op_RegI] = NULL;
+  idealreg2spillmask[Op_RegN] = NULL;
   idealreg2spillmask[Op_RegL] = NULL;
   idealreg2spillmask[Op_RegF] = NULL;
   idealreg2spillmask[Op_RegD] = NULL;
   idealreg2spillmask[Op_RegP] = NULL;
 
   idealreg2debugmask[Op_RegI] = NULL;
+  idealreg2debugmask[Op_RegN] = NULL;
   idealreg2debugmask[Op_RegL] = NULL;
   idealreg2debugmask[Op_RegF] = NULL;
   idealreg2debugmask[Op_RegD] = NULL;
   idealreg2debugmask[Op_RegP] = NULL;
+  debug_only(_mem_node = NULL;)   // Ideal memory node consumed by mach node
 }
 
 //------------------------------warp_incoming_stk_arg------------------------
 // This warps a VMReg into an OptoReg::Name
 OptoReg::Name Matcher::warp_incoming_stk_arg( VMReg reg ) {

@@ -270,11 +274,11 @@
   // _shared[_idx] is cleared is guaranteed to not be shared, and thus
   // can be a valid interior of some tree.
   find_shared( C->root() );
   find_shared( C->top() );
 
-  C->print_method("Before Matching", 2);
+  C->print_method("Before Matching");
 
   // Swap out to old-space; emptying new-space 
   Arena *old = C->node_arena()->move_contents(C->old_arena());
 
   // Save debug and profile information for nodes in old space:

@@ -367,21 +371,23 @@
 // Disallow any debug info in outgoing argument areas by setting the
 // initial mask accordingly.
 void Matcher::init_first_stack_mask() {
 
   // Allocate storage for spill masks as masks for the appropriate load type.
-  RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask)*10);
-  idealreg2spillmask[Op_RegI] = &rms[0];
-  idealreg2spillmask[Op_RegL] = &rms[1];
-  idealreg2spillmask[Op_RegF] = &rms[2];
-  idealreg2spillmask[Op_RegD] = &rms[3];
-  idealreg2spillmask[Op_RegP] = &rms[4];
-  idealreg2debugmask[Op_RegI] = &rms[5];
-  idealreg2debugmask[Op_RegL] = &rms[6];
-  idealreg2debugmask[Op_RegF] = &rms[7];
-  idealreg2debugmask[Op_RegD] = &rms[8];
-  idealreg2debugmask[Op_RegP] = &rms[9];
+  RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask)*12);
+  idealreg2spillmask[Op_RegN] = &rms[0];
+  idealreg2spillmask[Op_RegI] = &rms[1];
+  idealreg2spillmask[Op_RegL] = &rms[2];
+  idealreg2spillmask[Op_RegF] = &rms[3];
+  idealreg2spillmask[Op_RegD] = &rms[4];
+  idealreg2spillmask[Op_RegP] = &rms[5];
+  idealreg2debugmask[Op_RegN] = &rms[6];
+  idealreg2debugmask[Op_RegI] = &rms[7];
+  idealreg2debugmask[Op_RegL] = &rms[8];
+  idealreg2debugmask[Op_RegF] = &rms[9];
+  idealreg2debugmask[Op_RegD] = &rms[10];
+  idealreg2debugmask[Op_RegP] = &rms[11];
 
   OptoReg::Name i;
 
   // At first, start with the empty mask
   C->FIRST_STACK_mask().Clear();

@@ -400,10 +406,14 @@
 
   // Finally, set the "infinite stack" bit.
   C->FIRST_STACK_mask().set_AllStack();
 
   // Make spill masks.  Registers for their class, plus FIRST_STACK_mask.
+#ifdef _LP64
+  *idealreg2spillmask[Op_RegN] = *idealreg2regmask[Op_RegN];
+   idealreg2spillmask[Op_RegN]->OR(C->FIRST_STACK_mask());
+#endif
   *idealreg2spillmask[Op_RegI] = *idealreg2regmask[Op_RegI]; 
    idealreg2spillmask[Op_RegI]->OR(C->FIRST_STACK_mask());
   *idealreg2spillmask[Op_RegL] = *idealreg2regmask[Op_RegL]; 
    idealreg2spillmask[Op_RegL]->OR(C->FIRST_STACK_mask());
   *idealreg2spillmask[Op_RegF] = *idealreg2regmask[Op_RegF]; 

@@ -414,10 +424,11 @@
    idealreg2spillmask[Op_RegP]->OR(C->FIRST_STACK_mask());
 
   // Make up debug masks.  Any spill slot plus callee-save registers.
   // Caller-save registers are assumed to be trashable by the various
   // inline-cache fixup routines.
+  *idealreg2debugmask[Op_RegN]= *idealreg2spillmask[Op_RegN];
   *idealreg2debugmask[Op_RegI]= *idealreg2spillmask[Op_RegI];
   *idealreg2debugmask[Op_RegL]= *idealreg2spillmask[Op_RegL];
   *idealreg2debugmask[Op_RegF]= *idealreg2spillmask[Op_RegF];
   *idealreg2debugmask[Op_RegD]= *idealreg2spillmask[Op_RegD];
   *idealreg2debugmask[Op_RegP]= *idealreg2spillmask[Op_RegP];

@@ -429,10 +440,11 @@
   for( i=OptoReg::Name(0); i<OptoReg::Name(_last_Mach_Reg); i = OptoReg::add(i,1) ) {
     // registers the caller has to save do not work 
     if( _register_save_policy[i] == 'C' ||  
         _register_save_policy[i] == 'A' ||
         (_register_save_policy[i] == 'E' && exclude_soe) ) {
+      idealreg2debugmask[Op_RegN]->Remove(i);
       idealreg2debugmask[Op_RegI]->Remove(i); // Exclude save-on-call 
       idealreg2debugmask[Op_RegL]->Remove(i); // registers from debug
       idealreg2debugmask[Op_RegF]->Remove(i); // masks
       idealreg2debugmask[Op_RegD]->Remove(i);
       idealreg2debugmask[Op_RegP]->Remove(i); 

@@ -662,19 +674,25 @@
   const TypePtr* atp = TypePtr::BOTTOM;
   // Share frame pointer while making spill ops
   set_shared(fp);
 
   // Compute generic short-offset Loads
+#ifdef _LP64
+  MachNode *spillCP = match_tree(new (C, 3) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM));
+#endif
   MachNode *spillI  = match_tree(new (C, 3) LoadINode(NULL,mem,fp,atp));
   MachNode *spillL  = match_tree(new (C, 3) LoadLNode(NULL,mem,fp,atp));
   MachNode *spillF  = match_tree(new (C, 3) LoadFNode(NULL,mem,fp,atp));
   MachNode *spillD  = match_tree(new (C, 3) LoadDNode(NULL,mem,fp,atp));
   MachNode *spillP  = match_tree(new (C, 3) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM));
   assert(spillI != NULL && spillL != NULL && spillF != NULL && 
          spillD != NULL && spillP != NULL, "");
 
   // Get the ADLC notion of the right regmask, for each basic type.
+#ifdef _LP64
+  idealreg2regmask[Op_RegN] = &spillCP->out_RegMask();
+#endif
   idealreg2regmask[Op_RegI] = &spillI->out_RegMask();
   idealreg2regmask[Op_RegL] = &spillL->out_RegMask();
   idealreg2regmask[Op_RegF] = &spillF->out_RegMask();
   idealreg2regmask[Op_RegD] = &spillD->out_RegMask();
   idealreg2regmask[Op_RegP] = &spillP->out_RegMask();

@@ -729,10 +747,11 @@
     }
   }
   if (nidx == Compile::AliasIdxBot && midx == Compile::AliasIdxTop) {
     switch (n->Opcode()) {
     case Op_StrComp:
+    case Op_AryEq:
     case Op_MemBarVolatile:
     case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type?
       nidx = Compile::AliasIdxTop;
       nat = NULL;
       break;

@@ -818,14 +837,20 @@
             if (m == NULL) { Matcher::soft_match_failure(); return NULL; }
           } else {                  // Nothing the matcher cares about
             if( n->is_Proj() && n->in(0)->is_Multi()) {       // Projections?
               // Convert to machine-dependent projection
               m = n->in(0)->as_Multi()->match( n->as_Proj(), this );
+#ifdef ASSERT
+              _new2old_map.map(m->_idx, n);
+#endif
               if (m->in(0) != NULL) // m might be top
-                collect_null_checks(m);
+                collect_null_checks(m, n);
             } else {                // Else just a regular 'ol guy
               m = n->clone();       // So just clone into new-space
+#ifdef ASSERT
+              _new2old_map.map(m->_idx, n);
+#endif
               // Def-Use edges will be added incrementally as Uses
               // of this node are matched.
               assert(m->outcnt() == 0, "no Uses of this clone yet");
             }
           }

@@ -865,15 +890,18 @@
       // Monitor boxes are also represented directly.
       for (i = cnt - 1; i >= debug_cnt; --i) { // For all debug inputs do
         Node *m = n->in(i);          // Get input
         int op = m->Opcode();
         assert((op == Op_BoxLock) == jvms->is_monitor_use(i), "boxes only at monitor sites");
-        if( op == Op_ConI || op == Op_ConP ||
+        if( op == Op_ConI || op == Op_ConP || op == Op_ConN ||
             op == Op_ConF || op == Op_ConD || op == Op_ConL
             // || op == Op_BoxLock  // %%%% enable this and remove (+++) in chaitin.cpp
             ) {
           m = m->clone();
+#ifdef ASSERT
+          _new2old_map.map(m->_idx, n);
+#endif
           mstack.push(m, Post_Visit, n, i); // Don't neet to visit
           mstack.push(m->in(0), Visit, m, 0);
         } else {
           mstack.push(m, Visit, n, i);
         }

@@ -1137,11 +1165,14 @@
 
   LabelRootDepth = 0;
 
   // StoreNodes require their Memory input to match any LoadNodes
   Node *mem = n->is_Store() ? n->in(MemNode::Memory) : (Node*)1 ;
-
+#ifdef ASSERT
+  Node* save_mem_node = _mem_node;
+  _mem_node = n->is_Store() ? (Node*)n : NULL;
+#endif
   // State object for root node of match tree
   // Allocate it on _states_arena - stack allocation can cause stack overflow.
   State *s = new (&_states_arena) State;
   s->_kids[0] = NULL;
   s->_kids[1] = NULL;

@@ -1170,17 +1201,18 @@
   }
   // Reduce input tree based upon the state labels to machine Nodes
   MachNode *m = ReduceInst( s, s->_rule[mincost], mem );
 #ifdef ASSERT
   _old2new_map.map(n->_idx, m);
+  _new2old_map.map(m->_idx, (Node*)n);
 #endif
   
   // Add any Matcher-ignored edges
   uint cnt = n->req();
   uint start = 1;
   if( mem != (Node*)1 ) start = MemNode::Memory+1;
-  if( n->Opcode() == Op_AddP ) {
+  if( n->is_AddP() ) {
     assert( mem == (Node*)1, "" );
     start = AddPNode::Base+1;
   }
   for( i = start; i < cnt; i++ ) {
     if( !n->match_edge(i) ) {

@@ -1189,10 +1221,11 @@
       else
         m->add_req( n->in(i) ); 
     }
   }
 
+  debug_only( _mem_node = save_mem_node; )
   return m;
 }
 
 
 //------------------------------match_into_reg---------------------------------

@@ -1204,11 +1237,11 @@
   const Type *t = m->bottom_type();
 
   if( t->singleton() ) {
     // Never force constants into registers.  Allow them to match as
     // constants or registers.  Copies of the same value will share
-    // the same register.  See find_shared_constant.
+    // the same register.  See find_shared_node.
     return false;
   } else {                      // Not a constant
     // Stop recursion if they have different Controls.
     // Slot 0 of constants is not really a Control.
     if( control && m->in(0) && control != m->in(0) ) {

@@ -1228,10 +1261,15 @@
           break;                // m->in(0)?  If so, we can use it
       }
       if( j == max_scan )       // No post-domination before scan end?
         return true;            // Then break the match tree up
     }
+    if (m->is_DecodeN() && Matcher::clone_shift_expressions) {
+      // These are commonly used in address expressions and can
+      // efficiently fold into them on X64 in some cases.
+      return false;
+    }
   }
 
   // Not forceably cloning.  If shared, put it into a register.
   return shared;
 }

@@ -1346,17 +1384,20 @@
 
 // Con nodes reduced using the same rule can share their MachNode
 // which reduces the number of copies of a constant in the final
 // program.  The register allocator is free to split uses later to
 // split live ranges.
-MachNode* Matcher::find_shared_constant(Node* leaf, uint rule) {
-  if (!leaf->is_Con()) return NULL;
+MachNode* Matcher::find_shared_node(Node* leaf, uint rule) {
+  if (!leaf->is_Con() && !leaf->is_DecodeN()) return NULL;
 
   // See if this Con has already been reduced using this rule.
-  if (_shared_constants.Size() <= leaf->_idx) return NULL;
-  MachNode* last = (MachNode*)_shared_constants.at(leaf->_idx);
+  if (_shared_nodes.Size() <= leaf->_idx) return NULL;
+  MachNode* last = (MachNode*)_shared_nodes.at(leaf->_idx);
   if (last != NULL && rule == last->rule()) {
+    // Don't expect control change for DecodeN
+    if (leaf->is_DecodeN())
+      return last;
     // Get the new space root.
     Node* xroot = new_node(C->root());
     if (xroot == NULL) {
       // This shouldn't happen give the order of matching.
       return NULL;

@@ -1398,22 +1439,24 @@
 //     Build the operand, place it inside the instruction
 //     Call ReduceOper.
 MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) {
   assert( rule >= NUM_OPERANDS, "called with operand rule" );
 
-  MachNode* shared_con = find_shared_constant(s->_leaf, rule);
-  if (shared_con != NULL) {
-    return shared_con;
+  MachNode* shared_node = find_shared_node(s->_leaf, rule);
+  if (shared_node != NULL) {
+    return shared_node;
   }
 
   // Build the object to represent this state & prepare for recursive calls
   MachNode *mach = s->MachNodeGenerator( rule, C );
   mach->_opnds[0] = s->MachOperGenerator( _reduceOp[rule], C );
   assert( mach->_opnds[0] != NULL, "Missing result operand" );
   Node *leaf = s->_leaf;
   // Check for instruction or instruction chain rule
   if( rule >= _END_INST_CHAIN_RULE || rule < _BEGIN_INST_CHAIN_RULE ) {
+    assert(C->node_arena()->contains(s->_leaf) || !has_new_node(s->_leaf),
+           "duplicating node that's already been matched");
     // Instruction
     mach->add_req( leaf->in(0) ); // Set initial control
     // Reduce interior of complex instruction
     ReduceInst_Interior( s, rule, mem, mach, 1 );
   } else {

@@ -1421,15 +1464,44 @@
     mach->add_req(0);             // Set initial control to none
     ReduceInst_Chain_Rule( s, rule, mem, mach );
   }
 
   // If a Memory was used, insert a Memory edge
-  if( mem != (Node*)1 )
+  if( mem != (Node*)1 ) {
     mach->ins_req(MemNode::Memory,mem);
+#ifdef ASSERT
+    // Verify adr type after matching memory operation
+    const MachOper* oper = mach->memory_operand();
+    if (oper != NULL && oper != (MachOper*)-1 &&
+        mach->adr_type() != TypeRawPtr::BOTTOM) { // non-direct addressing mode
+      // It has a unique memory operand.  Find corresponding ideal mem node.
+      Node* m = NULL;
+      if (leaf->is_Mem()) {
+        m = leaf;
+      } else {
+        m = _mem_node;
+        assert(m != NULL && m->is_Mem(), "expecting memory node");
+      }
+      const Type* mach_at = mach->adr_type();
+      // DecodeN node consumed by an address may have different type
+      // then its input. Don't compare types for such case.
+      if (m->adr_type() != mach_at && m->in(MemNode::Address)->is_AddP() &&
+          m->in(MemNode::Address)->in(AddPNode::Address)->is_DecodeN()) {
+        mach_at = m->adr_type();
+      }
+      if (m->adr_type() != mach_at) {
+        m->dump();
+        tty->print_cr("mach:");
+        mach->dump(1);
+      }
+      assert(m->adr_type() == mach_at, "matcher should not change adr type");
+    }
+#endif
+  }
 
   // If the _leaf is an AddP, insert the base edge
-  if( leaf->Opcode() == Op_AddP )
+  if( leaf->is_AddP() )
     mach->ins_req(AddPNode::Base,leaf->in(AddPNode::Base));
 
   uint num_proj = _proj_list.size();
 
   // Perform any 1-to-many expansions required

@@ -1440,10 +1512,13 @@
       ex->in(1)->set_req(0, C->root());
     // Remove old node from the graph
     for( uint i=0; i<mach->req(); i++ ) {
       mach->set_req(i,NULL);
     }
+#ifdef ASSERT
+    _new2old_map.map(ex->_idx, s->_leaf);
+#endif
   }
 
   // PhaseChaitin::fixup_spills will sometimes generate spill code
   // via the matcher.  By the time, nodes have been wired into the CFG,
   // and any further nodes generated by expand rules will be left hanging

@@ -1453,13 +1528,13 @@
   if (_allocation_started) {
     guarantee(ex == mach, "no expand rules during spill generation");
     guarantee(_proj_list.size() == num_proj, "no allocation during spill generation");
   }
 
-  if (leaf->is_Con()) {
+  if (leaf->is_Con() || leaf->is_DecodeN()) {
     // Record the con for sharing
-    _shared_constants.map(leaf->_idx, ex);
+    _shared_nodes.map(leaf->_idx, ex);
   }
 
   return ex;
 }
 

@@ -1486,20 +1561,23 @@
   } else {
     // Chain from the result of an instruction
     assert( newrule >= _LAST_MACH_OPER, "Do NOT chain from internal operand");
     mach->_opnds[1] = s->MachOperGenerator( _reduceOp[catch_op], C );
     Node *mem1 = (Node*)1;
+    debug_only(Node *save_mem_node = _mem_node;)
     mach->add_req( ReduceInst(s, newrule, mem1) );
+    debug_only(_mem_node = save_mem_node;)
   }
   return;
 }
 
 
 uint Matcher::ReduceInst_Interior( State *s, int rule, Node *&mem, MachNode *mach, uint num_opnds ) {
   if( s->_leaf->is_Load() ) {
     Node *mem2 = s->_leaf->in(MemNode::Memory);
     assert( mem == (Node*)1 || mem == mem2, "multiple Memories being matched at once?" );
+    debug_only( if( mem == (Node*)1 ) _mem_node = s->_leaf;)
     mem = mem2;
   }
   if( s->_leaf->in(0) != NULL && s->_leaf->req() > 1) {
     if( mach->in(0) == NULL ) 
       mach->set_req(0, s->_leaf->in(0));

@@ -1539,11 +1617,13 @@
       } else {
         // instruction --> call build operand(  ) to catch result
         //             --> ReduceInst( newrule )
         mach->_opnds[num_opnds++] = s->MachOperGenerator( _reduceOp[catch_op], C );
         Node *mem1 = (Node*)1;
+        debug_only(Node *save_mem_node = _mem_node;)
         mach->add_req( ReduceInst( newstate, newrule, mem1 ) );
+        debug_only(_mem_node = save_mem_node;)
       }
     }
     assert( mach->_opnds[num_opnds-1], "" );
   }
   return num_opnds;

@@ -1570,10 +1650,11 @@
   }
 
   if( s->_leaf->is_Load() ) {
     assert( mem == (Node*)1, "multiple Memories being matched at once?" );
     mem = s->_leaf->in(MemNode::Memory);
+    debug_only(_mem_node = s->_leaf;)
   }
   if( s->_leaf->in(0) && s->_leaf->req() > 1) {
     if( !mach->in(0) ) 
       mach->set_req(0,s->_leaf->in(0));
     else {

@@ -1594,11 +1675,13 @@
 
     } else {                    // Child is a new instruction
       // Reduce the instruction, and add a direct pointer from this
       // machine instruction to the newly reduced one.
       Node *mem1 = (Node*)1;
+      debug_only(Node *save_mem_node = _mem_node;)
       mach->add_req( ReduceInst( kid, newrule, mem1 ) );
+      debug_only(_mem_node = save_mem_node;)
     }
   }
 }
 
 

@@ -1648,10 +1731,11 @@
 
       switch( n->Opcode() ) {  // Handle some opcodes special
       case Op_Phi:             // Treat Phis as shared roots
       case Op_Parm:
       case Op_Proj:            // All handled specially during matching
+      case Op_SafePointScalarObject:
         set_shared(n);
         set_dontcare(n);
         break;
       case Op_If:
       case Op_CountedLoopEnd:

@@ -1693,20 +1777,29 @@
       case Op_Jump:
         mstack.push(n->in(1), Visit);         // Switch Value
         mstack.push(n->in(0), Pre_Visit);     // Visit Control input
         continue;                             // while (mstack.is_nonempty())                   
       case Op_StrComp:
+      case Op_AryEq:
         set_shared(n); // Force result into register (it will be anyways)
         break;
       case Op_ConP: {  // Convert pointers above the centerline to NUL
         TypeNode *tn = n->as_Type(); // Constants derive from type nodes
         const TypePtr* tp = tn->type()->is_ptr();
         if (tp->_ptr == TypePtr::AnyNull) {
           tn->set_type(TypePtr::NULL_PTR);
         }
         break;
       }
+      case Op_ConN: {  // Convert narrow pointers above the centerline to NUL
+        TypeNode *tn = n->as_Type(); // Constants derive from type nodes
+        const TypePtr* tp = tn->type()->make_ptr();
+        if (tp && tp->_ptr == TypePtr::AnyNull) {
+          tn->set_type(TypeNarrowOop::NULL_PTR);
+        }
+        break;
+      }
       case Op_Binary:         // These are introduced in the Post_Visit state.
         ShouldNotReachHere();
         break;
       case Op_StoreB:         // Do match these, despite no ideal reg
       case Op_StoreC:

@@ -1714,10 +1807,11 @@
       case Op_StoreD:
       case Op_StoreF:
       case Op_StoreI:
       case Op_StoreL:
       case Op_StoreP:
+      case Op_StoreN:
       case Op_Store16B:
       case Op_Store8B:
       case Op_Store4B:
       case Op_Store8C:
       case Op_Store4C:

@@ -1736,13 +1830,15 @@
       case Op_LoadC:
       case Op_LoadD:
       case Op_LoadF:
       case Op_LoadI:
       case Op_LoadKlass:
+      case Op_LoadNKlass:
       case Op_LoadL:
       case Op_LoadS:
       case Op_LoadP:
+      case Op_LoadN:
       case Op_LoadRange:
       case Op_LoadD_unaligned:
       case Op_LoadL_unaligned:
       case Op_Load16B:
       case Op_Load8B:

@@ -1786,17 +1882,23 @@
           continue; // for(int i = ...)
         } 
 
         // Clone addressing expressions as they are "free" in most instructions
         if( mem_op && i == MemNode::Address && mop == Op_AddP ) {
+          if (m->in(AddPNode::Base)->Opcode() == Op_DecodeN) {
+            // Bases used in addresses must be shared but since
+            // they are shared through a DecodeN they may appear
+            // to have a single use so force sharing here.
+            set_shared(m->in(AddPNode::Base)->in(1));
+          }
           Node *off = m->in(AddPNode::Offset);
           if( off->is_Con() ) {
             set_visited(m);  // Flag as visited now
             Node *adr = m->in(AddPNode::Address);
 
             // Intel, ARM and friends can handle 2 adds in addressing mode
-            if( clone_shift_expressions && adr->Opcode() == Op_AddP &&
+            if( clone_shift_expressions && adr->is_AddP() &&
                 // AtomicAdd is not an addressing expression.
                 // Cheap to find it by looking for screwy base.
                 !adr->in(AddPNode::Base)->is_top() ) {
               set_visited(adr);  // Flag as visited now
               Node *shift = adr->in(AddPNode::Offset);

@@ -1850,14 +1952,16 @@
       mstack.pop(); // Remove node from stack
 
       // Now hack a few special opcodes
       switch( n->Opcode() ) {       // Handle some opcodes special
       case Op_StorePConditional:
+      case Op_StoreIConditional:
       case Op_StoreLConditional:
       case Op_CompareAndSwapI:
       case Op_CompareAndSwapL:
-      case Op_CompareAndSwapP: {   // Convert trinary to binary-tree
+      case Op_CompareAndSwapP:
+      case Op_CompareAndSwapN: {   // Convert trinary to binary-tree
         Node *newval = n->in(MemNode::ValueIn );
         Node *oldval  = n->in(LoadStoreNode::ExpectedIn);
         Node *pair = new (C, 3) BinaryNode( oldval, newval );
         n->set_req(MemNode::ValueIn,pair);
         n->del_req(LoadStoreNode::ExpectedIn);

@@ -1865,10 +1969,11 @@
       }
       case Op_CMoveD:              // Convert trinary to binary-tree
       case Op_CMoveF:
       case Op_CMoveI:
       case Op_CMoveL:
+      case Op_CMoveN:
       case Op_CMoveP: {
         // Restructure into a binary tree for Matching.  It's possible that
         // we could move this code up next to the graph reshaping for IfNodes
         // or vice-versa, but I do not want to debug this for Ladybird.
         // 10/2/2000 CNC.

@@ -1899,34 +2004,64 @@
 //---------------------------collect_null_checks-------------------------------
 // Find null checks in the ideal graph; write a machine-specific node for
 // it.  Used by later implicit-null-check handling.  Actually collects
 // either an IfTrue or IfFalse for the common NOT-null path, AND the ideal
 // value being tested.
-void Matcher::collect_null_checks( Node *proj ) {
+void Matcher::collect_null_checks( Node *proj, Node *orig_proj ) {
   Node *iff = proj->in(0);
   if( iff->Opcode() == Op_If ) {
     // During matching If's have Bool & Cmp side-by-side
     BoolNode *b = iff->in(1)->as_Bool();
     Node *cmp = iff->in(2);
-    if( cmp->Opcode() == Op_CmpP ) {
-      if( cmp->in(2)->bottom_type() == TypePtr::NULL_PTR ) {
+    int opc = cmp->Opcode();
+    if (opc != Op_CmpP && opc != Op_CmpN) return;
 
+    const Type* ct = cmp->in(2)->bottom_type();
+    if (ct == TypePtr::NULL_PTR ||
+        (opc == Op_CmpN && ct == TypeNarrowOop::NULL_PTR)) {
+
+      bool push_it = false;
         if( proj->Opcode() == Op_IfTrue ) {
           extern int all_null_checks_found;
           all_null_checks_found++;
           if( b->_test._test == BoolTest::ne ) {
-            _null_check_tests.push(proj);
-            _null_check_tests.push(cmp->in(1));
+          push_it = true;
           }
         } else {
           assert( proj->Opcode() == Op_IfFalse, "" );
           if( b->_test._test == BoolTest::eq ) {
+          push_it = true;
+        }
+      }
+      if( push_it ) {
             _null_check_tests.push(proj);
-            _null_check_tests.push(cmp->in(1));
+        Node* val = cmp->in(1);
+#ifdef _LP64
+        if (UseCompressedOops && !Matcher::clone_shift_expressions &&
+            val->bottom_type()->isa_narrowoop()) {
+          //
+          // Look for DecodeN node which should be pinned to orig_proj.
+          // On platforms (Sparc) which can not handle 2 adds
+          // in addressing mode we have to keep a DecodeN node and
+          // use it to do implicit NULL check in address.
+          //
+          // DecodeN node was pinned to non-null path (orig_proj) during
+          // CastPP transformation in final_graph_reshaping_impl().
+          //
+          uint cnt = orig_proj->outcnt();
+          for (uint i = 0; i < orig_proj->outcnt(); i++) {
+            Node* d = orig_proj->raw_out(i);
+            if (d->is_DecodeN() && d->in(1) == val) {
+              val = d;
+              val->set_req(0, NULL); // Unpin now.
+              break;
           }
         }
       }
+#endif
+        _null_check_tests.push(val);
+      }
     }
   }
 }
 
 //---------------------------validate_null_checks------------------------------

@@ -2038,10 +2173,11 @@
     
     if (xop == Op_MemBarVolatile || 
         xop == Op_FastLock ||
         xop == Op_CompareAndSwapL ||
         xop == Op_CompareAndSwapP ||
+        xop == Op_CompareAndSwapN ||
         xop == Op_CompareAndSwapI)
       return true;
 
     if (x->is_MemBar()) {
       // We must retain this membar if there is an upcoming volatile