8148786: xml.tranform fails on x86-64
Summary: CCP computes wrong type for CountedLoop iv Phi
Reviewed-by: kvn
--- a/hotspot/src/share/vm/opto/loopnode.hpp Mon Feb 15 10:14:33 2016 +0100
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Wed Feb 17 10:59:04 2016 +0100
@@ -285,20 +285,29 @@
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 *phi() const { Node *tmp = incr (); return (tmp && tmp->req()==3) ? tmp->in(1) : 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();
+ if (tmp && tmp->req() == 3) {
+ Node* phi = tmp->in(1);
+ if (phi->is_Phi()) {
+ return phi->as_Phi();
+ }
+ }
+ return NULL;
+ }
CountedLoopNode *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
- if (phi() == NULL) {
+ PhiNode* iv_phi = phi();
+ if (iv_phi == NULL) {
return NULL;
}
- assert(phi()->is_Phi(), "should be PhiNode");
- Node *ln = phi()->in(0);
+ Node *ln = iv_phi->in(0);
if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) {
return (CountedLoopNode*)ln;
}
--- a/hotspot/src/share/vm/opto/phaseX.cpp Mon Feb 15 10:14:33 2016 +0100
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Wed Feb 17 10:59:04 2016 +0100
@@ -1471,6 +1471,27 @@
}
}
+// Return counted loop Phi if as a counted loop exit condition, cmp
+// compares the the induction variable with n
+static PhiNode* countedloop_phi_from_cmp(CmpINode* cmp, Node* n) {
+ for (DUIterator_Fast imax, i = cmp->fast_outs(imax); i < imax; i++) {
+ Node* bol = cmp->fast_out(i);
+ for (DUIterator_Fast i2max, i2 = bol->fast_outs(i2max); i2 < i2max; i2++) {
+ Node* iff = bol->fast_out(i2);
+ if (iff->is_CountedLoopEnd()) {
+ CountedLoopEndNode* cle = iff->as_CountedLoopEnd();
+ if (cle->limit() == n) {
+ PhiNode* phi = cle->phi();
+ if (phi != NULL) {
+ return phi;
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
void PhaseIterGVN::add_users_to_worklist( Node *n ) {
add_users_to_worklist0(n);
@@ -1500,18 +1521,7 @@
Node* bol = use->raw_out(0);
if (bol->outcnt() > 0) {
Node* iff = bol->raw_out(0);
- if (use_op == Op_CmpI &&
- iff->is_CountedLoopEnd()) {
- CountedLoopEndNode* cle = iff->as_CountedLoopEnd();
- if (cle->limit() == n && cle->phi() != NULL) {
- // If an opaque node feeds into the limit condition of a
- // CountedLoop, we need to process the Phi node for the
- // induction variable when the opaque node is removed:
- // the range of values taken by the Phi is now known and
- // so its type is also known.
- _worklist.push(cle->phi());
- }
- } else if (iff->outcnt() == 2) {
+ if (iff->outcnt() == 2) {
// Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the
// phi merging either 0 or 1 onto the worklist
Node* ifproj0 = iff->raw_out(0);
@@ -1526,6 +1536,15 @@
}
}
if (use_op == Op_CmpI) {
+ Node* phi = countedloop_phi_from_cmp((CmpINode*)use, n);
+ if (phi != NULL) {
+ // If an opaque node feeds into the limit condition of a
+ // CountedLoop, we need to process the Phi node for the
+ // induction variable when the opaque node is removed:
+ // the range of values taken by the Phi is now known and
+ // so its type is also known.
+ _worklist.push(phi);
+ }
Node* in1 = use->in(1);
for (uint i = 0; i < in1->outcnt(); i++) {
if (in1->raw_out(i)->Opcode() == Op_CastII) {
@@ -1714,6 +1733,15 @@
}
}
}
+ // If n is used in a counted loop exit condition then the type
+ // of the counted loop's Phi depends on the type of n. See
+ // PhiNode::Value().
+ if (m_op == Op_CmpI) {
+ PhiNode* phi = countedloop_phi_from_cmp((CmpINode*)m, n);
+ if (phi != NULL) {
+ worklist.push(phi);
+ }
+ }
}
}
}
--- a/hotspot/src/share/vm/opto/phaseX.hpp Mon Feb 15 10:14:33 2016 +0100
+++ b/hotspot/src/share/vm/opto/phaseX.hpp Wed Feb 17 10:59:04 2016 +0100
@@ -431,7 +431,7 @@
// Phase for iteratively performing local, pessimistic GVN-style optimizations.
// and ideal transformations on the graph.
class PhaseIterGVN : public PhaseGVN {
- private:
+private:
bool _delay_transform; // When true simply register the node when calling transform
// instead of actually optimizing it