< prev index next >

src/hotspot/share/opto/loopUnswitch.cpp

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2006, 2012, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2006, 2018, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 27,36 **** --- 27,40 ---- #include "opto/connode.hpp" #include "opto/convertnode.hpp" #include "opto/loopnode.hpp" #include "opto/opaquenode.hpp" #include "opto/rootnode.hpp" + #include "utilities/macros.hpp" + #if INCLUDE_SHENANDOAHGC + #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" + #endif //================= Loop Unswitching ===================== // // orig: transformed: // if (invariant-test) then
*** 52,62 **** // Note: the "else" clause may be empty //------------------------------policy_unswitching----------------------------- // Return TRUE or FALSE if the loop should be unswitched // (ie. clone loop with an invariant test that does not exit the loop) ! bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { if( !LoopUnswitching ) { return false; } if (!_head->is_Loop()) { return false; --- 56,66 ---- // Note: the "else" clause may be empty //------------------------------policy_unswitching----------------------------- // Return TRUE or FALSE if the loop should be unswitched // (ie. clone loop with an invariant test that does not exit the loop) ! bool IdealLoopTree::policy_unswitching(PhaseIdealLoop *phase, bool shenandoah_opts) const { if( !LoopUnswitching ) { return false; } if (!_head->is_Loop()) { return false;
*** 73,93 **** } LoopNode* head = _head->as_Loop(); if (head->unswitch_count() + 1 > head->unswitch_max()) { return false; } ! return phase->find_unswitching_candidate(this) != NULL; } //------------------------------find_unswitching_candidate----------------------------- // Find candidate "if" for unswitching ! IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop) const { // Find first invariant test that doesn't exit the loop LoopNode *head = loop->_head->as_Loop(); IfNode* unswitch_iff = NULL; Node* n = head->in(LoopNode::LoopBackControl); while (n != head) { Node* n_dom = idom(n); if (n->is_Region()) { if (n_dom->is_If()) { IfNode* iff = n_dom->as_If(); --- 77,98 ---- } LoopNode* head = _head->as_Loop(); if (head->unswitch_count() + 1 > head->unswitch_max()) { return false; } ! return phase->find_unswitching_candidate(this, shenandoah_opts) != NULL; } //------------------------------find_unswitching_candidate----------------------------- // Find candidate "if" for unswitching ! IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop, bool shenandoah_opts) const { // Find first invariant test that doesn't exit the loop LoopNode *head = loop->_head->as_Loop(); IfNode* unswitch_iff = NULL; Node* n = head->in(LoopNode::LoopBackControl); + int loop_has_sfpts = -1; while (n != head) { Node* n_dom = idom(n); if (n->is_Region()) { if (n_dom->is_If()) { IfNode* iff = n_dom->as_If();
*** 97,106 **** --- 102,134 ---- // If condition is invariant and not a loop exit, // then found reason to unswitch. if (loop->is_invariant(bol) && !loop->is_loop_exit(iff)) { unswitch_iff = iff; } + #if INCLUDE_SHENANDOAHGC + else if (shenandoah_opts && + (ShenandoahWriteBarrierNode::is_heap_stable_test(iff)) && + (loop_has_sfpts == -1 || loop_has_sfpts == 0)) { + assert(UseShenandoahGC, "shenandoah only"); + assert(!loop->is_loop_exit(iff), "both branches should be in the loop"); + if (loop_has_sfpts == -1) { + for(uint i = 0; i < loop->_body.size(); i++) { + Node *m = loop->_body[i]; + if (m->is_SafePoint() && !m->is_CallLeaf()) { + loop_has_sfpts = 1; + break; + } + } + if (loop_has_sfpts == -1) { + loop_has_sfpts = 0; + } + } + if (!loop_has_sfpts) { + unswitch_iff = iff; + } + } + #endif } } } } n = n_dom;
*** 110,125 **** //------------------------------do_unswitching----------------------------- // Clone loop with an invariant test (that does not exit) and // insert a clone of the test that selects which version to // execute. ! void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) { // Find first invariant test that doesn't exit the loop LoopNode *head = loop->_head->as_Loop(); ! IfNode* unswitch_iff = find_unswitching_candidate((const IdealLoopTree *)loop); assert(unswitch_iff != NULL, "should be at least one"); #ifndef PRODUCT if (TraceLoopOpts) { tty->print("Unswitch %d ", head->unswitch_count()+1); --- 138,160 ---- //------------------------------do_unswitching----------------------------- // Clone loop with an invariant test (that does not exit) and // insert a clone of the test that selects which version to // execute. ! void PhaseIdealLoop::do_unswitching(IdealLoopTree *loop, Node_List &old_new, bool shenandoah_opts) { // Find first invariant test that doesn't exit the loop LoopNode *head = loop->_head->as_Loop(); ! IfNode* unswitch_iff = find_unswitching_candidate((const IdealLoopTree *)loop, shenandoah_opts); ! ! #if INCLUDE_SHENANDOAHGC ! if (ShenandoahWriteBarrierNode::is_heap_stable_test(unswitch_iff)) { ! ShenandoahWriteBarrierNode::move_heap_stable_test_out_of_loop(unswitch_iff, this); ! } ! #endif ! assert(unswitch_iff != NULL, "should be at least one"); #ifndef PRODUCT if (TraceLoopOpts) { tty->print("Unswitch %d ", head->unswitch_count()+1);
< prev index next >