# HG changeset patch # User mhaupt # Date 1426691790 -3600 # Wed Mar 18 16:16:30 2015 +0100 # Node ID 60e12e0658af4403c79fe3da5bb3ca386761c363 # Parent 9c3582c915c11cef3a2b4e83c7ccebcc7e3c2e56 8004073: Implement C2 Ideal node specific dump() method Summary: add Node::dump_rel() to dump a node and its related nodes (the notion of "related" depends on the node at hand); add Node::dump_comp() to dump a node in compact representation; add Node::dump_rel_comp() to dump a node and its related nodes in compact representation; add the required machinery; extend some C2 IR nodes with compact and related dumping Reviewed-by: diff --git a/src/share/vm/opto/addnode.hpp b/src/share/vm/opto/addnode.hpp --- a/src/share/vm/opto/addnode.hpp +++ b/src/share/vm/opto/addnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,6 +68,10 @@ // Supplied function to return the additive identity type virtual const Type *add_id() const = 0; +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif + }; //------------------------------AddINode--------------------------------------- @@ -158,6 +162,10 @@ // Do not match base-ptr edge virtual uint match_edge(uint idx) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------OrINode---------------------------------------- diff --git a/src/share/vm/opto/arraycopynode.cpp b/src/share/vm/opto/arraycopynode.cpp --- a/src/share/vm/opto/arraycopynode.cpp +++ b/src/share/vm/opto/arraycopynode.cpp @@ -79,10 +79,15 @@ #ifndef PRODUCT const char* ArrayCopyNode::_kind_names[] = {"arraycopy", "arraycopy, validated arguments", "clone", "oop array clone", "CopyOf", "CopyOfRange"}; + void ArrayCopyNode::dump_spec(outputStream *st) const { CallNode::dump_spec(st); st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : ""); } + +void ArrayCopyNode::dump_comp_spec(outputStream* st) const { + st->print("%s%s", _kind_names[_kind], _alloc_tightly_coupled ? ",tight" : ""); +} #endif intptr_t ArrayCopyNode::get_length_if_constant(PhaseGVN *phase) const { diff --git a/src/share/vm/opto/arraycopynode.hpp b/src/share/vm/opto/arraycopynode.hpp --- a/src/share/vm/opto/arraycopynode.hpp +++ b/src/share/vm/opto/arraycopynode.hpp @@ -164,6 +164,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream* st) const; #endif }; #endif // SHARE_VM_OPTO_ARRAYCOPYNODE_HPP diff --git a/src/share/vm/opto/callnode.cpp b/src/share/vm/opto/callnode.cpp --- a/src/share/vm/opto/callnode.cpp +++ b/src/share/vm/opto/callnode.cpp @@ -52,6 +52,7 @@ const Type *StartNode::Value(PhaseTransform *phase) const { return _domain; } #ifndef PRODUCT void StartNode::dump_spec(outputStream *st) const { st->print(" #"); _domain->dump_on(st);} +void StartNode::dump_comp_spec(outputStream *st) const { /* empty */ } #endif //------------------------------Ideal------------------------------------------ @@ -121,6 +122,23 @@ if( !Verbose && !WizardMode ) bottom_type()->dump_on(st); } } + +void ParmNode::dump_comp_spec(outputStream *st) const { + if (_con < TypeFunc::Parms) { + st->print("%s", names[_con]); + } else { + st->print("%d:", _con-TypeFunc::Parms); + // unconditionally dump bottom_type + bottom_type()->dump_on(st); + } +} + +// For a ParmNode, all immediate inputs and outputs are considered relevant +// both in compact and standard representation. +void ParmNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -1, false, false); +} #endif uint ParmNode::ideal_reg() const { @@ -948,6 +966,14 @@ if( _method ) _method->print_short_name(st); CallNode::dump_spec(st); } + +void CallJavaNode::dump_comp_spec(outputStream* st) const { + if (_method) { + _method->print_short_name(st); + } else { + st->print(""); + } +} #endif //============================================================================= @@ -995,6 +1021,16 @@ } CallJavaNode::dump_spec(st); } + +void CallStaticJavaNode::dump_comp_spec(outputStream* st) const { + if (_method) { + _method->print_short_name(st); + } else if (_name) { + st->print("%s", _name); + } else { + st->print(""); + } +} #endif //============================================================================= @@ -1130,6 +1166,19 @@ st->print(" SafePoint "); _replaced_nodes.dump(st); } + +// The related nodes of a SafepointNode are all data inputs, excluding the +// control boundary, as well as all outputs till level 2 (to include projection +// nodes and targets). In compact mode, just include inputs till level 1 and +// outputs as before. +void SafePointNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -2, false, false); +} #endif const RegMask &SafePointNode::in_RegMask(uint idx) const { @@ -1676,6 +1725,27 @@ _counter->set_tag(NamedCounter::EliminatedLockCounter); } } + +const char* AbstractLockNode::_kind_names[] = {"Regular", "NonEscObj", "Coarsened", "Nested"}; + +void AbstractLockNode::dump_spec(outputStream* st) const { + st->print("%s ", _kind_names[_kind]); + CallNode::dump_spec(st); +} + +void AbstractLockNode::dump_comp_spec(outputStream* st) const { + st->print("%s", _kind_names[_kind]); +} + +// The related set of lock nodes includes the control boundary. +void AbstractLockNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, true); + } + this->collect_nodes(out_rel, -2, false, false); +} #endif //============================================================================= diff --git a/src/share/vm/opto/callnode.hpp b/src/share/vm/opto/callnode.hpp --- a/src/share/vm/opto/callnode.hpp +++ b/src/share/vm/opto/callnode.hpp @@ -84,6 +84,7 @@ virtual uint ideal_reg() const { return 0; } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream *st) const; #endif }; @@ -110,6 +111,8 @@ virtual uint ideal_reg() const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream *st) const; + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; @@ -476,6 +479,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; @@ -675,6 +679,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream *st) const; #endif }; @@ -730,6 +735,7 @@ virtual int Opcode() const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream *st) const; #endif }; @@ -951,6 +957,7 @@ } _kind; #ifndef PRODUCT NamedCounter* _counter; + static const char* _kind_names[Nested+1]; #endif protected: @@ -1005,6 +1012,9 @@ #ifndef PRODUCT void create_lock_counter(JVMState* s); NamedCounter* counter() const { return _counter; } + virtual void dump_spec(outputStream* st) const; + virtual void dump_comp_spec(outputStream* st) const; + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; diff --git a/src/share/vm/opto/cfgnode.cpp b/src/share/vm/opto/cfgnode.cpp --- a/src/share/vm/opto/cfgnode.cpp +++ b/src/share/vm/opto/cfgnode.cpp @@ -2047,11 +2047,33 @@ return RegMask::Empty; } +#ifndef PRODUCT +//-------------------------------rel------------------------------------------- +// The related nodes of a GotoNode are all inputs at level 1, as well as the +// outputs at level 1. This is regardless of compact mode. +void GotoNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -1, false, false); +} +#endif + + //============================================================================= const RegMask &JumpNode::out_RegMask() const { return RegMask::Empty; } +#ifndef PRODUCT +//-------------------------------rel------------------------------------------- +// The related nodes of a JumpNode are all inputs at level 1, as well as the +// outputs at level 2 (to include actual jump targets beyond projection nodes). +// This is regardless of compact mode. +void JumpNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -2, false, false); +} +#endif + //============================================================================= const RegMask &JProjNode::out_RegMask() const { return RegMask::Empty; @@ -2105,7 +2127,18 @@ #ifndef PRODUCT void JumpProjNode::dump_spec(outputStream *st) const { ProjNode::dump_spec(st); - st->print("@bci %d ",_dest_bci); + st->print("@bci %d ",_dest_bci); +} + +void JumpProjNode::dump_comp_spec(outputStream *st) const { + ProjNode::dump_comp_spec(st); + st->print("(%d)%d@%d", _switch_val, _proj_no, _dest_bci); +} + +void JumpProjNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + // The related nodes of a JumpProjNode are its inputs and outputs at level 1. + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -1, false, false); } #endif diff --git a/src/share/vm/opto/cfgnode.hpp b/src/share/vm/opto/cfgnode.hpp --- a/src/share/vm/opto/cfgnode.hpp +++ b/src/share/vm/opto/cfgnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -229,6 +229,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual Node *Identity( PhaseTransform *phase ); virtual const RegMask &out_RegMask() const; + +#ifndef PRODUCT + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; //------------------------------CProjNode-------------------------------------- @@ -382,6 +386,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; @@ -393,6 +398,11 @@ protected: // Type of If input when this branch is always taken virtual bool always_taken(const TypeTuple* t) const = 0; + +#ifndef PRODUCT +public: + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; class IfTrueNode : public IfProjNode { @@ -455,6 +465,9 @@ virtual int Opcode() const; virtual const RegMask& out_RegMask() const; virtual const Node* is_block_proj() const { return this; } +#ifndef PRODUCT + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; class JumpProjNode : public JProjNode { @@ -479,6 +492,8 @@ uint proj_no() const { return _proj_no; } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream *st) const; + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; diff --git a/src/share/vm/opto/convertnode.hpp b/src/share/vm/opto/convertnode.hpp --- a/src/share/vm/opto/convertnode.hpp +++ b/src/share/vm/opto/convertnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -197,6 +197,10 @@ virtual uint ideal_reg() const { return Op_RegF; } virtual Node *Identity( PhaseTransform *phase ); virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; @@ -209,6 +213,10 @@ virtual uint ideal_reg() const { return Op_RegD; } virtual Node *Identity( PhaseTransform *phase ); virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; diff --git a/src/share/vm/opto/countbitsnode.hpp b/src/share/vm/opto/countbitsnode.hpp --- a/src/share/vm/opto/countbitsnode.hpp +++ b/src/share/vm/opto/countbitsnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,10 @@ CountBitsNode(Node* in1) : Node(0, in1) {} const Type* bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //---------- CountLeadingZerosINode -------------------------------------------- diff --git a/src/share/vm/opto/divnode.hpp b/src/share/vm/opto/divnode.hpp --- a/src/share/vm/opto/divnode.hpp +++ b/src/share/vm/opto/divnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------DivLNode--------------------------------------- @@ -62,6 +66,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------DivFNode--------------------------------------- @@ -75,6 +83,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual const Type *bottom_type() const { return Type::FLOAT; } virtual uint ideal_reg() const { return Op_RegF; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------DivDNode--------------------------------------- @@ -88,6 +100,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------ModINode--------------------------------------- @@ -100,6 +116,10 @@ virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------ModLNode--------------------------------------- @@ -112,6 +132,10 @@ virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------ModFNode--------------------------------------- @@ -123,6 +147,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual const Type *bottom_type() const { return Type::FLOAT; } virtual uint ideal_reg() const { return Op_RegF; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------ModDNode--------------------------------------- @@ -134,6 +162,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------DivModNode--------------------------------------- @@ -156,6 +188,10 @@ ProjNode* div_proj() { return proj_out(div_proj_num); } ProjNode* mod_proj() { return proj_out(mod_proj_num); } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------DivModINode--------------------------------------- diff --git a/src/share/vm/opto/ifnode.cpp b/src/share/vm/opto/ifnode.cpp --- a/src/share/vm/opto/ifnode.cpp +++ b/src/share/vm/opto/ifnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1601,11 +1601,41 @@ return this; } +#ifndef PRODUCT +//---------------------------------rel----------------------------------------- +// An IfProjNode's related node set consists of its input (an IfNode) including +// the IfNode's condition, plus all of its outputs at level 1. In compact mode, +// the restrictions for IfNode apply (see IfNode::rel). +void IfProjNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + Node* ifNode = this->in(0); + in_rel->append(ifNode); + if (compact) { + ifNode->collect_nodes(in_rel, 3, false, true); + } else { + ifNode->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -1, false, false); +} + //------------------------------dump_spec-------------------------------------- -#ifndef PRODUCT void IfNode::dump_spec(outputStream *st) const { st->print("P=%f, C=%f",_prob,_fcnt); } + +//---------------------------------rel----------------------------------------- +// For an IfNode, the set of related output nodes is just the output nodes till +// depth 2, i.e, the IfTrue/IfFalse projection nodes plus the nodes they refer. +// The related input nodes contain no control nodes, but all data nodes +// pertaining to the condition. In compact mode, the input nodes are collected +// up to a depth of 3. +void IfNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 3, false, true); + } else { + this->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -2, false, false); +} #endif //------------------------------idealize_test---------------------------------- diff --git a/src/share/vm/opto/movenode.cpp b/src/share/vm/opto/movenode.cpp --- a/src/share/vm/opto/movenode.cpp +++ b/src/share/vm/opto/movenode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -396,3 +396,17 @@ return TypeLong::make( v.get_jlong() ); } +#ifndef PRODUCT +//----------------------------BinaryNode--------------------------------------- +// The set of related nodes for a BinaryNode is all data inputs and all outputs +// till level 2 (i.e., one beyond the associated CMoveNode). In compact mode, +// it's the inputs till level 1 and the outputs till level 2. +void BinaryNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, true); + } else { + this->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -2, false, false); +} +#endif diff --git a/src/share/vm/opto/movenode.hpp b/src/share/vm/opto/movenode.hpp --- a/src/share/vm/opto/movenode.hpp +++ b/src/share/vm/opto/movenode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,6 +145,10 @@ BinaryNode( Node *n1, Node *n2 ) : Node(0,n1,n2) { } virtual int Opcode() const; virtual uint ideal_reg() const { return 0; } + +#ifndef PRODUCT + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; diff --git a/src/share/vm/opto/mulnode.hpp b/src/share/vm/opto/mulnode.hpp --- a/src/share/vm/opto/mulnode.hpp +++ b/src/share/vm/opto/mulnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,6 +75,9 @@ // Supplied function to return the multiplicative opcode virtual int mul_opcode() const = 0; +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------MulINode--------------------------------------- @@ -149,6 +152,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AndINode--------------------------------------- @@ -196,6 +203,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------LShiftLNode------------------------------------ @@ -209,6 +220,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------RShiftINode------------------------------------ @@ -222,6 +237,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------RShiftLNode------------------------------------ @@ -234,6 +253,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; @@ -248,6 +271,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------URShiftLNode----------------------------------- @@ -261,6 +288,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; #endif // SHARE_VM_OPTO_MULNODE_HPP diff --git a/src/share/vm/opto/multnode.cpp b/src/share/vm/opto/multnode.cpp --- a/src/share/vm/opto/multnode.cpp +++ b/src/share/vm/opto/multnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,6 +118,20 @@ bool ProjNode::pinned() const { return in(0)->pinned(); } #ifndef PRODUCT void ProjNode::dump_spec(outputStream *st) const { st->print("#%d",_con); if(_is_io_use) st->print(" (i_o_use)");} + +void ProjNode::dump_comp_spec(outputStream *st) const { + for (DUIterator i = this->outs(); this->has_out(i); i++) { + Node* o = this->out(i); + if (NotANode(o)) { + st->print("[?]"); + } else if (o == NULL) { + st->print("[_]"); + } else { + st->print("[%d]", o->_idx); + } + } + st->print("#%d", _con); +} #endif //----------------------------check_con---------------------------------------- diff --git a/src/share/vm/opto/multnode.hpp b/src/share/vm/opto/multnode.hpp --- a/src/share/vm/opto/multnode.hpp +++ b/src/share/vm/opto/multnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,6 +87,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream *st) const; #endif // Return uncommon trap call node if proj is for "proj->[region->..]call_uct" diff --git a/src/share/vm/opto/node.cpp b/src/share/vm/opto/node.cpp --- a/src/share/vm/opto/node.cpp +++ b/src/share/vm/opto/node.cpp @@ -1489,16 +1489,6 @@ #ifndef PRODUCT -//----------------------------NotANode---------------------------------------- -// Used in debugging code to avoid walking across dead or uninitialized edges. -static inline bool NotANode(const Node* n) { - if (n == NULL) return true; - if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc. - if (*(address*)n == badAddress) return true; // kill by Node::destruct - return false; -} - - //------------------------------find------------------------------------------ // Find a neighbor of this Node with the given _idx // If idx is negative, find its absolute value, following both _in and _out. @@ -1636,11 +1626,11 @@ //------------------------------dump------------------------------------------ // Dump a Node -void Node::dump(const char* suffix, outputStream *st) const { +void Node::dump(const char* suffix, bool mark, outputStream *st) const { Compile* C = Compile::current(); bool is_new = C->node_arena()->contains(this); C->_in_dump_cnt++; - st->print("%c%d\t%s\t=== ", is_new ? ' ' : 'o', _idx, Name()); + st->print("%c%d%s\t%s\t=== ", is_new ? ' ' : 'o', _idx, mark ? " >" : "", Name()); // Dump the required and precedence inputs dump_req(st); @@ -1760,42 +1750,60 @@ st->print("]] "); } -//------------------------------dump_nodes------------------------------------- -static void dump_nodes(const Node* start, int d, bool only_ctrl) { - Node* s = (Node*)start; // remove const - if (NotANode(s)) return; - - uint depth = (uint)ABS(d); - int direction = d; - Compile* C = Compile::current(); - GrowableArray nstack(C->unique()); - - nstack.append(s); +//----------------------------collect_nodes_i---------------------------------- +// Collects nodes from an Ideal graph, starting from a given start node and +// moving in a given direction until a certain depth (distance from the start +// node) is reached. Duplicates are ignored. +// Arguments: +// nstack: the nodes are collected into this array. +// start: the node at which to start collecting. +// direction: if this is a positive number, collect input nodes; if it is +// a negative number, collect output nodes. +// depth: collect nodes up to this distance from the start node. +// include_start: whether to include the start node in the result collection. +// only_ctrl: whether to regard control edges only during traversal. +// only_data: whether to regard data edges only during traversal. +static void collect_nodes_i(GrowableArray *nstack, const Node* start, int direction, uint depth, bool include_start, bool only_ctrl, bool only_data) { + Node* s = (Node*) start; // remove const + nstack->append(s); int begin = 0; int end = 0; for(uint i = 0; i < depth; i++) { - end = nstack.length(); + end = nstack->length(); for(int j = begin; j < end; j++) { - Node* tp = nstack.at(j); + Node* tp = nstack->at(j); uint limit = direction > 0 ? tp->len() : tp->outcnt(); for(uint k = 0; k < limit; k++) { Node* n = direction > 0 ? tp->in(k) : tp->raw_out(k); if (NotANode(n)) continue; // do not recurse through top or the root (would reach unrelated stuff) - if (n->is_Root() || n->is_top()) continue; + if (n->is_Root() || n->is_top()) continue; if (only_ctrl && !n->is_CFG()) continue; + if (only_data && n->is_CFG()) continue; - bool on_stack = nstack.contains(n); + bool on_stack = nstack->contains(n); if (!on_stack) { - nstack.append(n); + nstack->append(n); } } } begin = end; } - end = nstack.length(); - if (direction > 0) { + if (!include_start) { + nstack->remove(s); + } +} + +//------------------------------dump_nodes------------------------------------- +static void dump_nodes(const Node* start, int d, bool only_ctrl) { + if (NotANode(start)) return; + + GrowableArray nstack(Compile::current()->unique()); + collect_nodes_i(&nstack, start, d, (uint) ABS(d), true, only_ctrl, false); + + int end = nstack.length(); + if (d > 0) { for(int j = end-1; j >= 0; j--) { nstack.at(j)->dump(); } @@ -1817,6 +1825,210 @@ dump_nodes(this, d, true); } +//------------------------------dump_comp-------------------------------------- +void Node::dump_comp() const { + this->dump_comp("\n"); +} + +//------------------------------dump_comp-------------------------------------- +// Dump a Node in compact representation, i.e., just print its name and index. +// Nodes can specify additional specifics to print in compact representation by +// implementing dump_compact_spec. +void Node::dump_comp(const char* suffix, outputStream *st) const { + Compile* C = Compile::current(); + C->_in_dump_cnt++; + st->print("%s(%d)", Name(), _idx); + this->dump_comp_spec(st); + if (suffix) { + st->print("%s", suffix); + } + C->_in_dump_cnt--; +} + +//------------------------------dump_rel--------------------------------------- +// Dump a Node's related nodes - the notion of "related" depends on the Node at +// hand and is determined by the implementation of the virtual method rel. +void Node::dump_rel() const { + Compile* C = Compile::current(); + GrowableArray in_rel(C->unique()); + GrowableArray out_rel(C->unique()); + this->rel(&in_rel, &out_rel, false); + for (int i = in_rel.length() - 1; i >= 0; i--) { + in_rel.at(i)->dump(); + } + this->dump("\n", true); + for (int i = 0; i < out_rel.length(); i++) { + out_rel.at(i)->dump(); + } +} + +//------------------------------dump_rel--------------------------------------- +// Dump a Node's related nodes up to a given depth (distance from the start +// node). +// Arguments: +// d_in: depth for input nodes. +// d_out: depth for output nodes (note: this also is a positive number). +void Node::dump_rel(uint d_in, uint d_out) const { + Compile* C = Compile::current(); + GrowableArray in_rel(C->unique()); + GrowableArray out_rel(C->unique()); + + // call collect_nodes_i directly + collect_nodes_i(&in_rel, this, 1, d_in, false, false, false); + collect_nodes_i(&out_rel, this, -1, d_out, false, false, false); + + for (int i = in_rel.length() - 1; i >= 0; i--) { + in_rel.at(i)->dump(); + } + this->dump("\n", true); + for (int i = 0; i < out_rel.length(); i++) { + out_rel.at(i)->dump(); + } +} + +//---------------------------dump_rel_comp------------------------------------- +// Dump a Node's related nodes in compact representation. The notion of +// "related" depends on the Node at hand and is determined by the implementation +// of the virtual method rel. +void Node::dump_rel_comp() const { + Compile* C = Compile::current(); + GrowableArray in_rel(C->unique()); + GrowableArray out_rel(C->unique()); + this->rel(&in_rel, &out_rel, true); + int n_in = in_rel.length(); + int n_out = out_rel.length(); + + this->dump_comp(n_in == 0 ? "\n" : " "); + for (int i = 0; i < n_in; i++) { + in_rel.at(i)->dump_comp(i == n_in - 1 ? "\n" : " "); + } + for (int i = 0; i < n_out; i++) { + out_rel.at(i)->dump_comp(i == n_out - 1 ? "\n" : " "); + } +} + +//--------------------------------rel------------------------------------------ +// Collect a Node's related nodes. The default behaviour just collects the +// inputs and outputs at depth 1, including both control and data flow edges, +// regardless of whether the presentation is compact or not. +void Node::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + collect_nodes_i(in_rel, this, 1, 1, false, false, false); + collect_nodes_i(out_rel, this, -1, 1, false, false, false); +} + +//---------------------------collect_nodes------------------------------------- +// An entry point to the low-level node collection facility, to start from a +// given node in the graph. The start node is by default not included in the +// result. +// Arguments: +// ns: collect the nodes into this data structure. +// d: the depth (distance from start node) to which nodes should be +// collected. A value >0 indicates input nodes, a value <0, output +// nodes. +// ctrl: include only control nodes. +// data: include only data nodes. +void Node::collect_nodes(GrowableArray *ns, int d, bool ctrl, bool data) const { + if (ctrl && data) { + // ignore nonsensical combination + return; + } + collect_nodes_i(ns, this, d, (uint) ABS(d), false, ctrl, data); +} + +//--------------------------collect_nodes_in----------------------------------- +static void collect_nodes_in(Node* start, GrowableArray *ns, bool primary_is_data, bool collect_secondary) { + // The maximum depth is determined using a BFS that visits all primary (data + // or control) inputs and increments the depth at each level. + uint d_in = 0; + GrowableArray nodes(Compile::current()->unique()); + nodes.push(start); + int nodes_at_current_level = 1; + int n_idx = 0; + while (nodes_at_current_level > 0) { + // Add all primary inputs reachable from the current level to the list, and + // increase the depth if there were any. + int nodes_at_next_level = 0; + bool nodes_added = false; + while (nodes_at_current_level > 0) { + nodes_at_current_level--; + Node* current = nodes.at(n_idx++); + for (uint i = 0; i < current->len(); i++) { + Node* n = current->in(i); + if (NotANode(n)) { + continue; + } + if ((primary_is_data && n->is_CFG()) || (!primary_is_data && !n->is_CFG())) { + continue; + } + if (!nodes.contains(n)) { + nodes.push(n); + nodes_added = true; + nodes_at_next_level++; + } + } + } + if (nodes_added) { + d_in++; + } + nodes_at_current_level = nodes_at_next_level; + } + start->collect_nodes(ns, d_in, !primary_is_data, primary_is_data); + if (collect_secondary) { + // Now, iterate over the secondary nodes in ns and add the respective + // boundary reachable from them. + GrowableArray sns(Compile::current()->unique()); + for (GrowableArrayIterator it = ns->begin(); it != ns->end(); ++it) { + Node* n = *it; + n->collect_nodes(&sns, 1, primary_is_data, !primary_is_data); + for (GrowableArrayIterator d = sns.begin(); d != sns.end(); ++d) { + ns->append_if_missing(*d); + } + sns.clear(); + } + } +} + +//---------------------collect_nodes_in_all_data------------------------------- +// Collect the entire data input graph. Include the control boundary if +// requested. +// Arguments: +// ns: collect the nodes into this data structure. +// ctrl: if true, include the control boundary. +void Node::collect_nodes_in_all_data(GrowableArray *ns, bool ctrl) const { + collect_nodes_in((Node*) this, ns, true, ctrl); +} + +//--------------------------collect_nodes_in_all_ctrl-------------------------- +// Collect the entire control input graph. Include the data boundary if +// requested. +// ns: collect the nodes into this data structure. +// data: if true, include the control boundary. +void Node::collect_nodes_in_all_ctrl(GrowableArray *ns, bool data) const { + collect_nodes_in((Node*) this, ns, false, data); +} + +//------------------collect_nodes_out_all_ctrl_boundary------------------------ +// Collect the entire output graph until hitting control node boundaries, and +// include those. +void Node::collect_nodes_out_all_ctrl_boundary(GrowableArray *ns) const { + // Perform a BFS and stop at control nodes. + GrowableArray nodes(Compile::current()->unique()); + nodes.push((Node*) this); + while (nodes.length() > 0) { + Node* current = nodes.pop(); + if (NotANode(current)) { + continue; + } + ns->append_if_missing(current); + if (!current->is_CFG()) { + for (DUIterator i = current->outs(); current->has_out(i); i++) { + nodes.push(current->out(i)); + } + } + } + ns->remove((Node*) this); +} + // VERIFICATION CODE // For each input edge to a node (ie - for each Use-Def edge), verify that // there is a corresponding Def-Use edge. @@ -2173,6 +2385,11 @@ st->print(" #"); _type->dump_on(st); } } + +void TypeNode::dump_comp_spec(outputStream *st) const { + st->print("#"); + _type->dump_on(st); +} #endif uint TypeNode::hash() const { return Node::hash() + _type->hash(); diff --git a/src/share/vm/opto/node.hpp b/src/share/vm/opto/node.hpp --- a/src/share/vm/opto/node.hpp +++ b/src/share/vm/opto/node.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1038,13 +1038,44 @@ Node* find(int idx) const; // Search the graph for the given idx. Node* find_ctrl(int idx) const; // Search control ancestors for the given idx. void dump() const { dump("\n"); } // Print this node. - void dump(const char* suffix, outputStream *st = tty) const;// Print this node. + void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node. void dump(int depth) const; // Print this node, recursively to depth d void dump_ctrl(int depth) const; // Print control nodes, to depth d - virtual void dump_req(outputStream *st = tty) const; // Print required-edge info - virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info - virtual void dump_out(outputStream *st = tty) const; // Print the output edge info - virtual void dump_spec(outputStream *st) const {}; // Print per-node info + void dump_comp() const; // Print this node in compact representation. + // Print this node in compact representation. + void dump_comp(const char* suffix, outputStream *st = tty) const; + virtual void dump_req(outputStream *st = tty) const; // Print required-edge info + virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info + virtual void dump_out(outputStream *st = tty) const; // Print the output edge info + virtual void dump_spec(outputStream *st) const {}; // Print per-node info + // Print compact per-node info + virtual void dump_comp_spec(outputStream *st) const { dump_spec(st); } + void dump_rel() const; // Print related nodes (depends on node at hand). + // Print related nodes up to given depths for input and output nodes. + void dump_rel(uint d_in, uint d_out) const; + void dump_rel_comp() const; // Print related nodes in compact representation. + // Collect related nodes. + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; + // Collect nodes starting from this node, explicitly including/excluding control and data links. + void collect_nodes(GrowableArray *ns, int d, bool ctrl, bool data) const; + + // Node collectors, to be used in implementations of Node::rel(). + // Collect the entire data input graph. Include control inputs if requested. + void collect_nodes_in_all_data(GrowableArray *ns, bool ctrl) const; + // Collect the entire control input graph. Include data inputs if requested. + void collect_nodes_in_all_ctrl(GrowableArray *ns, bool data) const; + // Collect the entire output graph until hitting and including control nodes. + void collect_nodes_out_all_ctrl_boundary(GrowableArray *ns) const; + // Collect the entire data input graph, and outputs till level 1. + void collect_nodes_in_data_out_1(GrowableArray *is, GrowableArray *os, bool compact) const { + if (compact) { + this->collect_nodes(is, 1, false, true); + } else { + this->collect_nodes_in_all_data(is, false); + } + this->collect_nodes(os, -1, false, false); + } + void verify_edges(Unique_Node_List &visited); // Verify bi-directional edges void verify() const; // Check Def-Use info for my subgraph static void verify_recur(const Node *n, int verify_depth, VectorSet &old_space, VectorSet &new_space); @@ -1091,6 +1122,29 @@ #endif }; + +#ifndef PRODUCT + +// Used in debugging code to avoid walking across dead or uninitialized edges. +inline bool NotANode(const Node* n) { + if (n == NULL) return true; + if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc. + if (*(address*)n == badAddress) return true; // kill by Node::destruct + return false; +} + +// This macro provides a common definition of related node retrieval for all +// "arithmetic" nodes, which have no common superclass. The data input trees +// are relevant (until a control node boundary is hit), and the outgoing edges +// till level 1. In compact mode, inputs are collected till level 1 as well. +#define REL_IN_DATA_OUT_1 \ + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { \ + this->collect_nodes_in_data_out_1(in_rel, out_rel, compact); \ + } + +#endif + + //----------------------------------------------------------------------------- // Iterators over DU info, and associated Node functions. @@ -1618,6 +1672,7 @@ virtual uint ideal_reg() const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_comp_spec(outputStream *st) const; #endif }; diff --git a/src/share/vm/opto/rootnode.cpp b/src/share/vm/opto/rootnode.cpp --- a/src/share/vm/opto/rootnode.cpp +++ b/src/share/vm/opto/rootnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,3 +88,18 @@ const RegMask &HaltNode::out_RegMask() const { return RegMask::Empty; } + +#ifndef PRODUCT +//-------------------------------rel------------------------------------------- +// Include all control inputs in the related set, and also the input data +// boundary. In compact mode, include all inputs till level 2. Also include +// all outputs at level 1. +void HaltNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 2, false, false); + } else { + this->collect_nodes_in_all_ctrl(in_rel, true); + } + this->collect_nodes(out_rel, -1, false, false); +} +#endif diff --git a/src/share/vm/opto/rootnode.hpp b/src/share/vm/opto/rootnode.hpp --- a/src/share/vm/opto/rootnode.hpp +++ b/src/share/vm/opto/rootnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,10 @@ virtual const RegMask &out_RegMask() const; virtual uint ideal_reg() const { return NotAMachineReg; } virtual uint match_edge(uint idx) const { return 0; } + +#ifndef PRODUCT + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; #endif // SHARE_VM_OPTO_ROOTNODE_HPP diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp --- a/src/share/vm/opto/subnode.cpp +++ b/src/share/vm/opto/subnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -498,6 +498,37 @@ return this; } +#ifndef PRODUCT +//------------------------------rel-------------------------------------------- +// Related nodes of comparison nodes include all data inputs (until hitting a +// control boundary) as well as all outputs until and including control nodes +// as well as their projections. In compact mode, data inputs till depth 1 and +// all outputs till depth 1 are considered. +void CmpNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, true); + this->collect_nodes(out_rel, -1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, false); + this->collect_nodes_out_all_ctrl_boundary(out_rel); + // Now, find all control nodes in out_rel, and include their projections + // and projection targets (if any) in the result. + GrowableArray proj(Compile::current()->unique()); + for (GrowableArrayIterator it = out_rel->begin(); it != out_rel->end(); ++it) { + Node* n = *it; + if (n->is_CFG() && !n->is_Proj()) { + // Assume projections and projection targets are found at levels 1 and 2. + n->collect_nodes(&proj, -2, false, false); + for (GrowableArrayIterator p = proj.begin(); p != proj.end(); ++p) { + out_rel->append_if_missing(*p); + } + proj.clear(); + } + } + } +} +#endif + //============================================================================= //------------------------------cmp-------------------------------------------- // Simplify a CmpI (compare 2 integers) node, based on local information. @@ -1396,17 +1427,31 @@ return _test.cc2logical( phase->type( in(1) ) ); } +#ifndef PRODUCT //------------------------------dump_spec-------------------------------------- // Dump special per-node info -#ifndef PRODUCT void BoolNode::dump_spec(outputStream *st) const { st->print("["); _test.dump_on(st); st->print("]"); } + +//---------------------------------rel----------------------------------------- +// A BoolNode's related nodes are all of its data inputs, and all of its +// outputs until control nodes are hit, which are included. In compact +// representation, inputs till level 3 and immediate outputs are included. +void BoolNode::rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 3, false, true); + this->collect_nodes(out_rel, -1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, false); + this->collect_nodes_out_all_ctrl_boundary(out_rel); + } +} #endif -//------------------------------is_counted_loop_exit_test-------------------------------------- +//----------------------is_counted_loop_exit_test------------------------------ // Returns true if node is used by a counted loop node. bool BoolNode::is_counted_loop_exit_test() { for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) { diff --git a/src/share/vm/opto/subnode.hpp b/src/share/vm/opto/subnode.hpp --- a/src/share/vm/opto/subnode.hpp +++ b/src/share/vm/opto/subnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,6 +61,14 @@ // This is returned whenever the subtracts inputs are the same. virtual const Type *add_id() const = 0; +#ifndef PRODUCT + // For most subclasses of SubNode, it makes sense to take the standard + // approach to related nodes computation: take all data inputs until control + // boundaries are hit, and take the outputs till depth 1. This will be varied + // for certain nodes that have a connection to control in themselves (such as + // CmpNode and subclasses). + REL_IN_DATA_OUT_1; +#endif }; @@ -140,6 +148,13 @@ const Type *add_id() const { return TypeInt::ZERO; } const Type *bottom_type() const { return TypeInt::CC; } virtual uint ideal_reg() const { return Op_RegFlags; } + +#ifndef PRODUCT + // CmpNode and subclasses include all data inputs (until hitting a control + // boundary) in their related node set, as well as all outputs until and + // including eventual control nodes and their projections. + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; //------------------------------CmpINode--------------------------------------- @@ -311,6 +326,7 @@ bool is_counted_loop_exit_test(); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void rel(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; @@ -320,6 +336,10 @@ class AbsNode : public Node { public: AbsNode( Node *value ) : Node(0,value) {} + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AbsINode--------------------------------------- @@ -373,6 +393,10 @@ class NegNode : public Node { public: NegNode( Node *in1 ) : Node(0,in1) {} + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------NegFNode--------------------------------------- @@ -413,6 +437,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------CosDNode--------------------------------------- @@ -427,6 +455,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; @@ -442,6 +474,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; @@ -453,6 +489,10 @@ virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; @@ -468,6 +508,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------ExpDNode--------------------------------------- @@ -482,6 +526,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------LogDNode--------------------------------------- @@ -496,6 +544,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------Log10DNode--------------------------------------- @@ -510,6 +562,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------PowDNode--------------------------------------- @@ -524,6 +580,10 @@ const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } virtual const Type *Value( PhaseTransform *phase ) const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //-------------------------------ReverseBytesINode-------------------------------- diff --git a/src/share/vm/opto/vectornode.hpp b/src/share/vm/opto/vectornode.hpp --- a/src/share/vm/opto/vectornode.hpp +++ b/src/share/vm/opto/vectornode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,10 @@ public: AddVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AddVSNode-------------------------------------- @@ -80,6 +84,10 @@ public: AddVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AddVINode-------------------------------------- @@ -88,6 +96,10 @@ public: AddVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AddVLNode-------------------------------------- @@ -96,6 +108,10 @@ public: AddVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AddVFNode-------------------------------------- @@ -104,6 +120,10 @@ public: AddVFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AddVDNode-------------------------------------- @@ -112,6 +132,10 @@ public: AddVDNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------ReductionNode------------------------------------ @@ -123,6 +147,10 @@ static ReductionNode* make(int opc, Node *ctrl, Node* in1, Node* in2, BasicType bt); static int opcode(int opc, BasicType bt); static bool implemented(int opc, uint vlen, BasicType bt); + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------AddReductionVINode-------------------------------------- @@ -171,6 +199,10 @@ public: SubVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------SubVSNode-------------------------------------- @@ -179,6 +211,10 @@ public: SubVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------SubVINode-------------------------------------- @@ -187,6 +223,10 @@ public: SubVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------SubVLNode-------------------------------------- @@ -195,6 +235,10 @@ public: SubVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------SubVFNode-------------------------------------- @@ -203,6 +247,10 @@ public: SubVFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------SubVDNode-------------------------------------- @@ -211,6 +259,10 @@ public: SubVDNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------MulVSNode-------------------------------------- @@ -219,6 +271,10 @@ public: MulVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------MulVINode-------------------------------------- @@ -227,6 +283,10 @@ public: MulVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------MulVLNode-------------------------------------- @@ -243,6 +303,10 @@ public: MulVFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------MulVDNode-------------------------------------- @@ -251,6 +315,10 @@ public: MulVDNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------MulReductionVINode-------------------------------------- @@ -299,6 +367,10 @@ public: DivVFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------DivVDNode-------------------------------------- @@ -307,6 +379,10 @@ public: DivVDNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------LShiftVBNode----------------------------------- @@ -315,6 +391,10 @@ public: LShiftVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------LShiftVSNode----------------------------------- @@ -323,6 +403,10 @@ public: LShiftVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------LShiftVINode----------------------------------- @@ -331,6 +415,10 @@ public: LShiftVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------LShiftVLNode----------------------------------- @@ -339,6 +427,10 @@ public: LShiftVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------RShiftVBNode----------------------------------- @@ -347,6 +439,10 @@ public: RShiftVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------RShiftVSNode----------------------------------- @@ -355,6 +451,10 @@ public: RShiftVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------RShiftVINode----------------------------------- @@ -363,6 +463,10 @@ public: RShiftVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------RShiftVLNode----------------------------------- @@ -371,6 +475,10 @@ public: RShiftVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------URShiftVBNode---------------------------------- @@ -379,6 +487,10 @@ public: URShiftVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------URShiftVSNode---------------------------------- @@ -387,6 +499,10 @@ public: URShiftVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------URShiftVINode---------------------------------- @@ -395,6 +511,10 @@ public: URShiftVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------URShiftVLNode---------------------------------- @@ -403,6 +523,10 @@ public: URShiftVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------LShiftCntVNode--------------------------------- @@ -430,6 +554,10 @@ public: AndVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------OrVNode--------------------------------------- @@ -438,6 +566,10 @@ public: OrVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //------------------------------XorVNode--------------------------------------- @@ -446,6 +578,10 @@ public: XorVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; + +#ifndef PRODUCT + REL_IN_DATA_OUT_1; +#endif }; //================================= M E M O R Y ===============================