//============================================================================= ReturnNode::ReturnNode(Node *cntrl, Node *i_o, Node *memory, Node *frameptr, Node *retadr ) : Node(TypeFunc::Parms) { set_req(TypeFunc::Control,cntrl); set_req(TypeFunc::I_O,i_o); set_req(TypeFunc::Memory,memory); set_req(TypeFunc::FramePtr,frameptr); set_req(TypeFunc::ReturnAdr,retadr); }
//============================================================================= HaltNode::HaltNode( Node *ctrl, Node *frameptr ) : Node(TypeFunc::Parms) { Node* top = Compile::current()->top(); set_req(TypeFunc::Control, ctrl ); set_req(TypeFunc::I_O, top); set_req(TypeFunc::Memory, top); set_req(TypeFunc::FramePtr, frameptr ); set_req(TypeFunc::ReturnAdr,top); }
//============================================================================= //------------------------------Ideal------------------------------------------ // Check for power-of-2 multiply, then try the regular MulNode::Ideal Node *MulLNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Swap constant to right if( in(1)->is_Con() ) { Node *t = in(1); set_req(1,in(2)); set_req(2,t); } else if( !in(2)->is_Con() ) return MulNode::Ideal(phase, can_reshape); // Now we have a constant Node on the right and the constant in con const TypeLong *tl2 = phase->type( in(2) )->isa_long(); if( !tl2 ) return NULL; // Might be top jlong con = tl2->isa_long()->get_con(); if( con == CONST64(0) ) return NULL; // By zero is handled by Value call if( con == CONST64(1) ) return NULL; // By one is handled by Identity call // Check for negative constant; if so negate the final result bool sign_flip = false; if( con < 0 ) { con = -con; sign_flip = true; } // Get low bit; check for being the only bit Node *res = NULL; jlong bit1 = con & -con; // Extract low bit if( bit1 == con ) { // Found a power of 2? res = new (3) LShiftLNode( in(1), phase->intcon(log2_long(bit1)) ); } else { // Check for constant with 2 bits set jlong bit2 = con-bit1; bit2 = bit2 & -bit2; // Extract 2nd bit if( bit2 + bit1 == con ) { // Found all bits in con? Node *n1 = phase->transform( new (3) LShiftLNode( in(1), phase->intcon(log2_long(bit1)) ) ); Node *n2 = phase->transform( new (3) LShiftLNode( in(1), phase->intcon(log2_long(bit2)) ) ); res = new (3) AddLNode( n2, n1 ); } else { // Sleezy: power-of-2 -1. Next time be generic. jlong temp = con + 1; if( temp == (temp & -temp) ) { Node *n1 = phase->transform( new (3) LShiftLNode( in(1), phase->intcon(log2_long(temp)) ) ); res = new (3) SubLNode( n1, in(1) ); } else { return MulNode::Ideal(phase, can_reshape); } } } if( sign_flip ) { // Need to negate result? res = phase->transform(res);// Transform, before making the zero con res = new (3) SubLNode(phase->makecon(TypeLong::ZERO),res); } return res; // Return final result }
/* * Creates peudo DEV:DFx files. */ void initpseudodevices(void) { ULONG lock; int i; pseudo_dev_created = 0; pseudo_dev_assigned = 0; for(i=0;i<4;++i) dfx_done[i]=0; /* check if dev: already exists */ set_req(0);lock = Lock(amiga_dev_path,SHARED_LOCK);set_req(1); if(!lock) { char name[80]; set_req(0);lock = Lock(pseudo_dev_path,SHARED_LOCK);set_req(1); if(!lock) { /* create it */ lock = CreateDir(pseudo_dev_path); if(!lock) goto fail; UnLock(lock);lock = Lock(pseudo_dev_path,SHARED_LOCK); pseudo_dev_created = 1; } strcpy(name,amiga_dev_path); if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0'; if(!AssignLock(name,lock)) {UnLock(lock);goto fail;} /* the lock is the assign now */ pseudo_dev_assigned = 1; } else UnLock(lock); /* Create the dev:DFi entry */ for(i=0;i<4;++i) if(device_exists("trackdisk.device",i)) { ULONG fd; char name[80]; sprintf(name,"%sDF%d",amiga_dev_path,i); fd = Open(name,MODE_NEWFILE); if(fd) {Close(fd);dfx_done[i]=1;} } return; fail: fprintf(stderr,"Failed to create pseudo dev: entry!\n"); }
//============================================================================= RethrowNode::RethrowNode( Node* cntrl, Node* i_o, Node* memory, Node* frameptr, Node* ret_adr, Node* exception ) : Node(TypeFunc::Parms + 1) { set_req(TypeFunc::Control , cntrl ); set_req(TypeFunc::I_O , i_o ); set_req(TypeFunc::Memory , memory ); set_req(TypeFunc::FramePtr , frameptr ); set_req(TypeFunc::ReturnAdr, ret_adr); set_req(TypeFunc::Parms , exception); }
void set_monitor(const JVMState* jvms, uint idx, Node *c) { assert(verify_jvms(jvms), "jvms must match"); set_req(_jvmadj + jvms->monoff() + idx, c); }
//============================================================================= //------------------------------Idealize--------------------------------------- // MINs show up in range-check loop limit calculations. Look for // "MIN2(x+c0,MIN2(y,x+c1))". Pick the smaller constant: "MIN2(x+c0,y)" Node *MinINode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *progress = NULL; // Force a right-spline graph Node *l = in(1); Node *r = in(2); // Transform MinI1( MinI2(a,b), c) into MinI1( a, MinI2(b,c) ) // to force a right-spline graph for the rest of MinINode::Ideal(). if( l->Opcode() == Op_MinI ) { assert( l != l->in(1), "dead loop in MinINode::Ideal" ); r = phase->transform(new (phase->C) MinINode(l->in(2),r)); l = l->in(1); set_req(1, l); set_req(2, r); return this; } // Get left input & constant Node *x = l; int x_off = 0; if( x->Opcode() == Op_AddI && // Check for "x+c0" and collect constant x->in(2)->is_Con() ) { const Type *t = x->in(2)->bottom_type(); if( t == Type::TOP ) return NULL; // No progress x_off = t->is_int()->get_con(); x = x->in(1); } // Scan a right-spline-tree for MINs Node *y = r; int y_off = 0; // Check final part of MIN tree if( y->Opcode() == Op_AddI && // Check for "y+c1" and collect constant y->in(2)->is_Con() ) { const Type *t = y->in(2)->bottom_type(); if( t == Type::TOP ) return NULL; // No progress y_off = t->is_int()->get_con(); y = y->in(1); } if( x->_idx > y->_idx && r->Opcode() != Op_MinI ) { swap_edges(1, 2); return this; } if( r->Opcode() == Op_MinI ) { assert( r != r->in(2), "dead loop in MinINode::Ideal" ); y = r->in(1); // Check final part of MIN tree if( y->Opcode() == Op_AddI &&// Check for "y+c1" and collect constant y->in(2)->is_Con() ) { const Type *t = y->in(2)->bottom_type(); if( t == Type::TOP ) return NULL; // No progress y_off = t->is_int()->get_con(); y = y->in(1); } if( x->_idx > y->_idx ) return new (phase->C) MinINode(r->in(1),phase->transform(new (phase->C) MinINode(l,r->in(2)))); // See if covers: MIN2(x+c0,MIN2(y+c1,z)) if( !phase->eqv(x,y) ) return NULL; // If (y == x) transform MIN2(x+c0, MIN2(x+c1,z)) into // MIN2(x+c0 or x+c1 which less, z). return new (phase->C) MinINode(phase->transform(new (phase->C) AddINode(x,phase->intcon(MIN2(x_off,y_off)))),r->in(2)); } else { // See if covers: MIN2(x+c0,y+c1) if( !phase->eqv(x,y) ) return NULL; // If (y == x) transform MIN2(x+c0,x+c1) into x+c0 or x+c1 which less. return new (phase->C) AddINode(x,phase->intcon(MIN2(x_off,y_off))); } }
//------------------------------Idealize--------------------------------------- Node *AddPNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Bail out if dead inputs if( phase->type( in(Address) ) == Type::TOP ) return NULL; // If the left input is an add of a constant, flatten the expression tree. const Node *n = in(Address); if (n->is_AddP() && n->in(Base) == in(Base)) { const AddPNode *addp = n->as_AddP(); // Left input is an AddP assert( !addp->in(Address)->is_AddP() || addp->in(Address)->as_AddP() != addp, "dead loop in AddPNode::Ideal" ); // Type of left input's right input const Type *t = phase->type( addp->in(Offset) ); if( t == Type::TOP ) return NULL; const TypeX *t12 = t->is_intptr_t(); if( t12->is_con() ) { // Left input is an add of a constant? // If the right input is a constant, combine constants const Type *temp_t2 = phase->type( in(Offset) ); if( temp_t2 == Type::TOP ) return NULL; const TypeX *t2 = temp_t2->is_intptr_t(); Node* address; Node* offset; if( t2->is_con() ) { // The Add of the flattened expression address = addp->in(Address); offset = phase->MakeConX(t2->get_con() + t12->get_con()); } else { // Else move the constant to the right. ((A+con)+B) into ((A+B)+con) address = phase->transform(new (phase->C) AddPNode(in(Base),addp->in(Address),in(Offset))); offset = addp->in(Offset); } PhaseIterGVN *igvn = phase->is_IterGVN(); if( igvn ) { set_req_X(Address,address,igvn); set_req_X(Offset,offset,igvn); } else { set_req(Address,address); set_req(Offset,offset); } return this; } } // Raw pointers? if( in(Base)->bottom_type() == Type::TOP ) { // If this is a NULL+long form (from unsafe accesses), switch to a rawptr. if (phase->type(in(Address)) == TypePtr::NULL_PTR) { Node* offset = in(Offset); return new (phase->C) CastX2PNode(offset); } } // If the right is an add of a constant, push the offset down. // Convert: (ptr + (offset+con)) into (ptr+offset)+con. // The idea is to merge array_base+scaled_index groups together, // and only have different constant offsets from the same base. const Node *add = in(Offset); if( add->Opcode() == Op_AddX && add->in(1) != add ) { const Type *t22 = phase->type( add->in(2) ); if( t22->singleton() && (t22 != Type::TOP) ) { // Right input is an add of a constant? set_req(Address, phase->transform(new (phase->C) AddPNode(in(Base),in(Address),add->in(1)))); set_req(Offset, add->in(2)); PhaseIterGVN *igvn = phase->is_IterGVN(); if (add->outcnt() == 0 && igvn) { // add disconnected. igvn->_worklist.push((Node*)add); } return this; // Made progress } } return NULL; // No progress }
//------------------------------Idealize--------------------------------------- // If we get here, we assume we are associative! Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) { const Type *t1 = phase->type( in(1) ); const Type *t2 = phase->type( in(2) ); int con_left = t1->singleton(); int con_right = t2->singleton(); // Check for commutative operation desired if( commute(this,con_left,con_right) ) return this; AddNode *progress = NULL; // Progress flag // Convert "(x+1)+2" into "x+(1+2)". If the right input is a // constant, and the left input is an add of a constant, flatten the // expression tree. Node *add1 = in(1); Node *add2 = in(2); int add1_op = add1->Opcode(); int this_op = Opcode(); if( con_right && t2 != Type::TOP && // Right input is a constant? add1_op == this_op ) { // Left input is an Add? // Type of left _in right input const Type *t12 = phase->type( add1->in(2) ); if( t12->singleton() && t12 != Type::TOP ) { // Left input is an add of a constant? // Check for rare case of closed data cycle which can happen inside // unreachable loops. In these cases the computation is undefined. #ifdef ASSERT Node *add11 = add1->in(1); int add11_op = add11->Opcode(); if( (add1 == add1->in(1)) || (add11_op == this_op && add11->in(1) == add1) ) { assert(false, "dead loop in AddNode::Ideal"); } #endif // The Add of the flattened expression Node *x1 = add1->in(1); Node *x2 = phase->makecon( add1->as_Add()->add_ring( t2, t12 )); PhaseIterGVN *igvn = phase->is_IterGVN(); if( igvn ) { set_req_X(2,x2,igvn); set_req_X(1,x1,igvn); } else { set_req(2,x2); set_req(1,x1); } progress = this; // Made progress add1 = in(1); add1_op = add1->Opcode(); } } // Convert "(x+1)+y" into "(x+y)+1". Push constants down the expression tree. if( add1_op == this_op && !con_right ) { Node *a12 = add1->in(2); const Type *t12 = phase->type( a12 ); if( t12->singleton() && t12 != Type::TOP && (add1 != add1->in(1)) && !(add1->in(1)->is_Phi() && add1->in(1)->as_Phi()->is_tripcount()) ) { assert(add1->in(1) != this, "dead loop in AddNode::Ideal"); add2 = add1->clone(); add2->set_req(2, in(2)); add2 = phase->transform(add2); set_req(1, add2); set_req(2, a12); progress = this; add2 = a12; } } // Convert "x+(y+1)" into "(x+y)+1". Push constants down the expression tree. int add2_op = add2->Opcode(); if( add2_op == this_op && !con_left ) { Node *a22 = add2->in(2); const Type *t22 = phase->type( a22 ); if( t22->singleton() && t22 != Type::TOP && (add2 != add2->in(1)) && !(add2->in(1)->is_Phi() && add2->in(1)->as_Phi()->is_tripcount()) ) { assert(add2->in(1) != this, "dead loop in AddNode::Ideal"); Node *addx = add2->clone(); addx->set_req(1, in(1)); addx->set_req(2, add2->in(1)); addx = phase->transform(addx); set_req(1, addx); set_req(2, a22); progress = this; PhaseIterGVN *igvn = phase->is_IterGVN(); if (add2->outcnt() == 0 && igvn) { // add disconnected. igvn->_worklist.push(add2); } } } return progress; }
void set_box_node(Node* box) { set_req(2, box); }
//------------------------------Ideal------------------------------------------ // We also canonicalize the Node, moving constants to the right input, // and flatten expressions (so that 1+x+2 becomes x+3). Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) { const Type *t1 = phase->type( in(1) ); const Type *t2 = phase->type( in(2) ); Node *progress = NULL; // Progress flag // We are OK if right is a constant, or right is a load and // left is a non-constant. if( !(t2->singleton() || (in(2)->is_Load() && !(t1->singleton() || in(1)->is_Load())) ) ) { if( t1->singleton() || // Left input is a constant? // Otherwise, sort inputs (commutativity) to help value numbering. (in(1)->_idx > in(2)->_idx) ) { swap_edges(1, 2); const Type *t = t1; t1 = t2; t2 = t; progress = this; // Made progress } } // If the right input is a constant, and the left input is a product of a // constant, flatten the expression tree. uint op = Opcode(); if( t2->singleton() && // Right input is a constant? op != Op_MulF && // Float & double cannot reassociate op != Op_MulD ) { if( t2 == Type::TOP ) return NULL; Node *mul1 = in(1); if( mul1 == this ) { // Check for dead cycle set_req(1, phase->C->top()); return this; // Make it trivially dead } if( mul1->Opcode() == mul_opcode() ) { // Left input is a multiply? // Mul of a constant? const Type *t12 = phase->type( mul1->in(2) ); if( t12->singleton() && t12 != Type::TOP) { // Left input is an add of a constant? // Compute new constant; check for overflow const Type *tcon01 = mul1->is_Mul()->mul_ring(t2,t12); if( tcon01->singleton() ) { // The Mul of the flattened expression set_req(1, mul1->in(1)); set_req(2, phase->makecon( tcon01 )); t2 = tcon01; progress = this; // Made progress } } } // If the right input is a constant, and the left input is an add of a // constant, flatten the tree: (X+con1)*con0 ==> X*con0 + con1*con0 const Node *add1 = in(1); if( add1->Opcode() == add_opcode() ) { // Left input is an add? // Add of a constant? const Type *t12 = phase->type( add1->in(2) ); if( t12->singleton() && t12 != Type::TOP ) { // Left input is an add of a constant? // Check if the add node is dead and self-referencing, // to avoid infinite loop (no progress). if( add1->in(1) == add1 ) return progress; // Compute new constant; check for overflow const Type *tcon01 = mul_ring(t2,t12); if( tcon01->singleton() ) { // Convert (X+con1)*con0 into X*con0 Node *mul = clone(); // mul = ()*con0 mul->set_req(1,add1->in(1)); // mul = X*con0 mul = phase->transform(mul); Node *add2 = add1->clone(); add2->set_req(1, mul); // X*con0 + con0*con1 add2->set_req(2, phase->makecon(tcon01) ); progress = add2; } } } // End of is left input an add } // End of is right input a Mul return progress; }
void set_memory ( Node *c ) { set_req(TypeFunc::Memory ,c); }
void set_i_o ( Node *c ) { set_req(TypeFunc::I_O ,c); }
void set_control ( Node *c ) { set_req(TypeFunc::Control,c); }
void set_argument(JVMState* jvms, uint idx, Node *c) { assert(verify_jvms(jvms), "jvms must match"); set_req(jvms->argoff() + idx, c); }
void set_stack(JVMState* jvms, uint idx, Node *c) { assert(verify_jvms(jvms), "jvms must match"); set_req(jvms->stkoff() + idx, c); }