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