src/share/vm/opto/memnode.cpp

changeset 509
2a9af0b9cb1c
parent 503
daf38130e60d
child 517
de93acbb64fc
     1.1 --- a/src/share/vm/opto/memnode.cpp	Thu Mar 20 13:51:55 2008 -0700
     1.2 +++ b/src/share/vm/opto/memnode.cpp	Thu Mar 20 15:11:44 2008 -0700
     1.3 @@ -29,6 +29,8 @@
     1.4  #include "incls/_precompiled.incl"
     1.5  #include "incls/_memnode.cpp.incl"
     1.6  
     1.7 +static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem,  const TypePtr *tp, const TypePtr *adr_check, outputStream *st);
     1.8 +
     1.9  //=============================================================================
    1.10  uint MemNode::size_of() const { return sizeof(*this); }
    1.11  
    1.12 @@ -87,6 +89,60 @@
    1.13  
    1.14  #endif
    1.15  
    1.16 +Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) {
    1.17 +  const TypeOopPtr *tinst = t_adr->isa_oopptr();
    1.18 +  if (tinst == NULL || !tinst->is_instance_field())
    1.19 +    return mchain;  // don't try to optimize non-instance types
    1.20 +  uint instance_id = tinst->instance_id();
    1.21 +  Node *prev = NULL;
    1.22 +  Node *result = mchain;
    1.23 +  while (prev != result) {
    1.24 +    prev = result;
    1.25 +    // skip over a call which does not affect this memory slice
    1.26 +    if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) {
    1.27 +      Node *proj_in = result->in(0);
    1.28 +      if (proj_in->is_Call()) {
    1.29 +        CallNode *call = proj_in->as_Call();
    1.30 +        if (!call->may_modify(t_adr, phase)) {
    1.31 +          result = call->in(TypeFunc::Memory);
    1.32 +        }
    1.33 +      } else if (proj_in->is_Initialize()) {
    1.34 +        AllocateNode* alloc = proj_in->as_Initialize()->allocation();
    1.35 +        // Stop if this is the initialization for the object instance which
    1.36 +        // which contains this memory slice, otherwise skip over it.
    1.37 +        if (alloc != NULL && alloc->_idx != instance_id) {
    1.38 +          result = proj_in->in(TypeFunc::Memory);
    1.39 +        }
    1.40 +      } else if (proj_in->is_MemBar()) {
    1.41 +        result = proj_in->in(TypeFunc::Memory);
    1.42 +      }
    1.43 +    } else if (result->is_MergeMem()) {
    1.44 +      result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty);
    1.45 +    }
    1.46 +  }
    1.47 +  return result;
    1.48 +}
    1.49 +
    1.50 +Node *MemNode::optimize_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) {
    1.51 +  const TypeOopPtr *t_oop = t_adr->isa_oopptr();
    1.52 +  bool is_instance = (t_oop != NULL) && t_oop->is_instance_field();
    1.53 +  PhaseIterGVN *igvn = phase->is_IterGVN();
    1.54 +  Node *result = mchain;
    1.55 +  result = optimize_simple_memory_chain(result, t_adr, phase);
    1.56 +  if (is_instance && igvn != NULL  && result->is_Phi()) {
    1.57 +    PhiNode *mphi = result->as_Phi();
    1.58 +    assert(mphi->bottom_type() == Type::MEMORY, "memory phi required");
    1.59 +    const TypePtr *t = mphi->adr_type();
    1.60 +    if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM) {
    1.61 +      // clone the Phi with our address type
    1.62 +      result = mphi->split_out_instance(t_adr, igvn);
    1.63 +    } else {
    1.64 +      assert(phase->C->get_alias_index(t) == phase->C->get_alias_index(t_adr), "correct memory chain");
    1.65 +    }
    1.66 +  }
    1.67 +  return result;
    1.68 +}
    1.69 +
    1.70  static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem,  const TypePtr *tp, const TypePtr *adr_check, outputStream *st) {
    1.71    uint alias_idx = phase->C->get_alias_index(tp);
    1.72    Node *mem = mmem;
    1.73 @@ -266,6 +322,8 @@
    1.74    if (offset == Type::OffsetBot)
    1.75      return NULL;            // cannot unalias unless there are precise offsets
    1.76  
    1.77 +  const TypeOopPtr *addr_t = adr->bottom_type()->isa_oopptr();
    1.78 +
    1.79    intptr_t size_in_bytes = memory_size();
    1.80  
    1.81    Node* mem = in(MemNode::Memory);   // start searching here...
    1.82 @@ -345,6 +403,22 @@
    1.83          return mem;         // let caller handle steps (c), (d)
    1.84        }
    1.85  
    1.86 +    } else if (addr_t != NULL && addr_t->is_instance_field()) {
    1.87 +      // Can't use optimize_simple_memory_chain() since it needs PhaseGVN.
    1.88 +      if (mem->is_Proj() && mem->in(0)->is_Call()) {
    1.89 +        CallNode *call = mem->in(0)->as_Call();
    1.90 +        if (!call->may_modify(addr_t, phase)) {
    1.91 +          mem = call->in(TypeFunc::Memory);
    1.92 +          continue;         // (a) advance through independent call memory
    1.93 +        }
    1.94 +      } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) {
    1.95 +        mem = mem->in(0)->in(TypeFunc::Memory);
    1.96 +        continue;           // (a) advance through independent MemBar memory
    1.97 +      } else if (mem->is_MergeMem()) {
    1.98 +        int alias_idx = phase->C->get_alias_index(adr_type());
    1.99 +        mem = mem->as_MergeMem()->memory_at(alias_idx);
   1.100 +        continue;           // (a) advance through independent MergeMem memory
   1.101 +      }
   1.102      }
   1.103  
   1.104      // Unless there is an explicit 'continue', we must bail out here,
   1.105 @@ -1011,6 +1085,122 @@
   1.106      }
   1.107    }
   1.108  
   1.109 +  Node* mem = in(MemNode::Memory);
   1.110 +  const TypePtr *addr_t = phase->type(address)->isa_ptr();
   1.111 +
   1.112 +  if (addr_t != NULL) {
   1.113 +    // try to optimize our memory input
   1.114 +    Node* opt_mem = MemNode::optimize_memory_chain(mem, addr_t, phase);
   1.115 +    if (opt_mem != mem) {
   1.116 +      set_req(MemNode::Memory, opt_mem);
   1.117 +      return this;
   1.118 +    }
   1.119 +    const TypeOopPtr *t_oop = addr_t->isa_oopptr();
   1.120 +    if (can_reshape && opt_mem->is_Phi() &&
   1.121 +        (t_oop != NULL) && t_oop->is_instance_field()) {
   1.122 +      assert(t_oop->offset() != Type::OffsetBot && t_oop->offset() != Type::OffsetTop, "");
   1.123 +      Node *region = opt_mem->in(0);
   1.124 +      uint cnt = opt_mem->req();
   1.125 +      for( uint i = 1; i < cnt; i++ ) {
   1.126 +        Node *in = opt_mem->in(i);
   1.127 +        if( in == NULL ) {
   1.128 +          region = NULL; // Wait stable graph
   1.129 +          break;
   1.130 +        }
   1.131 +      }
   1.132 +      if (region != NULL) {
   1.133 +        // Check for loop invariant.
   1.134 +        if (cnt == 3) {
   1.135 +          for( uint i = 1; i < cnt; i++ ) {
   1.136 +            Node *in = opt_mem->in(i);
   1.137 +            Node* m = MemNode::optimize_memory_chain(in, addr_t, phase);
   1.138 +            if (m == opt_mem) {
   1.139 +              set_req(MemNode::Memory, opt_mem->in(cnt - i)); // Skip this phi.
   1.140 +              return this;
   1.141 +            }
   1.142 +          }
   1.143 +        }
   1.144 +        // Split through Phi (see original code in loopopts.cpp).
   1.145 +        assert(phase->C->have_alias_type(addr_t), "instance should have alias type");
   1.146 +        const Type* this_type = this->bottom_type();
   1.147 +        int this_index  = phase->C->get_alias_index(addr_t);
   1.148 +        int this_offset = addr_t->offset();
   1.149 +        int this_iid    = addr_t->is_oopptr()->instance_id();
   1.150 +        int wins = 0;
   1.151 +        PhaseIterGVN *igvn = phase->is_IterGVN();
   1.152 +        Node *phi = new (igvn->C, region->req()) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset);
   1.153 +        for( uint i = 1; i < region->req(); i++ ) {
   1.154 +          Node *x;
   1.155 +          Node* the_clone = NULL;
   1.156 +          if( region->in(i) == phase->C->top() ) {
   1.157 +            x = phase->C->top();      // Dead path?  Use a dead data op
   1.158 +          } else {
   1.159 +            x = this->clone();        // Else clone up the data op
   1.160 +            the_clone = x;            // Remember for possible deletion.
   1.161 +            // Alter data node to use pre-phi inputs
   1.162 +            if( this->in(0) == region ) {
   1.163 +              x->set_req( 0, region->in(i) );
   1.164 +            } else {
   1.165 +              x->set_req( 0, NULL );
   1.166 +            }
   1.167 +            for( uint j = 1; j < this->req(); j++ ) {
   1.168 +              Node *in = this->in(j);
   1.169 +              if( in->is_Phi() && in->in(0) == region )
   1.170 +                x->set_req( j, in->in(i) ); // Use pre-Phi input for the clone
   1.171 +            }
   1.172 +          }
   1.173 +          // Check for a 'win' on some paths
   1.174 +          const Type *t = x->Value(igvn);
   1.175 +
   1.176 +          bool singleton = t->singleton();
   1.177 +
   1.178 +          // See comments in PhaseIdealLoop::split_thru_phi().
   1.179 +          if( singleton && t == Type::TOP ) {
   1.180 +            singleton &= region->is_Loop() && (i != LoopNode::EntryControl);
   1.181 +          }
   1.182 +
   1.183 +          if( singleton ) {
   1.184 +            wins++;
   1.185 +            x = igvn->makecon(t);
   1.186 +          } else {
   1.187 +            // We now call Identity to try to simplify the cloned node.
   1.188 +            // Note that some Identity methods call phase->type(this).
   1.189 +            // Make sure that the type array is big enough for
   1.190 +            // our new node, even though we may throw the node away.
   1.191 +            // (This tweaking with igvn only works because x is a new node.)
   1.192 +            igvn->set_type(x, t);
   1.193 +            Node *y = x->Identity(igvn);
   1.194 +            if( y != x ) {
   1.195 +              wins++;
   1.196 +              x = y;
   1.197 +            } else {
   1.198 +              y = igvn->hash_find(x);
   1.199 +              if( y ) {
   1.200 +                wins++;
   1.201 +                x = y;
   1.202 +              } else {
   1.203 +                // Else x is a new node we are keeping
   1.204 +                // We do not need register_new_node_with_optimizer
   1.205 +                // because set_type has already been called.
   1.206 +                igvn->_worklist.push(x);
   1.207 +              }
   1.208 +            }
   1.209 +          }
   1.210 +          if (x != the_clone && the_clone != NULL)
   1.211 +            igvn->remove_dead_node(the_clone);
   1.212 +          phi->set_req(i, x);
   1.213 +        }
   1.214 +        if( wins > 0 ) {
   1.215 +          // Record Phi
   1.216 +          igvn->register_new_node_with_optimizer(phi);
   1.217 +          return phi;
   1.218 +        } else {
   1.219 +          igvn->remove_dead_node(phi);
   1.220 +        }
   1.221 +      }
   1.222 +    }
   1.223 +  }
   1.224 +
   1.225    // Check for prior store with a different base or offset; make Load
   1.226    // independent.  Skip through any number of them.  Bail out if the stores
   1.227    // are in an endless dead cycle and report no progress.  This is a key

mercurial