//------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. // Move constants to the right.
Node *CMoveNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (in(0) != NULL && remove_dead_region(phase, can_reshape)) { returnthis;
} // Don't bother trying to transform a dead node if (in(0) != NULL && in(0)->is_top()) { return NULL;
}
assert(in(Condition) != this &&
in(IfFalse) != this &&
in(IfTrue) != this, "dead loop in CMoveNode::Ideal"); if (phase->type(in(Condition)) == Type::TOP ||
phase->type(in(IfFalse)) == Type::TOP ||
phase->type(in(IfTrue)) == Type::TOP) { return NULL;
} // Canonicalize the node by moving constants to the right input. if (in(Condition)->is_Bool() && phase->type(in(IfFalse))->singleton() && !phase->type(in(IfTrue))->singleton()) {
BoolNode* b = in(Condition)->as_Bool()->negate(phase); return make(in(Control), phase->transform(b), in(IfTrue), in(IfFalse), _type);
} return NULL;
}
//------------------------------is_cmove_id------------------------------------ // Helper function to check for CMOVE identity. Shared with PhiNode::Identity
Node *CMoveNode::is_cmove_id( PhaseTransform *phase, Node *cmp, Node *t, Node *f, BoolNode *b ) { // Check for Cmp'ing and CMove'ing same values if ((cmp->in(1) == f && cmp->in(2) == t) || // Swapped Cmp is OK
(cmp->in(2) == f && cmp->in(1) == t)) { // Give up this identity check for floating points because it may choose incorrect // value around 0.0 and -0.0 if ( cmp->Opcode()==Op_CmpF || cmp->Opcode()==Op_CmpD ) return NULL; // Check for "(t==f)?t:f;" and replace with "f" if( b->_test._test == BoolTest::eq ) return f; // Allow the inverted case as well // Check for "(t!=f)?t:f;" and replace with "t" if( b->_test._test == BoolTest::ne ) return t;
} return NULL;
}
//------------------------------Identity--------------------------------------- // Conditional-move is an identity if both inputs are the same, or the test // true or false.
Node* CMoveNode::Identity(PhaseGVN* phase) { // C-moving identical inputs? if (in(IfFalse) == in(IfTrue)) { return in(IfFalse); // Then it doesn't matter
} if (phase->type(in(Condition)) == TypeInt::ZERO) { return in(IfFalse); // Always pick left(false) input
} if (phase->type(in(Condition)) == TypeInt::ONE) { return in(IfTrue); // Always pick right(true) input
}
// Check for CMove'ing a constant after comparing against the constant. // Happens all the time now, since if we compare equality vs a constant in // the parser, we "know" the variable is constant on one path and we force // it. Thus code like "if( x==0 ) {/*EMPTY*/}" ends up inserting a // conditional move: "x = (x==0)?0:x;". Yucko. This fix is slightly more // general in that we don't need constants. if( in(Condition)->is_Bool() ) {
BoolNode *b = in(Condition)->as_Bool();
Node *cmp = b->in(1); if( cmp->is_Cmp() ) {
Node *id = is_cmove_id( phase, cmp, in(IfTrue), in(IfFalse), b ); if( id ) return id;
}
}
returnthis;
}
//------------------------------Value------------------------------------------ // Result is the meet of inputs const Type* CMoveNode::Value(PhaseGVN* phase) const { if (phase->type(in(Condition)) == Type::TOP) { return Type::TOP;
} if (phase->type(in(IfTrue)) == Type::TOP || phase->type(in(IfFalse)) == Type::TOP) { return Type::TOP;
} const Type* t = phase->type(in(IfFalse))->meet_speculative(phase->type(in(IfTrue))); return t->filter(_type);
}
//------------------------------make------------------------------------------- // Make a correctly-flavored CMove. Since _type is directly determined // from the inputs we do not need to specify it here.
CMoveNode *CMoveNode::make(Node *c, Node *bol, Node *left, Node *right, const Type *t) { switch( t->basic_type() ) { case T_INT: returnnew CMoveINode( bol, left, right, t->is_int() ); case T_FLOAT: returnnew CMoveFNode( bol, left, right, t ); case T_DOUBLE: returnnew CMoveDNode( bol, left, right, t ); case T_LONG: returnnew CMoveLNode( bol, left, right, t->is_long() ); case T_OBJECT: returnnew CMovePNode( c, bol, left, right, t->is_oopptr() ); case T_ADDRESS: returnnew CMovePNode( c, bol, left, right, t->is_ptr() ); case T_NARROWOOP: returnnew CMoveNNode( c, bol, left, right, t ); default:
ShouldNotReachHere(); return NULL;
}
}
//============================================================================= //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. // Check for conversions to boolean
Node *CMoveINode::Ideal(PhaseGVN *phase, bool can_reshape) { // Try generic ideal's first
Node *x = CMoveNode::Ideal(phase, can_reshape); if( x ) return x;
// If zero is on the left (false-case, no-move-case) it must mean another // constant is on the right (otherwise the shared CMove::Ideal code would // have moved the constant to the right). This situation is bad for x86 because // the zero has to be manifested in a register with a XOR which kills flags, // which are live on input to the CMoveI, leading to a situation which causes // excessive spilling. See bug 4677505. if( phase->type(in(IfFalse)) == TypeInt::ZERO && !(phase->type(in(IfTrue)) == TypeInt::ZERO) ) { if( in(Condition)->is_Bool() ) {
BoolNode* b = in(Condition)->as_Bool();
BoolNode* b2 = b->negate(phase); return make(in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type);
}
}
// Check for vs 0 or 1 if( !bol->in(1)->is_Cmp() ) return NULL; const CmpNode *cmp = bol->in(1)->as_Cmp(); if( phase->type(cmp->in(2)) == TypeInt::ZERO ) {
} elseif( phase->type(cmp->in(2)) == TypeInt::ONE ) { // Allow cmp-vs-1 if the other input is bounded by 0-1 if( phase->type(cmp->in(1)) != TypeInt::BOOL ) return NULL;
flip = 1 - flip;
} elsereturn NULL;
// Convert to a bool (flipped) // Build int->bool conversion if (PrintOpto) { tty->print_cr("CMOV to I2B"); }
Node *n = new Conv2BNode( cmp->in(1) ); if( flip )
n = new XorINode( phase->transform(n), phase->intcon(1) );
return n;
}
//============================================================================= //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. // Check for absolute value
Node *CMoveFNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Try generic ideal's first
Node *x = CMoveNode::Ideal(phase, can_reshape); if( x ) return x;
int cmp_zero_idx = 0; // Index of compare input where to look for zero int phi_x_idx = 0; // Index of phi input where to find naked x
// Find zero input of CmpF; the other input is being abs'd
Node *cmpf = bol->in(1); if( cmpf->Opcode() != Op_CmpF ) return NULL;
Node *X = NULL; bool flip = false; if( phase->type(cmpf->in(cmp_zero_idx)) == TypeF::ZERO ) {
X = cmpf->in(3 - cmp_zero_idx);
} elseif (phase->type(cmpf->in(3 - cmp_zero_idx)) == TypeF::ZERO) { // The test is inverted, we should invert the result...
X = cmpf->in(cmp_zero_idx);
flip = true;
} else { return NULL;
}
// If X is found on the appropriate phi input, find the subtract on the other if( X != in(phi_x_idx) ) return NULL; int phi_sub_idx = phi_x_idx == IfTrue ? IfFalse : IfTrue;
Node *sub = in(phi_sub_idx);
// Allow only SubF(0,X) and fail out for all others; NegF is not OK if( sub->Opcode() != Op_SubF ||
sub->in(2) != X ||
phase->type(sub->in(1)) != TypeF::ZERO ) return NULL;
Node *abs = new AbsFNode( X ); if( flip )
abs = new SubFNode(sub->in(1), phase->transform(abs));
return abs;
}
//============================================================================= //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. // Check for absolute value
Node *CMoveDNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Try generic ideal's first
Node *x = CMoveNode::Ideal(phase, can_reshape); if( x ) return x;
int cmp_zero_idx = 0; // Index of compare input where to look for zero int phi_x_idx = 0; // Index of phi input where to find naked x
// Find zero input of CmpD; the other input is being abs'd
Node *cmpd = bol->in(1); if( cmpd->Opcode() != Op_CmpD ) return NULL;
Node *X = NULL; bool flip = false; if( phase->type(cmpd->in(cmp_zero_idx)) == TypeD::ZERO ) {
X = cmpd->in(3 - cmp_zero_idx);
} elseif (phase->type(cmpd->in(3 - cmp_zero_idx)) == TypeD::ZERO) { // The test is inverted, we should invert the result...
X = cmpd->in(cmp_zero_idx);
flip = true;
} else { return NULL;
}
// If X is found on the appropriate phi input, find the subtract on the other if( X != in(phi_x_idx) ) return NULL; int phi_sub_idx = phi_x_idx == IfTrue ? IfFalse : IfTrue;
Node *sub = in(phi_sub_idx);
// Allow only SubD(0,X) and fail out for all others; NegD is not OK if( sub->Opcode() != Op_SubD ||
sub->in(2) != X ||
phase->type(sub->in(1)) != TypeD::ZERO ) return NULL;
Node *abs = new AbsDNode( X ); if( flip )
abs = new SubDNode(sub->in(1), phase->transform(abs));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.