//------------------------------Ideal------------------------------------------ Node *AddDNode::Ideal(PhaseGVN *phase, bool can_reshape) { if( IdealizedNumerics && !phase->C->method()->is_strict() ) { return AddNode::Ideal(phase, can_reshape); // commutative and associative transforms } // Floating point additions are not associative because of boundary conditions (infinity) return commute(this, phase->type( in(1) )->singleton(), phase->type( in(2) )->singleton() ) ? this : NULL; }
bool can_pull (patch p1, patch p2) { return commute (p2, p1); }
//------------------------------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; }
bool can_pull (modification m1, modification m2) { return commute (m2, m1); }