//------------------------------expand_unlock_node----------------------
void PhaseMacroExpand::expand_unlock_node(UnlockNode*lock) {
    if( !InlineFastPathLocking ) return;

    // If inlining the fast-path locking code, do it now.  Inserts a
    // diamond control-flow, with the call on the slow-path.  Fencing is
    // included in the both the FastLock test (on success) and the
    // slow-path call.  Memory Phi's are inserted at the diamond merge to
    // prevent hoisting mem ops into the fast-path side (where they might
    // bypass the FastUnlock because it does not carry memory edges).
    Node*ctl=lock->in(TypeFunc::Control);
    Node*obj=lock->in(TypeFunc::Parms+0);
    Node *flock = new (C, 2) FastUnlockNode( ctl, obj );
    RegionNode *region = new (C, 3) RegionNode(3);
    transform_later(region);
    Node*slow_path=opt_iff(region,flock);

    // Make the merge point
    PhiNode*memphi=new(C,3)PhiNode(region,Type::MEMORY,TypePtr::BOTTOM);
    transform_later(memphi);
    Node *mem = lock->in(TypeFunc::Memory);
    memphi->init_req(2,mem);    // Plug in the fast-path

    Node*lock_ctl=lock->proj_out(TypeFunc::Control);
    Node*lock_mem=lock->proj_out(TypeFunc::Memory);
    _igvn.hash_delete(lock_ctl);
    _igvn.hash_delete(lock_mem);
    _igvn.subsume_node_keep_old(lock_ctl,region);
    _igvn.subsume_node_keep_old(lock_mem,memphi);
    // Plug in the slow-path
    region->init_req(1,lock_ctl);
    memphi->init_req(1,lock_mem);
    lock->set_req(TypeFunc::Control,slow_path);
}
// --- opt_iff ---------------------------------------------------------------
Node* PhaseMacroExpand::opt_iff(Node* region, Node* iff) {
    IfNode *opt_iff = transform_later(iff)->as_If();

    // Fast path taken; set region slot 2
    Node *fast_taken = transform_later( new (C, 1) IfFalseNode(opt_iff) );
    region->init_req(2,fast_taken); // Capture fast-control

    // Fast path not-taken, i.e. slow path
    Node *slow_taken = transform_later( new (C, 1) IfTrueNode(opt_iff) );
    return slow_taken;
}
//------------------------------expand_safepoint_node----------------------
void PhaseMacroExpand::expand_safepoint_node(SafePointNode *safe) {
    // Make a fast-path/slow-path diamond around the explicit poll
    Node*tls=new(C,1)ThreadLocalNode();
    transform_later(tls);
    ConLNode *off = _igvn.longcon(in_bytes(JavaThread::please_self_suspend_offset()));
    Node *adr = new (C, 4) AddPNode( C->top(), tls, off );
    transform_later(adr);
    Node *pss = LoadNode::make(C, NULL, safe->in(TypeFunc::Memory), adr, TypeRawPtr::BOTTOM, TypeInt::INT, T_INT);
    transform_later(pss);
    Node *cmp = new (C, 3) CmpINode( pss, _igvn.intcon(0) );
    transform_later(cmp);
    Node*bol=new(C,2)BoolNode(cmp,BoolTest::ne);
    transform_later(bol);
    Node *region = new (C, 3) RegionNode(3);
    transform_later(region);
    IfNode*iff= new (C, 2) IfNode(safe->in(TypeFunc::Control), bol, PROB_UNLIKELY_MAG(6), COUNT_UNKNOWN );
    Node *slow_path = opt_iff(region,iff);
    _igvn.hash_delete(safe);
    safe->set_req(TypeFunc::Control,slow_path);
    _igvn.subsume_node_keep_old(safe,region);
    region->init_req(1,safe);
}
 Node* basic_plus_adr(Node* base, Node* ptr, Node* offset) {
   Node* adr = new (C) AddPNode(base, ptr, offset);
   return transform_later(adr);
 }
