cfgnode.cpp revision 223
1472N/A * Copyright 1997-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1472N/A * CA 95054 USA or visit www.sun.com if you need additional information or 1879N/A// Portions of code courtesy of Clifford Click 1879N/A// Optimization - Graph Style 1879N/A#
include "incls/_precompiled.incl" 1879N/A//============================================================================= 0N/A//------------------------------Value------------------------------------------ 0N/A// Compute the type of the RegionNode. 0N/A for(
uint i=
1; i<
req(); ++i ) {
// For all paths in 0N/A if( !n )
continue;
// Missing inputs are TOP 0N/A return Type::
TOP;
// All paths dead? Then so are we 0N/A//------------------------------Identity--------------------------------------- 0N/A// Check for Region being Identity. 0N/A // Cannot have Region be an identity, even if it has only 1 input. 0N/A // Phi users cannot have their Region input folded away for them, 0N/A // since they need to select the proper data input 0N/A//------------------------------merge_region----------------------------------- 0N/A// If a Region flows into a Region, merge into one big happy merge. This is 0N/A// hard to do if there is stuff that has to happen 0N/A r->
in(0) == r &&
// Not already collapsed? 0N/A r->
outcnt() ==
2 ) {
// Self user and 'region' user only? 0N/A return NULL;
// Only flatten if no Phi users 0N/A // igvn->hash_delete( phi ); 0N/A // Append inputs to 'r' onto 'region' 0N/A // Move an input from 'r' to 'region' 0N/A // Update phis of 'region' 0N/A //for( uint k = 0; k < max; k++ ) { 0N/A // Node *phi = region->out(k); 0N/A // if( phi->is_Phi() ) { 0N/A // phi->add_req(phi->in(i)); 0N/A rreq++;
// One more input to Region 0N/A }
// Found a region to merge into Region 0N/A // Clobber pointer to the now dead 'r' 0N/A//--------------------------------has_phi-------------------------------------- 0N/A// Helper function: Return any PhiNode that uses this region or NULL 0N/A//-----------------------------has_unique_phi---------------------------------- 0N/A// Helper function: Return the only PhiNode that uses this region or NULL 0N/A // Check that only one use is a Phi 0N/A//------------------------------check_phi_clipping----------------------------- 0N/A// Helper function for RegionNode's identification of FP clipping 0N/A// Check inputs to the Phi 0N/A//------------------------------check_if_clipping------------------------------ 1484N/A// Helper function for RegionNode's identification of FP clipping 0N/A// Check that inputs to Region come from two IfNodes, 0N/A // Check control structure above RegionNode for (if ( if ) ) 0N/A // Check that all inputs are projections 1484N/A // Check that #1 and #2 are ifTrue and ifFalse from same If 0N/A // Check that control for in10 comes from other branch of IF from in3 0N/A // Control pattern checks 0N/A//------------------------------check_convf2i_clipping------------------------- 0N/A// Helper function for RegionNode's identification of FP clipping 0N/A// Verify that the value input to the phi comes from "ConvF2I; LShift; RShift" 0N/A // Check for the RShiftNode 1703N/A // Check for the LShiftNode 1703N/A // Check for the ConvF2INode 1703N/A // Check that shift amounts are only to get sign bits set after F2I 0N/A // Shifts are necessary but current transformation eliminates them 0N/A // OK to return the result of ConvF2I without shifting 0N/A//------------------------------check_compare_clipping------------------------- 0N/A// Helper function for RegionNode's identification of FP clipping 0N/A // Test that the float value being compared against 0N/A // is equivalent to the int value used as a limit 0N/A//------------------------------is_unreachable_region-------------------------- 0N/A// Find if the Region node is reachable from the root. 0N/A // First, cut the simple case of fallthrough region when NONE of 0N/A // region's phis references itself directly or through a data node. 0N/A continue;
// Safe case - no loops 0N/A // Skip if only one use is an other Phi or Call or Uncommon trap. 0N/A // It is safe to consider this case as fallthrough. 0N/A // Check when phi references itself directly or through an other node. 0N/A break;
// Found possible unsafe data loop. 0N/A return false;
// An unsafe case was NOT found - don't need graph walk. 1504N/A // Unsafe case - check if the Region node is reachable from root. 1504N/A // Mark all control nodes reachable from root outputs 0N/A return false;
// We reached the Region node - it is not dead. 1504N/A return true;
// The Region node is unreachable - it is dead. 0N/A//------------------------------Ideal------------------------------------------ 0N/A// Return a node which is more "ideal" than the current node. Must preserve 0N/A// the CFG, but we can still strip out dead paths. 0N/A // Check for RegionNode with no Phi users and both inputs come from either 0N/A // arm of the same IF. If found, then the control-flow split is useless. 0N/A // Add the IF Projections to the worklist. They (and the IF itself) 0N/A // will be eliminated if dead. 0N/A return this;
// Record progress 0N/A // Remove TOP or NULL input paths. If only 1 input path remains, this Region 0N/A // degrades to a copy. 0N/A int cnt = 0;
// Count of values merging 0N/A // Remove useless control copy inputs 0N/A cnt++;
// One more value merging 0N/A while(
progress) {
// Need to establish property over all users 0N/A // If it is LoopNopde it had 2 (+1 itself) inputs and 0N/A // one of them was cut. The loop is dead if it was EntryContol. 0N/A // Yes, the region will be removed during the next step below. 0N/A // Cut the backedge input and remove phis since no data paths left. 0N/A // We don't cut outputs to other nodes here since we need to put them 0N/A // Break dead loop data path. 0N/A // Eagerly replace phis with top to avoid phis copies generation. 0N/A if(
cnt <=
1 ) {
// Only 1 path in? 0N/A // No inputs or all inputs are NULL. 0N/A // During IGVN phase such region will be subsumed by TOP node 0N/A // so region's phis will have TOP as control node. 0N/A // Kill phis here to avoid it. PhiNode::is_copy() will be always false. 1703N/A // Also set other user's input to top. 1914N/A // The fallthrough case since we already checked dead loops above. 0N/A // Eagerly replace phis to avoid copies generation. 428N/A // Remove the RegionNode itself from DefUse info 0N/A return this;
// Record progress 0N/A // If a Region flows into a Region, merge into one big happy merge. 0N/A // Check if this region is the root of a clipping idiom on floats 0N/A // Check that only one use is a Phi and that it simplifies to two constants + 0N/A // Check inputs to the Phi 0N/A // Control pattern checks, now verify compares 0N/A // Only remaining check is that bot_in == top_in == (Phi's val + mods) 0N/A // Check for the ConvF2INode 0N/A // Matched pattern, including LShiftI; RShiftI, replace with integer compares 0N/A // update input edges to region node 0N/A // remove unnecessary 'LShiftI; RShiftI' idiom 0N/A // Return transformed region node 0N/A// Find the one non-null required input. RegionNode only 0N/A//============================================================================= 0N/A// note that these functions assume that the _adr_type field is flattened 0N/A//----------------------------make--------------------------------------------- 0N/A// create a new phi with edges matching r and set (initially) to x 0N/A // Fill in all inputs, except those which the region does not yet have 0N/A//------------------------slice_memory----------------------------------------- 0N/A// create a new phi with narrowed memory type 0N/A // convert self-loops, or else we get a bad graph 0N/A//------------------------split_out_instance----------------------------------- 0N/A// Split out an instance type from a bottom phi. 0N/A "bottom or raw memory required");
0N/A // Check if an appropriate node already exists. 0N/A i = 0;
// will get incremented at top of loop 0N/A//------------------------verify_adr_type-------------------------------------- 0N/A // recheck constructor invariants: 0N/A "adr_type must be consistent across phi nest");
0N/A // ignore top inputs 0N/A "adr_type must be consistent at leaves of phi nest");
0N/A// Verify a whole nest of phis rooted at this one. 0N/A "Phi::adr_type must be pre-normalized");
0N/A//------------------------------Value------------------------------------------ 0N/A// Compute the type of the PhiNode 0N/A if( !r )
// Copy or dead 0N/A // Note: During parsing, phis are often transformed before their regions. 0N/A // This means we have to use type_or_null to defend against untyped regions. 0N/A // Check for trip-counted loop. If so, be smarter. 0N/A ((
const Node*)l->
phi() ==
this) ) {
// Trip counted loop! 0N/A // protect against init_trip() or limit() returning NULL 0N/A if(
lo &&
hi ) {
// Dying loops might have TOP here 0N/A if(
lo->
_hi <
hi->
_lo )
// Reversed endpoints are well defined :-( 0N/A // Until we have harmony between classes and interfaces in the type 0N/A // lattice, we must tread carefully around phis which implicitly 0N/A // convert the one to the other. 0N/A // Default case: merge all inputs 0N/A for (
uint i =
1; i <
req(); ++i) {
// For all paths in 0N/A // Reachable control path? 0N/A // We assume that each input of an interface-valued Phi is a true 0N/A // subtype of that interface. This might not be true of the meet 0N/A // of all the input types. The lattice is not distributive in 0N/A // such cases. Ward off asserts in type.cpp by refusing to do 0N/A // meets between interfaces and proper classes. 0N/A // The worst-case type (from ciTypeFlow) should be consistent with "t". 0N/A // That is, we expect that "t->higher_equal(_type)" holds true. 0N/A // There are various exceptions: 0N/A // - Inputs which are phis might in fact be widened unnecessarily. 0N/A // For example, an input might be a widened int while the phi is a short. 0N/A // - Inputs might be BotPtrs but this phi is dependent on a null check, 0N/A // and postCCP has removed the cast which encodes the result of the check. 0N/A // - The type of this phi is an interface, and the inputs are classes. 0N/A // - Value calls on inputs might produce fuzzy results. 0N/A // (Occurrences of this case suggest improvements to Value methods.) 0N/A // It is not possible to see Type::BOTTOM values as phi inputs, 0N/A // because the ciTypeFlow pre-pass produces verifier-quality types. 0N/A // The following logic has been moved into TypeOopPtr::filter. 0N/A // Check for evil case of 't' being a class and '_type' expecting an 0N/A // interface. This can happen because the bytecodes do not contain 0N/A // enough type info to distinguish a Java-level interface variable 0N/A // from a Java-level object variable. If we meet 2 classes which 0N/A // both implement interface I, but their meet is at 'j/l/O' which 0N/A // doesn't implement I, we have no way to tell if the result should 0N/A // be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows 0N/A // into a Phi which "knows" it's an Interface type we'll have to 0N/A // Otherwise it's something stupid like non-overlapping int ranges 0N/A // found on dying counted loops. 0N/A // If we have an interface-typed Phi and we narrow to a class type, the join 0N/A // should report back the class. However, if we have a J/L/Object 0N/A // class-typed Phi and an interface flows in, it's possible that the meet & 0N/A // join report an interface back out. This isn't possible but happens 0N/A // because the type system doesn't interact well with interfaces. 0N/A // Happens in a CTW of rt.jar, 320-341, no extra flags 0N/A // Deal with conversion problems found in data loops. 0N/A//------------------------------is_diamond_phi--------------------------------- 0N/A// Does this Phi represent a simple well-shaped diamond merge? Return the 0N/A// index of the true path or 0 otherwise. 0N/A // Check for a 2-path merge 0N/A // Check that both paths come from the same If 0N/A // Check for branching opposite expected 0N/A//----------------------------check_cmove_id----------------------------------- 0N/A// Check for CMove'ing a constant after comparing against the constant. 0N/A// Happens all the time now, since if we compare equality vs a constant in 0N/A// the parser, we "know" the variable is constant on one path and we force 0N/A// it. Thus code like "if( x==0 ) {/*EMPTY*/}" ends up inserting a 0N/A// conditional move: "x = (x==0)?0:x;". Yucko. This fix is slightly more 0N/A// general in that we don't need constants. Since CMove's are only inserted 0N/A// in very special circumstances, we do it here on generic Phi's. 0N/A // is_diamond_phi() has guaranteed the correctness of the nodes sequence: 0N/A // phi->region->if_proj->ifnode->bool->cmp 0N/A // Either value might be a cast that depends on a branch of 'iff'. 0N/A // Since the 'id' value will float free of the diamond, either 0N/A // decast or return failure. 0N/A // Don't know how to disentangle this value. 0N/A//------------------------------Identity--------------------------------------- 0N/A// Check for Region being Identity. 0N/A // Check for no merging going on 0N/A // (There used to be special-case code here when this->region->is_Loop. 0N/A // It would check for a tributary phi on the backedge that the main phi 0N/A // trivially, perhaps with a single cast. The unique_input method 0N/A // does all this and more, by reducing such tributaries to 'this'.) 0N/A return this;
// No identity 0N/A//-----------------------------unique_input------------------------------------ 0N/A// Find the unique value, discounting top, self-loops, and casts. 0N/A// Return top if there are no inputs, and self if there are multiple. 0N/A // 1) One unique direct input, or 0N/A // 2) some of the inputs have an intervening ConstraintCast and 0N/A // the type of input is the same or sharper (more specific) 0N/A // than the phi's type. 0N/A // 3) an input is a self loop 0N/A // 1) input or 2) input or 3) input __ 0N/A // \ / | cast phi cast 0N/A if (r ==
NULL)
return in(
1);
// Already degraded to a Copy 0N/A continue;
// ignore unreachable control path 0N/A continue;
// ignore if top, or in(i) and "this" are in a data cycle 0N/A // Check for a unique uncasted input 0N/A // Check for a unique direct input 0N/A//------------------------------is_x2logic------------------------------------- 0N/A// Check for simple convert-to-boolean pattern 0N/A// If:(C Bool) Region:(IfF IfT) Phi:(Region 0 1) 0N/A// Convert Phi to an ConvIB. 0N/A // Convert the true/false index into an expected 0/1 return. 0N/A // Map 2->0 and 1->1. 0N/A // is_diamond_phi() has guaranteed the correctness of the nodes sequence: 0N/A // phi->region->if_proj->ifnode->bool->cmp 0N/A // Check for compare vs 0 0N/A // Allow cmp-vs-1 if the other input is bounded by 0-1 0N/A // Check for boolean test backwards 0N/A // Build int->bool conversion 0N/A//------------------------------is_cond_add------------------------------------ 0N/A// Check for simple conditional add pattern: "(P < Q) ? X+Y : X;" 0N/A// To be profitable the control flow has to disappear; there can be no other 0N/A// values merging here. We replace the test-and-branch with: 0N/A// "(sgn(P-Q))&Y) + X". Basically, convert "(P < Q)" into 0 or -1 by 0N/A// moving the carry bit from (P-Q) into a register with 'sbb EAX,EAX'. 0N/A// Then convert Y to 0-or-Y and finally add. 0N/A// This is a key transform for SpecJava _201_compress. 0N/A // is_diamond_phi() has guaranteed the correctness of the nodes sequence: 0N/A // phi->region->if_proj->ifnode->bool->cmp 0N/A // Make sure only merging this one phi here 0N/A // Make sure each arm of the diamond has exactly one output, which we assume 0N/A // is the region. Otherwise, the control flow won't disappear. 0N/A // Check for "(P < Q)" of type signed int 0N/A /*&&op != Op_SubI && 0N/A // Not so profitable if compare and add are constants 0N/A//------------------------------is_absolute------------------------------------ 0N/A// Check for absolute value. 0N/A int phi_x_idx = 0;
// Index of phi input where to find naked x 0N/A // ABS ends with the merge of 2 control flow paths. 0N/A // Find the false path from the true path. With only 2 inputs, 3 - x works nicely. 0N/A // is_diamond_phi() has guaranteed the correctness of the nodes sequence: 0N/A // phi->region->if_proj->ifnode->bool->cmp 1504N/A // Find zero input of compare; the other input is being abs'd 0N/A // The test is inverted, we should invert the result... 0N/A // Next get the 2 pieces being selected, one is the original value 0N/A // and the other is the negated value. 0N/A // Check other phi input for subtract node 0N/A // Allow only Sub(0,X) and fail out for all others; Neg is not OK //------------------------------split_once------------------------------------- // Helper for split_flow_path if(
phi->
in(i) ==
val ) {
// Found a path with val? // Register the new node but do not transform it. Cannot transform until the // entire Region/Phi conglerate has been hacked as a single huge transform. // Now I can point to the new node. //------------------------------split_flow_path-------------------------------- // Check for merging identical values and split flow paths return NULL;
// Bail out on funny non-value stuff if(
phi->
req() <=
3 )
// Need at least 2 matched inputs and a return NULL;
// third unequal input to be worth doing for( i =
1; i <
phi->
req()-
1; i++ ) {
if( i >=
phi->
req() )
// Only split for constants uint hit = 0;
// Number of times it occurs for( ; i <
phi->
req(); i++ ){
// Count occurances of constant if(
hit <=
1 ||
// Make sure we find 2 or more hit ==
phi->
req()-
1 )
// and not ALL the same value // Now start splitting out the flow paths that merge the same value. // Split first the RegionNode. // Now split all other Phis than this one for( i =
phi->
req()-
1; i > 0; i-- ) {
//============================================================================= //------------------------------simple_data_loop_check------------------------- // Try to determing if the phi node in a simple safe/unsafe data loop. // enum LoopSafety { Safe = 0, Unsafe, UnsafeLoop }; // Safe - safe case when the phi and it's inputs reference only safe data // Unsafe - the phi and it's inputs reference unsafe data nodes but there // is no reference back to the phi - need a graph walk // to determine if it is in a loop; // UnsafeLoop - unsafe case when the phi references itself directly or through // Note: a safe data node is a node which could/never reference itself during // GVN transformations. For now it is Con, Proj, Phi, CastPP, CheckCastPP. // I mark Phi nodes as safe node not only because they can reference itself // but also to prevent mistaking the fallthrough case inside an outer loop // as dead loop when the phi references itselfs through an other phi. // It is unsafe loop if the phi node references itself directly. // Unsafe loop if the phi node references itself through an unsafe data node. // Exclude cases with null inputs or data nodes which could reference // itself (safe for dead loops). // Check inputs of phi's inputs also. // It is much less expensive then full graph walk. // Check the most common case (about 30% of all cases): // phi->Load/Store->AddP->(ConP ConP Con)/(Parm Parm Con). // The phi references an unsafe node - need full analysis. return Safe;
// Safe case - we can optimize the phi node. //------------------------------is_unsafe_data_reference----------------------- // If phi can be reached through the data input - it is data loop. // First, check simple cases when phi references itself directly or // through an other node. return true;
// phi references itself - unsafe loop return false;
// Safe case - phi could be replaced with the unique input. // Unsafe case when we should go through data graph to determine // if the phi references itself. return true;
// Data loop return false;
// The phi is not reachable from its inputs //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Must preserve // the CFG, but we can still strip out dead paths. // The next should never happen after 6297035 fix. if(
is_copy() )
// Already degraded to a Copy ? return NULL;
// No change Node *r =
in(0);
// RegionNode // Note: During parsing, phis are often transformed before their regions. // This means we have to use type_or_null to defend against untyped regions. return NULL;
// No change // The are 2 situations when only one valid phi's input is left // (in addition to Region input). // One: region is not loop - replace phi with this input. // Two: region is loop - replace phi with top since this data path is dead // and we need to break the dead data loop. for(
uint j =
1; j <
req(); ++j ){
// For all paths in // Check unreachable control paths Node* n =
in(j);
// Get the input if (n !=
top) {
// Not already top? if (
uin ==
top) {
// Simplest case: no alive inputs. return NULL;
// Identity will return TOP // Only one not-NULL unique input path is left. // Determine if this input is backedge of a loop. // (Skip new phis which have no uses and dead regions). // First, take the short cut when we know it is a loop and // the EntryControl data path is dead. // Then, check if there is a data loop when phi references itself directly // or through other data nodes. // Break this data loop to avoid creation of a dead loop. // We can't return top if we are in Parse phase - cut inputs only // let Identity to handle the case. // The unique input must eventually be detected by the Identity call. // print this output before failing assert // Check for CMove'ing identity. If it would be unsafe, // handle it here. In the safe case, let Identity handle it. // Check for simple convert-to-boolean pattern // Check for absolute value // Check for conditional add // These 4 optimizations could subsume the phi: // have to check for a dead data loop creation. // We can't return top if we are in Parse phase - cut inputs only // to stop further optimizations for this phi. Identity will return TOP. assert(
req() ==
3,
"only diamond merge phi here");
// Check for merging identical values and split flow paths // This optimization only modifies phi - don't need to check for dead loop. // Split phis through memory merges, so that the memory merges will go away. // Piggy-back this transformation on the search for a unique input.... // It will be as if the merged memory is the unique value of the phi. // (Do not attempt this optimization unless parsing is complete. // It would make the parser's memory-merge logic sick.) // (MergeMemNode is not dead_loop_safe - need to check for dead loop.) // see if this phi should be sliced for(
uint i=
1; i<
req(); ++i ) {
// For all paths in // This restriction is temporarily necessary to ensure termination: // found at least one non-empty MergeMem // Patch the existing phi to select an input from the merge: // Phi:AT1(...MergeMem(m0, m1, m2)...) into // compress paths and change unreachable cycles to TOP // If not, we can update the input infinitely along a MergeMem cycle // Equivalent code is in MemNode::Ideal_common // If tranformed to a MergeMem, get the desired slice // Otherwise the returned node represents memory for every slice // Update input if it is progress over what we have now // We know that at least one MergeMem->base_memory() == this // (saw_self == true). If all other inputs also references this phi // (directly or through data nodes) - it is dead loop. continue;
// skip known cases return top;
// all inputs reference back to this phi - dead loop // Phi(...MergeMem(m0, m1:AT1, m2:AT2)...) into // MergeMem(Phi(...m0...), Phi:AT1(...m1...), Phi:AT2(...m2...)) // Must eagerly register phis, since they participate in loops. // If we have not seen this slice yet, make a phi for it. // Distribute all self-loops. {
// (Extra braces to hide mms.) // now transform the new nodes, and return the mergemem // Replace self with the result. // Other optimizations on the memory chain for(
uint i=
1; i<
req(); ++i ) {
// For all paths in //------------------------------out_RegMask------------------------------------ //============================================================================= // If the input is reachable, then we are executed. // If the input is not reachable, then we are not executed. return in(0);
// Simple copy of incoming control //============================================================================= //============================================================================= //============================================================================= //============================================================================= //------------------------------Value------------------------------------------ // Compute the type of the PCTableNode. If reachable it is a tuple of // Control, otherwise the table targets are not reachable return Type::
TOP;
// All paths dead? Then so are we //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Strip out //============================================================================= //============================================================================= //------------------------------Value------------------------------------------ // Check for being unreachable, or for coming from a Rethrow. Rethrow's cannot // have the default "fall_through_index" path. // Unreachable? Then so are all paths from here. // First assume all paths are reachable // Identify cases that will always throw an exception // () virtual or interface call with NULL receiver // () call is a check cast with incompatible arguments // Rethrows always throw exceptions, never return // Check for null reciever to virtual or interface calls }
// End of if not a runtime stub }
// End of if have call above me }
// End of slot 1 is not a projection//============================================================================= //------------------------------Identity--------------------------------------- // If only 1 target is possible, choose it if it is the main control // If my value is control and no other value is, then treat as ID // If we remove the last CatchProj and elide the Catch/CatchProj, then we // also remove any exception table entry. Thus we must know the call // feeding the Catch will not really throw an exception. This is ok for // the main fall-thru control (happens when we know a call can never throw // an exception) or for "rethrow", because a further optimnization will // yank the rethrow (happens when we inline a function that can throw an // exception and the caller has no handler). Not legal, e.g., for passing // a NULL receiver to a v-call, or passing bad types to a slow-check-cast. // These cases MUST throw an exception via the runtime system, so the VM // will be looking for a table entry. Node *
proj =
in(0)->
in(
1);
// Expect a proj feeding CatchNode // Search for any other path being control for (
uint i = 0; i < t->
cnt(); i++) {
// Only my path is possible; I am identity on control to the jump //============================================================================= //------------------------------Identity--------------------------------------- // Check for CreateEx being Identity. // We only come from CatchProj, unless the CatchProj goes away. // If the CatchProj is optimized away, then we just carry the // exception oop through. //============================================================================= //------------------------------Value------------------------------------------ // Check for being unreachable. //------------------------------Ideal------------------------------------------ // Check for no longer being part of a loop // Dead code elimination can sometimes delete this projection so // if it's not there, there's nothing to do.