8039298: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)->higher_equal(TypePtr::NULL_PTR))
Convert the assert into the runtime check to skip IGVN optimizations for problematic memory nodes. Eliminate dead nodes more aggressively. Reviewed-by: twisti, iveresov
This commit is contained in:
parent
3e18a6f16d
commit
c909ac41de
hotspot/src/share/vm/opto
@ -704,6 +704,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
#endif
|
||||
set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
|
||||
set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
|
||||
set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it
|
||||
|
||||
if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
|
||||
// Make sure the method being compiled gets its own MDO,
|
||||
@ -988,6 +989,8 @@ Compile::Compile( ciEnv* ci_env,
|
||||
set_print_assembly(PrintFrameConverterAssembly);
|
||||
set_parsed_irreducible_loop(false);
|
||||
#endif
|
||||
set_has_irreducible_loop(false); // no loops
|
||||
|
||||
CompileWrapper cw(this);
|
||||
Init(/*AliasLevel=*/ 0);
|
||||
init_tf((*generator)());
|
||||
@ -1158,7 +1161,7 @@ StartNode* Compile::start() const {
|
||||
if( start->is_Start() )
|
||||
return start->as_Start();
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
fatal("Did not find Start node!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -319,6 +319,7 @@ class Compile : public Phase {
|
||||
bool _trace_opto_output;
|
||||
bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing
|
||||
#endif
|
||||
bool _has_irreducible_loop; // Found irreducible loops
|
||||
// JSR 292
|
||||
bool _has_method_handle_invokes; // True if this method has MethodHandle invokes.
|
||||
RTMState _rtm_state; // State of Restricted Transactional Memory usage
|
||||
@ -604,6 +605,8 @@ class Compile : public Phase {
|
||||
void set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; }
|
||||
int _in_dump_cnt; // Required for dumping ir nodes.
|
||||
#endif
|
||||
bool has_irreducible_loop() const { return _has_irreducible_loop; }
|
||||
void set_has_irreducible_loop(bool z) { _has_irreducible_loop = z; }
|
||||
|
||||
// JSR 292
|
||||
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
|
||||
|
@ -267,9 +267,9 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
|
||||
|
||||
// Counted loop head must be a good RegionNode with only 3 not NULL
|
||||
// control input edges: Self, Entry, LoopBack.
|
||||
if (x->in(LoopNode::Self) == NULL || x->req() != 3)
|
||||
if (x->in(LoopNode::Self) == NULL || x->req() != 3 || loop->_irreducible) {
|
||||
return false;
|
||||
|
||||
}
|
||||
Node *init_control = x->in(LoopNode::EntryControl);
|
||||
Node *back_control = x->in(LoopNode::LoopBackControl);
|
||||
if (init_control == NULL || back_control == NULL) // Partially dead
|
||||
@ -1523,11 +1523,11 @@ bool IdealLoopTree::beautify_loops( PhaseIdealLoop *phase ) {
|
||||
|
||||
// If I have one hot backedge, peel off myself loop.
|
||||
// I better be the outermost loop.
|
||||
if( _head->req() > 3 ) {
|
||||
if (_head->req() > 3 && !_irreducible) {
|
||||
split_outer_loop( phase );
|
||||
result = true;
|
||||
|
||||
} else if( !_head->is_Loop() && !_irreducible ) {
|
||||
} else if (!_head->is_Loop() && !_irreducible) {
|
||||
// Make a new LoopNode to replace the old loop head
|
||||
Node *l = new (phase->C) LoopNode( _head->in(1), _head->in(2) );
|
||||
l = igvn.register_new_node_with_optimizer(l, _head);
|
||||
@ -2939,6 +2939,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
|
||||
return pre_order;
|
||||
}
|
||||
}
|
||||
C->set_has_irreducible_loop(_has_irreducible_loops);
|
||||
}
|
||||
|
||||
// This Node might be a decision point for loops. It is only if
|
||||
|
@ -308,33 +308,16 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
|
||||
int alias_idx = phase->C->get_alias_index(t_adr->is_ptr());
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
Node* base = NULL;
|
||||
if (address->is_AddP())
|
||||
if (address->is_AddP()) {
|
||||
base = address->in(AddPNode::Base);
|
||||
}
|
||||
if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) &&
|
||||
!t_adr->isa_rawptr()) {
|
||||
// Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true.
|
||||
Compile* C = phase->C;
|
||||
tty->cr();
|
||||
tty->print_cr("===== NULL+offs not RAW address =====");
|
||||
if (C->is_dead_node(this->_idx)) tty->print_cr("'this' is dead");
|
||||
if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead");
|
||||
if (C->is_dead_node(mem->_idx)) tty->print_cr("'mem' is dead");
|
||||
if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead");
|
||||
if (C->is_dead_node(base->_idx)) tty->print_cr("'base' is dead");
|
||||
tty->cr();
|
||||
base->dump(1);
|
||||
tty->cr();
|
||||
this->dump(2);
|
||||
tty->print("this->adr_type(): "); adr_type()->dump(); tty->cr();
|
||||
tty->print("phase->type(address): "); t_adr->dump(); tty->cr();
|
||||
tty->print("phase->type(base): "); phase->type(address)->dump(); tty->cr();
|
||||
tty->cr();
|
||||
// Skip this node optimization if its address has TOP base.
|
||||
return NodeSentinel; // caller will return NULL
|
||||
}
|
||||
assert(base == NULL || t_adr->isa_rawptr() ||
|
||||
!phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?");
|
||||
#endif
|
||||
|
||||
// Avoid independent memory operations
|
||||
Node* old_mem = mem;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "opto/cfgnode.hpp"
|
||||
#include "opto/connode.hpp"
|
||||
#include "opto/loopnode.hpp"
|
||||
#include "opto/machnode.hpp"
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/node.hpp"
|
||||
@ -1263,6 +1264,7 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) {
|
||||
|
||||
Node *top = igvn->C->top();
|
||||
nstack.push(dead);
|
||||
bool has_irreducible_loop = igvn->C->has_irreducible_loop();
|
||||
|
||||
while (nstack.size() > 0) {
|
||||
dead = nstack.pop();
|
||||
@ -1277,13 +1279,31 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) {
|
||||
assert (!use->is_Con(), "Control for Con node should be Root node.");
|
||||
use->set_req(0, top); // Cut dead edge to prevent processing
|
||||
nstack.push(use); // the dead node again.
|
||||
} else if (!has_irreducible_loop && // Backedge could be alive in irreducible loop
|
||||
use->is_Loop() && !use->is_Root() && // Don't kill Root (RootNode extends LoopNode)
|
||||
use->in(LoopNode::EntryControl) == dead) { // Dead loop if its entry is dead
|
||||
use->set_req(LoopNode::EntryControl, top); // Cut dead edge to prevent processing
|
||||
use->set_req(0, top); // Cut self edge
|
||||
nstack.push(use);
|
||||
} else { // Else found a not-dead user
|
||||
// Dead if all inputs are top or null
|
||||
bool dead_use = !use->is_Root(); // Keep empty graph alive
|
||||
for (uint j = 1; j < use->req(); j++) {
|
||||
if (use->in(j) == dead) { // Turn all dead inputs into TOP
|
||||
Node* in = use->in(j);
|
||||
if (in == dead) { // Turn all dead inputs into TOP
|
||||
use->set_req(j, top);
|
||||
} else if (in != NULL && !in->is_top()) {
|
||||
dead_use = false;
|
||||
}
|
||||
}
|
||||
igvn->_worklist.push(use);
|
||||
if (dead_use) {
|
||||
if (use->is_Region()) {
|
||||
use->set_req(0, top); // Cut self edge
|
||||
}
|
||||
nstack.push(use);
|
||||
} else {
|
||||
igvn->_worklist.push(use);
|
||||
}
|
||||
}
|
||||
// Refresh the iterator, since any number of kills might have happened.
|
||||
k = dead->last_outs(kmin);
|
||||
|
Loading…
x
Reference in New Issue
Block a user