//--- expand_allocation ------------------------------------------------------
void PhaseMacroExpand::expand_allocate(AllocateNode*A) {
    // See if we are forced to go slow-path.
    if( A->_entry_point == (address)SharedRuntime::_new )
        return;      // Always go slow-path - required for finalizers, etc

    Node*A_ctl=A->proj_out(TypeFunc::Control);
    Node*A_mem=A->proj_out(TypeFunc::Memory);
    Node*A_oop=A->proj_out(TypeFunc::Parms+0);

    // Inject a fast-path / slow-path diamond.  Fast-path is still milli-code,
    // which returns an oop or null - and does not block, nor GC, nor kill
    // registers.  If we have an allocation failure the fast-path leaves the
    // regs in-place for a slow-path call which DOES block, GC, etc.
    Node*ctl=A->in(TypeFunc::Control);
    Node*kid=A->in(AllocateNode::KID);
    Node*siz=A->in(AllocateNode::AllocSize);
    Node*xtr=A->in(AllocateNode::ExtraSlow);
    Node *len = A->is_AllocateArray() ? A->in(AllocateNode::ALength) : C->top();

    if ( !A_oop && ( !A->is_AllocateArray() || ( _igvn.type(A->in(AllocateNode::ALength))->higher_equal(TypeInt::POS) ) ) ) {
        tty->print_cr("Dead allocation should be removed earlier");
        Unimplemented();
    }

    // Convert the array element count to a Long value,
    // and fold in the EKID value for oop-arrays.
    const TypeOopPtr *toop = A->_tf->range()->field_at(TypeFunc::Parms+0)->is_ptr()->cast_to_ptr_type(TypePtr::BotPTR)->is_oopptr();
    if( len != C->top() ) {
        assert0( A->is_AllocateArray() );
        Node*lenl=transform_later(new(C,2)ConvI2LNode(len));
        Node*ekid=A->in(AllocateNode::EKID);
        if( ekid->bottom_type() != TypeInt::ZERO ) {
            // Have an EKID?  Smash the array length and EKID together.
            Node *ekidl  = transform_later(new (C,2) CastP2XNode(0,ekid));
            Node *ekidshf= transform_later(new (C,3) LShiftLNode(ekidl,_igvn.intcon(32)));
            Node *combo  = transform_later(new (C,3)     OrLNode(lenl,ekidshf));
            len=combo;
        } else {
            len=lenl;
        }
        // Crunch arguments for matching.  The old ExtraSlow argument is used to
        // make more gating control flow in this function, but is not an argument
        // to the runtime call.  Neither is the EKID argument: the slow-path will
        // compute it's own EKID.
        A->set_req(AllocateNode::ExtraSlow,len);
        A->set_req(AllocateNode::ALength,C->top());
        A->set_req(AllocateNode::EKID,C->top());
    } else {
        A->set_req(AllocateNode::ExtraSlow,_igvn.zerocon(T_INT));
        assert0( !A->is_AllocateArray() );
    }

    // Extra slow-path test required?
    RegionNode *region2 = NULL;
    if( xtr->bottom_type() != TypeInt::ZERO ) { // Commonly, no extra test required
        // Extra slow-path tests can be required for fast-pathing reflection
        // allocation (and cloning).  If the new object requires e.g. finalization
        // or further class linking/loading.
        Node *cmp = transform_later(new(C,3)CmpINode(xtr,_igvn.zerocon(T_INT)));
        Node*bol=transform_later(new(C,2)BoolNode(cmp,BoolTest::eq));
        Node *iff = new (C, 2) IfNode( ctl, bol, PROB_LIKELY_MAG(5), COUNT_UNKNOWN );
        region2=new(C,3)RegionNode(3);
        transform_later(region2);
        ctl = opt_iff(region2,iff);
    }

    FastAllocNode *fal = new (C, 4) FastAllocNode(kid,siz,toop,len);
    fal->set_req(0,ctl);
    transform_later(fal);
    Node *mem = new (C,1) SCMemProjNode(fal);
    transform_later(mem);

    Node *cmp = transform_later(new(C,3)CmpPNode(fal,_igvn.zerocon(T_OBJECT)));
    Node*bol=transform_later(new(C,2)BoolNode(cmp,BoolTest::eq));
    Node*iff=new(C,2)IfNode(ctl,bol,PROB_UNLIKELY_MAG(5),COUNT_UNKNOWN);
    RegionNode *region = new (C, 3) RegionNode(3);
    transform_later(region);
    Node *slow_path = opt_iff(region,iff);

    // Make the merge point
    PhiNode*phimem=new(C,3)PhiNode(region,Type::MEMORY,TypePtr::BOTTOM);
    transform_later(phimem);
    phimem->init_req(2,mem);    // Plug in the fast-path

    PhiNode*phioop=NULL;
    if (A_oop) {
        phioop = new (C, 3) PhiNode(region,toop);
        transform_later(phioop);
        phioop->init_req(2,fal);    // Plug in the fast-path
    }

    _igvn.hash_delete(A_ctl);
    _igvn.hash_delete(A_mem);
    if (A_oop) _igvn.hash_delete (A_oop);
    _igvn.subsume_node_keep_old(A_ctl,region);
    _igvn.subsume_node_keep_old(A_mem,phimem);
    if (A_oop) _igvn.subsume_node_keep_old(A_oop,phioop);

    // Plug in the slow-path
    region->init_req(1,A_ctl);
    phimem->init_req(1,A_mem);
    if (A_oop) phioop->init_req(1,A_oop);
    if( xtr->bottom_type() != TypeInt::ZERO ) { // Commonly, no extra test required
        region2->init_req(1,slow_path);
        slow_path = region2;
    }
    A->set_req(TypeFunc::Control,slow_path);
    // The slow-path call now directly calls into the runtime.
    A->_entry_point = (address)SharedRuntime::_new;
}