1 /* 2 * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_OPTO_REGALLOC_HPP 26 #define SHARE_OPTO_REGALLOC_HPP 27 28 #include "code/vmreg.hpp" 29 #include "opto/block.hpp" 30 #include "opto/matcher.hpp" 31 #include "opto/phase.hpp" 32 33 class Node; 34 class Matcher; 35 class PhaseCFG; 36 37 #define MAX_REG_ALLOCATORS 10 38 39 //------------------------------PhaseRegAlloc------------------------------------ 40 // Abstract register allocator 41 class PhaseRegAlloc : public Phase { 42 friend class VMStructs; 43 static void (*_alloc_statistics[MAX_REG_ALLOCATORS])(); 44 static int _num_allocators; 45 46 protected: 47 OptoRegPair *_node_regs; 48 uint _node_regs_max_index; 49 VectorSet _node_oops; // Mapping from node indices to oopiness 50 51 void alloc_node_regs(int size); // allocate _node_regs table with at least "size" elements 52 53 PhaseRegAlloc( uint unique, PhaseCFG &cfg, Matcher &matcher, 54 void (*pr_stats)()); 55 public: 56 PhaseCFG &_cfg; // Control flow graph 57 uint _framesize; // Size of frame in stack-slots. not counting preserve area 58 OptoReg::Name _max_reg; // Past largest register seen 59 Matcher &_matcher; // Convert Ideal to MachNodes node_regs_max_index() const60 uint node_regs_max_index() const { return _node_regs_max_index; } 61 62 // Get the register associated with the Node get_reg_first(const Node * n) const63 OptoReg::Name get_reg_first( const Node *n ) const { 64 debug_only( if( n->_idx >= _node_regs_max_index ) n->dump(); ); 65 assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array"); 66 return _node_regs[n->_idx].first(); 67 } get_reg_second(const Node * n) const68 OptoReg::Name get_reg_second( const Node *n ) const { 69 debug_only( if( n->_idx >= _node_regs_max_index ) n->dump(); ); 70 assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array"); 71 return _node_regs[n->_idx].second(); 72 } 73 74 // Do all the real work of allocate 75 virtual void Register_Allocate() = 0; 76 77 78 // notify the register allocator that "node" is a new reference 79 // to the value produced by "old_node" 80 virtual void add_reference( const Node *node, const Node *old_node) = 0; 81 82 83 // Set the register associated with a new Node set_bad(uint idx)84 void set_bad( uint idx ) { 85 assert( idx < _node_regs_max_index, "Exceeded _node_regs array"); 86 _node_regs[idx].set_bad(); 87 } set1(uint idx,OptoReg::Name reg)88 void set1( uint idx, OptoReg::Name reg ) { 89 assert( idx < _node_regs_max_index, "Exceeded _node_regs array"); 90 _node_regs[idx].set1(reg); 91 } set2(uint idx,OptoReg::Name reg)92 void set2( uint idx, OptoReg::Name reg ) { 93 assert( idx < _node_regs_max_index, "Exceeded _node_regs array"); 94 _node_regs[idx].set2(reg); 95 } set_pair(uint idx,OptoReg::Name hi,OptoReg::Name lo)96 void set_pair( uint idx, OptoReg::Name hi, OptoReg::Name lo ) { 97 assert( idx < _node_regs_max_index, "Exceeded _node_regs array"); 98 _node_regs[idx].set_pair(hi, lo); 99 } set_ptr(uint idx,OptoReg::Name reg)100 void set_ptr( uint idx, OptoReg::Name reg ) { 101 assert( idx < _node_regs_max_index, "Exceeded _node_regs array"); 102 _node_regs[idx].set_ptr(reg); 103 } 104 // Set and query if a node produces an oop 105 void set_oop( const Node *n, bool ); 106 bool is_oop( const Node *n ) const; 107 108 // Convert a register number to a stack offset 109 int reg2offset ( OptoReg::Name reg ) const; 110 int reg2offset_unchecked( OptoReg::Name reg ) const; 111 112 // Convert a stack offset to a register number 113 OptoReg::Name offset2reg( int stk_offset ) const; 114 115 // Get the register encoding associated with the Node get_encode(const Node * n) const116 int get_encode(const Node *n) const { 117 assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array"); 118 OptoReg::Name first = _node_regs[n->_idx].first(); 119 OptoReg::Name second = _node_regs[n->_idx].second(); 120 assert( !OptoReg::is_valid(second) || second == first+1, "" ); 121 assert(OptoReg::is_reg(first), "out of range"); 122 return Matcher::_regEncode[first]; 123 } 124 125 #ifndef PRODUCT 126 static int _total_framesize; 127 static int _max_framesize; 128 129 virtual void dump_frame() const = 0; 130 virtual char *dump_register( const Node *n, char *buf ) const = 0; 131 static void print_statistics(); 132 #endif 133 }; 134 135 #endif // SHARE_OPTO_REGALLOC_HPP 136