matcher.cpp revision 420
1988N/A * Copyright 1997-2008 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#
include "incls/_precompiled.incl" 1879N/A//---------------------------Matcher------------------------------------------- 1879N/A//------------------------------warp_incoming_stk_arg------------------------ 1879N/A// This warps a VMReg into an OptoReg::Name 1879N/A // the compiler cannot represent this method's calling sequence 0N/A//---------------------------compute_old_SP------------------------------------ 0N/A // Make sure that the new graph only references new nodes 2842N/A//---------------------------match--------------------------------------------- 2842N/A // One-time initialization of some register masks. 2842N/A // Pointers take 2 slots in 64-bit land 2842N/A // Map a Java-signature return type into return register-value 2842N/A // machine registers for 0, 1 and 2 returned values. 0N/A // Get ideal-register return type 0N/A // Get machine return register 0N/A // And mask for same 0N/A // Need the method signature to determine the incoming argument types, 0N/A // because the types determine which registers the incoming arguments are 0N/A // in, and this affects the matched code. 0N/A // Pass array of ideal registers and length to USER code (from the AD file) 0N/A // that will convert this to an array of register numbers. 0N/A // Sanity check users' calling convention. Real handy while trying to 0N/A // get the initial port correct. 0N/A "parameters in register must be preserved by runtime stubs");
1988N/A "calling conv. must produce distinct regs");
0N/A // Do some initial frame layout. 0N/A // Compute the old incoming SP (may be called FP) as 0N/A // OptoReg::stack0() + locks + in_preserve_stack_slots + pad2. 0N/A // Compute highest incoming stack argument as 0N/A // _old_SP + out_preserve_stack_slots + incoming argument size. 0N/A // Permit args to have no register 0N/A // calling_convention returns stack arguments as a count of 0N/A // slots beyond OptoReg::stack0()/VMRegImpl::stack0. We need to convert this to 1988N/A // the allocators point of view, taking into account all the 0N/A // preserve area, locks & pad2. 1507N/A // Saved biased stack-slot register number 0N/A // Finally, make sure the incoming arguments take up an even number of 0N/A // words, in case the arguments or locals need to contain doubleword stack 0N/A // slots. The rest of the system assumes that stack slot pairs (in 0N/A // particular, in the spill area) which look aligned will in fact be 0N/A // aligned relative to the stack pointer in the target machine. Double 0N/A // stack slots will always be allocated aligned. 0N/A // Compute highest outgoing stack argument as 0N/A // _new_SP + out_preserve_stack_slots + max(outgoing argument size). 0N/A // the compiler cannot represent this method's calling sequence 0N/A if (C->
failing())
return;
// bailed out on incoming arg failure 0N/A // Collect roots of matcher trees. Every node for which 0N/A // _shared[_idx] is cleared is guaranteed to not be shared, and thus 0N/A // can be a valid interior of some tree. 0N/A // Swap out to old-space; emptying new-space 0N/A // Save debug and profile information for nodes in old space: 0N/A // Pre-size the new_node table to avoid the need for range checks. 0N/A // Reset node counter so MachNodes start with _idx at 0 0N/A // Recursively match trees from old space into new space. 0N/A // Correct leaves of new-space Nodes; they point to old-space. 0N/A // During matching shared constants were attached to C->root() 0N/A // because xroot wasn't available yet, so transfer the uses to 0N/A // Now smoke old-space 0N/A // ------------------------ 0N/A // Set up save-on-entry registers 0N/A//------------------------------Fixup_Save_On_Entry---------------------------- 0N/A// The stated purpose of this routine is to take care of save-on-entry 0N/A// registers. However, the overall goal of the Match phase is to convert into 0N/A// machine-specific instructions which have RegMasks to guide allocation. 0N/A// So what this procedure really does is put a valid RegMask on each input 0N/A// to the machine-specific variations of all Return, TailCall and Halt 0N/A// instructions. It also adds edgs to define the save-on-entry values (and of 0N/A// course gives them a mask). 0N/A // Do all the pre-defined register masks 0N/A//---------------------------init_first_stack_mask----------------------------- 0N/A// Create the initial stack mask used by values spilling to the stack. 0N/A// Disallow any debug info in outgoing argument areas by setting the 0N/A// initial mask accordingly. 0N/A // Allocate storage for spill masks as masks for the appropriate load type. 0N/A // At first, start with the empty mask 0N/A // Add in the incoming argument area 0N/A // Add in all bits past the outgoing argument area 0N/A "must be able to represent all call arguments in reg mask");
0N/A // Finally, set the "infinite stack" bit. 0N/A // Make spill masks. Registers for their class, plus FIRST_STACK_mask. 0N/A // Make up debug masks. Any spill slot plus callee-save registers. 0N/A // Caller-save registers are assumed to be trashable by the various 0N/A // inline-cache fixup routines. 0N/A // Prevent stub compilations from attempting to reference 0N/A // callee-saved registers from debug info 0N/A // registers the caller has to save do not work 0N/A//---------------------------is_save_on_entry---------------------------------- 0N/A // Also save argument registers in the trampolining stubs 0N/A//---------------------------Fixup_Save_On_Entry------------------------------- 0N/A // Count number of save-on-entry registers. 0N/A // Find the procedure Start Node 0N/A // Save argument registers in the trampolining stubs 0N/A // Input RegMask array shared by all Returns. 0N/A // The type for doubles and longs has a count of 2, but 0N/A // there is only 1 returned value 0N/A // Returns have 0 or 1 returned values depending on call signature. 0N/A // Return register is specified by return_value in the AD file. 0N/A // Input RegMask array shared by all Rethrows. 0N/A // Rethrow takes exception oop only, but in the argument 0 slot. 0N/A // Need two slots for ptrs in 64-bit land 0N/A // Input RegMask array shared by all TailCalls 0N/A // Input RegMask array shared by all TailJumps 0N/A // TailCalls have 2 returned values (target & moop), whose masks come 0N/A // TailCall to extract these masks and put the correct masks into 0N/A // the tail_call_rms array. 0N/A // TailJumps have 2 returned values (target & ex_oop), whose masks come 0N/A // TailJump to extract these masks and put the correct masks into 0N/A // the tail_jump_rms array. 0N/A // Input RegMask array shared by all Halts 0N/A // Capture the return input masks into each exit flavor 0N/A // Next unused projection number from Start. 0N/A // Do all the save-on-entry registers. Make projections from Start for 0N/A // them, and give them a use at the exit points. To the allocator, they 0N/A // look like incoming register arguments. 0N/A // Add the save-on-entry to the mask array 0N/A // Halts need the SOE registers, but only in the stack as debug info. 0N/A // A just-prior uncommon-trap or deoptimization will use the SOE regs. 0N/A // Is this a RegF low half of a RegD? Double up 2 adjacent RegF's 0N/A // into a single RegD. 0N/A // Add other bit for double 0N/A else if( (i&
1) ==
1 &&
// Else check for high half of double 0N/A // Is this a RegI low half of a RegL? Double up 2 adjacent RegI's 0N/A // into a single RegL. 0N/A else if( (i&
1) == 0 &&
0N/A // Add other bit for long 0N/A else if( (i&
1) ==
1 &&
// Else check for high half of long 0N/A // Make a projection for it off the Start 0N/A // Add a use of the SOE register to all exit paths 0N/A }
// End of if a save-on-entry register 0N/A }
// End of for all machine registers 0N/A//------------------------------init_spill_mask-------------------------------- 0N/A // pointers are twice as big 0N/A // Start at OptoReg::stack0() 0N/A // STACK_ONLY_mask is all stack bits 0N/A // Also set the "infinite stack" bit. 0N/A // Copy the register names over into the shared world 0N/A // SharedInfo::regName[i] = regName[i]; 0N/A // Handy RegMasks per machine register 0N/A // Grab the Frame Pointer 0N/A // Share frame pointer while making spill ops 0N/A // Compute generic short-offset Loads 0N/A // Get the ADLC notion of the right regmask, for each basic type. 0N/A // Detune the assert for cases like (AndI 0xFF (LoadB p)). 0N/A // %%% Kludgery. Instead, fix ideal adr_type methods for all these cases: 0N/A "must not lose alias info when matching");
0N/A//------------------------------MStack----------------------------------------- 0N/A// State and MStack class used in xform() and find_shared() iterative methods. 0N/A//------------------------------xform------------------------------------------ 0N/A// Given a Node in old-space, Match him (Label/Reduce) to produce a machine 0N/A// Node in new-space. Given a new-space Node, recursively walk his children. 0N/A // Old-space or new-space check 0N/A // Calls match special. They match alone with no children. 0N/A // Their children, the incoming arguments, match normally. 0N/A }
else {
// Nothing the matcher cares about 0N/A // Convert to machine-dependent projection 0N/A }
else {
// Else just a regular 'ol guy 0N/A m = n->
clone();
// So just clone into new-space 0N/A // Def-Use edges will be added incrementally as Uses 0N/A // of this node are matched. 0N/A n = m;
// n is now a new-space node 0N/A // Put precedence edges on stack first (match them last). 0N/A // set -1 to call add_prec() instead of set_req() during Step1 0N/A // For constant debug info, I'd rather have unmatched constants. 0N/A // Now do only debug info. Clone constants rather than matching. 0N/A // Constants are represented directly in the debug info without 0N/A // the need for executable machine instructions. 0N/A // Monitor boxes are also represented directly. 0N/A // || op == Op_BoxLock // %%%% enable this and remove (+++) in chaitin.cpp 0N/A // And now walk his children, and convert his inputs to new-space. 0N/A for( ; i >= 0; --i ) {
// For all normal inputs do 0N/A // Set xformed input 0N/A if (p !=
NULL) {
// root doesn't have parent 0N/A }
// while (mstack.is_nonempty()) 0N/A return n;
// Return new-space Node 0N/A//------------------------------warp_outgoing_stk_arg------------------------ 2062N/A // Convert outgoing argument location to a pre-biased stack offset 0N/A // Adjust the stack slot offset to be the register number used 0N/A // by the allocator. 0N/A // Keep track of the largest numbered stack slot used for an arg. 0N/A // Largest used slot per call-site indicates the amount of stack 0N/A // that is killed by the call. 0N/A//------------------------------match_sfpt------------------------------------- 0N/A// Helper function to match call instructions. Calls match special. 2062N/A// They match alone with no children. Their children, the incoming 0N/A// arguments, match normally. 0N/A // Split out case for SafePoint vs Call 0N/A // Match just the call, nothing else 0N/A // Copy data from the Ideal SafePoint to the machine version 0N/A // This is a non-call safepoint 0N/A // Advertise the correct memory effects (for anti-dependence computation). 0N/A // Allocate a private array of RegMasks. These RegMasks are not shared. 0N/A // Do all the pre-defined non-Empty register masks 0N/A // Place first outgoing argument can possibly be put. 0N/A // Compute max outgoing register number per call site. 0N/A // Calls to C may hammer extra stack slots above and beyond any arguments. 2062N/A // These are usually backing store for register arguments for varargs. 0N/A // Do the normal argument list (parameters) register masks 0N/A if(
argcnt > 0 ) {
// Skip it all if we have no args 0N/A // V-call to pick proper calling convention 0N/A // Sanity check users' calling convention. Really handy during 0N/A // the initial porting effort. Fairly expensive otherwise. 0N/A for (
int j = 0; j < i; j++) {
0N/A // Visit each argument. Compute its outgoing register mask. 2062N/A // Return results now can have 2 bits returned. 2062N/A // Compute max over all outgoing arguments both per call-site 0N/A // and over the entire method. 0N/A // Address of incoming argument mask to fill in 0N/A continue;
// Avoid Halves 0N/A // Grab first register, adjust stack slots and insert in mask. 0N/A // Grab second register (if any), adjust stack slots and insert in mask. 0N/A }
// End of for all arguments 0N/A // Compute number of stack slots needed to restore stack in case of 0N/A // Pascal-style argument popping. 0N/A // Compute the max stack slot killed by any call. These will not be 0N/A // available for debug info, and will be used to adjust FIRST_STACK_mask 0N/A // after all call sites have been visited. 0N/A // Kill the outgoing argument area, including any non-argument holes and 0N/A // any legacy C-killed slots. Use Fat-Projections to do the killing. 0N/A // Since the max-per-method covers the max-per-call-site and debug info 0N/A // is excluded on the max-per-method basis, debug info cannot land in 0N/A // this killed area. 0N/A // Transfer the safepoint information from the call to the mcall 0N/A // Move the JVMState list 0N/A // Debug inputs begin just after the last incoming parameter 0N/A // Registers killed by the call are set in the local scheduling pass 0N/A // of Global Code Motion. 0N/A//---------------------------match_tree---------------------------------------- 0N/A// Match a Ideal Node DAG - turn it into a tree; Label & Reduce. Used as part 0N/A// of the whole-sale conversion from Ideal to Mach Nodes. Also used for 0N/A// making GotoNodes while building the CFG and in init_spill_mask() to identify 1601N/A// a Load's result RegMask for memoization in idealreg2regmask[] 1601N/A // Set the mark for all locally allocated State objects. 1601N/A // When this call returns, the _states_arena arena will be reset 1601N/A // freeing all State objects. 1601N/A // StoreNodes require their Memory input to match any LoadNodes 1601N/A // State object for root node of match tree 1601N/A // Allocate it on _states_arena - stack allocation can cause stack overflow. 0N/A // Label the input tree, allocating labels from top-level arena 0N/A // The minimum cost match for the whole tree is found at the root State 0N/A // Reduce input tree based upon the state labels to machine Nodes 0N/A // Add any Matcher-ignored edges 0N/A//------------------------------match_into_reg--------------------------------- 0N/A// Choose to either match this Node in a register or part of the current 0N/A// match tree. Return true for requiring a register and false for matching 0N/A// as part of the current match tree. 1601N/A // Never force constants into registers. Allow them to match as 1601N/A // constants or registers. Copies of the same value will share 1601N/A // the same register. See find_shared_node. 0N/A }
else {
// Not a constant 0N/A // Stop recursion if they have different Controls. 0N/A // Slot 0 of constants is not really a Control. 0N/A // Actually, we can live with the most conservative control we 0N/A // find, if it post-dominates the others. This allows us to 0N/A if( x == m->
in(0) )
// Does 'control' post-dominate 0N/A break;
// m->in(0)? If so, we can use it 0N/A if( j ==
max_scan )
// No post-domination before scan end? 0N/A return true;
// Then break the match tree up 0N/A // These are commonly used in address expressions and can 0N/A // efficiently fold into them on X64 in some cases. 342N/A // Not forceably cloning. If shared, put it into a register. 0N/A//------------------------------Instruction Selection-------------------------- 0N/A// Label method walks a "tree" of nodes, using the ADLC generated DFA to match 0N/A// ideal nodes to machine instructions. Trees are delimited by shared Nodes, 0N/A// things the Matcher does not match (e.g., Memory), and things with different 0N/A// Controls (hence forced into different blocks). We pass in the Control 0N/A// selected for this entire State tree. 0N/A// The Matcher works on Trees, but an Intel add-to-memory requires a DAG: the 0N/A// Store and the Load must have identical Memories (as well as identical 0N/A// pointers). Since the Matcher does not have anything for Memory (and 1734N/A// does not handle DAGs), I have to match the Memory input myself. If the 0N/A// Tree root is a Store, I require all Loads to have the identical memory. 0N/A // Since Label_Root is a recursive function, its possible that we might run 0N/A // out of stack space. See bugs 6272980 & 6227033 for more info. 0N/A // Examine children for memory state 1823N/A // Can only subsume a child into your match-tree if that child's memory state 0N/A // is not modified along the path to another input. 1213N/A // It is unsafe even if the other inputs are separate roots. 0N/A for( i =
1; i <
cnt; i++ ){
// For my children 0N/A // Allocate states out of a private arena 0N/A // Recursively label the State tree. 0N/A // Check for leaves of the State Tree; things that cannot be a part of 0N/A // the current tree. If it finds any, that value is matched as a 0N/A // register operand. If not, then the normal matching is used. 0N/A // Stop recursion if this is LoadNode and the root of this tree is a 0N/A // StoreNode and the load & store have different memories. 0N/A // Can NOT include the match of a subtree when its memory state 0N/A // is used by any of the other subtrees 0N/A // Print when we exclude matching due to different memory states at input-loads 342N/A // Switch to a register-only opcode; this value must be in a register 342N/A // and cannot be subsumed as part of a larger instruction. 342N/A // If match tree has no control and we do, adopt it for entire tree 342N/A // Else match as a normal part of the match tree. 2842N/A // Call DFA to match this node, and return 0N/A// Con nodes reduced using the same rule can share their MachNode 0N/A// which reduces the number of copies of a constant in the final 0N/A// program. The register allocator is free to split uses later to 0N/A// split live ranges. 0N/A // See if this Con has already been reduced using this rule. 0N/A // Don't expect control change for DecodeN 0N/A // Get the new space root. 0N/A // This shouldn't happen give the order of matching. 0N/A // Shared constants need to have their control be root so they 0N/A // can be scheduled properly. 0N/A//------------------------------ReduceInst------------------------------------- 0N/A// Reduce a State tree (with given Control) into a tree of MachNodes. 0N/A// This routine (and it's cohort ReduceOper) convert Ideal Nodes into 0N/A// complicated machine Nodes. Each MachNode covers some tree of Ideal Nodes. 0N/A// Each MachNode has a number of complicated MachOper operands; each 0N/A// MachOper also covers a further tree of Ideal Nodes. 0N/A// The root of the Ideal match tree is always an instruction, so we enter 0N/A// the recursion here. After building the MachNode, we need to recurse 0N/A// the tree checking for these cases: 0N/A// (1) Child is an instruction - 0N/A// Build the instruction (recursively), add it as an edge. 0N/A// Build a simple operand (register) to hold the result of the instruction. 0N/A// (2) Child is an interior part of an instruction - 0N/A// Skip over it (do nothing) 0N/A// (3) Child is the start of a operand - 0N/A// Build the operand, place it inside the instruction 0N/A // Build the object to represent this state & prepare for recursive calls 0N/A // Check for instruction or instruction chain rule 0N/A "duplicating node that's already been matched");
0N/A // Reduce interior of complex instruction 0N/A // Instruction chain rules are data-dependent on their inputs 0N/A // If a Memory was used, insert a Memory edge 0N/A // Verify adr type after matching memory operation 0N/A // It has a unique memory operand. Find corresponding ideal mem node. 0N/A // DecodeN node consumed by an address may have different type 0N/A // then its input. Don't compare types for such case. 0N/A // If the _leaf is an AddP, insert the base edge 0N/A // Perform any 1-to-many expansions required 0N/A // Remove old node from the graph 0N/A // PhaseChaitin::fixup_spills will sometimes generate spill code 0N/A // via the matcher. By the time, nodes have been wired into the CFG, 0N/A // and any further nodes generated by expand rules will be left hanging 0N/A // in space, and will not get emitted as output code. Catch this. 0N/A // Also, catch any new register allocation constraints ("projections") 0N/A // generated belatedly during spill code generation. 2842N/A // Record the con for sharing 0N/A // 'op' is what I am expecting to receive 0N/A // Operand type to catch childs result 0N/A // This is what my child will give me. 0N/A // Choose between operand class or not. 0N/A // This is what I will recieve. 0N/A // New rule for child. Chase operand classes to get the actual rule. 0N/A // Chain from operand or operand class, may be output of shared node 0N/A "Bad AD file: Instruction chain rule must chain from operand");
0N/A // Insert operand into array of operands for this instruction 0N/A // Chain from the result of an instruction 0N/A // Now recursively walk the state tree & add operand list. 0N/A for(
uint i=0; i<
2; i++ ) {
// binary tree 0N/A // 'op' is what I am expecting to receive 0N/A // Operand type to catch childs result 0N/A // This is what my child will give me. 0N/A // Choose between operand class or not. 0N/A // This is what I will receive. 0N/A // New rule for child. Chase operand classes to get the actual rule. 1142N/A // Insert operand into array of operands for this instruction 0N/A }
else {
// Child is internal operand or new instruction 0N/A // internal operand --> call ReduceInst_Interior 0N/A // Interior of complex instruction. Do nothing but recurse. 0N/A // instruction --> call build operand( ) to catch result 2062N/A // --> ReduceInst( newrule ) 0N/A// This routine walks the interior of possible complex operands. 0N/A// At each point we check our children in the match tree: 2081N/A// We are a leaf; add _leaf field as an input to the MachNode 2081N/A// (2) Child is an internal operand - 2081N/A// Skip over it ( do nothing ) 2081N/A// (3) Child is an instruction - 2081N/A// Call ReduceInst recursively and 2081N/A// and instruction as an input to the MachNode 0N/A // Leaf? And not subsumed? 0N/A // Internal operand; recurse but do nothing else 0N/A }
else {
// Child is a new instruction 0N/A // Reduce the instruction, and add a direct pointer from this 0N/A // machine instruction to the newly reduced one. 0N/A// ------------------------------------------------------------------------- 0N/A// Java-Java calling convention 0N/A// (what you use when Java calls Java) 0N/A//------------------------------find_receiver---------------------------------- 0N/A// For a given signature, return the OptoReg for parameter 0. 0N/A // Return argument 0 register. In the LP64 build pointers 0N/A // take 2 registers, but the VM wants only the 'main' name. 0N/A// A method-klass-holder may be passed in the inline_cache_reg 0N/A// and then expanded into the inline_cache_reg and a method_oop register 0N/A// defined in ad_<arch>.cpp 0N/A//------------------------------find_shared------------------------------------ 0N/A// Set bits if Node is shared or otherwise a root 0N/A // Allocate stack of size C->unique() * 2 to avoid frequent realloc 0N/A // Node is shared and has no reason to clone. Flag it as shared. 0N/A // This causes it to match into a register for the sharing. 0N/A switch( n->
Opcode() ) {
// Handle some opcodes special 0N/A case Op_Proj:
// All handled specially during matching 49N/A // Convert (If (Bool (CmpX A B))) into (If (Bool) (CmpX A B)). Helps 49N/A // with matching cmp/branch in 1 instruction. The Matcher needs the 441N/A // Bool and CmpX side-by-side, because it can only get at constants 441N/A // that are at the leaves of Match trees, and the Bool's condition acts 441N/A continue;
// while (mstack.is_nonempty()) 1762N/A continue;
// while (mstack.is_nonempty()) 1762N/A case Op_ConP: {
// Convert pointers above the centerline to NUL 441N/A case Op_ConN: {
// Convert narrow pointers above the centerline to NUL 0N/A // Must be root of match tree due to prior load conflict 0N/A // Fall into default case 0N/A for(
int i = n->
req() -
1; i >= 0; --i) {
// For my children 0N/A if (m ==
NULL)
continue;
// Ignore NULLs 0N/A // Must clone all producers of flags, or we will not match correctly. 0N/A // Suppose a compare setting int-flags is shared (e.g., a switch-tree) 0N/A // then it will match into an ideal Op_RegFlags. Alas, the fp-flags 0N/A // are also there, so we may match a float-branch to int-flags and 0N/A // expect the allocator to haul the flags from the int-side to the 0N/A // fp-side. No can do. 0N/A continue;
// for(int i = ...) 0N/A // Clone addressing expressions as they are "free" in most instructions 0N/A // Bases used in addresses must be shared but since 0N/A // they are shared through a DecodeN they may appear 0N/A // to have a single use so force sharing here. 0N/A // Intel, ARM and friends can handle 2 adds in addressing mode 0N/A // AtomicAdd is not an addressing expression. 0N/A // Cheap to find it by looking for screwy base. 0N/A // Check for shift by small constant as well 0N/A // Allow Matcher to match the rule which bypass 0N/A // ConvI2L operation for an array index on LP64 0N/A // if the index value is positive. 0N/A }
else {
// Sparc, Alpha, PPC and friends 0N/A // Clone X+offset as it also folds into most addressing expressions 0N/A continue;
// for(int i = ...) 0N/A }
// if( off->is_Con() ) 0N/A }
// for(int i = ...) 0N/A // We cannot remove the Cmp input from the Bool here, as the Bool may be 0N/A // shared and all users of the Bool need to move the Cmp in parallel. 0N/A // This leaves both the Bool and the If pointing at the Cmp. To 0N/A // prevent the Matcher from trying to Match the Cmp along both paths 0N/A // BoolNode::match_edge always returns a zero. 0N/A // We reorder the Op_If in a pre-order manner, so we can visit without 0N/A // accidently sharing the Cmp (the Bool and the If make 2 users). 0N/A // Now hack a few special opcodes 0N/A switch( n->
Opcode() ) {
// Handle some opcodes special 0N/A // Restructure into a binary tree for Matching. It's possible that 0N/A // we could move this code up next to the graph reshaping for IfNodes 0N/A // or vice-versa, but I do not want to debug this for Ladybird. 0N/A }
// end of while (mstack.is_nonempty()) 0N/A// machine-independent root to machine-dependent root 0N/A//---------------------------collect_null_checks------------------------------- 0N/A// Find null checks in the ideal graph; write a machine-specific node for 0N/A// it. Used by later implicit-null-check handling. Actually collects 0N/A// either an IfTrue or IfFalse for the common NOT-null path, AND the ideal 0N/A// value being tested. 0N/A // During matching If's have Bool & Cmp side-by-side 0N/A // Look for DecodeN node which should be pinned to orig_proj. 0N/A // On platforms (Sparc) which can not handle 2 adds 0N/A // in addressing mode we have to keep a DecodeN node and 0N/A // use it to do implicit NULL check in address. 0N/A // DecodeN node was pinned to non-null path (orig_proj) during 0N/A // CastPP transformation in final_graph_reshaping_impl(). 0N/A//---------------------------validate_null_checks------------------------------ 0N/A// Its possible that the value being NULL checked is not the root of a match 0N/A// tree. If so, I cannot use the value in an implicit null check. 0N/A // Is a match-tree root, so replace with the matched value 0N/A // Yank from candidate list 0N/A// acting as an Acquire and thus we don't need an Acquire here. We 0N/A// retain the Node to act as a compiler ordering barrier. 0N/A// acting as a Release and thus we don't need a Release here. We 0N/A// retain the Node to act as a compiler ordering barrier. 0N/A // The iff might be some random subclass of If or bol might be Con-Top 0N/A// atomic instruction acting as a store_load barrier without any 0N/A// intervening volatile load, and thus we don't need a barrier here. 0N/A// We retain the Node to act as a compiler ordering barrier. 0N/A // Get the Proj node, ctrl, that can be used to iterate forward 0N/A // We don't need current barrier if we see another or a lock 0N/A // before seeing volatile load. 0N/A // Op_Fastunlock previously appeared in the Op_* list below. 0N/A // With the advent of 1-0 lock operations we're no longer guaranteed 0N/A // that a monitor exit operation contains a serializing instruction. 0N/A // We must retain this membar if there is an upcoming volatile 0N/A // load, which will be preceded by acquire membar. 0N/A // For other kinds of barriers, check by pretending we 0N/A // are them, and seeing if we can be removed. 0N/A // Delicate code to detect case of an upcoming fastlock block 0N/A // The iff might be some random subclass of If or bol might be Con-Top 0N/A // probably not necessary to check for these 0N/A//============================================================================= 0N/A//---------------------------State--------------------------------------------- 0N/A //memset(_cost, -1, sizeof(_cost)); 0N/A //memset(_rule, -1, sizeof(_rule)); 0N/A//---------------------------dump---------------------------------------------- 0N/A // Check for valid entry 0N/A for( i=0; i<
2; i++ )