aoqi@0: /* aoqi@0: * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@1: /* aoqi@1: * This file has been modified by Loongson Technology in 2015. These aoqi@1: * modifications are Copyright (c) 2015 Loongson Technology, and are made aoqi@1: * available on the same license terms set forth above. aoqi@1: */ aoqi@1: aoqi@0: #ifndef SHARE_VM_OPTO_OUTPUT_HPP aoqi@0: #define SHARE_VM_OPTO_OUTPUT_HPP aoqi@0: aoqi@0: #include "opto/block.hpp" aoqi@0: #include "opto/node.hpp" aoqi@0: #ifdef TARGET_ARCH_MODEL_x86_32 aoqi@0: # include "adfiles/ad_x86_32.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_ARCH_MODEL_x86_64 aoqi@0: # include "adfiles/ad_x86_64.hpp" aoqi@0: #endif aoqi@1: #ifdef TARGET_ARCH_MODEL_mips_64 aoqi@1: # include "adfiles/ad_mips_64.hpp" aoqi@1: #endif aoqi@0: #ifdef TARGET_ARCH_MODEL_sparc aoqi@0: # include "adfiles/ad_sparc.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_ARCH_MODEL_zero aoqi@0: # include "adfiles/ad_zero.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_ARCH_MODEL_arm aoqi@0: # include "adfiles/ad_arm.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_ARCH_MODEL_ppc_32 aoqi@0: # include "adfiles/ad_ppc_32.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_ARCH_MODEL_ppc_64 aoqi@0: # include "adfiles/ad_ppc_64.hpp" aoqi@0: #endif aoqi@0: aoqi@0: class Arena; aoqi@0: class Bundle; aoqi@0: class Block; aoqi@0: class Block_Array; aoqi@0: class Node; aoqi@0: class Node_Array; aoqi@0: class Node_List; aoqi@0: class PhaseCFG; aoqi@0: class PhaseChaitin; aoqi@0: class Pipeline_Use_Element; aoqi@0: class Pipeline_Use; aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: #define DEBUG_ARG(x) , x aoqi@0: #else aoqi@0: #define DEBUG_ARG(x) aoqi@0: #endif aoqi@0: aoqi@0: // Define the initial sizes for allocation of the resizable code buffer aoqi@0: enum { aoqi@0: initial_code_capacity = 16 * 1024, aoqi@0: initial_stub_capacity = 4 * 1024, aoqi@0: initial_const_capacity = 4 * 1024, aoqi@0: initial_locs_capacity = 3 * 1024 aoqi@0: }; aoqi@0: aoqi@0: //------------------------------Scheduling---------------------------------- aoqi@0: // This class contains all the information necessary to implement instruction aoqi@0: // scheduling and bundling. aoqi@0: class Scheduling { aoqi@0: aoqi@0: private: aoqi@0: // Arena to use aoqi@0: Arena *_arena; aoqi@0: aoqi@0: // Control-Flow Graph info aoqi@0: PhaseCFG *_cfg; aoqi@0: aoqi@0: // Register Allocation info aoqi@0: PhaseRegAlloc *_regalloc; aoqi@0: aoqi@0: // Number of nodes in the method aoqi@0: uint _node_bundling_limit; aoqi@0: aoqi@0: // List of scheduled nodes. Generated in reverse order aoqi@0: Node_List _scheduled; aoqi@0: aoqi@0: // List of nodes currently available for choosing for scheduling aoqi@0: Node_List _available; aoqi@0: aoqi@0: // For each instruction beginning a bundle, the number of following aoqi@0: // nodes to be bundled with it. aoqi@0: Bundle *_node_bundling_base; aoqi@0: aoqi@0: // Mapping from register to Node aoqi@0: Node_List _reg_node; aoqi@0: aoqi@0: // Free list for pinch nodes. aoqi@0: Node_List _pinch_free_list; aoqi@0: aoqi@0: // Latency from the beginning of the containing basic block (base 1) aoqi@0: // for each node. aoqi@0: unsigned short *_node_latency; aoqi@0: aoqi@0: // Number of uses of this node within the containing basic block. aoqi@0: short *_uses; aoqi@0: aoqi@0: // Schedulable portion of current block. Skips Region/Phi/CreateEx up aoqi@0: // front, branch+proj at end. Also skips Catch/CProj (same as aoqi@0: // branch-at-end), plus just-prior exception-throwing call. aoqi@0: uint _bb_start, _bb_end; aoqi@0: aoqi@0: // Latency from the end of the basic block as scheduled aoqi@0: unsigned short *_current_latency; aoqi@0: aoqi@0: // Remember the next node aoqi@0: Node *_next_node; aoqi@0: aoqi@0: // Use this for an unconditional branch delay slot aoqi@0: Node *_unconditional_delay_slot; aoqi@0: aoqi@0: // Pointer to a Nop aoqi@0: MachNopNode *_nop; aoqi@0: aoqi@0: // Length of the current bundle, in instructions aoqi@0: uint _bundle_instr_count; aoqi@0: aoqi@0: // Current Cycle number, for computing latencies and bundling aoqi@0: uint _bundle_cycle_number; aoqi@0: aoqi@0: // Bundle information aoqi@0: Pipeline_Use_Element _bundle_use_elements[resource_count]; aoqi@0: Pipeline_Use _bundle_use; aoqi@0: aoqi@0: // Dump the available list aoqi@0: void dump_available() const; aoqi@0: aoqi@0: public: aoqi@0: Scheduling(Arena *arena, Compile &compile); aoqi@0: aoqi@0: // Destructor aoqi@0: NOT_PRODUCT( ~Scheduling(); ) aoqi@0: aoqi@0: // Step ahead "i" cycles aoqi@0: void step(uint i); aoqi@0: aoqi@0: // Step ahead 1 cycle, and clear the bundle state (for example, aoqi@0: // at a branch target) aoqi@0: void step_and_clear(); aoqi@0: aoqi@0: Bundle* node_bundling(const Node *n) { aoqi@0: assert(valid_bundle_info(n), "oob"); aoqi@0: return (&_node_bundling_base[n->_idx]); aoqi@0: } aoqi@0: aoqi@0: bool valid_bundle_info(const Node *n) const { aoqi@0: return (_node_bundling_limit > n->_idx); aoqi@0: } aoqi@0: aoqi@0: bool starts_bundle(const Node *n) const { aoqi@0: return (_node_bundling_limit > n->_idx && _node_bundling_base[n->_idx].starts_bundle()); aoqi@0: } aoqi@0: aoqi@0: // Do the scheduling aoqi@0: void DoScheduling(); aoqi@0: aoqi@0: // Compute the local latencies walking forward over the list of aoqi@0: // nodes for a basic block aoqi@0: void ComputeLocalLatenciesForward(const Block *bb); aoqi@0: aoqi@0: // Compute the register antidependencies within a basic block aoqi@0: void ComputeRegisterAntidependencies(Block *bb); aoqi@0: void verify_do_def( Node *n, OptoReg::Name def, const char *msg ); aoqi@0: void verify_good_schedule( Block *b, const char *msg ); aoqi@0: void anti_do_def( Block *b, Node *def, OptoReg::Name def_reg, int is_def ); aoqi@0: void anti_do_use( Block *b, Node *use, OptoReg::Name use_reg ); aoqi@0: aoqi@0: // Add a node to the current bundle aoqi@0: void AddNodeToBundle(Node *n, const Block *bb); aoqi@0: aoqi@0: // Add a node to the list of available nodes aoqi@0: void AddNodeToAvailableList(Node *n); aoqi@0: aoqi@0: // Compute the local use count for the nodes in a block, and compute aoqi@0: // the list of instructions with no uses in the block as available aoqi@0: void ComputeUseCount(const Block *bb); aoqi@0: aoqi@0: // Choose an instruction from the available list to add to the bundle aoqi@0: Node * ChooseNodeToBundle(); aoqi@0: aoqi@0: // See if this Node fits into the currently accumulating bundle aoqi@0: bool NodeFitsInBundle(Node *n); aoqi@0: aoqi@0: // Decrement the use count for a node aoqi@0: void DecrementUseCounts(Node *n, const Block *bb); aoqi@0: aoqi@0: // Garbage collect pinch nodes for reuse by other blocks. aoqi@0: void garbage_collect_pinch_nodes(); aoqi@0: // Clean up a pinch node for reuse (helper for above). aoqi@0: void cleanup_pinch( Node *pinch ); aoqi@0: aoqi@0: // Information for statistics gathering aoqi@0: #ifndef PRODUCT aoqi@0: private: aoqi@0: // Gather information on size of nops relative to total aoqi@0: uint _branches, _unconditional_delays; aoqi@0: aoqi@0: static uint _total_nop_size, _total_method_size; aoqi@0: static uint _total_branches, _total_unconditional_delays; aoqi@0: static uint _total_instructions_per_bundle[Pipeline::_max_instrs_per_cycle+1]; aoqi@0: aoqi@0: public: aoqi@0: static void print_statistics(); aoqi@0: aoqi@0: static void increment_instructions_per_bundle(uint i) { aoqi@0: _total_instructions_per_bundle[i]++; aoqi@0: } aoqi@0: aoqi@0: static void increment_nop_size(uint s) { aoqi@0: _total_nop_size += s; aoqi@0: } aoqi@0: aoqi@0: static void increment_method_size(uint s) { aoqi@0: _total_method_size += s; aoqi@0: } aoqi@0: #endif aoqi@0: aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_OPTO_OUTPUT_HPP