8256655: rework long counted loop handling
Reviewed-by: kvn, thartmann, vlivanov
This commit is contained in:
parent
13bd2e82ca
commit
3d460bd295
@ -109,13 +109,13 @@ static bool commute(Node *add, bool con_left, bool con_right) {
|
||||
//------------------------------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) );
|
||||
const Type *t1 = phase->type(in(1));
|
||||
const Type *t2 = phase->type(in(2));
|
||||
bool con_left = t1->singleton();
|
||||
bool con_right = t2->singleton();
|
||||
|
||||
// Check for commutative operation desired
|
||||
if( commute(this,con_left,con_right) ) return this;
|
||||
if (commute(this, con_left, con_right)) return this;
|
||||
|
||||
AddNode *progress = NULL; // Progress flag
|
||||
|
||||
@ -126,27 +126,27 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
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?
|
||||
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?
|
||||
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) ) {
|
||||
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 ));
|
||||
Node *x2 = phase->makecon(add1->as_Add()->add_ring(t2, t12));
|
||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||
if( igvn ) {
|
||||
if (igvn) {
|
||||
set_req_X(2,x2,igvn);
|
||||
set_req_X(1,x1,igvn);
|
||||
} else {
|
||||
@ -160,11 +160,11 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
|
||||
// Convert "(x+1)+y" into "(x+y)+1". Push constants down the expression tree.
|
||||
if( add1_op == this_op && !con_right ) {
|
||||
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()) ) {
|
||||
if (t12->singleton() && t12 != Type::TOP && (add1 != add1->in(1)) &&
|
||||
!(add1->in(1)->is_Phi() && (add1->in(1)->as_Phi()->is_tripcount(T_INT) || add1->in(1)->as_Phi()->is_tripcount(T_LONG)))) {
|
||||
assert(add1->in(1) != this, "dead loop in AddNode::Ideal");
|
||||
add2 = add1->clone();
|
||||
add2->set_req(2, in(2));
|
||||
@ -178,11 +178,11 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
|
||||
// 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 ) {
|
||||
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()) ) {
|
||||
if (t22->singleton() && t22 != Type::TOP && (add2 != add2->in(1)) &&
|
||||
!(add2->in(1)->is_Phi() && (add2->in(1)->as_Phi()->is_tripcount(T_INT) || add2->in(1)->as_Phi()->is_tripcount(T_LONG)))) {
|
||||
assert(add2->in(1) != this, "dead loop in AddNode::Ideal");
|
||||
Node *addx = add2->clone();
|
||||
addx->set_req(1, in(1));
|
||||
@ -235,6 +235,17 @@ const Type *AddNode::add_of_identity( const Type *t1, const Type *t2 ) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AddNode* AddNode::make(Node* in1, Node* in2, BasicType bt) {
|
||||
switch (bt) {
|
||||
case T_INT:
|
||||
return new AddINode(in1, in2);
|
||||
case T_LONG:
|
||||
return new AddLNode(in1, in2);
|
||||
default:
|
||||
fatal("Not implemented for %s", type2name(bt));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//------------------------------Idealize---------------------------------------
|
||||
@ -907,26 +918,32 @@ Node* MaxNode::build_min_max(Node* a, Node* b, bool is_max, bool is_unsigned, co
|
||||
bool is_int = gvn.type(a)->isa_int();
|
||||
assert(is_int || gvn.type(a)->isa_long(), "int or long inputs");
|
||||
assert(is_int == (gvn.type(b)->isa_int() != NULL), "inconsistent inputs");
|
||||
Node* hook = NULL;
|
||||
if (gvn.is_IterGVN()) {
|
||||
// Make sure a and b are not destroyed
|
||||
hook = new Node(2);
|
||||
hook->init_req(0, a);
|
||||
hook->init_req(1, b);
|
||||
}
|
||||
Node* res = NULL;
|
||||
if (!is_unsigned) {
|
||||
if (is_max) {
|
||||
if (is_int) {
|
||||
Node* res = gvn.transform(new MaxINode(a, b));
|
||||
res = gvn.transform(new MaxINode(a, b));
|
||||
assert(gvn.type(res)->is_int()->_lo >= t->is_int()->_lo && gvn.type(res)->is_int()->_hi <= t->is_int()->_hi, "type doesn't match");
|
||||
return res;
|
||||
} else {
|
||||
Node* cmp = gvn.transform(new CmpLNode(a, b));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
res = gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
}
|
||||
} else {
|
||||
if (is_int) {
|
||||
Node* res = gvn.transform(new MinINode(a, b));
|
||||
assert(gvn.type(res)->is_int()->_lo >= t->is_int()->_lo && gvn.type(res)->is_int()->_hi <= t->is_int()->_hi, "type doesn't match");
|
||||
return res;
|
||||
} else {
|
||||
Node* cmp = gvn.transform(new CmpLNode(b, a));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
res = gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -934,24 +951,28 @@ Node* MaxNode::build_min_max(Node* a, Node* b, bool is_max, bool is_unsigned, co
|
||||
if (is_int) {
|
||||
Node* cmp = gvn.transform(new CmpUNode(a, b));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveINode(bol, a, b, t->is_int()));
|
||||
res = gvn.transform(new CMoveINode(bol, a, b, t->is_int()));
|
||||
} else {
|
||||
Node* cmp = gvn.transform(new CmpULNode(a, b));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
res = gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
}
|
||||
} else {
|
||||
if (is_int) {
|
||||
Node* cmp = gvn.transform(new CmpUNode(b, a));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveINode(bol, a, b, t->is_int()));
|
||||
res = gvn.transform(new CMoveINode(bol, a, b, t->is_int()));
|
||||
} else {
|
||||
Node* cmp = gvn.transform(new CmpULNode(b, a));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
res = gvn.transform(new CMoveLNode(bol, a, b, t->is_long()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hook != NULL) {
|
||||
hook->destruct(&gvn);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Node* MaxNode::build_min_max_diff_with_zero(Node* a, Node* b, bool is_max, const Type* t, PhaseGVN& gvn) {
|
||||
@ -964,31 +985,43 @@ Node* MaxNode::build_min_max_diff_with_zero(Node* a, Node* b, bool is_max, const
|
||||
} else {
|
||||
zero = gvn.longcon(0);
|
||||
}
|
||||
Node* hook = NULL;
|
||||
if (gvn.is_IterGVN()) {
|
||||
// Make sure a and b are not destroyed
|
||||
hook = new Node(2);
|
||||
hook->init_req(0, a);
|
||||
hook->init_req(1, b);
|
||||
}
|
||||
Node* res = NULL;
|
||||
if (is_max) {
|
||||
if (is_int) {
|
||||
Node* cmp = gvn.transform(new CmpINode(a, b));
|
||||
Node* sub = gvn.transform(new SubINode(a, b));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveINode(bol, sub, zero, t->is_int()));
|
||||
res = gvn.transform(new CMoveINode(bol, sub, zero, t->is_int()));
|
||||
} else {
|
||||
Node* cmp = gvn.transform(new CmpLNode(a, b));
|
||||
Node* sub = gvn.transform(new SubLNode(a, b));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveLNode(bol, sub, zero, t->is_long()));
|
||||
res = gvn.transform(new CMoveLNode(bol, sub, zero, t->is_long()));
|
||||
}
|
||||
} else {
|
||||
if (is_int) {
|
||||
Node* cmp = gvn.transform(new CmpINode(b, a));
|
||||
Node* sub = gvn.transform(new SubINode(a, b));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveINode(bol, sub, zero, t->is_int()));
|
||||
res = gvn.transform(new CMoveINode(bol, sub, zero, t->is_int()));
|
||||
} else {
|
||||
Node* cmp = gvn.transform(new CmpLNode(b, a));
|
||||
Node* sub = gvn.transform(new SubLNode(a, b));
|
||||
Node* bol = gvn.transform(new BoolNode(cmp, BoolTest::lt));
|
||||
return gvn.transform(new CMoveLNode(bol, sub, zero, t->is_long()));
|
||||
res = gvn.transform(new CMoveLNode(bol, sub, zero, t->is_long()));
|
||||
}
|
||||
}
|
||||
if (hook != NULL) {
|
||||
hook->destruct(&gvn);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -68,6 +68,11 @@ public:
|
||||
// Supplied function to return the additive identity type
|
||||
virtual const Type *add_id() const = 0;
|
||||
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return false;
|
||||
}
|
||||
static AddNode* make(Node* in1, Node* in2, BasicType bt);
|
||||
};
|
||||
|
||||
//------------------------------AddINode---------------------------------------
|
||||
@ -81,6 +86,10 @@ public:
|
||||
virtual const Type *bottom_type() const { return TypeInt::INT; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_INT;
|
||||
}
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
};
|
||||
|
||||
@ -95,6 +104,10 @@ public:
|
||||
virtual const Type *bottom_type() const { return TypeLong::LONG; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_LONG;
|
||||
}
|
||||
virtual uint ideal_reg() const { return Op_RegL; }
|
||||
};
|
||||
|
||||
|
@ -54,6 +54,10 @@ class ConstraintCastNode: public TypeNode {
|
||||
TypeNode* dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const;
|
||||
static Node* make_cast(int opcode, Node* c, Node *n, const Type *t, bool carry_dependency);
|
||||
static Node* make(Node* c, Node *n, const Type *t, BasicType bt);
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
@ -87,6 +91,10 @@ class CastIINode: public ConstraintCastNode {
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_INT;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream* st) const;
|
||||
@ -99,6 +107,10 @@ public:
|
||||
: ConstraintCastNode(n, t, carry_dependency){
|
||||
init_class_id(Class_CastLL);
|
||||
}
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_LONG;
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegL; }
|
||||
};
|
||||
|
@ -1084,30 +1084,32 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
|
||||
return Type::TOP;
|
||||
|
||||
// Check for trip-counted loop. If so, be smarter.
|
||||
CountedLoopNode* l = r->is_CountedLoop() ? r->as_CountedLoop() : NULL;
|
||||
BaseCountedLoopNode* l = r->is_BaseCountedLoop() ? r->as_BaseCountedLoop() : NULL;
|
||||
if (l && ((const Node*)l->phi() == this)) { // Trip counted loop!
|
||||
// protect against init_trip() or limit() returning NULL
|
||||
if (l->can_be_counted_loop(phase)) {
|
||||
const Node *init = l->init_trip();
|
||||
const Node *limit = l->limit();
|
||||
const Node* init = l->init_trip();
|
||||
const Node* limit = l->limit();
|
||||
const Node* stride = l->stride();
|
||||
if (init != NULL && limit != NULL && stride != NULL) {
|
||||
const TypeInt* lo = phase->type(init)->isa_int();
|
||||
const TypeInt* hi = phase->type(limit)->isa_int();
|
||||
const TypeInt* stride_t = phase->type(stride)->isa_int();
|
||||
const TypeInteger* lo = phase->type(init)->isa_integer(l->bt());
|
||||
const TypeInteger* hi = phase->type(limit)->isa_integer(l->bt());
|
||||
const TypeInteger* stride_t = phase->type(stride)->isa_integer(l->bt());
|
||||
if (lo != NULL && hi != NULL && stride_t != NULL) { // Dying loops might have TOP here
|
||||
assert(stride_t->_hi >= stride_t->_lo, "bad stride type");
|
||||
assert(stride_t->hi_as_long() >= stride_t->lo_as_long(), "bad stride type");
|
||||
BoolTest::mask bt = l->loopexit()->test_trip();
|
||||
// If the loop exit condition is "not equal", the condition
|
||||
// would not trigger if init > limit (if stride > 0) or if
|
||||
// init < limit if (stride > 0) so we can't deduce bounds
|
||||
// for the iv from the exit condition.
|
||||
if (bt != BoolTest::ne) {
|
||||
if (stride_t->_hi < 0) { // Down-counter loop
|
||||
if (stride_t->hi_as_long() < 0) { // Down-counter loop
|
||||
swap(lo, hi);
|
||||
return TypeInt::make(MIN2(lo->_lo, hi->_lo) , hi->_hi, 3)->filter_speculative(_type);
|
||||
} else if (stride_t->_lo >= 0) {
|
||||
return TypeInt::make(lo->_lo, MAX2(lo->_hi, hi->_hi), 3)->filter_speculative(_type);
|
||||
return TypeInteger::make(MIN2(lo->lo_as_long(), hi->lo_as_long()), hi->hi_as_long(), 3,
|
||||
l->bt())->filter_speculative(_type);
|
||||
} else if (stride_t->lo_as_long() >= 0) {
|
||||
return TypeInteger::make(lo->lo_as_long(), MAX2(lo->hi_as_long(), hi->hi_as_long()), 3,
|
||||
l->bt())->filter_speculative(_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2446,9 +2448,10 @@ bool PhiNode::is_data_loop(RegionNode* r, Node* uin, const PhaseGVN* phase) {
|
||||
}
|
||||
|
||||
//------------------------------is_tripcount-----------------------------------
|
||||
bool PhiNode::is_tripcount() const {
|
||||
return (in(0) != NULL && in(0)->is_CountedLoop() &&
|
||||
in(0)->as_CountedLoop()->phi() == this);
|
||||
bool PhiNode::is_tripcount(BasicType bt) const {
|
||||
return (in(0) != NULL && in(0)->is_BaseCountedLoop() &&
|
||||
in(0)->as_BaseCountedLoop()->operates_on(bt, true) &&
|
||||
in(0)->as_BaseCountedLoop()->phi() == this);
|
||||
}
|
||||
|
||||
//------------------------------out_RegMask------------------------------------
|
||||
@ -2475,7 +2478,7 @@ void PhiNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_re
|
||||
|
||||
void PhiNode::dump_spec(outputStream *st) const {
|
||||
TypeNode::dump_spec(st);
|
||||
if (is_tripcount()) {
|
||||
if (is_tripcount(T_INT) || is_tripcount(T_LONG)) {
|
||||
st->print(" #tripcount");
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ public:
|
||||
// Accessors
|
||||
RegionNode* region() const { Node* r = in(Region); assert(!r || r->is_Region(), ""); return (RegionNode*)r; }
|
||||
|
||||
bool is_tripcount() const;
|
||||
bool is_tripcount(BasicType bt) const;
|
||||
|
||||
// Determine a unique non-trivial input, if any.
|
||||
// Ignore casts if it helps. Return NULL on failure.
|
||||
|
@ -144,6 +144,8 @@ macro(CountedLoop)
|
||||
macro(CountedLoopEnd)
|
||||
macro(OuterStripMinedLoop)
|
||||
macro(OuterStripMinedLoopEnd)
|
||||
macro(LongCountedLoop)
|
||||
macro(LongCountedLoopEnd)
|
||||
macro(CountLeadingZerosI)
|
||||
macro(CountLeadingZerosL)
|
||||
macro(CountTrailingZerosI)
|
||||
|
@ -3395,6 +3395,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
|
||||
case Op_Loop:
|
||||
assert(!n->as_Loop()->is_transformed_long_loop() || _loop_opts_cnt == 0, "should have been turned into a counted loop");
|
||||
case Op_CountedLoop:
|
||||
case Op_LongCountedLoop:
|
||||
case Op_OuterStripMinedLoop:
|
||||
if (n->as_Loop()->is_inner_loop()) {
|
||||
frc.inc_inner_loop_count();
|
||||
@ -3713,7 +3714,7 @@ bool Compile::final_graph_reshaping() {
|
||||
|
||||
// Here so verification code in final_graph_reshaping_walk()
|
||||
// always see an OuterStripMinedLoopEnd
|
||||
if (n->is_OuterStripMinedLoopEnd()) {
|
||||
if (n->is_OuterStripMinedLoopEnd() || n->is_LongCountedLoopEnd()) {
|
||||
IfNode* init_iff = n->as_If();
|
||||
Node* iff = new IfNode(init_iff->in(0), init_iff->in(1), init_iff->_prob, init_iff->_fcnt);
|
||||
n->subsume_by(iff, this);
|
||||
|
@ -460,14 +460,14 @@ const Type* ConvL2INode::Value(PhaseGVN* phase) const {
|
||||
const Type *t = phase->type( in(1) );
|
||||
if( t == Type::TOP ) return Type::TOP;
|
||||
const TypeLong *tl = t->is_long();
|
||||
const TypeInt* ti = TypeInt::INT;
|
||||
if (tl->is_con()) {
|
||||
// Easy case.
|
||||
return TypeInt::make((jint)tl->get_con());
|
||||
// Easy case.
|
||||
ti = TypeInt::make((jint)tl->get_con());
|
||||
} else if (tl->_lo >= min_jint && tl->_hi <= max_jint) {
|
||||
ti = TypeInt::make((jint)tl->_lo, (jint)tl->_hi, tl->_widen);
|
||||
}
|
||||
if (tl->_lo >= min_jint && tl->_hi <= max_jint) {
|
||||
return TypeInt::make((jint)tl->_lo, (jint)tl->_hi, tl->_widen);
|
||||
}
|
||||
return bottom_type();
|
||||
return ti->filter(_type);
|
||||
}
|
||||
|
||||
//------------------------------Ideal------------------------------------------
|
||||
|
@ -178,11 +178,13 @@ class ConvL2FNode : public Node {
|
||||
|
||||
//------------------------------ConvL2INode------------------------------------
|
||||
// Convert long to integer
|
||||
class ConvL2INode : public Node {
|
||||
class ConvL2INode : public TypeNode {
|
||||
public:
|
||||
ConvL2INode( Node *in1 ) : Node(0,in1) {}
|
||||
ConvL2INode(Node *in1, const TypeInt* t = TypeInt::INT)
|
||||
: TypeNode(t, 2) {
|
||||
init_req(1, in1);
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
virtual const Type *bottom_type() const { return TypeInt::INT; }
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
virtual const Type* Value(PhaseGVN* phase) const;
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
|
@ -1728,7 +1728,7 @@ static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff) {
|
||||
// CountedLoopEnds want the back-control test to be TRUE, irregardless of
|
||||
// whether they are testing a 'gt' or 'lt' condition. The 'gt' condition
|
||||
// happens in count-down loops
|
||||
if (iff->is_CountedLoopEnd()) return NULL;
|
||||
if (iff->is_BaseCountedLoopEnd()) return NULL;
|
||||
if (!iff->in(1)->is_Bool()) return NULL; // Happens for partially optimized IF tests
|
||||
BoolNode *b = iff->in(1)->as_Bool();
|
||||
BoolTest bt = b->_test;
|
||||
|
@ -1277,7 +1277,7 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
||||
}
|
||||
|
||||
CountedLoopNode *cl = NULL;
|
||||
if (head->is_valid_counted_loop()) {
|
||||
if (head->is_valid_counted_loop(T_INT)) {
|
||||
cl = head->as_CountedLoop();
|
||||
// do nothing for iteration-splitted loops
|
||||
if (!cl->is_normal_loop()) return false;
|
||||
|
@ -93,7 +93,7 @@ void IdealLoopTree::record_for_igvn() {
|
||||
// Compute loop trip count if possible. Do not recalculate trip count for
|
||||
// split loops (pre-main-post) which have their limits and inits behind Opaque node.
|
||||
void IdealLoopTree::compute_trip_count(PhaseIdealLoop* phase) {
|
||||
if (!_head->as_Loop()->is_valid_counted_loop()) {
|
||||
if (!_head->as_Loop()->is_valid_counted_loop(T_INT)) {
|
||||
return;
|
||||
}
|
||||
CountedLoopNode* cl = _head->as_CountedLoop();
|
||||
@ -484,6 +484,7 @@ uint IdealLoopTree::estimate_peeling(PhaseIdealLoop *phase) {
|
||||
// Standard IF only has one input value to check for loop invariance.
|
||||
assert(test->Opcode() == Op_If ||
|
||||
test->Opcode() == Op_CountedLoopEnd ||
|
||||
test->Opcode() == Op_LongCountedLoopEnd ||
|
||||
test->Opcode() == Op_RangeCheck,
|
||||
"Check this code when new subtype is added");
|
||||
// Condition is not a member of this loop?
|
||||
@ -768,7 +769,7 @@ void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) {
|
||||
bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop* phase) const {
|
||||
CountedLoopNode* cl = _head->as_CountedLoop();
|
||||
assert(cl->is_normal_loop(), "");
|
||||
if (!cl->is_valid_counted_loop()) {
|
||||
if (!cl->is_valid_counted_loop(T_INT)) {
|
||||
return false; // Malformed counted loop.
|
||||
}
|
||||
if (!cl->has_exact_trip_count()) {
|
||||
@ -847,7 +848,7 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) {
|
||||
CountedLoopNode *cl = _head->as_CountedLoop();
|
||||
assert(cl->is_normal_loop() || cl->is_main_loop(), "");
|
||||
|
||||
if (!cl->is_valid_counted_loop()) {
|
||||
if (!cl->is_valid_counted_loop(T_INT)) {
|
||||
return false; // Malformed counted loop
|
||||
}
|
||||
|
||||
@ -3131,7 +3132,7 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
|
||||
return false; // Dead loop
|
||||
}
|
||||
CountedLoopNode *cl = _head->as_CountedLoop();
|
||||
if (!cl->is_valid_counted_loop()) {
|
||||
if (!cl->is_valid_counted_loop(T_INT)) {
|
||||
return false; // Malformed loop
|
||||
}
|
||||
if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) {
|
||||
@ -3244,7 +3245,7 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
|
||||
//------------------------------do_one_iteration_loop--------------------------
|
||||
// Convert one iteration loop into normal code.
|
||||
bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) {
|
||||
if (!_head->as_Loop()->is_valid_counted_loop()) {
|
||||
if (!_head->as_Loop()->is_valid_counted_loop(T_INT)) {
|
||||
return false; // Only for counted loop
|
||||
}
|
||||
CountedLoopNode *cl = _head->as_CountedLoop();
|
||||
@ -3260,10 +3261,9 @@ bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) {
|
||||
#endif
|
||||
|
||||
Node *init_n = cl->init_trip();
|
||||
#ifdef ASSERT
|
||||
// Loop boundaries should be constant since trip count is exact.
|
||||
assert(init_n->get_int() + cl->stride_con() >= cl->limit()->get_int(), "should be one iteration");
|
||||
#endif
|
||||
assert((cl->stride_con() > 0 && init_n->get_int() + cl->stride_con() >= cl->limit()->get_int()) ||
|
||||
(cl->stride_con() < 0 && init_n->get_int() + cl->stride_con() <= cl->limit()->get_int()), "should be one iteration");
|
||||
// Replace the phi at loop head with the value of the init_trip.
|
||||
// Then the CountedLoopEnd will collapse (backedge will not be taken)
|
||||
// and all loop-invariant uses of the exit values will be correct.
|
||||
@ -3306,7 +3306,7 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n
|
||||
}
|
||||
CountedLoopNode *cl = _head->as_CountedLoop();
|
||||
|
||||
if (!cl->is_valid_counted_loop()) return true; // Ignore various kinds of broken loops
|
||||
if (!cl->is_valid_counted_loop(T_INT)) return true; // Ignore various kinds of broken loops
|
||||
|
||||
// Do nothing special to pre- and post- loops
|
||||
if (cl->is_pre_loop() || cl->is_post_loop()) return true;
|
||||
@ -3721,7 +3721,7 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) {
|
||||
|
||||
// Must have constant stride
|
||||
CountedLoopNode* head = lpt->_head->as_CountedLoop();
|
||||
if (!head->is_valid_counted_loop() || !head->is_normal_loop()) {
|
||||
if (!head->is_valid_counted_loop(T_INT) || !head->is_normal_loop()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ bool CountedLoopReserveKit::create_reserve() {
|
||||
return false;
|
||||
}
|
||||
CountedLoopNode *cl = _lpt->_head->as_CountedLoop();
|
||||
if (!cl->is_valid_counted_loop()) {
|
||||
if (!cl->is_valid_counted_loop(T_INT)) {
|
||||
if (TraceLoopOpts) {
|
||||
tty->print_cr("CountedLoopReserveKit::create_reserve: %d not valid counted loop", cl->_idx);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,7 @@
|
||||
#include "opto/type.hpp"
|
||||
|
||||
class CmpNode;
|
||||
class CountedLoopEndNode;
|
||||
class BaseCountedLoopEndNode;
|
||||
class CountedLoopNode;
|
||||
class IdealLoopTree;
|
||||
class LoopNode;
|
||||
@ -150,7 +150,7 @@ public:
|
||||
in(1) != NULL && phase->type(in(1)) != Type::TOP &&
|
||||
in(2) != NULL && phase->type(in(2)) != Type::TOP;
|
||||
}
|
||||
bool is_valid_counted_loop() const;
|
||||
bool is_valid_counted_loop(BasicType bt) const;
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
#endif
|
||||
@ -192,7 +192,36 @@ public:
|
||||
// produce a loop-body control and the trip counter value. Since
|
||||
// CountedLoopNodes behave like RegionNodes I still have a standard CFG model.
|
||||
|
||||
class CountedLoopNode : public LoopNode {
|
||||
class BaseCountedLoopNode : public LoopNode {
|
||||
public:
|
||||
BaseCountedLoopNode(Node *entry, Node *backedge)
|
||||
: LoopNode(entry, backedge) {
|
||||
}
|
||||
|
||||
Node *init_control() const { return in(EntryControl); }
|
||||
Node *back_control() const { return in(LoopBackControl); }
|
||||
|
||||
Node* init_trip() const;
|
||||
Node* stride() const;
|
||||
bool stride_is_con() const;
|
||||
Node* limit() const;
|
||||
Node* incr() const;
|
||||
Node* phi() const;
|
||||
|
||||
BaseCountedLoopEndNode* loopexit_or_null() const;
|
||||
BaseCountedLoopEndNode* loopexit() const;
|
||||
|
||||
virtual BasicType bt() const = 0;
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return false;
|
||||
}
|
||||
|
||||
static BaseCountedLoopNode* make(Node* entry, Node* backedge, BasicType bt);
|
||||
};
|
||||
|
||||
|
||||
class CountedLoopNode : public BaseCountedLoopNode {
|
||||
// Size is bigger to hold _main_idx. However, _main_idx does not change
|
||||
// the semantics so it does not appear in the hash & cmp functions.
|
||||
virtual uint size_of() const { return sizeof(*this); }
|
||||
@ -216,8 +245,8 @@ class CountedLoopNode : public LoopNode {
|
||||
int _slp_maximum_unroll_factor;
|
||||
|
||||
public:
|
||||
CountedLoopNode( Node *entry, Node *backedge )
|
||||
: LoopNode(entry, backedge), _main_idx(0), _trip_count(max_juint),
|
||||
CountedLoopNode(Node *entry, Node *backedge)
|
||||
: BaseCountedLoopNode(entry, backedge), _main_idx(0), _trip_count(max_juint),
|
||||
_unrolled_count_log2(0), _node_count_before_unroll(0),
|
||||
_slp_maximum_unroll_factor(0) {
|
||||
init_class_id(Class_CountedLoop);
|
||||
@ -228,20 +257,14 @@ public:
|
||||
virtual int Opcode() const;
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
|
||||
Node *init_control() const { return in(EntryControl); }
|
||||
Node *back_control() const { return in(LoopBackControl); }
|
||||
CountedLoopEndNode *loopexit_or_null() const;
|
||||
CountedLoopEndNode *loopexit() const;
|
||||
Node *init_trip() const;
|
||||
Node *stride() const;
|
||||
CountedLoopEndNode* loopexit_or_null() const { return (CountedLoopEndNode*) BaseCountedLoopNode::loopexit_or_null(); }
|
||||
CountedLoopEndNode* loopexit() const { return (CountedLoopEndNode*) BaseCountedLoopNode::loopexit(); }
|
||||
int stride_con() const;
|
||||
bool stride_is_con() const;
|
||||
Node *limit() const;
|
||||
Node *incr() const;
|
||||
Node *phi() const;
|
||||
|
||||
// Match increment with optional truncation
|
||||
static Node* match_incr_with_optional_truncation(Node* expr, Node** trunc1, Node** trunc2, const TypeInt** trunc_type);
|
||||
static Node*
|
||||
match_incr_with_optional_truncation(Node* expr, Node** trunc1, Node** trunc2, const TypeInteger** trunc_type,
|
||||
BasicType bt);
|
||||
|
||||
// A 'main' loop has a pre-loop and a post-loop. The 'main' loop
|
||||
// can run short a few iterations and may start a few iterations in.
|
||||
@ -316,34 +339,64 @@ public:
|
||||
static Node* skip_predicates_from_entry(Node* ctrl);
|
||||
Node* skip_predicates();
|
||||
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_INT;
|
||||
}
|
||||
virtual BasicType bt() const {
|
||||
return T_INT;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class LongCountedLoopNode : public BaseCountedLoopNode {
|
||||
public:
|
||||
LongCountedLoopNode(Node *entry, Node *backedge)
|
||||
: BaseCountedLoopNode(entry, backedge) {
|
||||
init_class_id(Class_LongCountedLoop);
|
||||
}
|
||||
|
||||
virtual int Opcode() const;
|
||||
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_LONG;
|
||||
}
|
||||
|
||||
virtual BasicType bt() const {
|
||||
return T_LONG;
|
||||
}
|
||||
|
||||
LongCountedLoopEndNode* loopexit_or_null() const { return (LongCountedLoopEndNode*) BaseCountedLoopNode::loopexit_or_null(); }
|
||||
LongCountedLoopEndNode* loopexit() const { return (LongCountedLoopEndNode*) BaseCountedLoopNode::loopexit(); }
|
||||
jlong stride_con() const;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------CountedLoopEndNode-----------------------------
|
||||
// CountedLoopEndNodes end simple trip counted loops. They act much like
|
||||
// IfNodes.
|
||||
class CountedLoopEndNode : public IfNode {
|
||||
|
||||
class BaseCountedLoopEndNode : public IfNode {
|
||||
public:
|
||||
enum { TestControl, TestValue };
|
||||
|
||||
CountedLoopEndNode( Node *control, Node *test, float prob, float cnt )
|
||||
: IfNode( control, test, prob, cnt) {
|
||||
init_class_id(Class_CountedLoopEnd);
|
||||
BaseCountedLoopEndNode(Node *control, Node *test, float prob, float cnt)
|
||||
: IfNode(control, test, prob, cnt) {
|
||||
init_class_id(Class_BaseCountedLoopEnd);
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
|
||||
Node *cmp_node() const { return (in(TestValue)->req() >=2) ? in(TestValue)->in(1) : NULL; }
|
||||
Node *incr() const { Node *tmp = cmp_node(); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; }
|
||||
Node *limit() const { Node *tmp = cmp_node(); return (tmp && tmp->req()==3) ? tmp->in(2) : NULL; }
|
||||
Node *stride() const { Node *tmp = incr (); return (tmp && tmp->req()==3) ? tmp->in(2) : NULL; }
|
||||
Node *init_trip() const { Node *tmp = phi (); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; }
|
||||
int stride_con() const;
|
||||
bool stride_is_con() const { Node *tmp = stride (); return (tmp != NULL && tmp->is_Con()); }
|
||||
BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; }
|
||||
PhiNode *phi() const {
|
||||
Node *tmp = incr();
|
||||
Node* incr() const { Node* tmp = cmp_node(); return (tmp && tmp->req() == 3) ? tmp->in(1) : NULL; }
|
||||
Node* limit() const { Node* tmp = cmp_node(); return (tmp && tmp->req() == 3) ? tmp->in(2) : NULL; }
|
||||
Node* stride() const { Node* tmp = incr(); return (tmp && tmp->req() == 3) ? tmp->in(2) : NULL; }
|
||||
Node* init_trip() const { Node* tmp = phi(); return (tmp && tmp->req() == 3) ? tmp->in(1) : NULL; }
|
||||
bool stride_is_con() const { Node *tmp = stride(); return (tmp != NULL && tmp->is_Con()); }
|
||||
|
||||
PhiNode* phi() const {
|
||||
Node* tmp = incr();
|
||||
if (tmp && tmp->req() == 3) {
|
||||
Node* phi = tmp->in(1);
|
||||
if (phi->is_Phi()) {
|
||||
@ -352,7 +405,8 @@ public:
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
CountedLoopNode *loopnode() const {
|
||||
|
||||
BaseCountedLoopNode* loopnode() const {
|
||||
// The CountedLoopNode that goes with this CountedLoopEndNode may
|
||||
// have been optimized out by the IGVN so be cautious with the
|
||||
// pattern matching on the graph
|
||||
@ -360,11 +414,47 @@ public:
|
||||
if (iv_phi == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Node *ln = iv_phi->in(0);
|
||||
if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit_or_null() == this) {
|
||||
return (CountedLoopNode*)ln;
|
||||
Node* ln = iv_phi->in(0);
|
||||
if (!ln->is_BaseCountedLoop() || ln->as_BaseCountedLoop()->loopexit_or_null() != this) {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
if (!ln->operates_on(bt(), true)) {
|
||||
return NULL;
|
||||
}
|
||||
return ln->as_BaseCountedLoop();
|
||||
}
|
||||
|
||||
BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; }
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return false;
|
||||
}
|
||||
|
||||
jlong stride_con() const;
|
||||
virtual BasicType bt() const = 0;
|
||||
|
||||
static BaseCountedLoopEndNode* make(Node* control, Node* test, float prob, float cnt, BasicType bt);
|
||||
};
|
||||
|
||||
class CountedLoopEndNode : public BaseCountedLoopEndNode {
|
||||
public:
|
||||
|
||||
CountedLoopEndNode(Node *control, Node *test, float prob, float cnt)
|
||||
: BaseCountedLoopEndNode(control, test, prob, cnt) {
|
||||
init_class_id(Class_CountedLoopEnd);
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
|
||||
CountedLoopNode* loopnode() const {
|
||||
return (CountedLoopNode*) BaseCountedLoopEndNode::loopnode();
|
||||
}
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_INT;
|
||||
}
|
||||
|
||||
virtual BasicType bt() const {
|
||||
return T_INT;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
@ -372,48 +462,72 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
class LongCountedLoopEndNode : public BaseCountedLoopEndNode {
|
||||
public:
|
||||
LongCountedLoopEndNode(Node *control, Node *test, float prob, float cnt)
|
||||
: BaseCountedLoopEndNode(control, test, prob, cnt) {
|
||||
init_class_id(Class_LongCountedLoopEnd);
|
||||
}
|
||||
|
||||
inline CountedLoopEndNode* CountedLoopNode::loopexit_or_null() const {
|
||||
LongCountedLoopNode* loopnode() const {
|
||||
return (LongCountedLoopNode*) BaseCountedLoopEndNode::loopnode();
|
||||
}
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_LONG;
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
|
||||
virtual BasicType bt() const {
|
||||
return T_LONG;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline BaseCountedLoopEndNode* BaseCountedLoopNode::loopexit_or_null() const {
|
||||
Node* bctrl = back_control();
|
||||
if (bctrl == NULL) return NULL;
|
||||
|
||||
Node* lexit = bctrl->in(0);
|
||||
return (CountedLoopEndNode*)
|
||||
(lexit->Opcode() == Op_CountedLoopEnd ? lexit : NULL);
|
||||
if (!lexit->is_BaseCountedLoopEnd()) {
|
||||
return NULL;
|
||||
}
|
||||
BaseCountedLoopEndNode* result = lexit->as_BaseCountedLoopEnd();
|
||||
if (!result->operates_on(bt(), true)) {
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline CountedLoopEndNode* CountedLoopNode::loopexit() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
inline BaseCountedLoopEndNode* BaseCountedLoopNode::loopexit() const {
|
||||
BaseCountedLoopEndNode* cle = loopexit_or_null();
|
||||
assert(cle != NULL, "loopexit is NULL");
|
||||
return cle;
|
||||
}
|
||||
|
||||
inline Node* CountedLoopNode::init_trip() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
inline Node* BaseCountedLoopNode::init_trip() const {
|
||||
BaseCountedLoopEndNode* cle = loopexit_or_null();
|
||||
return cle != NULL ? cle->init_trip() : NULL;
|
||||
}
|
||||
inline Node* CountedLoopNode::stride() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
inline Node* BaseCountedLoopNode::stride() const {
|
||||
BaseCountedLoopEndNode* cle = loopexit_or_null();
|
||||
return cle != NULL ? cle->stride() : NULL;
|
||||
}
|
||||
inline int CountedLoopNode::stride_con() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
return cle != NULL ? cle->stride_con() : 0;
|
||||
}
|
||||
inline bool CountedLoopNode::stride_is_con() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
|
||||
inline bool BaseCountedLoopNode::stride_is_con() const {
|
||||
BaseCountedLoopEndNode* cle = loopexit_or_null();
|
||||
return cle != NULL && cle->stride_is_con();
|
||||
}
|
||||
inline Node* CountedLoopNode::limit() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
inline Node* BaseCountedLoopNode::limit() const {
|
||||
BaseCountedLoopEndNode* cle = loopexit_or_null();
|
||||
return cle != NULL ? cle->limit() : NULL;
|
||||
}
|
||||
inline Node* CountedLoopNode::incr() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
inline Node* BaseCountedLoopNode::incr() const {
|
||||
BaseCountedLoopEndNode* cle = loopexit_or_null();
|
||||
return cle != NULL ? cle->incr() : NULL;
|
||||
}
|
||||
inline Node* CountedLoopNode::phi() const {
|
||||
CountedLoopEndNode* cle = loopexit_or_null();
|
||||
inline Node* BaseCountedLoopNode::phi() const {
|
||||
BaseCountedLoopEndNode* cle = loopexit_or_null();
|
||||
return cle != NULL ? cle->phi() : NULL;
|
||||
}
|
||||
|
||||
@ -821,8 +935,8 @@ public:
|
||||
Node *get_late_ctrl( Node *n, Node *early );
|
||||
Node *get_early_ctrl( Node *n );
|
||||
Node *get_early_ctrl_for_expensive(Node *n, Node* earliest);
|
||||
void set_early_ctrl( Node *n );
|
||||
void set_subtree_ctrl( Node *root );
|
||||
void set_early_ctrl(Node* n, bool update_body);
|
||||
void set_subtree_ctrl(Node* n, bool update_body);
|
||||
void set_ctrl( Node *n, Node *ctrl ) {
|
||||
assert( !has_node(n) || has_ctrl(n), "" );
|
||||
assert( ctrl->in(0), "cannot set dead control node" );
|
||||
@ -1054,9 +1168,10 @@ public:
|
||||
Node* loop_iv_stride(Node* incr, IdealLoopTree* loop, Node*& xphi);
|
||||
PhiNode* loop_iv_phi(Node* xphi, Node* phi_incr, Node* x, IdealLoopTree* loop);
|
||||
|
||||
bool is_counted_loop(Node* n, IdealLoopTree* &loop);
|
||||
bool is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_bt);
|
||||
|
||||
void long_loop_replace_long_iv(Node* iv_to_replace, Node* inner_iv, Node* outer_phi, Node* inner_head);
|
||||
bool is_long_counted_loop(Node* x, IdealLoopTree* loop, Node_List &old_new);
|
||||
bool transform_long_counted_loop(IdealLoopTree* loop, Node_List &old_new);
|
||||
#ifdef ASSERT
|
||||
bool convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* loop);
|
||||
#endif
|
||||
@ -1490,6 +1605,10 @@ public:
|
||||
#endif
|
||||
|
||||
void rpo(Node* start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list) const;
|
||||
|
||||
void check_long_counted_loop(IdealLoopTree* loop, Node* x) NOT_DEBUG_RETURN;
|
||||
|
||||
LoopNode* create_inner_head(IdealLoopTree* loop, LongCountedLoopNode* head, LongCountedLoopEndNode* exit_test);
|
||||
};
|
||||
|
||||
|
||||
|
@ -285,7 +285,7 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exc
|
||||
if (cd->depends_only_on_test()) {
|
||||
assert(cd->in(0) == dp, "");
|
||||
_igvn.replace_input_of(cd, 0, prevdom);
|
||||
set_early_ctrl(cd);
|
||||
set_early_ctrl(cd, false);
|
||||
IdealLoopTree *new_loop = get_loop(get_ctrl(cd));
|
||||
if (old_loop != new_loop) {
|
||||
if (!old_loop->_child) old_loop->_body.yank(cd);
|
||||
@ -515,7 +515,7 @@ Node *PhaseIdealLoop::convert_add_to_muladd(Node* n) {
|
||||
if (in1->Opcode() == Op_MulI && in2->Opcode() == Op_MulI) {
|
||||
IdealLoopTree* loop_n = get_loop(get_ctrl(n));
|
||||
if (loop_n->is_counted() &&
|
||||
loop_n->_head->as_Loop()->is_valid_counted_loop() &&
|
||||
loop_n->_head->as_Loop()->is_valid_counted_loop(T_INT) &&
|
||||
Matcher::match_rule_supported(Op_MulAddVS2VI) &&
|
||||
Matcher::match_rule_supported(Op_MulAddS2I)) {
|
||||
Node* mul_in1 = in1->in(1);
|
||||
@ -1038,7 +1038,8 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) {
|
||||
|
||||
// Do not clone the trip counter through on a CountedLoop
|
||||
// (messes up the canonical shape).
|
||||
if ((n_blk->is_CountedLoop() || (n_blk->is_Loop() && n_blk->as_Loop()->is_transformed_long_loop())) && n->Opcode() == Op_AddI) {
|
||||
if (((n_blk->is_CountedLoop() || (n_blk->is_Loop() && n_blk->as_Loop()->is_transformed_long_loop())) && n->Opcode() == Op_AddI) ||
|
||||
(n_blk->is_LongCountedLoop() && n->Opcode() == Op_AddL)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -2292,7 +2293,7 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd
|
||||
int PhaseIdealLoop::stride_of_possible_iv(Node* iff) {
|
||||
Node* trunc1 = NULL;
|
||||
Node* trunc2 = NULL;
|
||||
const TypeInt* ttype = NULL;
|
||||
const TypeInteger* ttype = NULL;
|
||||
if (!iff->is_If() || iff->in(1) == NULL || !iff->in(1)->is_Bool()) {
|
||||
return 0;
|
||||
}
|
||||
@ -2313,7 +2314,7 @@ int PhaseIdealLoop::stride_of_possible_iv(Node* iff) {
|
||||
for (uint i = 1; i < phi->req(); i++) {
|
||||
Node* in = phi->in(i);
|
||||
Node* add = CountedLoopNode::match_incr_with_optional_truncation(in,
|
||||
&trunc1, &trunc2, &ttype);
|
||||
&trunc1, &trunc2, &ttype, T_INT);
|
||||
if (add && add->in(1) == phi) {
|
||||
add2 = add->in(2);
|
||||
break;
|
||||
@ -2323,7 +2324,7 @@ int PhaseIdealLoop::stride_of_possible_iv(Node* iff) {
|
||||
// (If (Bool (CmpX addtrunc:(Optional-trunc((AddI (Phi ...addtrunc...) add2)) )))
|
||||
Node* addtrunc = cmp1;
|
||||
Node* add = CountedLoopNode::match_incr_with_optional_truncation(addtrunc,
|
||||
&trunc1, &trunc2, &ttype);
|
||||
&trunc1, &trunc2, &ttype, T_INT);
|
||||
if (add && add->in(1)->is_Phi()) {
|
||||
Node* phi = add->in(1);
|
||||
for (uint i = 1; i < phi->req(); i++) {
|
||||
@ -3493,7 +3494,7 @@ void PhaseIdealLoop::reorg_offsets(IdealLoopTree *loop) {
|
||||
// Loop's shape could be messed up by iteration_split_impl.
|
||||
if (!loop->_head->is_CountedLoop())
|
||||
return;
|
||||
if (!loop->_head->as_Loop()->is_valid_counted_loop())
|
||||
if (!loop->_head->as_Loop()->is_valid_counted_loop(T_INT))
|
||||
return;
|
||||
|
||||
CountedLoopNode *cl = loop->_head->as_CountedLoop();
|
||||
|
@ -1507,6 +1507,16 @@ const TypeInt* Node::find_int_type() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const TypeInteger* Node::find_integer_type(BasicType bt) const {
|
||||
if (this->is_Type()) {
|
||||
return this->as_Type()->type()->isa_integer(bt);
|
||||
} else if (this->is_Con()) {
|
||||
assert(is_Mach(), "should be ConNode(TypeNode) or else a MachNode");
|
||||
return this->bottom_type()->isa_integer(bt);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get a pointer constant from a ConstNode.
|
||||
// Returns the constant if it is a pointer ConstNode
|
||||
intptr_t Node::get_ptr() const {
|
||||
|
@ -42,6 +42,8 @@ class AliasInfo;
|
||||
class AllocateArrayNode;
|
||||
class AllocateNode;
|
||||
class ArrayCopyNode;
|
||||
class BaseCountedLoopNode;
|
||||
class BaseCountedLoopEndNode;
|
||||
class Block;
|
||||
class BoolNode;
|
||||
class BoxLockNode;
|
||||
@ -89,6 +91,8 @@ class LoadNode;
|
||||
class LoadStoreNode;
|
||||
class LoadStoreConditionalNode;
|
||||
class LockNode;
|
||||
class LongCountedLoopNode;
|
||||
class LongCountedLoopEndNode;
|
||||
class LoopNode;
|
||||
class MachBranchNode;
|
||||
class MachCallDynamicJavaNode;
|
||||
@ -641,7 +645,9 @@ public:
|
||||
DEFINE_CLASS_ID(Catch, PCTable, 0)
|
||||
DEFINE_CLASS_ID(Jump, PCTable, 1)
|
||||
DEFINE_CLASS_ID(If, MultiBranch, 1)
|
||||
DEFINE_CLASS_ID(CountedLoopEnd, If, 0)
|
||||
DEFINE_CLASS_ID(BaseCountedLoopEnd, If, 0)
|
||||
DEFINE_CLASS_ID(CountedLoopEnd, BaseCountedLoopEnd, 0)
|
||||
DEFINE_CLASS_ID(LongCountedLoopEnd, BaseCountedLoopEnd, 1)
|
||||
DEFINE_CLASS_ID(RangeCheck, If, 1)
|
||||
DEFINE_CLASS_ID(OuterStripMinedLoopEnd, If, 2)
|
||||
DEFINE_CLASS_ID(NeverBranch, MultiBranch, 2)
|
||||
@ -713,7 +719,9 @@ public:
|
||||
DEFINE_CLASS_ID(Region, Node, 5)
|
||||
DEFINE_CLASS_ID(Loop, Region, 0)
|
||||
DEFINE_CLASS_ID(Root, Loop, 0)
|
||||
DEFINE_CLASS_ID(CountedLoop, Loop, 1)
|
||||
DEFINE_CLASS_ID(BaseCountedLoop, Loop, 1)
|
||||
DEFINE_CLASS_ID(CountedLoop, BaseCountedLoop, 0)
|
||||
DEFINE_CLASS_ID(LongCountedLoop, BaseCountedLoop, 1)
|
||||
DEFINE_CLASS_ID(OuterStripMinedLoop, Loop, 2)
|
||||
|
||||
DEFINE_CLASS_ID(Sub, Node, 6)
|
||||
@ -816,6 +824,8 @@ public:
|
||||
DEFINE_CLASS_QUERY(Allocate)
|
||||
DEFINE_CLASS_QUERY(AllocateArray)
|
||||
DEFINE_CLASS_QUERY(ArrayCopy)
|
||||
DEFINE_CLASS_QUERY(BaseCountedLoop)
|
||||
DEFINE_CLASS_QUERY(BaseCountedLoopEnd)
|
||||
DEFINE_CLASS_QUERY(Bool)
|
||||
DEFINE_CLASS_QUERY(BoxLock)
|
||||
DEFINE_CLASS_QUERY(Call)
|
||||
@ -854,6 +864,8 @@ public:
|
||||
DEFINE_CLASS_QUERY(Initialize)
|
||||
DEFINE_CLASS_QUERY(Jump)
|
||||
DEFINE_CLASS_QUERY(JumpProj)
|
||||
DEFINE_CLASS_QUERY(LongCountedLoop)
|
||||
DEFINE_CLASS_QUERY(LongCountedLoopEnd)
|
||||
DEFINE_CLASS_QUERY(Load)
|
||||
DEFINE_CLASS_QUERY(LoadStore)
|
||||
DEFINE_CLASS_QUERY(LoadStoreConditional)
|
||||
@ -1095,6 +1107,7 @@ public:
|
||||
}
|
||||
// Here's where the work is done. Can produce non-constant int types too.
|
||||
const TypeInt* find_int_type() const;
|
||||
const TypeInteger* find_integer_type(BasicType bt) const;
|
||||
|
||||
// Same thing for long (and intptr_t, via type.hpp):
|
||||
jlong get_long() const {
|
||||
@ -1108,6 +1121,11 @@ public:
|
||||
}
|
||||
const TypeLong* find_long_type() const;
|
||||
|
||||
jlong get_integer_as_long(BasicType bt) const {
|
||||
const TypeInteger* t = find_integer_type(bt);
|
||||
guarantee(t != NULL, "must be con");
|
||||
return t->get_con_as_long(bt);
|
||||
}
|
||||
const TypePtr* get_ptr_type() const;
|
||||
|
||||
// These guys are called by code generated by ADLC:
|
||||
@ -1217,6 +1235,12 @@ public:
|
||||
uint _del_tick; // Bumped when a deletion happens..
|
||||
#endif
|
||||
#endif
|
||||
public:
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
Unimplemented();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -787,6 +787,16 @@ ConLNode* PhaseTransform::longcon(jlong l) {
|
||||
_lcons[l-_lcon_min] = lcon; // Cache small integers
|
||||
return lcon;
|
||||
}
|
||||
ConNode* PhaseTransform::integercon(jlong l, BasicType bt) {
|
||||
if (bt == T_INT) {
|
||||
jint int_con = (jint)l;
|
||||
assert(((long)int_con) == l, "not an int");
|
||||
return intcon(int_con);
|
||||
}
|
||||
assert(bt == T_LONG, "not an integer");
|
||||
return longcon(l);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------zerocon-----------------------------------------
|
||||
// Fast zero or null constant. Same as "transform(ConNode::make(Type::get_zero_type(bt)))"
|
||||
|
@ -115,6 +115,18 @@ const Type* SubNode::Value(PhaseGVN* phase) const {
|
||||
|
||||
}
|
||||
|
||||
SubNode* SubNode::make(Node* in1, Node* in2, BasicType bt) {
|
||||
switch (bt) {
|
||||
case T_INT:
|
||||
return new SubINode(in1, in2);
|
||||
case T_LONG:
|
||||
return new SubLNode(in1, in2);
|
||||
default:
|
||||
fatal("Not implemented for %s", type2name(bt));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//------------------------------Helper function--------------------------------
|
||||
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
// Supplied function to return the additive identity type.
|
||||
// This is returned whenever the subtracts inputs are the same.
|
||||
virtual const Type *add_id() const = 0;
|
||||
|
||||
static SubNode* make(Node* in1, Node* in2, BasicType bt);
|
||||
};
|
||||
|
||||
|
||||
@ -148,6 +150,10 @@ public:
|
||||
// including eventual control nodes and their projections.
|
||||
virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------CmpINode---------------------------------------
|
||||
@ -158,6 +164,10 @@ public:
|
||||
virtual int Opcode() const;
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual const Type *sub( const Type *, const Type * ) const;
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_INT && signed_int;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------CmpUNode---------------------------------------
|
||||
@ -169,6 +179,10 @@ public:
|
||||
virtual const Type *sub( const Type *, const Type * ) const;
|
||||
const Type* Value(PhaseGVN* phase) const;
|
||||
bool is_index_range_check() const;
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_INT && !signed_int;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------CmpPNode---------------------------------------
|
||||
@ -199,6 +213,10 @@ public:
|
||||
virtual int Opcode() const;
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual const Type *sub( const Type *, const Type * ) const;
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_LONG && signed_int;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------CmpULNode---------------------------------------
|
||||
@ -208,6 +226,10 @@ public:
|
||||
CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { }
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* sub(const Type*, const Type*) const;
|
||||
virtual bool operates_on(BasicType bt, bool signed_int) const {
|
||||
assert(bt == T_INT || bt == T_LONG, "unsupported");
|
||||
return bt == T_LONG && !signed_int;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------CmpL3Node--------------------------------------
|
||||
|
@ -106,7 +106,7 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) {
|
||||
assert(lpt->_head->is_CountedLoop(), "must be");
|
||||
CountedLoopNode *cl = lpt->_head->as_CountedLoop();
|
||||
|
||||
if (!cl->is_valid_counted_loop()) return; // skip malformed counted loop
|
||||
if (!cl->is_valid_counted_loop(T_INT)) return; // skip malformed counted loop
|
||||
|
||||
bool post_loop_allowed = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop());
|
||||
if (post_loop_allowed) {
|
||||
|
@ -1354,6 +1354,22 @@ const TypeInteger* TypeInteger::make(jlong lo, jlong hi, int w, BasicType bt) {
|
||||
return TypeLong::make(lo, hi, w);
|
||||
}
|
||||
|
||||
jlong TypeInteger::get_con_as_long(BasicType bt) const {
|
||||
if (bt == T_INT) {
|
||||
return is_int()->get_con();
|
||||
}
|
||||
assert(bt == T_LONG, "basic type not an int or long");
|
||||
return is_long()->get_con();
|
||||
}
|
||||
|
||||
const TypeInteger* TypeInteger::bottom(BasicType bt) {
|
||||
if (bt == T_INT) {
|
||||
return TypeInt::INT;
|
||||
}
|
||||
assert(bt == T_LONG, "basic type not an int or long");
|
||||
return TypeLong::LONG;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Convience common pre-built types.
|
||||
const TypeInt *TypeInt::MAX; // INT_MAX
|
||||
|
@ -284,7 +284,6 @@ public:
|
||||
|
||||
const TypeInt *is_int() const;
|
||||
const TypeInt *isa_int() const; // Returns NULL if not an Int
|
||||
const TypeInteger* isa_integer() const;
|
||||
const TypeInteger* is_integer(BasicType bt) const;
|
||||
const TypeInteger* isa_integer(BasicType bt) const;
|
||||
const TypeLong *is_long() const;
|
||||
@ -539,6 +538,8 @@ public:
|
||||
jlong get_con_as_long(BasicType bt) const;
|
||||
|
||||
static const TypeInteger* make(jlong lo, jlong hi, int w, BasicType bt);
|
||||
|
||||
static const TypeInteger* bottom(BasicType type);
|
||||
};
|
||||
|
||||
|
||||
|
@ -718,6 +718,22 @@ extern const char* type2name_tab[T_CONFLICT+1]; // Map a BasicType to a jcha
|
||||
inline const char* type2name(BasicType t) { return (uint)t < T_CONFLICT+1 ? type2name_tab[t] : NULL; }
|
||||
extern BasicType name2type(const char* name);
|
||||
|
||||
inline jlong max_signed_integer(BasicType bt) {
|
||||
if (bt == T_INT) {
|
||||
return max_jint;
|
||||
}
|
||||
assert(bt == T_LONG, "unsupported");
|
||||
return max_jlong;
|
||||
}
|
||||
|
||||
inline jlong min_signed_integer(BasicType bt) {
|
||||
if (bt == T_INT) {
|
||||
return min_jint;
|
||||
}
|
||||
assert(bt == T_LONG, "unsupported");
|
||||
return min_jlong;
|
||||
}
|
||||
|
||||
// Auxiliary math routines
|
||||
// least common multiple
|
||||
extern size_t lcm(size_t a, size_t b);
|
||||
|
Loading…
x
Reference in New Issue
Block a user