< prev index next > src/hotspot/share/opto/cfgnode.cpp
Print this page
#include "opto/addnode.hpp"
#include "opto/castnode.hpp"
#include "opto/cfgnode.hpp"
#include "opto/connode.hpp"
#include "opto/convertnode.hpp"
+ #include "opto/inlinetypenode.hpp"
#include "opto/loopnode.hpp"
#include "opto/machnode.hpp"
#include "opto/movenode.hpp"
#include "opto/narrowptrnode.hpp"
#include "opto/mulnode.hpp"
}
return true; // The Region node is unreachable - it is dead.
}
- bool RegionNode::try_clean_mem_phi(PhaseGVN *phase) {
+ Node* PhiNode::try_clean_mem_phi(PhaseGVN *phase) {
// Incremental inlining + PhaseStringOpts sometimes produce:
//
// cmpP with 1 top input
// |
// If
// the Region stays in the graph. The top input from the cmpP is
// propagated forward and a subgraph that is useful goes away. The
// code below replaces the Phi with the MergeMem so that the Region
// is simplified.
- PhiNode* phi = has_unique_phi();
- if (phi && phi->type() == Type::MEMORY && req() == 3 && phi->is_diamond_phi(true)) {
+ if (type() == Type::MEMORY && is_diamond_phi(true)) {
MergeMemNode* m = NULL;
- assert(phi->req() == 3, "same as region");
+ assert(req() == 3, "same as region");
+ Node* r = in(0);
for (uint i = 1; i < 3; ++i) {
- Node *mem = phi->in(i);
- if (mem && mem->is_MergeMem() && in(i)->outcnt() == 1) {
+ Node *mem = in(i);
+ if (mem && mem->is_MergeMem() && r->in(i)->outcnt() == 1) {
// Nothing is control-dependent on path #i except the region itself.
m = mem->as_MergeMem();
uint j = 3 - i;
- Node* other = phi->in(j);
+ Node* other = in(j);
if (other && other == m->base_memory()) {
// m is a successor memory to other, and is not pinned inside the diamond, so push it out.
// This will allow the diamond to collapse completely.
- phase->is_IterGVN()->replace_node(phi, m);
- return true;
+ return m;
}
}
}
}
- return false;
+ return NULL;
}
//------------------------------Ideal------------------------------------------
// Return a node which is more "ideal" than the current node. Must preserve
// the CFG, but we can still strip out dead paths.
// Check for RegionNode with no Phi users and both inputs come from either
// arm of the same IF. If found, then the control-flow split is useless.
bool has_phis = false;
if (can_reshape) { // Need DU info to check for Phi users
has_phis = (has_phi() != NULL); // Cache result
- if (has_phis && try_clean_mem_phi(phase)) {
- has_phis = false;
+ if (has_phis) {
+ PhiNode* phi = has_unique_phi();
+ if (phi != NULL) {
+ Node* m = phi->try_clean_mem_phi(phase);
+ if (m != NULL) {
+ phase->is_IterGVN()->replace_node(phi, m);
+ has_phis = false;
+ }
+ }
}
if (!has_phis) { // No Phi users? Nothing merging?
for (uint i = 1; i < req()-1; i++) {
Node *if1 = in(i);
//----------------------------make---------------------------------------------
// create a new phi with edges matching r and set (initially) to x
PhiNode* PhiNode::make(Node* r, Node* x, const Type *t, const TypePtr* at) {
uint preds = r->req(); // Number of predecessor paths
- assert(t != Type::MEMORY || at == flatten_phi_adr_type(at), "flatten at");
+ assert(t != Type::MEMORY || at == flatten_phi_adr_type(at) || (flatten_phi_adr_type(at) == TypeAryPtr::INLINES && Compile::current()->flattened_accesses_share_alias()), "flatten at");
PhiNode* p = new PhiNode(r, t, at);
for (uint j = 1; j < preds; j++) {
// Fill in all inputs, except those which the region does not yet have
if (r->in(j) != NULL)
p->init_req(j, x);
// convert the one to the other.
const TypePtr* ttp = _type->make_ptr();
const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL;
const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_klassptr() : NULL;
bool is_intf = false;
- if (ttip != NULL) {
- ciKlass* k = ttip->klass();
- if (k->is_loaded() && k->is_interface())
- is_intf = true;
- }
- if (ttkp != NULL) {
- ciKlass* k = ttkp->klass();
- if (k->is_loaded() && k->is_interface())
- is_intf = true;
+ if (ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
+ is_intf = true;
+ } else if (ttkp != NULL && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
+ is_intf = true;
}
// Default case: merge all inputs
const Type *t = Type::TOP; // Merged type starting value
for (uint i = 1; i < req(); ++i) {// For all paths in
// both implement interface I, but their meet is at 'j/l/O' which
// doesn't implement I, we have no way to tell if the result should
// be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows
// into a Phi which "knows" it's an Interface type we'll have to
// uplift the type.
- if (!t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface()) {
+ if (!t->empty() && ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
assert(ft == _type, ""); // Uplift to interface
- } else if (!t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
+ } else if (!t->empty() && ttkp != NULL && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
assert(ft == _type, ""); // Uplift to interface
} else {
// We also have to handle 'evil cases' of interface- vs. class-arrays
Type::get_arrays_base_elements(jt, _type, NULL, &ttip);
if (!t->empty() && ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
if (true_path != 0) {
Node* id = is_cmove_id(phase, true_path);
if (id != NULL) return id;
}
+ if (phase->is_IterGVN()) {
+ Node* m = try_clean_mem_phi(phase);
+ if (m != NULL) {
+ return m;
+ }
+ }
+
+
// Looking for phis with identical inputs. If we find one that has
// type TypePtr::BOTTOM, replace the current phi with the bottom phi.
if (phase->is_IterGVN() && type() == Type::MEMORY && adr_type() !=
TypePtr::BOTTOM && !adr_type()->is_known_instance()) {
uint phi_len = req();
// Note: During parsing, phis are often transformed before their regions.
// This means we have to use type_or_null to defend against untyped regions.
if( phase->type_or_null(r) == Type::TOP ) // Dead code?
return NULL; // No change
+ // If all inputs are inline types of the same type, push the inline type node down
+ // through the phi because inline type nodes should be merged through their input values.
+ if (req() > 2 && in(1) != NULL && in(1)->is_InlineTypeBase() && (can_reshape || in(1)->is_InlineType())) {
+ int opcode = in(1)->Opcode();
+ uint i = 2;
+ // Check if inputs are values of the same type
+ for (; i < req() && in(i) && in(i)->is_InlineTypeBase() && in(i)->cmp(*in(1)); i++) {
+ assert(in(i)->Opcode() == opcode, "mixing pointers and values?");
+ }
+ if (i == req()) {
+ InlineTypeBaseNode* vt = in(1)->as_InlineTypeBase()->clone_with_phis(phase, in(0));
+ for (uint i = 2; i < req(); ++i) {
+ vt->merge_with(phase, in(i)->as_InlineTypeBase(), i, i == (req()-1));
+ }
+ return vt;
+ }
+ }
+
Node *top = phase->C->top();
bool new_phi = (outcnt() == 0); // transforming new Phi
// No change for igvn if new phi is not hooked
if (new_phi && can_reshape)
return NULL;
// (MergeMemNode is not dead_loop_safe - need to check for dead loop.)
if (progress == NULL && can_reshape && type() == Type::MEMORY) {
// see if this phi should be sliced
uint merge_width = 0;
bool saw_self = false;
+ // TODO revisit this with JDK-8247216
+ bool mergemem_only = true;
for( uint i=1; i<req(); ++i ) {// For all paths in
Node *ii = in(i);
// TOP inputs should not be counted as safe inputs because if the
// Phi references itself through all other inputs then splitting the
// Phi through memory merges would create dead loop at later stage.
}
if (ii->is_MergeMem()) {
MergeMemNode* n = ii->as_MergeMem();
merge_width = MAX2(merge_width, n->req());
saw_self = saw_self || phase->eqv(n->base_memory(), this);
+ } else {
+ mergemem_only = false;
}
}
// This restriction is temporarily necessary to ensure termination:
- if (!saw_self && adr_type() == TypePtr::BOTTOM) merge_width = 0;
+ if (!mergemem_only && !saw_self && adr_type() == TypePtr::BOTTOM) merge_width = 0;
if (merge_width > Compile::AliasIdxRaw) {
// found at least one non-empty MergeMem
const TypePtr* at = adr_type();
if (at != TypePtr::BOTTOM) {
if( phase->type(in(1)) == Type::TOP ) return in(1);
if( phase->type(in(0)) == Type::TOP ) return in(0);
// We only come from CatchProj, unless the CatchProj goes away.
// If the CatchProj is optimized away, then we just carry the
// exception oop through.
+
+ // CheckCastPPNode::Ideal() for inline types reuses the exception
+ // paths of a call to perform an allocation: we can see a Phi here.
+ if (in(1)->is_Phi()) {
+ return this;
+ }
CallNode *call = in(1)->in(0)->as_Call();
return ( in(0)->is_CatchProj() && in(0)->in(0)->in(1) == in(1) )
? this
: call->in(TypeFunc::Parms);
< prev index next >