c1_Optimizer.cpp revision 1819
1N/A * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 1N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1N/A * This code is free software; you can redistribute it and/or modify it 1N/A * under the terms of the GNU General Public License version 2 only, as 1N/A * published by the Free Software Foundation. 1N/A * This code is distributed in the hope that it will be useful, but WITHOUT 1N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1N/A * version 2 for more details (a copy is included in the LICENSE file that 1N/A * accompanied this code). 1N/A * You should have received a copy of the GNU General Public License version 1N/A * 2 along with this work; if not, write to the Free Software Foundation, 1N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1N/A#
include "incls/_precompiled.incl" for (
int i = 0; i < e; i++) {
// sux is disconnected from graph so disconnect from exception handlers // 1) find conditional expression // check if block ends with an If // check if If works on int or object types // (we cannot handle If's working on long, float or doubles yet, // since IfOp doesn't support them - these If's show up if cmp // operations followed by If's are eliminated) // one Constant may be present between BlockBegin and BlockEnd // check if both branches end with a goto // check if both gotos merge into the same block // check if at least one word was pushed on sux_state // check if phi function is present at end of successor stack and that // only this phi was pushed on the stack // get the values that were pushed in the true- and false-branch // backend does not support floats // check that successor has no other phi functions but sux_phi // this can happen when t_block or f_block contained additonal stores to local variables // that are no longer represented by explicit instructions // true and false blocks can't have phis // 2) substitute conditional expression // with an IfOp followed by a Goto // cut if_ away and get node before // append constants of true- and false-block if necessary // clone constants because original block must not be destroyed // append Goto to successor // prepare state for Goto // Adjust control flow graph // substitute the phi if possible // 3) successfully eliminated a conditional expression if (
x_ifop !=
NULL) {
// x is an ifop, y is a constant // find conditional expressions & replace them with IfOps int _merge_count;
// the number of block pairs successfully merged // Note: It would be sufficient to check for the number of successors (= 1) // in order to decide if this block can be merged potentially. That // would then also include switch statements w/ only a default case. // However, in that case we would need to make sure the switch tag // expression is executed if it can produce observable side effects. // We should probably have the canonicalizer simplifying such switch // statements and then we are sure we don't miss these merge opportunities // here (was bug - gri 7/7/99). // verify that state at the end of block and at the beginning of sux are equal // no phi functions must be present at beginning of sux // find instruction before end & append first instruction of sux block // add exception handlers of deleted block, if any // also substitute predecessor of exception handler tty->
print_cr(
"%d. merged B%d & B%d (stack size = %d)",
// Find the instruction before if_, starting with ifop. // When if_ and ifop are not in the same block, prev // becomes NULL In such (rare) cases it is not // profitable to perform the optimization. // repeat since the same block may merge again // merge blocks if possible // Because of a static contained within (for the purpose of iteration // over instructions), it is only valid to have one of these active at ValueSet*
_set;
// current state, propagated to subsequent BlockBegins // Returns true if caused a change in the block's state. // In some situations (like NullCheck(x); getfield(x)) the debug // information from the explicit NullCheck can be used to populate // the getfield, even if the two instructions are in different // scopes; this allows implicit null checks to be used but the // correct exception information to be generated. We must clear the // last-traversed NullCheck when we reach a potentially-exception- // throwing instruction, as well as in some other cases. // Handlers for relevant instructions // (separated out from NullCheckVisitor for clarity) // The basic contract is that these must leave the instruction in // the desired state; must not assume anything about the state of // the instruction. We make multiple passes over some basic blocks // and the last pass is the only one whose result is valid. // There may be other instructions which need to clear the last // explicit null check. Anything across which we can not hoist the // debug information for a NullCheck instruction must clear it. It // might be safer to pattern match "NullCheck ; {AccessField, // ArrayLength, LoadIndexed}" but it is more easily structured this way. // Should test to see performance hit of clearing it for all handlers // with empty bodies below. If it is negligible then we should leave // that in for safety, otherwise should think more about it. assert(*p !=
NULL,
"should not find NULL instructions");
// clear out an old explicit null checks tty->
print_cr(
" ...iterating block %d in null check elimination for %s::%s%s",
// Create new state if none present (only happens at root) // Initial state is that local 0 (receiver) is non-null for // Local 0 is used in this scope // Must copy block's state to avoid mutating it during iteration // through the block -- otherwise "not-null" states can accidentally // propagate "up" through the block during processing of backward // branches and algorithm is incorrect (and does not converge) // allow visiting of Phis belonging to this block // Propagate the state before this block into the exception // handlers. They aren't true successors since we aren't guaranteed // to execute the whole block before executing them. Also putting // them on first seems to help reduce the amount of iteration to // Iterate through block, updating state. // Mark instructions in this block as visitable as they are seen // in the instruction list. This keeps the iteration from // visiting instructions which are references in other blocks or // visiting instructions more than once. // Propagate state to successors if necessary // If the field is a non-null static final object field (as is // often the case for sun.misc.Unsafe), put this LoadField into tty->
print_cr(
"AccessField %d proven non-null by static final non-null oop check",
// Value is non-null => update AccessField tty->
print_cr(
"Folded NullCheck %d into AccessField %d's null check for value %d",
tty->
print_cr(
"AccessField %d of value %d proves value to be non-null", x->
id(),
obj->
id());
// Ensure previous passes do not cause wrong state // Value is non-null => update AccessArray tty->
print_cr(
"Folded NullCheck %d into ArrayLength %d's null check for value %d",
// Ensure previous passes do not cause wrong state // Value is non-null => update AccessArray tty->
print_cr(
"Folded NullCheck %d into LoadIndexed %d's null check for value %d",
// Ensure previous passes do not cause wrong state // Value is non-null => update AccessArray // Ensure previous passes do not cause wrong state // Already proven to be non-null => this NullCheck is useless // Don't unpin since that may shrink obj's live range and make it unavailable for debug info. // The code generator won't emit LIR for a NullCheck that cannot trap. // May be null => add to map and set last explicit NullCheck // make sure it's pinned if it can trap tty->
print_cr(
"NullCheck %d of value %d proves value to be non-null", x->
id(),
obj->
id());
// Value is non-null => update AccessMonitor tty->
print_cr(
"Eliminated AccessMonitor %d's null check for value %d", x->
id(),
obj->
id());
tty->
print_cr(
"AccessMonitor %d of value %d proves value to be non-null", x->
id(),
obj->
id());
// Ensure previous passes do not cause wrong state // Value is non-null => update Intrinsic // Ensure previous passes do not cause wrong state // Value is non-null => update Phi tty->
print_cr(
"Eliminated Phi %d's null check for phifun because all inputs are non-null", x->
id());
tty->
print_cr(
"Starting null check elimination for method %s::%s%s",
// walk over the graph looking for exception // handlers and iterate over them as well // exception handlers need to be treated as additional roots tty->
print_cr(
"Done with null check elimination for method %s::%s%s",